Merge pull request #333 from schungx/master
Serialize/Deserialize for Dynamic and wasm-bindgen/stdweb features.
This commit is contained in:
commit
0a763542ad
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@ -18,7 +18,7 @@ jobs:
|
|||||||
os: [ubuntu-latest]
|
os: [ubuntu-latest]
|
||||||
flags:
|
flags:
|
||||||
- ""
|
- ""
|
||||||
- "--features serde,internals"
|
- "--features metadata,internals"
|
||||||
- "--features unchecked"
|
- "--features unchecked"
|
||||||
- "--features sync"
|
- "--features sync"
|
||||||
- "--features no_optimize"
|
- "--features no_optimize"
|
||||||
@ -32,7 +32,7 @@ jobs:
|
|||||||
- "--features no_module"
|
- "--features no_module"
|
||||||
- "--features no_closure"
|
- "--features no_closure"
|
||||||
- "--features unicode-xid-ident"
|
- "--features unicode-xid-ident"
|
||||||
- "--features sync,no_function,no_float,no_optimize,no_module,no_closure,serde,unchecked"
|
- "--features sync,no_function,no_float,no_optimize,no_module,no_closure,metadata,unchecked"
|
||||||
toolchain: [stable]
|
toolchain: [stable]
|
||||||
experimental: [false]
|
experimental: [false]
|
||||||
include:
|
include:
|
||||||
|
35
Cargo.toml
35
Cargo.toml
@ -6,7 +6,7 @@ members = [
|
|||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "rhai"
|
name = "rhai"
|
||||||
version = "0.19.10"
|
version = "0.19.11"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
authors = ["Jonathan Turner", "Lukáš Hozda", "Stephen Chung", "jhwgh1968"]
|
authors = ["Jonathan Turner", "Lukáš Hozda", "Stephen Chung", "jhwgh1968"]
|
||||||
description = "Embedded scripting for Rust"
|
description = "Embedded scripting for Rust"
|
||||||
@ -23,7 +23,8 @@ keywords = [ "scripting" ]
|
|||||||
categories = [ "no-std", "embedded", "wasm", "parser-implementations" ]
|
categories = [ "no-std", "embedded", "wasm", "parser-implementations" ]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
smallvec = { version = "1.4.2", default-features = false }
|
smallvec = { version = "1.6", default-features = false, features = ["union"] }
|
||||||
|
ahash = { version = "0.5", default-features = false }
|
||||||
rhai_codegen = { version = "0.3", path = "codegen" }
|
rhai_codegen = { version = "0.3", path = "codegen" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
@ -45,7 +46,11 @@ unicode-xid-ident = ["unicode-xid"] # allow Unicode Standard Annex #31 for ident
|
|||||||
metadata = [ "serde", "serde_json"] # enables exporting functions metadata to JSON
|
metadata = [ "serde", "serde_json"] # enables exporting functions metadata to JSON
|
||||||
|
|
||||||
# compiling for no-std
|
# compiling for no-std
|
||||||
no_std = [ "smallvec/union", "num-traits/libm", "hashbrown", "core-error", "libm", "ahash" ]
|
no_std = [ "smallvec/union", "num-traits/libm", "hashbrown", "core-error", "libm", "ahash/compile-time-rng" ]
|
||||||
|
|
||||||
|
# compiling for WASM
|
||||||
|
wasm-bindgen = [ "instant/wasm-bindgen" ]
|
||||||
|
stdweb = [ "instant/stdweb" ]
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = "fat"
|
lto = "fat"
|
||||||
@ -54,52 +59,46 @@ codegen-units = 1
|
|||||||
#panic = 'abort' # remove stack backtrace for no-std
|
#panic = 'abort' # remove stack backtrace for no-std
|
||||||
|
|
||||||
[dependencies.libm]
|
[dependencies.libm]
|
||||||
version = "0.2.1"
|
version = "0.2"
|
||||||
default_features = false
|
default_features = false
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.num-traits]
|
[dependencies.num-traits]
|
||||||
version = "0.2.11"
|
version = "0.2"
|
||||||
default-features = false
|
default-features = false
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.core-error]
|
[dependencies.core-error]
|
||||||
version = "0.0.0"
|
version = "0.0"
|
||||||
default_features = false
|
default_features = false
|
||||||
features = ["alloc"]
|
features = ["alloc"]
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.hashbrown]
|
[dependencies.hashbrown]
|
||||||
version = "0.7.1"
|
version = "0.7"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["ahash", "nightly", "inline-more"]
|
features = ["ahash", "nightly", "inline-more"]
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.ahash]
|
|
||||||
version = "0.3.2"
|
|
||||||
default-features = false
|
|
||||||
features = ["compile-time-rng"]
|
|
||||||
optional = true
|
|
||||||
|
|
||||||
[dependencies.serde]
|
[dependencies.serde]
|
||||||
version = "1.0.116"
|
version = "1.0"
|
||||||
default_features = false
|
default_features = false
|
||||||
features = ["derive", "alloc"]
|
features = ["derive", "alloc"]
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.serde_json]
|
[dependencies.serde_json]
|
||||||
version = "1.0.60"
|
version = "1.0"
|
||||||
default_features = false
|
default_features = false
|
||||||
features = ["alloc"]
|
features = ["alloc"]
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.unicode-xid]
|
[dependencies.unicode-xid]
|
||||||
version = "0.2.1"
|
version = "0.2"
|
||||||
default_features = false
|
default_features = false
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
instant= { version = "0.1.7", features = ["wasm-bindgen"] } # WASM implementation of std::time::Instant
|
instant= { version = "0.1" } # WASM implementation of std::time::Instant
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
features = [ "serde", "internals" ]
|
features = [ "metadata", "internals" ]
|
||||||
|
@ -22,7 +22,7 @@ Supported targets and builds
|
|||||||
* All common CPU targets for Windows, Linux and MacOS.
|
* All common CPU targets for Windows, Linux and MacOS.
|
||||||
* WebAssembly (WASM)
|
* WebAssembly (WASM)
|
||||||
* `no-std`
|
* `no-std`
|
||||||
* Minimum Rust version 1.45
|
* Minimum Rust version 1.49
|
||||||
|
|
||||||
|
|
||||||
Standard features
|
Standard features
|
||||||
@ -35,7 +35,7 @@ Standard features
|
|||||||
* Freely pass Rust variables/constants into a script via an external [`Scope`](https://rhaiscript.github.io/book/rust/scope.html) - all clonable Rust types are supported; no need to implement any special trait.
|
* Freely pass Rust variables/constants into a script via an external [`Scope`](https://rhaiscript.github.io/book/rust/scope.html) - all clonable Rust types are supported; no need to implement any special trait.
|
||||||
* Easily [call a script-defined function](https://rhaiscript.github.io/book/engine/call-fn.html) from Rust.
|
* Easily [call a script-defined function](https://rhaiscript.github.io/book/engine/call-fn.html) from Rust.
|
||||||
* Relatively little `unsafe` code (yes there are some for performance reasons).
|
* Relatively little `unsafe` code (yes there are some for performance reasons).
|
||||||
* Few dependencies (currently only [`smallvec`](https://crates.io/crates/smallvec)).
|
* Few dependencies (currently only [`smallvec`](https://crates.io/crates/smallvec) and [`ahash`](https://crates.io/crates/ahash)).
|
||||||
* Re-entrant scripting engine can be made `Send + Sync` (via the `sync` feature).
|
* Re-entrant scripting engine can be made `Send + Sync` (via the `sync` feature).
|
||||||
* Scripts are [optimized](https://rhaiscript.github.io/book/engine/optimize.html) (useful for template-based machine-generated scripts) for repeated evaluations.
|
* Scripts are [optimized](https://rhaiscript.github.io/book/engine/optimize.html) (useful for template-based machine-generated scripts) for repeated evaluations.
|
||||||
* Easy custom API development via [plugins](https://rhaiscript.github.io/book/plugins/index.html) system powered by procedural macros.
|
* Easy custom API development via [plugins](https://rhaiscript.github.io/book/plugins/index.html) system powered by procedural macros.
|
||||||
|
19
RELEASES.md
19
RELEASES.md
@ -1,6 +1,25 @@
|
|||||||
Rhai Release Notes
|
Rhai Release Notes
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
Version 0.19.11
|
||||||
|
===============
|
||||||
|
|
||||||
|
Breaking changes
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Rust compiler requirement raised to 1.49.
|
||||||
|
|
||||||
|
Bug fixes
|
||||||
|
---------
|
||||||
|
|
||||||
|
* Fixes compilation errors in `metadata` feature build.
|
||||||
|
|
||||||
|
Enhancements
|
||||||
|
------------
|
||||||
|
|
||||||
|
* `ahash` is used to hash function call parameters. This should yield speed improvements.
|
||||||
|
|
||||||
|
|
||||||
Version 0.19.10
|
Version 0.19.10
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rhai_codegen"
|
name = "rhai_codegen"
|
||||||
version = "0.3.1"
|
version = "0.3.2"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
authors = ["jhwgh1968"]
|
authors = ["jhwgh1968"]
|
||||||
description = "Procedural macro support package for Rhai, a scripting language for Rust"
|
description = "Procedural macro support package for Rhai, a scripting language for Rust"
|
||||||
|
39
src/ast.rs
39
src/ast.rs
@ -7,9 +7,9 @@ use crate::stdlib::{
|
|||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
boxed::Box,
|
boxed::Box,
|
||||||
fmt,
|
fmt,
|
||||||
hash::{Hash, Hasher},
|
hash::Hash,
|
||||||
num::{NonZeroU64, NonZeroUsize},
|
num::{NonZeroU64, NonZeroUsize},
|
||||||
ops::{Add, AddAssign, Deref, DerefMut},
|
ops::{Add, AddAssign},
|
||||||
string::String,
|
string::String,
|
||||||
vec,
|
vec,
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
@ -60,7 +60,7 @@ impl FnAccess {
|
|||||||
/// _(INTERNALS)_ A type containing information on a scripted function.
|
/// _(INTERNALS)_ A type containing information on a scripted function.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@ -266,12 +266,23 @@ impl AST {
|
|||||||
&mut self.statements
|
&mut self.statements
|
||||||
}
|
}
|
||||||
/// Get the internal shared [`Module`] containing all script-defined functions.
|
/// Get the internal shared [`Module`] containing all script-defined functions.
|
||||||
|
#[cfg(not(feature = "internals"))]
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn shared_lib(&self) -> Shared<Module> {
|
pub(crate) fn shared_lib(&self) -> Shared<Module> {
|
||||||
self.functions.clone()
|
self.functions.clone()
|
||||||
}
|
}
|
||||||
|
/// _(INTERNALS)_ Get the internal shared [`Module`] containing all script-defined functions.
|
||||||
|
/// Exported under the `internals` feature only.
|
||||||
|
#[cfg(feature = "internals")]
|
||||||
|
#[deprecated = "this method is volatile and may change"]
|
||||||
|
#[cfg(not(feature = "no_module"))]
|
||||||
|
#[cfg(not(feature = "no_function"))]
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn shared_lib(&self) -> Shared<Module> {
|
||||||
|
self.functions.clone()
|
||||||
|
}
|
||||||
/// Get the internal [`Module`] containing all script-defined functions.
|
/// Get the internal [`Module`] containing all script-defined functions.
|
||||||
#[cfg(not(feature = "internals"))]
|
#[cfg(not(feature = "internals"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -755,7 +766,7 @@ impl AsRef<Module> for AST {
|
|||||||
/// _(INTERNALS)_ An identifier containing an [immutable string][ImmutableString] name and a [position][Position].
|
/// _(INTERNALS)_ An identifier containing an [immutable string][ImmutableString] name and a [position][Position].
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||||
@ -776,7 +787,7 @@ impl fmt::Debug for Ident {
|
|||||||
/// _(INTERNALS)_ A type encapsulating the mode of a `return`/`throw` statement.
|
/// _(INTERNALS)_ A type encapsulating the mode of a `return`/`throw` statement.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
|
#[derive(Debug, Eq, PartialEq, Clone, Copy, Hash)]
|
||||||
@ -790,7 +801,7 @@ pub enum ReturnType {
|
|||||||
/// _(INTERNALS)_ An [`AST`] node, consisting of either an [`Expr`] or a [`Stmt`].
|
/// _(INTERNALS)_ An [`AST`] node, consisting of either an [`Expr`] or a [`Stmt`].
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone, Hash)]
|
#[derive(Debug, Clone, Hash)]
|
||||||
@ -814,7 +825,7 @@ impl<'a> From<&'a Expr> for ASTNode<'a> {
|
|||||||
/// _(INTERNALS)_ A statement.
|
/// _(INTERNALS)_ A statement.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone, Hash)]
|
#[derive(Debug, Clone, Hash)]
|
||||||
@ -1061,7 +1072,7 @@ impl Stmt {
|
|||||||
/// _(INTERNALS)_ A custom syntax expression.
|
/// _(INTERNALS)_ A custom syntax expression.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone, Hash)]
|
#[derive(Debug, Clone, Hash)]
|
||||||
@ -1077,7 +1088,7 @@ pub struct CustomExpr {
|
|||||||
/// _(INTERNALS)_ A binary expression.
|
/// _(INTERNALS)_ A binary expression.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone, Hash)]
|
#[derive(Debug, Clone, Hash)]
|
||||||
@ -1091,7 +1102,7 @@ pub struct BinaryExpr {
|
|||||||
/// _(INTERNALS)_ A function call.
|
/// _(INTERNALS)_ A function call.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone, Default, Hash)]
|
#[derive(Debug, Clone, Default, Hash)]
|
||||||
@ -1120,7 +1131,7 @@ pub struct FloatWrapper(FLOAT);
|
|||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
impl Hash for FloatWrapper {
|
impl Hash for FloatWrapper {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: crate::stdlib::hash::Hasher>(&self, state: &mut H) {
|
||||||
self.0.to_le_bytes().hash(state);
|
self.0.to_le_bytes().hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1140,7 +1151,7 @@ impl AsMut<FLOAT> for FloatWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
impl Deref for FloatWrapper {
|
impl crate::stdlib::ops::Deref for FloatWrapper {
|
||||||
type Target = FLOAT;
|
type Target = FLOAT;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
@ -1149,7 +1160,7 @@ impl Deref for FloatWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
impl DerefMut for FloatWrapper {
|
impl crate::stdlib::ops::DerefMut for FloatWrapper {
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
&mut self.0
|
&mut self.0
|
||||||
}
|
}
|
||||||
@ -1186,7 +1197,7 @@ impl FloatWrapper {
|
|||||||
/// _(INTERNALS)_ An expression sub-tree.
|
/// _(INTERNALS)_ An expression sub-tree.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone, Hash)]
|
#[derive(Debug, Clone, Hash)]
|
||||||
|
@ -45,7 +45,7 @@ pub const TYPICAL_MAP_SIZE: usize = 8; // Small maps are typical
|
|||||||
/// _(INTERNALS)_ A stack of imported [modules][Module].
|
/// _(INTERNALS)_ A stack of imported [modules][Module].
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
//
|
//
|
||||||
@ -498,7 +498,7 @@ impl<T: Into<Dynamic>> From<T> for Target<'_> {
|
|||||||
/// _(INTERNALS)_ A type that holds all the current states of the [`Engine`].
|
/// _(INTERNALS)_ A type that holds all the current states of the [`Engine`].
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone, Default)]
|
#[derive(Debug, Clone, Default)]
|
||||||
@ -538,7 +538,7 @@ impl State {
|
|||||||
/// _(INTERNALS)_ A type containing all the limits imposed by the [`Engine`].
|
/// _(INTERNALS)_ A type containing all the limits imposed by the [`Engine`].
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
|
@ -269,7 +269,7 @@ impl Engine {
|
|||||||
if let Some(prop) = extract_prop_from_getter(fn_name) {
|
if let Some(prop) = extract_prop_from_getter(fn_name) {
|
||||||
return EvalAltResult::ErrorDotExpr(
|
return EvalAltResult::ErrorDotExpr(
|
||||||
format!(
|
format!(
|
||||||
"Failed to get property '{}' of '{}' - the property may not exist, or it may be write-only",
|
"Unknown property '{}' - a getter is not registered for type '{}'",
|
||||||
prop,
|
prop,
|
||||||
self.map_type_name(args[0].type_name())
|
self.map_type_name(args[0].type_name())
|
||||||
),
|
),
|
||||||
@ -283,7 +283,7 @@ impl Engine {
|
|||||||
if let Some(prop) = extract_prop_from_setter(fn_name) {
|
if let Some(prop) = extract_prop_from_setter(fn_name) {
|
||||||
return EvalAltResult::ErrorDotExpr(
|
return EvalAltResult::ErrorDotExpr(
|
||||||
format!(
|
format!(
|
||||||
"Failed to set property '{}' of '{}' - the property may not exist, may be read-only, or '{}' is the wrong type",
|
"No writable property '{}' - a setter is not registered for type '{}' to handle '{}'",
|
||||||
prop,
|
prop,
|
||||||
self.map_type_name(args[0].type_name()),
|
self.map_type_name(args[0].type_name()),
|
||||||
self.map_type_name(args[1].type_name()),
|
self.map_type_name(args[1].type_name()),
|
||||||
|
@ -1676,9 +1676,8 @@ impl Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get an iterator to the functions in the [`Module`].
|
/// Get an iterator to the functions in the [`Module`].
|
||||||
#[cfg(not(feature = "no_optimize"))]
|
|
||||||
#[cfg(not(feature = "no_function"))]
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
#[allow(dead_code)]
|
||||||
pub(crate) fn iter_fn(&self) -> impl Iterator<Item = &FuncInfo> {
|
pub(crate) fn iter_fn(&self) -> impl Iterator<Item = &FuncInfo> {
|
||||||
self.functions.values()
|
self.functions.values()
|
||||||
}
|
}
|
||||||
@ -2004,7 +2003,7 @@ impl Module {
|
|||||||
/// A [`StaticVec`] is used because most namespace-qualified access contains only one level,
|
/// A [`StaticVec`] is used because most namespace-qualified access contains only one level,
|
||||||
/// and it is wasteful to always allocate a [`Vec`] with one element.
|
/// and it is wasteful to always allocate a [`Vec`] with one element.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Clone, Eq, PartialEq, Default, Hash)]
|
#[derive(Clone, Eq, PartialEq, Default, Hash)]
|
||||||
|
@ -11,7 +11,7 @@ use crate::{EvalAltResult, Position};
|
|||||||
/// _(INTERNALS)_ Error encountered when tokenizing the script text.
|
/// _(INTERNALS)_ Error encountered when tokenizing the script text.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
|
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
|
||||||
|
@ -178,8 +178,9 @@ impl fmt::Display for EvalAltResult {
|
|||||||
|
|
||||||
Self::ErrorDotExpr(s, _) if !s.is_empty() => write!(f, "{}", s)?,
|
Self::ErrorDotExpr(s, _) if !s.is_empty() => write!(f, "{}", s)?,
|
||||||
|
|
||||||
Self::ErrorIndexingType(_, _)
|
Self::ErrorIndexingType(s, _) => write!(f, "Indexer not registered for type '{}'", s)?,
|
||||||
| Self::ErrorUnboundThis(_)
|
|
||||||
|
Self::ErrorUnboundThis(_)
|
||||||
| Self::ErrorFor(_)
|
| Self::ErrorFor(_)
|
||||||
| Self::ErrorInExpr(_)
|
| Self::ErrorInExpr(_)
|
||||||
| Self::ErrorDotExpr(_, _)
|
| Self::ErrorDotExpr(_, _)
|
||||||
|
@ -4,10 +4,8 @@ use super::str::ImmutableStringDeserializer;
|
|||||||
use crate::dynamic::Union;
|
use crate::dynamic::Union;
|
||||||
use crate::stdlib::{any::type_name, boxed::Box, fmt, string::ToString};
|
use crate::stdlib::{any::type_name, boxed::Box, fmt, string::ToString};
|
||||||
use crate::{Dynamic, EvalAltResult, ImmutableString, LexError, Position};
|
use crate::{Dynamic, EvalAltResult, ImmutableString, LexError, Position};
|
||||||
use serde::de::{
|
use serde::de::{DeserializeSeed, Error, IntoDeserializer, MapAccess, SeqAccess, Visitor};
|
||||||
DeserializeSeed, Deserializer, Error, IntoDeserializer, MapAccess, SeqAccess, Visitor,
|
use serde::{Deserialize, Deserializer};
|
||||||
};
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
use crate::Array;
|
use crate::Array;
|
||||||
@ -50,13 +48,9 @@ impl<'de> DynamicDeserializer<'de> {
|
|||||||
visitor: V,
|
visitor: V,
|
||||||
) -> Result<V::Value, Box<EvalAltResult>> {
|
) -> Result<V::Value, Box<EvalAltResult>> {
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
{
|
return visitor.visit_i64(v);
|
||||||
visitor.visit_i64(v)
|
|
||||||
}
|
|
||||||
#[cfg(feature = "only_i32")]
|
#[cfg(feature = "only_i32")]
|
||||||
{
|
return visitor.visit_i32(v);
|
||||||
visitor.visit_i32(v)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
144
src/serde_impl/deserialize.rs
Normal file
144
src/serde_impl/deserialize.rs
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
//! Implementations of [`serde::Deserialize`].
|
||||||
|
|
||||||
|
use crate::stdlib::{fmt, string::ToString};
|
||||||
|
use crate::{Dynamic, ImmutableString, INT};
|
||||||
|
use serde::de::{Deserialize, Deserializer, Error, MapAccess, SeqAccess, Visitor};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
use crate::Array;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
use crate::Map;
|
||||||
|
|
||||||
|
struct DynamicVisitor;
|
||||||
|
|
||||||
|
impl<'d> Visitor<'d> for DynamicVisitor {
|
||||||
|
type Value = Dynamic;
|
||||||
|
|
||||||
|
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
f.write_str("any type that can be converted into a Dynamic")
|
||||||
|
}
|
||||||
|
fn visit_bool<E: Error>(self, v: bool) -> Result<Self::Value, E> {
|
||||||
|
Ok(v.into())
|
||||||
|
}
|
||||||
|
fn visit_i8<E: Error>(self, v: i8) -> Result<Self::Value, E> {
|
||||||
|
Ok(INT::from(v).into())
|
||||||
|
}
|
||||||
|
fn visit_i16<E: Error>(self, v: i16) -> Result<Self::Value, E> {
|
||||||
|
Ok(INT::from(v).into())
|
||||||
|
}
|
||||||
|
fn visit_i32<E: Error>(self, v: i32) -> Result<Self::Value, E> {
|
||||||
|
Ok(INT::from(v).into())
|
||||||
|
}
|
||||||
|
fn visit_i64<E: Error>(self, v: i64) -> Result<Self::Value, E> {
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
return Ok(v.into());
|
||||||
|
#[cfg(feature = "only_i32")]
|
||||||
|
if v > i32::MAX as i64 {
|
||||||
|
return Ok(Dynamic::from(v));
|
||||||
|
} else {
|
||||||
|
return self.visit_i32(v as i32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn visit_u8<E: Error>(self, v: u8) -> Result<Self::Value, E> {
|
||||||
|
Ok(INT::from(v).into())
|
||||||
|
}
|
||||||
|
fn visit_u16<E: Error>(self, v: u16) -> Result<Self::Value, E> {
|
||||||
|
Ok(INT::from(v).into())
|
||||||
|
}
|
||||||
|
fn visit_u32<E: Error>(self, v: u32) -> Result<Self::Value, E> {
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
return Ok(INT::from(v).into());
|
||||||
|
#[cfg(feature = "only_i32")]
|
||||||
|
if v > i32::MAX as u32 {
|
||||||
|
return Ok(Dynamic::from(v));
|
||||||
|
} else {
|
||||||
|
return self.visit_i32(v as i32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn visit_u64<E: Error>(self, v: u64) -> Result<Self::Value, E> {
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
if v > i64::MAX as u64 {
|
||||||
|
return Ok(Dynamic::from(v));
|
||||||
|
} else {
|
||||||
|
return self.visit_i64(v as i64);
|
||||||
|
}
|
||||||
|
#[cfg(feature = "only_i32")]
|
||||||
|
if v > i32::MAX as u64 {
|
||||||
|
return Ok(Dynamic::from(v));
|
||||||
|
} else {
|
||||||
|
return self.visit_i32(v as i32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
fn visit_f32<E: Error>(self, v: f32) -> Result<Self::Value, E> {
|
||||||
|
#[cfg(not(feature = "f32_float"))]
|
||||||
|
return self.visit_f64(v as f64);
|
||||||
|
#[cfg(feature = "f32_float")]
|
||||||
|
return Ok(v.into());
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
fn visit_f64<E: Error>(self, v: f64) -> Result<Self::Value, E> {
|
||||||
|
#[cfg(not(feature = "f32_float"))]
|
||||||
|
return Ok(v.into());
|
||||||
|
#[cfg(feature = "f32_float")]
|
||||||
|
return self.visit_f32(v as f32);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_char<E: Error>(self, v: char) -> Result<Self::Value, E> {
|
||||||
|
self.visit_string(v.to_string())
|
||||||
|
}
|
||||||
|
fn visit_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
|
||||||
|
Ok(v.into())
|
||||||
|
}
|
||||||
|
fn visit_borrowed_str<E: Error>(self, v: &str) -> Result<Self::Value, E> {
|
||||||
|
self.visit_str(v)
|
||||||
|
}
|
||||||
|
fn visit_string<E: Error>(self, v: String) -> Result<Self::Value, E> {
|
||||||
|
Ok(v.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_unit<E: Error>(self) -> Result<Self::Value, E> {
|
||||||
|
Ok(Dynamic::UNIT)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_newtype_struct<D: Deserializer<'d>>(self, de: D) -> Result<Self::Value, D::Error> {
|
||||||
|
Deserialize::deserialize(de)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
fn visit_seq<A: SeqAccess<'d>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
|
||||||
|
let mut arr: Array = Default::default();
|
||||||
|
|
||||||
|
while let Some(v) = seq.next_element()? {
|
||||||
|
arr.push(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(arr.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
fn visit_map<M: MapAccess<'d>>(self, mut map: M) -> Result<Self::Value, M::Error> {
|
||||||
|
let mut m: Map = Default::default();
|
||||||
|
|
||||||
|
while let Some((k, v)) = map.next_entry()? {
|
||||||
|
m.insert(k, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(m.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> Deserialize<'d> for Dynamic {
|
||||||
|
fn deserialize<D: Deserializer<'d>>(de: D) -> Result<Self, D::Error> {
|
||||||
|
de.deserialize_any(DynamicVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d> Deserialize<'d> for ImmutableString {
|
||||||
|
fn deserialize<D: Deserializer<'d>>(de: D) -> Result<Self, D::Error> {
|
||||||
|
let s: String = Deserialize::deserialize(de)?;
|
||||||
|
Ok(s.into())
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,6 @@ use crate::stdlib::{
|
|||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
collections::BTreeMap,
|
collections::BTreeMap,
|
||||||
string::{String, ToString},
|
string::{String, ToString},
|
||||||
vec,
|
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
use crate::{Engine, AST};
|
use crate::{Engine, AST};
|
||||||
@ -89,7 +88,7 @@ struct FnMetadata {
|
|||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub return_type: Option<String>,
|
pub return_type: Option<String>,
|
||||||
pub signature: String,
|
pub signature: String,
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||||
pub doc_comments: Vec<String>,
|
pub doc_comments: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,34 +124,35 @@ impl From<&crate::module::FuncInfo> for FnMetadata {
|
|||||||
FnType::Native
|
FnType::Native
|
||||||
},
|
},
|
||||||
num_params: info.params,
|
num_params: info.params,
|
||||||
params: if let Some(ref names) = info.param_names {
|
params: info
|
||||||
names
|
.param_names
|
||||||
.iter()
|
.iter()
|
||||||
.take(info.params)
|
.take(info.params)
|
||||||
.map(|s| {
|
.map(|s| {
|
||||||
let mut seg = s.splitn(2, ':');
|
let mut seg = s.splitn(2, ':');
|
||||||
let name = seg
|
let name = seg
|
||||||
.next()
|
.next()
|
||||||
.map(|s| s.trim().to_string())
|
.map(|s| s.trim().to_string())
|
||||||
.unwrap_or("_".to_string());
|
.unwrap_or("_".to_string());
|
||||||
let typ = seg.next().map(|s| s.trim().to_string());
|
let typ = seg.next().map(|s| s.trim().to_string());
|
||||||
FnParam { name, typ }
|
FnParam { name, typ }
|
||||||
})
|
})
|
||||||
.collect()
|
.collect(),
|
||||||
} else {
|
return_type: info
|
||||||
vec![]
|
.param_names
|
||||||
},
|
.last()
|
||||||
return_type: if let Some(ref names) = info.param_names {
|
.map(|s| s.to_string())
|
||||||
names
|
.or_else(|| Some("()".to_string())),
|
||||||
.last()
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.or_else(|| Some("()".to_string()))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
signature: info.gen_signature(),
|
signature: info.gen_signature(),
|
||||||
doc_comments: if info.func.is_script() {
|
doc_comments: if info.func.is_script() {
|
||||||
info.func.get_fn_def().comments.clone()
|
#[cfg(feature = "no_function")]
|
||||||
|
{
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "no_function"))]
|
||||||
|
{
|
||||||
|
info.func.get_fn_def().comments.clone()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Default::default()
|
Default::default()
|
||||||
},
|
},
|
||||||
@ -178,11 +178,7 @@ impl From<crate::ScriptFnMetadata<'_>> for FnMetadata {
|
|||||||
.collect(),
|
.collect(),
|
||||||
return_type: Some("Dynamic".to_string()),
|
return_type: Some("Dynamic".to_string()),
|
||||||
signature: info.to_string(),
|
signature: info.to_string(),
|
||||||
doc_comments: if info.comments.is_empty() {
|
doc_comments: info.comments.iter().map(|s| s.to_string()).collect(),
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(info.comments.iter().map(|s| s.to_string()).collect())
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -211,10 +207,10 @@ impl From<&crate::Module> for ModuleMetadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "metadata")]
|
||||||
impl Engine {
|
impl Engine {
|
||||||
/// Generate a list of all functions (including those defined in an [`AST`][crate::AST])
|
/// _(METADATA)_ Generate a list of all functions (including those defined in an
|
||||||
/// in JSON format. Available only under the `metadata` feature.
|
/// [`AST`][crate::AST]) in JSON format. Available only under the `metadata` feature.
|
||||||
///
|
///
|
||||||
/// Functions from the following sources are included:
|
/// Functions from the following sources are included:
|
||||||
/// 1) Functions defined in an [`AST`][crate::AST]
|
/// 1) Functions defined in an [`AST`][crate::AST]
|
||||||
@ -223,7 +219,7 @@ impl Engine {
|
|||||||
/// 4) Functions in global modules (optional)
|
/// 4) Functions in global modules (optional)
|
||||||
pub fn gen_fn_metadata_with_ast_to_json(
|
pub fn gen_fn_metadata_with_ast_to_json(
|
||||||
&self,
|
&self,
|
||||||
ast: &AST,
|
_ast: &AST,
|
||||||
include_global: bool,
|
include_global: bool,
|
||||||
) -> serde_json::Result<String> {
|
) -> serde_json::Result<String> {
|
||||||
let mut global: ModuleMetadata = Default::default();
|
let mut global: ModuleMetadata = Default::default();
|
||||||
@ -244,11 +240,10 @@ impl Engine {
|
|||||||
.map(|f| f.into())
|
.map(|f| f.into())
|
||||||
.for_each(|info| global.functions.push(info));
|
.for_each(|info| global.functions.push(info));
|
||||||
|
|
||||||
if let Some(ast) = ast {
|
#[cfg(not(feature = "no_function"))]
|
||||||
ast.iter_functions()
|
_ast.iter_functions()
|
||||||
.map(|f| f.into())
|
.map(|f| f.into())
|
||||||
.for_each(|info| global.functions.push(info));
|
.for_each(|info| global.functions.push(info));
|
||||||
}
|
|
||||||
|
|
||||||
global.functions.sort();
|
global.functions.sort();
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
//! Helper module defining serialization/deserialization support for [`serde`].
|
//! Helper module defining serialization/deserialization support for [`serde`].
|
||||||
|
|
||||||
pub mod de;
|
pub mod de;
|
||||||
|
mod deserialize;
|
||||||
pub mod ser;
|
pub mod ser;
|
||||||
|
mod serialize;
|
||||||
mod str;
|
mod str;
|
||||||
|
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
|
@ -4,9 +4,8 @@ use crate::stdlib::{boxed::Box, fmt, string::ToString};
|
|||||||
use crate::{Dynamic, EvalAltResult, Position};
|
use crate::{Dynamic, EvalAltResult, Position};
|
||||||
use serde::ser::{
|
use serde::ser::{
|
||||||
Error, SerializeMap, SerializeSeq, SerializeStruct, SerializeTuple, SerializeTupleStruct,
|
Error, SerializeMap, SerializeSeq, SerializeStruct, SerializeTuple, SerializeTupleStruct,
|
||||||
Serializer,
|
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::{Serialize, Serializer};
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
use crate::Array;
|
use crate::Array;
|
||||||
|
55
src/serde_impl/serialize.rs
Normal file
55
src/serde_impl/serialize.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
//! Implementations of [`serde::Serialize`].
|
||||||
|
|
||||||
|
use crate::dynamic::Union;
|
||||||
|
use crate::stdlib::string::ToString;
|
||||||
|
use crate::{Dynamic, ImmutableString};
|
||||||
|
use serde::ser::{Serialize, SerializeMap, Serializer};
|
||||||
|
|
||||||
|
impl Serialize for Dynamic {
|
||||||
|
fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
|
||||||
|
match &self.0 {
|
||||||
|
Union::Unit(_, _) => ser.serialize_unit(),
|
||||||
|
Union::Bool(x, _) => ser.serialize_bool(*x),
|
||||||
|
Union::Str(s, _) => ser.serialize_str(s.as_str()),
|
||||||
|
Union::Char(c, _) => ser.serialize_str(&c.to_string()),
|
||||||
|
#[cfg(not(feature = "only_i32"))]
|
||||||
|
Union::Int(x, _) => ser.serialize_i64(*x),
|
||||||
|
#[cfg(feature = "only_i32")]
|
||||||
|
Union::Int(x, _) => ser.serialize_i32(*x),
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
#[cfg(not(feature = "f32_float"))]
|
||||||
|
Union::Float(x, _) => ser.serialize_f64(**x),
|
||||||
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
#[cfg(feature = "f32_float")]
|
||||||
|
Union::Float(x, _) => ser.serialize_f32(*x),
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
Union::Array(a, _) => (**a).serialize(ser),
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
Union::Map(m, _) => {
|
||||||
|
let mut map = ser.serialize_map(Some(m.len()))?;
|
||||||
|
for (k, v) in m.iter() {
|
||||||
|
map.serialize_entry(k, v)?;
|
||||||
|
}
|
||||||
|
map.end()
|
||||||
|
}
|
||||||
|
Union::FnPtr(f, _) => ser.serialize_str(f.fn_name()),
|
||||||
|
#[cfg(not(feature = "no_std"))]
|
||||||
|
Union::TimeStamp(_, _) => unimplemented!("serialization of timestamp is not supported"),
|
||||||
|
|
||||||
|
Union::Variant(v, _) => ser.serialize_str((***v).type_name()),
|
||||||
|
|
||||||
|
#[cfg(not(feature = "no_closure"))]
|
||||||
|
#[cfg(not(feature = "sync"))]
|
||||||
|
Union::Shared(cell, _) => cell.borrow().serialize(ser),
|
||||||
|
#[cfg(not(feature = "no_closure"))]
|
||||||
|
#[cfg(feature = "sync")]
|
||||||
|
Union::Shared(cell, _) => cell.read().unwrap().serialize(ser),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Serialize for ImmutableString {
|
||||||
|
fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
|
||||||
|
ser.serialize_str(self.as_str())
|
||||||
|
}
|
||||||
|
}
|
34
src/token.rs
34
src/token.rs
@ -150,7 +150,7 @@ impl fmt::Debug for Position {
|
|||||||
/// _(INTERNALS)_ A Rhai language token.
|
/// _(INTERNALS)_ A Rhai language token.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
@ -742,7 +742,7 @@ impl From<Token> for String {
|
|||||||
/// _(INTERNALS)_ State of the tokenizer.
|
/// _(INTERNALS)_ State of the tokenizer.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This type is volatile and may change.
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Default)]
|
#[derive(Debug, Clone, Eq, PartialEq, Default)]
|
||||||
@ -764,23 +764,26 @@ pub struct TokenizeState {
|
|||||||
/// _(INTERNALS)_ Trait that encapsulates a peekable character input stream.
|
/// _(INTERNALS)_ Trait that encapsulates a peekable character input stream.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile Data Structure
|
||||||
///
|
///
|
||||||
/// This trait is volatile and may change.
|
/// This trait is volatile and may change.
|
||||||
pub trait InputStream {
|
pub trait InputStream {
|
||||||
fn unread(&mut self, ch: char);
|
/// Un-get a character back into the `InputStream`.
|
||||||
/// Get the next character
|
/// The next [`get_next`][InputStream::get_next] or [`peek_next`][InputStream::peek_next]
|
||||||
|
/// will return this character instead.
|
||||||
|
fn unget(&mut self, ch: char);
|
||||||
|
/// Get the next character from the `InputStream`.
|
||||||
fn get_next(&mut self) -> Option<char>;
|
fn get_next(&mut self) -> Option<char>;
|
||||||
/// Peek the next character
|
/// Peek the next character in the `InputStream`.
|
||||||
fn peek_next(&mut self) -> Option<char>;
|
fn peek_next(&mut self) -> Option<char>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// _(INTERNALS)_ Parse a string literal wrapped by `enclosing_char`.
|
/// _(INTERNALS)_ Parse a string literal wrapped by `enclosing_char`.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile API
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This function is volatile and may change.
|
||||||
pub fn parse_string_literal(
|
pub fn parse_string_literal(
|
||||||
stream: &mut impl InputStream,
|
stream: &mut impl InputStream,
|
||||||
state: &mut TokenizeState,
|
state: &mut TokenizeState,
|
||||||
@ -973,9 +976,9 @@ fn scan_block_comment(
|
|||||||
/// _(INTERNALS)_ Get the next token from the `stream`.
|
/// _(INTERNALS)_ Get the next token from the `stream`.
|
||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
///
|
///
|
||||||
/// # WARNING
|
/// # Volatile API
|
||||||
///
|
///
|
||||||
/// This type is volatile and may change.
|
/// This function is volatile and may change.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_next_token(
|
pub fn get_next_token(
|
||||||
stream: &mut impl InputStream,
|
stream: &mut impl InputStream,
|
||||||
@ -1088,12 +1091,12 @@ fn get_next_token_inner(
|
|||||||
}
|
}
|
||||||
// _ - cannot follow a decimal point
|
// _ - cannot follow a decimal point
|
||||||
'_' => {
|
'_' => {
|
||||||
stream.unread(next_char);
|
stream.unget(next_char);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// .. - reserved symbol, not a floating-point number
|
// .. - reserved symbol, not a floating-point number
|
||||||
'.' => {
|
'.' => {
|
||||||
stream.unread(next_char);
|
stream.unget(next_char);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// symbol after period - probably a float
|
// symbol after period - probably a float
|
||||||
@ -1104,7 +1107,7 @@ fn get_next_token_inner(
|
|||||||
}
|
}
|
||||||
// Not a floating-point number
|
// Not a floating-point number
|
||||||
_ => {
|
_ => {
|
||||||
stream.unread(next_char);
|
stream.unget(next_char);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1634,12 +1637,10 @@ pub struct MultiInputsStream<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl InputStream for MultiInputsStream<'_> {
|
impl InputStream for MultiInputsStream<'_> {
|
||||||
/// Buffer a character.
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn unread(&mut self, ch: char) {
|
fn unget(&mut self, ch: char) {
|
||||||
self.buf = Some(ch);
|
self.buf = Some(ch);
|
||||||
}
|
}
|
||||||
/// Get the next character
|
|
||||||
fn get_next(&mut self) -> Option<char> {
|
fn get_next(&mut self) -> Option<char> {
|
||||||
if let Some(ch) = self.buf.take() {
|
if let Some(ch) = self.buf.take() {
|
||||||
return Some(ch);
|
return Some(ch);
|
||||||
@ -1658,7 +1659,6 @@ impl InputStream for MultiInputsStream<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Peek the next character
|
|
||||||
fn peek_next(&mut self) -> Option<char> {
|
fn peek_next(&mut self) -> Option<char> {
|
||||||
if let Some(ch) = self.buf {
|
if let Some(ch) = self.buf {
|
||||||
return Some(ch);
|
return Some(ch);
|
||||||
|
@ -59,11 +59,7 @@ impl BuildHasher for StraightHasherBuilder {
|
|||||||
/// Create an instance of the default hasher.
|
/// Create an instance of the default hasher.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn get_hasher() -> impl Hasher {
|
pub fn get_hasher() -> impl Hasher {
|
||||||
#[cfg(feature = "no_std")]
|
|
||||||
let s: ahash::AHasher = Default::default();
|
let s: ahash::AHasher = Default::default();
|
||||||
#[cfg(not(feature = "no_std"))]
|
|
||||||
let s = crate::stdlib::collections::hash_map::DefaultHasher::new();
|
|
||||||
|
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use rhai::{
|
use rhai::{
|
||||||
serde::{from_dynamic, to_dynamic},
|
serde::{from_dynamic, to_dynamic},
|
||||||
Dynamic, Engine, EvalAltResult, INT,
|
Dynamic, Engine, EvalAltResult, ImmutableString, INT,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@ -290,15 +290,15 @@ fn test_serde_ser_untagged_enum() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serde_de_primary_types() -> Result<(), Box<EvalAltResult>> {
|
fn test_serde_de_primary_types() -> Result<(), Box<EvalAltResult>> {
|
||||||
assert_eq!(42_u16, from_dynamic(&Dynamic::from(42_u16))?);
|
assert_eq!(42, from_dynamic::<u16>(&Dynamic::from(42_u16))?);
|
||||||
assert_eq!(42 as INT, from_dynamic(&(42 as INT).into())?);
|
assert_eq!(42, from_dynamic::<INT>(&(42 as INT).into())?);
|
||||||
assert_eq!(true, from_dynamic(&true.into())?);
|
assert_eq!(true, from_dynamic::<bool>(&true.into())?);
|
||||||
assert_eq!((), from_dynamic(&().into())?);
|
assert_eq!((), from_dynamic::<()>(&().into())?);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
{
|
{
|
||||||
assert_eq!(123.456_f64, from_dynamic(&123.456_f64.into())?);
|
assert_eq!(123.456, from_dynamic::<f64>(&123.456_f64.into())?);
|
||||||
assert_eq!(123.456_f32, from_dynamic(&Dynamic::from(123.456_f32))?);
|
assert_eq!(123.456, from_dynamic::<f32>(&Dynamic::from(123.456_f32))?);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@ -311,14 +311,14 @@ fn test_serde_de_primary_types() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serde_de_integer_types() -> Result<(), Box<EvalAltResult>> {
|
fn test_serde_de_integer_types() -> Result<(), Box<EvalAltResult>> {
|
||||||
assert_eq!(42_i8, from_dynamic(&Dynamic::from(42 as INT))?);
|
assert_eq!(42, from_dynamic::<i8>(&Dynamic::from(42 as INT))?);
|
||||||
assert_eq!(42_i16, from_dynamic(&Dynamic::from(42 as INT))?);
|
assert_eq!(42, from_dynamic::<i16>(&Dynamic::from(42 as INT))?);
|
||||||
assert_eq!(42_i32, from_dynamic(&Dynamic::from(42 as INT))?);
|
assert_eq!(42, from_dynamic::<i32>(&Dynamic::from(42 as INT))?);
|
||||||
assert_eq!(42_i64, from_dynamic(&Dynamic::from(42 as INT))?);
|
assert_eq!(42, from_dynamic::<i64>(&Dynamic::from(42 as INT))?);
|
||||||
assert_eq!(42_u8, from_dynamic(&Dynamic::from(42 as INT))?);
|
assert_eq!(42, from_dynamic::<u8>(&Dynamic::from(42 as INT))?);
|
||||||
assert_eq!(42_u16, from_dynamic(&Dynamic::from(42 as INT))?);
|
assert_eq!(42, from_dynamic::<u16>(&Dynamic::from(42 as INT))?);
|
||||||
assert_eq!(42_u32, from_dynamic(&Dynamic::from(42 as INT))?);
|
assert_eq!(42, from_dynamic::<u32>(&Dynamic::from(42 as INT))?);
|
||||||
assert_eq!(42_u64, from_dynamic(&Dynamic::from(42 as INT))?);
|
assert_eq!(42, from_dynamic::<u64>(&Dynamic::from(42 as INT))?);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -635,3 +635,42 @@ fn test_serde_de_untagged_enum() -> Result<(), Box<EvalAltResult>> {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
#[cfg(not(feature = "no_index"))]
|
||||||
|
fn test_serde_json() -> serde_json::Result<()> {
|
||||||
|
let s: ImmutableString = "hello".into();
|
||||||
|
assert_eq!(serde_json::to_string(&s)?, r#""hello""#);
|
||||||
|
|
||||||
|
let mut map = Map::new();
|
||||||
|
map.insert("a".into(), (123 as INT).into());
|
||||||
|
|
||||||
|
let arr: Array = vec![(1 as INT).into(), (2 as INT).into(), (3 as INT).into()];
|
||||||
|
map.insert("b".into(), arr.into());
|
||||||
|
map.insert("c".into(), true.into());
|
||||||
|
let d: Dynamic = map.into();
|
||||||
|
|
||||||
|
let json = serde_json::to_string(&d)?;
|
||||||
|
|
||||||
|
assert!(json.contains("\"a\":123"));
|
||||||
|
assert!(json.contains("\"b\":[1,2,3]"));
|
||||||
|
assert!(json.contains("\"c\":true"));
|
||||||
|
|
||||||
|
let d2: Dynamic = serde_json::from_str(&json)?;
|
||||||
|
|
||||||
|
assert!(d2.is::<Map>());
|
||||||
|
|
||||||
|
let mut m = d2.cast::<Map>();
|
||||||
|
|
||||||
|
assert_eq!(m["a"].as_int().unwrap(), 123);
|
||||||
|
assert!(m["c"].as_bool().unwrap());
|
||||||
|
|
||||||
|
let a = m.remove("b").unwrap().cast::<Array>();
|
||||||
|
|
||||||
|
assert_eq!(a.len(), 3);
|
||||||
|
assert_eq!(format!("{:?}", a), "[1, 2, 3]");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user