Merge pull request #356 from schungx/master
Protection against mutating constants in plugin functions.
This commit is contained in:
commit
0b0edc1818
@ -26,7 +26,7 @@ categories = [ "no-std", "embedded", "wasm", "parser-implementations" ]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
smallvec = { version = "1.6", default-features = false, features = ["union"] }
|
smallvec = { version = "1.6", default-features = false, features = ["union"] }
|
||||||
ahash = { version = "0.6", default-features = false }
|
ahash = { version = "0.6", default-features = false }
|
||||||
rhai_codegen = { version = "0.3", path = "codegen" }
|
rhai_codegen = { version = "0.3.3", path = "codegen" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
@ -44,7 +44,7 @@ no_function = [ "no_closure" ] # no script-defined functions (meaning no closur
|
|||||||
no_closure = [] # no automatic sharing and capture of anonymous functions to external variables
|
no_closure = [] # no automatic sharing and capture of anonymous functions to external variables
|
||||||
no_module = [] # no modules
|
no_module = [] # no modules
|
||||||
internals = [] # expose internal data structures
|
internals = [] # expose internal data structures
|
||||||
unicode-xid-ident = ["unicode-xid"] # allow Unicode Standard Annex #31 for identifiers.
|
unicode-xid-ident = [ "unicode-xid" ] # allow Unicode Standard Annex #31 for identifiers.
|
||||||
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
|
||||||
@ -107,5 +107,8 @@ optional = true
|
|||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
instant= { version = "0.1" } # WASM implementation of std::time::Instant
|
instant= { version = "0.1" } # WASM implementation of std::time::Instant
|
||||||
|
|
||||||
|
[target.'cfg(target_arch = "wasm64")'.dependencies]
|
||||||
|
instant= { version = "0.1" } # WASM implementation of std::time::Instant
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
features = [ "metadata", "internals" ]
|
features = [ "metadata", "internals" ]
|
||||||
|
@ -32,11 +32,12 @@ Standard features
|
|||||||
* Fairly efficient evaluation (1 million iterations in 0.3 sec on a single-core, 2.3 GHz Linux VM).
|
* Fairly efficient evaluation (1 million iterations in 0.3 sec on a single-core, 2.3 GHz Linux VM).
|
||||||
* Tight integration with native Rust [functions](https://rhai.rs/book/rust/functions.html) and [types]([#custom-types-and-methods](https://rhai.rs/book/rust/custom.html)), including [getters/setters](https://rhai.rs/book/rust/getters-setters.html), [methods](https://rhai.rs/book/rust/custom.html) and [indexers](https://rhai.rs/book/rust/indexers.html).
|
* Tight integration with native Rust [functions](https://rhai.rs/book/rust/functions.html) and [types]([#custom-types-and-methods](https://rhai.rs/book/rust/custom.html)), including [getters/setters](https://rhai.rs/book/rust/getters-setters.html), [methods](https://rhai.rs/book/rust/custom.html) and [indexers](https://rhai.rs/book/rust/indexers.html).
|
||||||
* Freely pass Rust variables/constants into a script via an external [`Scope`](https://rhai.rs/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://rhai.rs/book/rust/scope.html) - all clonable Rust types are supported; no need to implement any special trait.
|
||||||
|
* Built-in support for most common [data types](https://rhai.rs/book/language/values-and-types.html) including booleans, integers, floating-point numbers (including [`Decimal`](https://crates.io/crates/rust_decimal)), strings, Unicode characters, arrays and maps.
|
||||||
* Easily [call a script-defined function](https://rhai.rs/book/engine/call-fn.html) from Rust.
|
* Easily [call a script-defined function](https://rhai.rs/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) and [`ahash`](https://crates.io/crates/ahash)).
|
* 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).
|
||||||
* Compile once to AST form for repeated evaluations.
|
* Compile once to [AST](https://rhai.rs/book/engine/compile.html) form for repeated evaluations.
|
||||||
* Scripts are [optimized](https://rhai.rs/book/engine/optimize.html) (useful for template-based machine-generated scripts).
|
* Scripts are [optimized](https://rhai.rs/book/engine/optimize.html) (useful for template-based machine-generated scripts).
|
||||||
* Easy custom API development via [plugins](https://rhai.rs/book/plugins/index.html) system powered by procedural macros.
|
* Easy custom API development via [plugins](https://rhai.rs/book/plugins/index.html) system powered by procedural macros.
|
||||||
* [Function overloading](https://rhai.rs/book/language/overload.html) and [operator overloading](https://rhai.rs/book/rust/operators.html).
|
* [Function overloading](https://rhai.rs/book/language/overload.html) and [operator overloading](https://rhai.rs/book/rust/operators.html).
|
||||||
|
@ -12,6 +12,7 @@ Bug fixes
|
|||||||
New features
|
New features
|
||||||
------------
|
------------
|
||||||
|
|
||||||
|
* `#[rhai_fn(pure)]` attribute to mark a plugin function with `&mut` parameter as _pure_ so constants can be passed to it. Without it, passing a constant value into the `&mut` parameter will now raise an error.
|
||||||
* Comparisons between `FLOAT`/[`Decimal`](https://crates.io/crates/rust_decimal) and `INT` are now built in.
|
* Comparisons between `FLOAT`/[`Decimal`](https://crates.io/crates/rust_decimal) and `INT` are now built in.
|
||||||
|
|
||||||
Enhancements
|
Enhancements
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "rhai_codegen"
|
name = "rhai_codegen"
|
||||||
version = "0.3.2"
|
version = "0.3.3"
|
||||||
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"
|
||||||
|
@ -106,6 +106,7 @@ pub(crate) fn print_type(ty: &syn::Type) -> String {
|
|||||||
pub(crate) struct ExportedFnParams {
|
pub(crate) struct ExportedFnParams {
|
||||||
pub name: Vec<String>,
|
pub name: Vec<String>,
|
||||||
pub return_raw: bool,
|
pub return_raw: bool,
|
||||||
|
pub pure: bool,
|
||||||
pub skip: bool,
|
pub skip: bool,
|
||||||
pub special: FnSpecialAccess,
|
pub special: FnSpecialAccess,
|
||||||
pub namespace: FnNamespaceAccess,
|
pub namespace: FnNamespaceAccess,
|
||||||
@ -144,6 +145,7 @@ impl ExportedParams for ExportedFnParams {
|
|||||||
} = info;
|
} = info;
|
||||||
let mut name = Vec::new();
|
let mut name = Vec::new();
|
||||||
let mut return_raw = false;
|
let mut return_raw = false;
|
||||||
|
let mut pure = false;
|
||||||
let mut skip = false;
|
let mut skip = false;
|
||||||
let mut namespace = FnNamespaceAccess::Unset;
|
let mut namespace = FnNamespaceAccess::Unset;
|
||||||
let mut special = FnSpecialAccess::None;
|
let mut special = FnSpecialAccess::None;
|
||||||
@ -224,6 +226,8 @@ impl ExportedParams for ExportedFnParams {
|
|||||||
("index_get", Some(s)) | ("index_set", Some(s)) | ("return_raw", Some(s)) => {
|
("index_get", Some(s)) | ("index_set", Some(s)) | ("return_raw", Some(s)) => {
|
||||||
return Err(syn::Error::new(s.span(), "extraneous value"))
|
return Err(syn::Error::new(s.span(), "extraneous value"))
|
||||||
}
|
}
|
||||||
|
("pure", None) => pure = true,
|
||||||
|
("pure", Some(s)) => return Err(syn::Error::new(s.span(), "extraneous value")),
|
||||||
("return_raw", None) => return_raw = true,
|
("return_raw", None) => return_raw = true,
|
||||||
("return_raw", Some(s)) => {
|
("return_raw", Some(s)) => {
|
||||||
return Err(syn::Error::new(s.span(), "extraneous value"))
|
return Err(syn::Error::new(s.span(), "extraneous value"))
|
||||||
@ -255,6 +259,7 @@ impl ExportedParams for ExportedFnParams {
|
|||||||
Ok(ExportedFnParams {
|
Ok(ExportedFnParams {
|
||||||
name,
|
name,
|
||||||
return_raw,
|
return_raw,
|
||||||
|
pure,
|
||||||
skip,
|
skip,
|
||||||
special,
|
special,
|
||||||
namespace,
|
namespace,
|
||||||
@ -634,19 +639,19 @@ impl ExportedFn {
|
|||||||
.map(|r| r.span())
|
.map(|r| r.span())
|
||||||
.unwrap_or_else(|| proc_macro2::Span::call_site());
|
.unwrap_or_else(|| proc_macro2::Span::call_site());
|
||||||
if self.params.return_raw {
|
if self.params.return_raw {
|
||||||
quote_spanned! { return_span=>
|
quote_spanned! { return_span =>
|
||||||
pub #dynamic_signature {
|
pub #dynamic_signature {
|
||||||
#name(#(#arguments),*)
|
#name(#(#arguments),*)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if self.return_dynamic {
|
} else if self.return_dynamic {
|
||||||
quote_spanned! { return_span=>
|
quote_spanned! { return_span =>
|
||||||
pub #dynamic_signature {
|
pub #dynamic_signature {
|
||||||
Ok(#name(#(#arguments),*))
|
Ok(#name(#(#arguments),*))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
quote_spanned! { return_span=>
|
quote_spanned! { return_span =>
|
||||||
pub #dynamic_signature {
|
pub #dynamic_signature {
|
||||||
Ok(Dynamic::from(#name(#(#arguments),*)))
|
Ok(Dynamic::from(#name(#(#arguments),*)))
|
||||||
}
|
}
|
||||||
@ -746,18 +751,33 @@ impl ExportedFn {
|
|||||||
syn::Type::Reference(syn::TypeReference { ref elem, .. }) => elem.as_ref(),
|
syn::Type::Reference(syn::TypeReference { ref elem, .. }) => elem.as_ref(),
|
||||||
p => p,
|
p => p,
|
||||||
};
|
};
|
||||||
let downcast_span = quote_spanned!(
|
let downcast_span = quote_spanned!(arg_type.span() =>
|
||||||
arg_type.span()=> &mut args[0usize].write_lock::<#arg_type>().unwrap());
|
&mut args[0usize].write_lock::<#arg_type>().unwrap()
|
||||||
|
);
|
||||||
unpack_statements.push(
|
unpack_statements.push(
|
||||||
syn::parse2::<syn::Stmt>(quote! {
|
syn::parse2::<syn::Stmt>(quote! {
|
||||||
let #var = #downcast_span;
|
let #var = #downcast_span;
|
||||||
})
|
})
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
|
if !self.params().pure {
|
||||||
|
let arg_lit_str =
|
||||||
|
syn::LitStr::new(&pat.to_token_stream().to_string(), pat.span());
|
||||||
|
unpack_statements.push(
|
||||||
|
syn::parse2::<syn::Stmt>(quote! {
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant(#arg_lit_str.to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
}
|
||||||
input_type_names.push(arg_name);
|
input_type_names.push(arg_name);
|
||||||
input_type_exprs.push(
|
input_type_exprs.push(
|
||||||
syn::parse2::<syn::Expr>(quote_spanned!(
|
syn::parse2::<syn::Expr>(quote_spanned!(arg_type.span() =>
|
||||||
arg_type.span()=> TypeId::of::<#arg_type>()
|
TypeId::of::<#arg_type>()
|
||||||
))
|
))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
@ -792,22 +812,25 @@ impl ExportedFn {
|
|||||||
syn::Type::Path(ref p) if p.path == str_type_path => {
|
syn::Type::Path(ref p) if p.path == str_type_path => {
|
||||||
is_string = true;
|
is_string = true;
|
||||||
is_ref = true;
|
is_ref = true;
|
||||||
quote_spanned!(arg_type.span()=>
|
quote_spanned!(arg_type.span() =>
|
||||||
mem::take(args[#i]).take_immutable_string().unwrap())
|
mem::take(args[#i]).take_immutable_string().unwrap()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
_ => panic!("internal error: why wasn't this found earlier!?"),
|
_ => panic!("internal error: why wasn't this found earlier!?"),
|
||||||
},
|
},
|
||||||
syn::Type::Path(ref p) if p.path == string_type_path => {
|
syn::Type::Path(ref p) if p.path == string_type_path => {
|
||||||
is_string = true;
|
is_string = true;
|
||||||
is_ref = false;
|
is_ref = false;
|
||||||
quote_spanned!(arg_type.span()=>
|
quote_spanned!(arg_type.span() =>
|
||||||
mem::take(args[#i]).take_string().unwrap())
|
mem::take(args[#i]).take_string().unwrap()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
is_string = false;
|
is_string = false;
|
||||||
is_ref = false;
|
is_ref = false;
|
||||||
quote_spanned!(arg_type.span()=>
|
quote_spanned!(arg_type.span() =>
|
||||||
mem::take(args[#i]).cast::<#arg_type>())
|
mem::take(args[#i]).cast::<#arg_type>()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -820,15 +843,15 @@ impl ExportedFn {
|
|||||||
input_type_names.push(arg_name);
|
input_type_names.push(arg_name);
|
||||||
if !is_string {
|
if !is_string {
|
||||||
input_type_exprs.push(
|
input_type_exprs.push(
|
||||||
syn::parse2::<syn::Expr>(quote_spanned!(
|
syn::parse2::<syn::Expr>(quote_spanned!(arg_type.span() =>
|
||||||
arg_type.span()=> TypeId::of::<#arg_type>()
|
TypeId::of::<#arg_type>()
|
||||||
))
|
))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
input_type_exprs.push(
|
input_type_exprs.push(
|
||||||
syn::parse2::<syn::Expr>(quote_spanned!(
|
syn::parse2::<syn::Expr>(quote_spanned!(arg_type.span() =>
|
||||||
arg_type.span()=> TypeId::of::<ImmutableString>()
|
TypeId::of::<ImmutableString>()
|
||||||
))
|
))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
@ -860,16 +883,16 @@ impl ExportedFn {
|
|||||||
.unwrap_or_else(|| proc_macro2::Span::call_site());
|
.unwrap_or_else(|| proc_macro2::Span::call_site());
|
||||||
let return_expr = if !self.params.return_raw {
|
let return_expr = if !self.params.return_raw {
|
||||||
if self.return_dynamic {
|
if self.return_dynamic {
|
||||||
quote_spanned! { return_span=>
|
quote_spanned! { return_span =>
|
||||||
Ok(#sig_name(#(#unpack_exprs),*))
|
Ok(#sig_name(#(#unpack_exprs),*))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
quote_spanned! { return_span=>
|
quote_spanned! { return_span =>
|
||||||
Ok(Dynamic::from(#sig_name(#(#unpack_exprs),*)))
|
Ok(Dynamic::from(#sig_name(#(#unpack_exprs),*)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
quote_spanned! { return_span=>
|
quote_spanned! { return_span =>
|
||||||
#sig_name(#(#unpack_exprs),*)
|
#sig_name(#(#unpack_exprs),*)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -878,9 +901,7 @@ impl ExportedFn {
|
|||||||
quote! {
|
quote! {
|
||||||
impl PluginFunction for #type_name {
|
impl PluginFunction for #type_name {
|
||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), #arg_count,
|
debug_assert_eq!(args.len(), #arg_count, "wrong arg count: {} != {}", args.len(), #arg_count);
|
||||||
"wrong arg count: {} != {}",
|
|
||||||
args.len(), #arg_count);
|
|
||||||
#(#unpack_statements)*
|
#(#unpack_statements)*
|
||||||
#return_expr
|
#return_expr
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ pub fn parse_register_macro(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
let export_name = match &items[1] {
|
let export_name = match &items[1] {
|
||||||
syn::Expr::Lit(lit_str) => quote_spanned!(items[1].span()=>
|
syn::Expr::Lit(lit_str) => quote_spanned!(items[1].span() =>
|
||||||
#lit_str.to_string()),
|
#lit_str.to_string()),
|
||||||
expr => quote! { #expr },
|
expr => quote! { #expr },
|
||||||
};
|
};
|
||||||
|
@ -587,6 +587,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 2usize,
|
debug_assert_eq!(args.len(), 2usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 2usize);
|
"wrong arg count: {} != {}", args.len(), 2usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg1 = mem::take(args[1usize]).cast::<usize>();
|
let arg1 = mem::take(args[1usize]).cast::<usize>();
|
||||||
let arg0 = &mut args[0usize].write_lock::<usize>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<usize>().unwrap();
|
||||||
Ok(Dynamic::from(increment(arg0, arg1)))
|
Ok(Dynamic::from(increment(arg0, arg1)))
|
||||||
|
@ -1218,6 +1218,83 @@ mod generate_tests {
|
|||||||
assert_streams_eq(item_mod.generate(), expected_tokens);
|
assert_streams_eq(item_mod.generate(), expected_tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mut_ref_pure_fn_module() {
|
||||||
|
let input_tokens: TokenStream = quote! {
|
||||||
|
pub mod ref_fn {
|
||||||
|
#[rhai_fn(pure)]
|
||||||
|
pub fn foo(x: &mut FLOAT, y: INT) -> FLOAT {
|
||||||
|
*x + y as FLOAT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let expected_tokens = quote! {
|
||||||
|
pub mod ref_fn {
|
||||||
|
pub fn foo(x: &mut FLOAT, y: INT) -> FLOAT {
|
||||||
|
*x + y as FLOAT
|
||||||
|
}
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub fn rhai_module_generate() -> Module {
|
||||||
|
let mut m = Module::new();
|
||||||
|
rhai_generate_into_module(&mut m, false);
|
||||||
|
m.build_index();
|
||||||
|
m
|
||||||
|
}
|
||||||
|
#[allow(unused_mut)]
|
||||||
|
pub fn rhai_generate_into_module(m: &mut Module, flatten: bool) {
|
||||||
|
m.set_fn("foo", FnNamespace::Internal, FnAccess::Public,
|
||||||
|
Some(&["x: &mut FLOAT", "y: INT", "FLOAT"]), &[core::any::TypeId::of::<FLOAT>(), core::any::TypeId::of::<INT>()],
|
||||||
|
foo_token().into());
|
||||||
|
if flatten {} else {}
|
||||||
|
}
|
||||||
|
#[allow(non_camel_case_types)]
|
||||||
|
struct foo_token();
|
||||||
|
impl PluginFunction for foo_token {
|
||||||
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
|
debug_assert_eq!(args.len(), 2usize,
|
||||||
|
"wrong arg count: {} != {}", args.len(), 2usize);
|
||||||
|
let arg1 = mem::take(args[1usize]).cast::<INT>();
|
||||||
|
let arg0 = &mut args[0usize].write_lock::<FLOAT>().unwrap();
|
||||||
|
Ok(Dynamic::from(foo(arg0, arg1)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_method_call(&self) -> bool { true }
|
||||||
|
fn is_variadic(&self) -> bool { false }
|
||||||
|
fn clone_boxed(&self) -> Box<dyn PluginFunction> {
|
||||||
|
Box::new(foo_token())
|
||||||
|
}
|
||||||
|
fn input_names(&self) -> Box<[&'static str]> {
|
||||||
|
new_vec!["x: &mut FLOAT", "y: INT"].into_boxed_slice()
|
||||||
|
}
|
||||||
|
fn input_types(&self) -> Box<[TypeId]> {
|
||||||
|
new_vec![TypeId::of::<FLOAT>(), TypeId::of::<INT>()].into_boxed_slice()
|
||||||
|
}
|
||||||
|
fn return_type(&self) -> &'static str {
|
||||||
|
"FLOAT"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn foo_token_callable() -> CallableFunction {
|
||||||
|
foo_token().into()
|
||||||
|
}
|
||||||
|
pub fn foo_token_input_names() -> Box<[&'static str]> {
|
||||||
|
foo_token().input_names()
|
||||||
|
}
|
||||||
|
pub fn foo_token_input_types() -> Box<[TypeId]> {
|
||||||
|
foo_token().input_types()
|
||||||
|
}
|
||||||
|
pub fn foo_token_return_type() -> &'static str {
|
||||||
|
foo_token().return_type()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let item_mod = syn::parse2::<Module>(input_tokens).unwrap();
|
||||||
|
assert_streams_eq(item_mod.generate(), expected_tokens);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn one_mut_ref_fn_module() {
|
fn one_mut_ref_fn_module() {
|
||||||
let input_tokens: TokenStream = quote! {
|
let input_tokens: TokenStream = quote! {
|
||||||
@ -1255,6 +1332,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 1usize,
|
debug_assert_eq!(args.len(), 1usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 1usize);
|
"wrong arg count: {} != {}", args.len(), 1usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg0 = &mut args[0usize].write_lock::<FLOAT>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<FLOAT>().unwrap();
|
||||||
Ok(Dynamic::from(increment(arg0)))
|
Ok(Dynamic::from(increment(arg0)))
|
||||||
}
|
}
|
||||||
@ -1333,6 +1415,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 1usize,
|
debug_assert_eq!(args.len(), 1usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 1usize);
|
"wrong arg count: {} != {}", args.len(), 1usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg0 = &mut args[0usize].write_lock::<FLOAT>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<FLOAT>().unwrap();
|
||||||
Ok(Dynamic::from(increment(arg0)))
|
Ok(Dynamic::from(increment(arg0)))
|
||||||
}
|
}
|
||||||
@ -1432,6 +1519,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 1usize,
|
debug_assert_eq!(args.len(), 1usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 1usize);
|
"wrong arg count: {} != {}", args.len(), 1usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg0 = &mut args[0usize].write_lock::<FLOAT>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<FLOAT>().unwrap();
|
||||||
Ok(Dynamic::from(increment(arg0)))
|
Ok(Dynamic::from(increment(arg0)))
|
||||||
}
|
}
|
||||||
@ -1530,6 +1622,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 1usize,
|
debug_assert_eq!(args.len(), 1usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 1usize);
|
"wrong arg count: {} != {}", args.len(), 1usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg0 = &mut args[0usize].write_lock::<u64>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<u64>().unwrap();
|
||||||
Ok(Dynamic::from(int_foo(arg0)))
|
Ok(Dynamic::from(int_foo(arg0)))
|
||||||
}
|
}
|
||||||
@ -1607,6 +1704,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 1usize,
|
debug_assert_eq!(args.len(), 1usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 1usize);
|
"wrong arg count: {} != {}", args.len(), 1usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg0 = &mut args[0usize].write_lock::<u64>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<u64>().unwrap();
|
||||||
Ok(Dynamic::from(int_foo(arg0)))
|
Ok(Dynamic::from(int_foo(arg0)))
|
||||||
}
|
}
|
||||||
@ -1683,6 +1785,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 2usize,
|
debug_assert_eq!(args.len(), 2usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 2usize);
|
"wrong arg count: {} != {}", args.len(), 2usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
||||||
let arg0 = &mut args[0usize].write_lock::<u64>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<u64>().unwrap();
|
||||||
Ok(Dynamic::from(int_foo(arg0, arg1)))
|
Ok(Dynamic::from(int_foo(arg0, arg1)))
|
||||||
@ -1763,6 +1870,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 2usize,
|
debug_assert_eq!(args.len(), 2usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 2usize);
|
"wrong arg count: {} != {}", args.len(), 2usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
||||||
let arg0 = &mut args[0usize].write_lock::<u64>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<u64>().unwrap();
|
||||||
Ok(Dynamic::from(int_foo(arg0, arg1)))
|
Ok(Dynamic::from(int_foo(arg0, arg1)))
|
||||||
@ -1842,6 +1954,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 2usize,
|
debug_assert_eq!(args.len(), 2usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 2usize);
|
"wrong arg count: {} != {}", args.len(), 2usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
||||||
let arg0 = &mut args[0usize].write_lock::<MyCollection>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<MyCollection>().unwrap();
|
||||||
Ok(Dynamic::from(get_by_index(arg0, arg1)))
|
Ok(Dynamic::from(get_by_index(arg0, arg1)))
|
||||||
@ -1927,6 +2044,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 2usize,
|
debug_assert_eq!(args.len(), 2usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 2usize);
|
"wrong arg count: {} != {}", args.len(), 2usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
||||||
let arg0 = &mut args[0usize].write_lock::<MyCollection>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<MyCollection>().unwrap();
|
||||||
Ok(Dynamic::from(get_by_index(arg0, arg1)))
|
Ok(Dynamic::from(get_by_index(arg0, arg1)))
|
||||||
@ -2008,6 +2130,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 3usize,
|
debug_assert_eq!(args.len(), 3usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 3usize);
|
"wrong arg count: {} != {}", args.len(), 3usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
||||||
let arg2 = mem::take(args[2usize]).cast::<FLOAT>();
|
let arg2 = mem::take(args[2usize]).cast::<FLOAT>();
|
||||||
let arg0 = &mut args[0usize].write_lock::<MyCollection>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<MyCollection>().unwrap();
|
||||||
@ -2097,6 +2224,11 @@ mod generate_tests {
|
|||||||
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
fn call(&self, context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
debug_assert_eq!(args.len(), 3usize,
|
debug_assert_eq!(args.len(), 3usize,
|
||||||
"wrong arg count: {} != {}", args.len(), 3usize);
|
"wrong arg count: {} != {}", args.len(), 3usize);
|
||||||
|
if args[0usize].is_read_only() {
|
||||||
|
return Err(Box::new(
|
||||||
|
EvalAltResult::ErrorAssignmentToConstant("x".to_string(), Position::NONE)
|
||||||
|
));
|
||||||
|
}
|
||||||
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
let arg1 = mem::take(args[1usize]).cast::<u64>();
|
||||||
let arg2 = mem::take(args[2usize]).cast::<FLOAT>();
|
let arg2 = mem::take(args[2usize]).cast::<FLOAT>();
|
||||||
let arg0 = &mut args[0usize].write_lock::<MyCollection>().unwrap();
|
let arg0 = &mut args[0usize].write_lock::<MyCollection>().unwrap();
|
||||||
|
@ -25,12 +25,12 @@ use crate::Array;
|
|||||||
use crate::Map;
|
use crate::Map;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
use crate::stdlib::time::Instant;
|
use crate::stdlib::time::Instant;
|
||||||
|
|
||||||
use fmt::Debug;
|
use fmt::Debug;
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))]
|
||||||
use instant::Instant;
|
use instant::Instant;
|
||||||
|
|
||||||
mod private {
|
mod private {
|
||||||
@ -807,7 +807,7 @@ impl Dynamic {
|
|||||||
/// [`Arc`][std::sync::Arc]`<`[`RwLock`][std::sync::RwLock]`<`[`Dynamic`]`>>`
|
/// [`Arc`][std::sync::Arc]`<`[`RwLock`][std::sync::RwLock]`<`[`Dynamic`]`>>`
|
||||||
/// depending on the `sync` feature.
|
/// depending on the `sync` feature.
|
||||||
///
|
///
|
||||||
/// Not available under [`no_closure`].
|
/// Not available under `no_closure`.
|
||||||
///
|
///
|
||||||
/// Shared [`Dynamic`] values are relatively cheap to clone as they simply increment the
|
/// Shared [`Dynamic`] values are relatively cheap to clone as they simply increment the
|
||||||
/// reference counts.
|
/// reference counts.
|
||||||
|
@ -807,7 +807,7 @@ pub fn is_anonymous_fn(fn_name: &str) -> bool {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn default_print(_s: &str) {
|
fn default_print(_s: &str) {
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
println!("{}", _s);
|
println!("{}", _s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -815,7 +815,7 @@ fn default_print(_s: &str) {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn default_debug(_s: &str, _source: Option<&str>, _pos: Position) {
|
fn default_debug(_s: &str, _source: Option<&str>, _pos: Position) {
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
if let Some(source) = _source {
|
if let Some(source) = _source {
|
||||||
println!("{} @ {:?} | {}", source, _pos, _s);
|
println!("{} @ {:?} | {}", source, _pos, _s);
|
||||||
} else {
|
} else {
|
||||||
@ -863,7 +863,7 @@ impl Engine {
|
|||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
module_resolver: Box::new(crate::module::resolvers::FileModuleResolver::new()),
|
module_resolver: Box::new(crate::module::resolvers::FileModuleResolver::new()),
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
#[cfg(any(feature = "no_std", target_arch = "wasm32",))]
|
#[cfg(any(feature = "no_std", target_arch = "wasm32",))]
|
||||||
|
@ -1028,7 +1028,7 @@ impl Engine {
|
|||||||
}
|
}
|
||||||
/// Read the contents of a file into a string.
|
/// Read the contents of a file into a string.
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_file(path: crate::stdlib::path::PathBuf) -> Result<String, Box<EvalAltResult>> {
|
fn read_file(path: crate::stdlib::path::PathBuf) -> Result<String, Box<EvalAltResult>> {
|
||||||
use crate::stdlib::io::Read;
|
use crate::stdlib::io::Read;
|
||||||
@ -1074,7 +1074,7 @@ impl Engine {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn compile_file(
|
pub fn compile_file(
|
||||||
&self,
|
&self,
|
||||||
@ -1116,7 +1116,7 @@ impl Engine {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn compile_file_with_scope(
|
pub fn compile_file_with_scope(
|
||||||
&self,
|
&self,
|
||||||
@ -1301,7 +1301,7 @@ impl Engine {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn eval_file<T: Variant + Clone>(
|
pub fn eval_file<T: Variant + Clone>(
|
||||||
&self,
|
&self,
|
||||||
@ -1331,7 +1331,7 @@ impl Engine {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn eval_file_with_scope<T: Variant + Clone>(
|
pub fn eval_file_with_scope<T: Variant + Clone>(
|
||||||
&self,
|
&self,
|
||||||
@ -1543,7 +1543,7 @@ impl Engine {
|
|||||||
///
|
///
|
||||||
/// Not available under `no_std` or `WASM`.
|
/// Not available under `no_std` or `WASM`.
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn consume_file(
|
pub fn consume_file(
|
||||||
&self,
|
&self,
|
||||||
@ -1556,7 +1556,7 @@ impl Engine {
|
|||||||
///
|
///
|
||||||
/// Not available under `no_std` or `WASM`.
|
/// Not available under `no_std` or `WASM`.
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn consume_file_with_scope(
|
pub fn consume_file_with_scope(
|
||||||
&self,
|
&self,
|
||||||
|
39
src/lib.rs
39
src/lib.rs
@ -41,7 +41,7 @@
|
|||||||
//! engine.register_fn("compute", compute_something);
|
//! engine.register_fn("compute", compute_something);
|
||||||
//!
|
//!
|
||||||
//! # #[cfg(not(feature = "no_std"))]
|
//! # #[cfg(not(feature = "no_std"))]
|
||||||
//! # #[cfg(not(target_arch = "wasm32"))]
|
//! # #[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
//! assert_eq!(
|
//! assert_eq!(
|
||||||
//! // Evaluate the script, expects a 'bool' return
|
//! // Evaluate the script, expects a 'bool' return
|
||||||
//! engine.eval_file::<bool>("my_script.rhai".into())?,
|
//! engine.eval_file::<bool>("my_script.rhai".into())?,
|
||||||
@ -61,6 +61,8 @@
|
|||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
|
// Internal modules
|
||||||
|
|
||||||
mod ast;
|
mod ast;
|
||||||
mod dynamic;
|
mod dynamic;
|
||||||
mod engine;
|
mod engine;
|
||||||
@ -79,8 +81,6 @@ mod parser;
|
|||||||
pub mod plugin;
|
pub mod plugin;
|
||||||
mod result;
|
mod result;
|
||||||
mod scope;
|
mod scope;
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
mod serde_impl;
|
|
||||||
mod stdlib;
|
mod stdlib;
|
||||||
mod syntax;
|
mod syntax;
|
||||||
mod token;
|
mod token;
|
||||||
@ -168,13 +168,8 @@ pub use module::ModuleResolver;
|
|||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
pub use module::resolvers as module_resolvers;
|
pub use module::resolvers as module_resolvers;
|
||||||
|
|
||||||
/// _(SERDE)_ Serialization and deserialization support for [`serde`](https://crates.io/crates/serde).
|
|
||||||
/// Exported under the `serde` feature.
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
pub mod serde {
|
pub mod serde;
|
||||||
pub use super::serde_impl::de::from_dynamic;
|
|
||||||
pub use super::serde_impl::ser::to_dynamic;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_optimize"))]
|
#[cfg(not(feature = "no_optimize"))]
|
||||||
pub use optimize::OptimizationLevel;
|
pub use optimize::OptimizationLevel;
|
||||||
@ -214,3 +209,29 @@ type StaticVec<T> = smallvec::SmallVec<[T; 4]>;
|
|||||||
/// Exported under the `internals` feature only.
|
/// Exported under the `internals` feature only.
|
||||||
#[cfg(feature = "internals")]
|
#[cfg(feature = "internals")]
|
||||||
pub type StaticVec<T> = smallvec::SmallVec<[T; 4]>;
|
pub type StaticVec<T> = smallvec::SmallVec<[T; 4]>;
|
||||||
|
|
||||||
|
// Compiler guards against mutually-exclusive feature flags
|
||||||
|
|
||||||
|
#[cfg(feature = "no_float")]
|
||||||
|
#[cfg(feature = "f32_float")]
|
||||||
|
compile_error!("'f32_float' cannot be used with 'no_float'");
|
||||||
|
|
||||||
|
#[cfg(feature = "no_std")]
|
||||||
|
#[cfg(feature = "wasm-bindgen")]
|
||||||
|
compile_error!("'wasm-bindgen' cannot be used with 'no-std'");
|
||||||
|
|
||||||
|
#[cfg(feature = "no_std")]
|
||||||
|
#[cfg(feature = "stdweb")]
|
||||||
|
compile_error!("'stdweb' cannot be used with 'no-std'");
|
||||||
|
|
||||||
|
#[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))]
|
||||||
|
#[cfg(feature = "no_std")]
|
||||||
|
compile_error!("'no_std' cannot be used for WASM target");
|
||||||
|
|
||||||
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
|
#[cfg(feature = "wasm-bindgen")]
|
||||||
|
compile_error!("'wasm-bindgen' should not be used non-WASM target");
|
||||||
|
|
||||||
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
|
#[cfg(feature = "stdweb")]
|
||||||
|
compile_error!("'stdweb' should not be used non-WASM target");
|
||||||
|
@ -9,11 +9,11 @@ mod collection;
|
|||||||
pub use collection::ModuleResolversCollection;
|
pub use collection::ModuleResolversCollection;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
mod file;
|
mod file;
|
||||||
|
|
||||||
#[cfg(not(feature = "no_std"))]
|
#[cfg(not(feature = "no_std"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
pub use file::FileModuleResolver;
|
pub use file::FileModuleResolver;
|
||||||
|
|
||||||
mod stat;
|
mod stat;
|
||||||
|
@ -575,7 +575,7 @@ fn optimize_expr(expr: &mut Expr, state: &mut State) {
|
|||||||
Expr::Array(x, _) => x.iter_mut().for_each(|expr| optimize_expr(expr, state)),
|
Expr::Array(x, _) => x.iter_mut().for_each(|expr| optimize_expr(expr, state)),
|
||||||
// #{ key:constant, .. }
|
// #{ key:constant, .. }
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::Map(_, _) if expr.is_constant()=> {
|
Expr::Map(_, _) if expr.is_constant() => {
|
||||||
state.set_dirty();
|
state.set_dirty();
|
||||||
*expr = Expr::DynamicConstant(Box::new(expr.get_constant_value().unwrap()), expr.position());
|
*expr = Expr::DynamicConstant(Box::new(expr.get_constant_value().unwrap()), expr.position());
|
||||||
}
|
}
|
||||||
|
@ -184,7 +184,7 @@ def_package!(crate:ArithmeticPackage:"Basic arithmetic", lib, {
|
|||||||
reg_functions!(lib += arith_numbers; i8, u8, i16, u16, i32, u32, u64);
|
reg_functions!(lib += arith_numbers; i8, u8, i16, u16, i32, u32, u64);
|
||||||
reg_functions!(lib += signed_numbers; i8, i16, i32);
|
reg_functions!(lib += signed_numbers; i8, i16, i32);
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
{
|
{
|
||||||
reg_functions!(lib += arith_num_128; i128, u128);
|
reg_functions!(lib += arith_num_128; i128, u128);
|
||||||
reg_functions!(lib += signed_num_128; i128);
|
reg_functions!(lib += signed_num_128; i128);
|
||||||
@ -211,7 +211,7 @@ gen_arithmetic_functions!(arith_numbers => i8, u8, i16, u16, i32, u32, u64);
|
|||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
#[cfg(not(feature = "only_i64"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
gen_arithmetic_functions!(arith_num_128 => i128, u128);
|
gen_arithmetic_functions!(arith_num_128 => i128, u128);
|
||||||
|
|
||||||
gen_signed_functions!(signed_basic => INT);
|
gen_signed_functions!(signed_basic => INT);
|
||||||
@ -222,7 +222,7 @@ gen_signed_functions!(signed_numbers => i8, i16, i32);
|
|||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
#[cfg(not(feature = "only_i64"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
gen_signed_functions!(signed_num_128 => i128);
|
gen_signed_functions!(signed_num_128 => i128);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
@ -22,22 +22,22 @@ macro_rules! gen_array_functions {
|
|||||||
#[export_module]
|
#[export_module]
|
||||||
pub mod functions {
|
pub mod functions {
|
||||||
#[rhai_fn(name = "push", name = "+=")]
|
#[rhai_fn(name = "push", name = "+=")]
|
||||||
pub fn push(list: &mut Array, item: $arg_type) {
|
pub fn push(array: &mut Array, item: $arg_type) {
|
||||||
list.push(Dynamic::from(item));
|
array.push(Dynamic::from(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(list: &mut Array, position: INT, item: $arg_type) {
|
pub fn insert(array: &mut Array, position: INT, item: $arg_type) {
|
||||||
if position <= 0 {
|
if position <= 0 {
|
||||||
list.insert(0, Dynamic::from(item));
|
array.insert(0, Dynamic::from(item));
|
||||||
} else if (position as usize) >= list.len() {
|
} else if (position as usize) >= array.len() {
|
||||||
push(list, item);
|
push(array, item);
|
||||||
} else {
|
} else {
|
||||||
list.insert(position as usize, Dynamic::from(item));
|
array.insert(position as usize, Dynamic::from(item));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn pad(_ctx: NativeCallContext, list: &mut Array, len: INT, item: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn pad(_ctx: NativeCallContext, array: &mut Array, len: INT, item: $arg_type) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
// Check if array will be over max size limit
|
// Check if array will be over max size limit
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
if _ctx.engine().max_array_size() > 0 && len > 0 && (len as usize) > _ctx.engine().max_array_size() {
|
if _ctx.engine().max_array_size() > 0 && len > 0 && (len as usize) > _ctx.engine().max_array_size() {
|
||||||
@ -46,8 +46,8 @@ macro_rules! gen_array_functions {
|
|||||||
).into();
|
).into();
|
||||||
}
|
}
|
||||||
|
|
||||||
if len > 0 && len as usize > list.len() {
|
if len > 0 && len as usize > array.len() {
|
||||||
list.resize(len as usize, Dynamic::from(item));
|
array.resize(len as usize, Dynamic::from(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Dynamic::UNIT)
|
Ok(Dynamic::UNIT)
|
||||||
@ -71,7 +71,7 @@ def_package!(crate:BasicArrayPackage:"Basic array utilities.", lib, {
|
|||||||
{
|
{
|
||||||
reg_functions!(lib += numbers; i8, u8, i16, u16, i32, i64, u32, u64);
|
reg_functions!(lib += numbers; i8, u8, i16, u16, i32, i64, u32, u64);
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
reg_functions!(lib += num_128; i128, u128);
|
reg_functions!(lib += num_128; i128, u128);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,117 +90,117 @@ def_package!(crate:BasicArrayPackage:"Basic array utilities.", lib, {
|
|||||||
|
|
||||||
#[export_module]
|
#[export_module]
|
||||||
mod array_functions {
|
mod array_functions {
|
||||||
#[rhai_fn(name = "len", get = "len")]
|
#[rhai_fn(name = "len", get = "len", pure)]
|
||||||
pub fn len(list: &mut Array) -> INT {
|
pub fn len(array: &mut Array) -> INT {
|
||||||
list.len() as INT
|
array.len() as INT
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "append", name = "+=")]
|
#[rhai_fn(name = "append", name = "+=")]
|
||||||
pub fn append(x: &mut Array, y: Array) {
|
pub fn append(array: &mut Array, y: Array) {
|
||||||
x.extend(y);
|
array.extend(y);
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(name = "+")]
|
||||||
pub fn concat(mut x: Array, y: Array) -> Array {
|
pub fn concat(mut array: Array, y: Array) -> Array {
|
||||||
x.extend(y);
|
array.extend(y);
|
||||||
x
|
array
|
||||||
}
|
}
|
||||||
pub fn pop(list: &mut Array) -> Dynamic {
|
pub fn pop(array: &mut Array) -> Dynamic {
|
||||||
list.pop().unwrap_or_else(|| ().into())
|
array.pop().unwrap_or_else(|| ().into())
|
||||||
}
|
}
|
||||||
pub fn shift(list: &mut Array) -> Dynamic {
|
pub fn shift(array: &mut Array) -> Dynamic {
|
||||||
if list.is_empty() {
|
if array.is_empty() {
|
||||||
().into()
|
().into()
|
||||||
} else {
|
} else {
|
||||||
list.remove(0)
|
array.remove(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn remove(list: &mut Array, len: INT) -> Dynamic {
|
pub fn remove(array: &mut Array, len: INT) -> Dynamic {
|
||||||
if len < 0 || (len as usize) >= list.len() {
|
if len < 0 || (len as usize) >= array.len() {
|
||||||
().into()
|
().into()
|
||||||
} else {
|
} else {
|
||||||
list.remove(len as usize)
|
array.remove(len as usize)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn clear(list: &mut Array) {
|
pub fn clear(array: &mut Array) {
|
||||||
list.clear();
|
array.clear();
|
||||||
}
|
}
|
||||||
pub fn truncate(list: &mut Array, len: INT) {
|
pub fn truncate(array: &mut Array, len: INT) {
|
||||||
if len >= 0 {
|
if len >= 0 {
|
||||||
list.truncate(len as usize);
|
array.truncate(len as usize);
|
||||||
} else {
|
} else {
|
||||||
list.clear();
|
array.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn chop(list: &mut Array, len: INT) {
|
pub fn chop(array: &mut Array, len: INT) {
|
||||||
if len as usize >= list.len() {
|
if len as usize >= array.len() {
|
||||||
} else if len >= 0 {
|
} else if len >= 0 {
|
||||||
list.drain(0..list.len() - len as usize);
|
array.drain(0..array.len() - len as usize);
|
||||||
} else {
|
} else {
|
||||||
list.clear();
|
array.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn reverse(list: &mut Array) {
|
pub fn reverse(array: &mut Array) {
|
||||||
list.reverse();
|
array.reverse();
|
||||||
}
|
}
|
||||||
pub fn splice(list: &mut Array, start: INT, len: INT, replace: Array) {
|
pub fn splice(array: &mut Array, start: INT, len: INT, replace: Array) {
|
||||||
let start = if start < 0 {
|
let start = if start < 0 {
|
||||||
0
|
0
|
||||||
} else if start as usize >= list.len() {
|
} else if start as usize >= array.len() {
|
||||||
list.len() - 1
|
array.len() - 1
|
||||||
} else {
|
} else {
|
||||||
start as usize
|
start as usize
|
||||||
};
|
};
|
||||||
|
|
||||||
let len = if len < 0 {
|
let len = if len < 0 {
|
||||||
0
|
0
|
||||||
} else if len as usize > list.len() - start {
|
} else if len as usize > array.len() - start {
|
||||||
list.len() - start
|
array.len() - start
|
||||||
} else {
|
} else {
|
||||||
len as usize
|
len as usize
|
||||||
};
|
};
|
||||||
|
|
||||||
list.splice(start..start + len, replace.into_iter());
|
array.splice(start..start + len, replace.into_iter());
|
||||||
}
|
}
|
||||||
pub fn extract(list: &mut Array, start: INT, len: INT) -> Array {
|
pub fn extract(array: &mut Array, start: INT, len: INT) -> Array {
|
||||||
let start = if start < 0 {
|
let start = if start < 0 {
|
||||||
0
|
0
|
||||||
} else if start as usize >= list.len() {
|
} else if start as usize >= array.len() {
|
||||||
list.len() - 1
|
array.len() - 1
|
||||||
} else {
|
} else {
|
||||||
start as usize
|
start as usize
|
||||||
};
|
};
|
||||||
|
|
||||||
let len = if len < 0 {
|
let len = if len < 0 {
|
||||||
0
|
0
|
||||||
} else if len as usize > list.len() - start {
|
} else if len as usize > array.len() - start {
|
||||||
list.len() - start
|
array.len() - start
|
||||||
} else {
|
} else {
|
||||||
len as usize
|
len as usize
|
||||||
};
|
};
|
||||||
|
|
||||||
list[start..start + len].iter().cloned().collect()
|
array[start..start + len].iter().cloned().collect()
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "extract")]
|
#[rhai_fn(name = "extract")]
|
||||||
pub fn extract_tail(list: &mut Array, start: INT) -> Array {
|
pub fn extract_tail(array: &mut Array, start: INT) -> Array {
|
||||||
let start = if start < 0 {
|
let start = if start < 0 {
|
||||||
0
|
0
|
||||||
} else if start as usize >= list.len() {
|
} else if start as usize >= array.len() {
|
||||||
list.len() - 1
|
array.len() - 1
|
||||||
} else {
|
} else {
|
||||||
start as usize
|
start as usize
|
||||||
};
|
};
|
||||||
|
|
||||||
list[start..].iter().cloned().collect()
|
array[start..].iter().cloned().collect()
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn map(
|
pub fn map(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
list: &mut Array,
|
array: &mut Array,
|
||||||
mapper: FnPtr,
|
mapper: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
let mut array = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, list.len()));
|
let mut ar = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, array.len()));
|
||||||
|
|
||||||
for (i, item) in list.iter().enumerate() {
|
for (i, item) in array.iter().enumerate() {
|
||||||
array.push(
|
ar.push(
|
||||||
mapper
|
mapper
|
||||||
.call_dynamic(ctx, None, [item.clone()])
|
.call_dynamic(ctx, None, [item.clone()])
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
@ -222,17 +222,17 @@ mod array_functions {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(array.into())
|
Ok(ar.into())
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn filter(
|
pub fn filter(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
list: &mut Array,
|
array: &mut Array,
|
||||||
filter: FnPtr,
|
filter: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
let mut array = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, list.len()));
|
let mut ar = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, array.len()));
|
||||||
|
|
||||||
for (i, item) in list.iter().enumerate() {
|
for (i, item) in array.iter().enumerate() {
|
||||||
if filter
|
if filter
|
||||||
.call_dynamic(ctx, None, [item.clone()])
|
.call_dynamic(ctx, None, [item.clone()])
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
@ -254,19 +254,19 @@ mod array_functions {
|
|||||||
.as_bool()
|
.as_bool()
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
array.push(item.clone());
|
ar.push(item.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(array.into())
|
Ok(ar.into())
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn index_of(
|
pub fn index_of(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
list: &mut Array,
|
array: &mut Array,
|
||||||
filter: FnPtr,
|
filter: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
for (i, item) in list.iter().enumerate() {
|
for (i, item) in array.iter().enumerate() {
|
||||||
if filter
|
if filter
|
||||||
.call_dynamic(ctx, None, [item.clone()])
|
.call_dynamic(ctx, None, [item.clone()])
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
@ -297,10 +297,10 @@ mod array_functions {
|
|||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn some(
|
pub fn some(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
list: &mut Array,
|
array: &mut Array,
|
||||||
filter: FnPtr,
|
filter: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
for (i, item) in list.iter().enumerate() {
|
for (i, item) in array.iter().enumerate() {
|
||||||
if filter
|
if filter
|
||||||
.call_dynamic(ctx, None, [item.clone()])
|
.call_dynamic(ctx, None, [item.clone()])
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
@ -331,10 +331,10 @@ mod array_functions {
|
|||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn all(
|
pub fn all(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
list: &mut Array,
|
array: &mut Array,
|
||||||
filter: FnPtr,
|
filter: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
for (i, item) in list.iter().enumerate() {
|
for (i, item) in array.iter().enumerate() {
|
||||||
if !filter
|
if !filter
|
||||||
.call_dynamic(ctx, None, [item.clone()])
|
.call_dynamic(ctx, None, [item.clone()])
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
@ -365,12 +365,12 @@ mod array_functions {
|
|||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn reduce(
|
pub fn reduce(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
list: &mut Array,
|
array: &mut Array,
|
||||||
reducer: FnPtr,
|
reducer: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
let mut result: Dynamic = Dynamic::UNIT;
|
let mut result: Dynamic = Dynamic::UNIT;
|
||||||
|
|
||||||
for (i, item) in list.iter().enumerate() {
|
for (i, item) in array.iter().enumerate() {
|
||||||
result = reducer
|
result = reducer
|
||||||
.call_dynamic(ctx, None, [result.clone(), item.clone()])
|
.call_dynamic(ctx, None, [result.clone(), item.clone()])
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
@ -396,7 +396,7 @@ mod array_functions {
|
|||||||
#[rhai_fn(name = "reduce", return_raw)]
|
#[rhai_fn(name = "reduce", return_raw)]
|
||||||
pub fn reduce_with_initial(
|
pub fn reduce_with_initial(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
list: &mut Array,
|
array: &mut Array,
|
||||||
reducer: FnPtr,
|
reducer: FnPtr,
|
||||||
initial: FnPtr,
|
initial: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
@ -409,7 +409,7 @@ mod array_functions {
|
|||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
for (i, item) in list.iter().enumerate() {
|
for (i, item) in array.iter().enumerate() {
|
||||||
result = reducer
|
result = reducer
|
||||||
.call_dynamic(ctx, None, [result.clone(), item.clone()])
|
.call_dynamic(ctx, None, [result.clone(), item.clone()])
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
@ -435,12 +435,12 @@ mod array_functions {
|
|||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn reduce_rev(
|
pub fn reduce_rev(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
list: &mut Array,
|
array: &mut Array,
|
||||||
reducer: FnPtr,
|
reducer: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
let mut result: Dynamic = Dynamic::UNIT;
|
let mut result: Dynamic = Dynamic::UNIT;
|
||||||
|
|
||||||
for (i, item) in list.iter().enumerate().rev() {
|
for (i, item) in array.iter().enumerate().rev() {
|
||||||
result = reducer
|
result = reducer
|
||||||
.call_dynamic(ctx, None, [result.clone(), item.clone()])
|
.call_dynamic(ctx, None, [result.clone(), item.clone()])
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
@ -466,7 +466,7 @@ mod array_functions {
|
|||||||
#[rhai_fn(name = "reduce_rev", return_raw)]
|
#[rhai_fn(name = "reduce_rev", return_raw)]
|
||||||
pub fn reduce_rev_with_initial(
|
pub fn reduce_rev_with_initial(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
list: &mut Array,
|
array: &mut Array,
|
||||||
reducer: FnPtr,
|
reducer: FnPtr,
|
||||||
initial: FnPtr,
|
initial: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
@ -479,7 +479,7 @@ mod array_functions {
|
|||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
for (i, item) in list.iter().enumerate().rev() {
|
for (i, item) in array.iter().enumerate().rev() {
|
||||||
result = reducer
|
result = reducer
|
||||||
.call_dynamic(ctx, None, [result.clone(), item.clone()])
|
.call_dynamic(ctx, None, [result.clone(), item.clone()])
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
@ -505,10 +505,10 @@ mod array_functions {
|
|||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn sort(
|
pub fn sort(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
list: &mut Array,
|
array: &mut Array,
|
||||||
comparer: FnPtr,
|
comparer: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
list.sort_by(|x, y| {
|
array.sort_by(|x, y| {
|
||||||
comparer
|
comparer
|
||||||
.call_dynamic(ctx, None, [x.clone(), y.clone()])
|
.call_dynamic(ctx, None, [x.clone(), y.clone()])
|
||||||
.ok()
|
.ok()
|
||||||
@ -541,23 +541,23 @@ mod array_functions {
|
|||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn drain(
|
pub fn drain(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
list: &mut Array,
|
array: &mut Array,
|
||||||
filter: FnPtr,
|
filter: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
let mut drained = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, list.len()));
|
let mut drained = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, array.len()));
|
||||||
|
|
||||||
let mut i = list.len();
|
let mut i = array.len();
|
||||||
|
|
||||||
while i > 0 {
|
while i > 0 {
|
||||||
i -= 1;
|
i -= 1;
|
||||||
|
|
||||||
if filter
|
if filter
|
||||||
.call_dynamic(ctx, None, [list[i].clone()])
|
.call_dynamic(ctx, None, [array[i].clone()])
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
||||||
if fn_sig.starts_with(filter.fn_name()) =>
|
if fn_sig.starts_with(filter.fn_name()) =>
|
||||||
{
|
{
|
||||||
filter.call_dynamic(ctx, None, [list[i].clone(), (i as INT).into()])
|
filter.call_dynamic(ctx, None, [array[i].clone(), (i as INT).into()])
|
||||||
}
|
}
|
||||||
_ => Err(err),
|
_ => Err(err),
|
||||||
})
|
})
|
||||||
@ -572,52 +572,52 @@ mod array_functions {
|
|||||||
.as_bool()
|
.as_bool()
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
drained.push(list.remove(i));
|
drained.push(array.remove(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(drained.into())
|
Ok(drained.into())
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "drain")]
|
#[rhai_fn(name = "drain")]
|
||||||
pub fn drain_range(list: &mut Array, start: INT, len: INT) -> Array {
|
pub fn drain_range(array: &mut Array, start: INT, len: INT) -> Array {
|
||||||
let start = if start < 0 {
|
let start = if start < 0 {
|
||||||
0
|
0
|
||||||
} else if start as usize >= list.len() {
|
} else if start as usize >= array.len() {
|
||||||
list.len() - 1
|
array.len() - 1
|
||||||
} else {
|
} else {
|
||||||
start as usize
|
start as usize
|
||||||
};
|
};
|
||||||
|
|
||||||
let len = if len < 0 {
|
let len = if len < 0 {
|
||||||
0
|
0
|
||||||
} else if len as usize > list.len() - start {
|
} else if len as usize > array.len() - start {
|
||||||
list.len() - start
|
array.len() - start
|
||||||
} else {
|
} else {
|
||||||
len as usize
|
len as usize
|
||||||
};
|
};
|
||||||
|
|
||||||
list.drain(start..start + len - 1).collect()
|
array.drain(start..start + len - 1).collect()
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn retain(
|
pub fn retain(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
list: &mut Array,
|
array: &mut Array,
|
||||||
filter: FnPtr,
|
filter: FnPtr,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
let mut drained = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, list.len()));
|
let mut drained = Array::with_capacity(max(TYPICAL_ARRAY_SIZE, array.len()));
|
||||||
|
|
||||||
let mut i = list.len();
|
let mut i = array.len();
|
||||||
|
|
||||||
while i > 0 {
|
while i > 0 {
|
||||||
i -= 1;
|
i -= 1;
|
||||||
|
|
||||||
if !filter
|
if !filter
|
||||||
.call_dynamic(ctx, None, [list[i].clone()])
|
.call_dynamic(ctx, None, [array[i].clone()])
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
||||||
if fn_sig.starts_with(filter.fn_name()) =>
|
if fn_sig.starts_with(filter.fn_name()) =>
|
||||||
{
|
{
|
||||||
filter.call_dynamic(ctx, None, [list[i].clone(), (i as INT).into()])
|
filter.call_dynamic(ctx, None, [array[i].clone(), (i as INT).into()])
|
||||||
}
|
}
|
||||||
_ => Err(err),
|
_ => Err(err),
|
||||||
})
|
})
|
||||||
@ -632,51 +632,51 @@ mod array_functions {
|
|||||||
.as_bool()
|
.as_bool()
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
drained.push(list.remove(i));
|
drained.push(array.remove(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(drained.into())
|
Ok(drained.into())
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "retain")]
|
#[rhai_fn(name = "retain")]
|
||||||
pub fn retain_range(list: &mut Array, start: INT, len: INT) -> Array {
|
pub fn retain_range(array: &mut Array, start: INT, len: INT) -> Array {
|
||||||
let start = if start < 0 {
|
let start = if start < 0 {
|
||||||
0
|
0
|
||||||
} else if start as usize >= list.len() {
|
} else if start as usize >= array.len() {
|
||||||
list.len() - 1
|
array.len() - 1
|
||||||
} else {
|
} else {
|
||||||
start as usize
|
start as usize
|
||||||
};
|
};
|
||||||
|
|
||||||
let len = if len < 0 {
|
let len = if len < 0 {
|
||||||
0
|
0
|
||||||
} else if len as usize > list.len() - start {
|
} else if len as usize > array.len() - start {
|
||||||
list.len() - start
|
array.len() - start
|
||||||
} else {
|
} else {
|
||||||
len as usize
|
len as usize
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut drained = list.drain(start + len..).collect::<Array>();
|
let mut drained = array.drain(start + len..).collect::<Array>();
|
||||||
drained.extend(list.drain(..start));
|
drained.extend(array.drain(..start));
|
||||||
|
|
||||||
drained
|
drained
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "==", return_raw)]
|
#[rhai_fn(name = "==", return_raw)]
|
||||||
pub fn equals(
|
pub fn equals(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
arr1: &mut Array,
|
array: &mut Array,
|
||||||
mut arr2: Array,
|
mut array2: Array,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
if arr1.len() != arr2.len() {
|
if array.len() != array2.len() {
|
||||||
return Ok(false.into());
|
return Ok(false.into());
|
||||||
}
|
}
|
||||||
if arr1.is_empty() {
|
if array.is_empty() {
|
||||||
return Ok(true.into());
|
return Ok(true.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let def_value = Some(false.into());
|
let def_value = Some(false.into());
|
||||||
|
|
||||||
for (a1, a2) in arr1.iter_mut().zip(arr2.iter_mut()) {
|
for (a1, a2) in array.iter_mut().zip(array2.iter_mut()) {
|
||||||
let equals = ctx
|
let equals = ctx
|
||||||
.call_fn_dynamic_raw(OP_EQUALS, true, false, &mut [a1, a2], def_value.as_ref())
|
.call_fn_dynamic_raw(OP_EQUALS, true, false, &mut [a1, a2], def_value.as_ref())
|
||||||
.map(|v| v.as_bool().unwrap_or(false))?;
|
.map(|v| v.as_bool().unwrap_or(false))?;
|
||||||
@ -691,10 +691,10 @@ mod array_functions {
|
|||||||
#[rhai_fn(name = "!=", return_raw)]
|
#[rhai_fn(name = "!=", return_raw)]
|
||||||
pub fn not_equals(
|
pub fn not_equals(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
arr1: &mut Array,
|
array: &mut Array,
|
||||||
arr2: Array,
|
array2: Array,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
equals(ctx, arr1, arr2).map(|r| (!r.as_bool().unwrap()).into())
|
equals(ctx, array, array2).map(|r| (!r.as_bool().unwrap()).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -706,7 +706,7 @@ gen_array_functions!(numbers => i8, u8, i16, u16, i32, i64, u32, u64);
|
|||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
#[cfg(not(feature = "only_i64"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
gen_array_functions!(num_128 => i128, u128);
|
gen_array_functions!(num_128 => i128, u128);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
@ -12,7 +12,7 @@ def_package!(crate:BasicFnPackage:"Basic Fn functions.", lib, {
|
|||||||
|
|
||||||
#[export_module]
|
#[export_module]
|
||||||
mod fn_ptr_functions {
|
mod fn_ptr_functions {
|
||||||
#[rhai_fn(name = "name", get = "name")]
|
#[rhai_fn(name = "name", get = "name", pure)]
|
||||||
pub fn name(f: &mut FnPtr) -> ImmutableString {
|
pub fn name(f: &mut FnPtr) -> ImmutableString {
|
||||||
f.get_fn_name().clone()
|
f.get_fn_name().clone()
|
||||||
}
|
}
|
||||||
@ -21,7 +21,7 @@ mod fn_ptr_functions {
|
|||||||
pub mod functions {
|
pub mod functions {
|
||||||
use crate::{calc_script_fn_hash, stdlib::iter::empty, INT};
|
use crate::{calc_script_fn_hash, stdlib::iter::empty, INT};
|
||||||
|
|
||||||
#[rhai_fn(name = "is_anonymous", get = "is_anonymous")]
|
#[rhai_fn(name = "is_anonymous", get = "is_anonymous", pure)]
|
||||||
pub fn is_anonymous(f: &mut FnPtr) -> bool {
|
pub fn is_anonymous(f: &mut FnPtr) -> bool {
|
||||||
f.is_anonymous()
|
f.is_anonymous()
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,6 @@ where
|
|||||||
Ok(StepRange::<T>(from, to, step))
|
Ok(StepRange::<T>(from, to, step))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
macro_rules! reg_range {
|
macro_rules! reg_range {
|
||||||
($lib:expr, $x:expr, $( $y:ty ),*) => (
|
($lib:expr, $x:expr, $( $y:ty ),*) => (
|
||||||
$(
|
$(
|
||||||
@ -58,9 +56,7 @@ macro_rules! reg_range {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
macro_rules! reg_stepped_range {
|
||||||
#[cfg(not(feature = "only_i64"))]
|
|
||||||
macro_rules! reg_step {
|
|
||||||
($lib:expr, $x:expr, $( $y:ty ),*) => (
|
($lib:expr, $x:expr, $( $y:ty ),*) => (
|
||||||
$(
|
$(
|
||||||
$lib.set_iterator::<StepRange<$y>>();
|
$lib.set_iterator::<StepRange<$y>>();
|
||||||
@ -68,38 +64,35 @@ macro_rules! reg_step {
|
|||||||
$lib.update_fn_metadata(hash, [
|
$lib.update_fn_metadata(hash, [
|
||||||
concat!("from: ", stringify!($y)),
|
concat!("from: ", stringify!($y)),
|
||||||
concat!("to: ", stringify!($y)),
|
concat!("to: ", stringify!($y)),
|
||||||
concat!("step: ", stringify!($y)), concat!("Iterator<Item=", stringify!($y), ">")
|
concat!("step: ", stringify!($y)),
|
||||||
|
concat!("Iterator<Item=", stringify!($y), ">")
|
||||||
]);
|
]);
|
||||||
)*
|
)*
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, {
|
def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, {
|
||||||
lib.set_iterator::<Range<INT>>();
|
reg_range!(lib, "range", INT);
|
||||||
let hash = lib.set_fn_2("range", get_range::<INT>);
|
|
||||||
lib.update_fn_metadata(hash, ["from: INT", "to: INT", "Iterator<Item=INT>"]);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
#[cfg(not(feature = "only_i64"))]
|
||||||
{
|
{
|
||||||
reg_range!(lib, "range", i8, u8, i16, u16, i32, i64, u32, u64);
|
reg_range!(lib, "range", i8, u8, i16, u16, i32, u32, i64, u64);
|
||||||
|
|
||||||
if cfg!(not(target_arch = "wasm32")) {
|
if cfg!(not(target_arch = "wasm32")) {
|
||||||
reg_range!(lib, "range", i128, u128);
|
reg_range!(lib, "range", i128, u128);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lib.set_iterator::<StepRange<INT>>();
|
reg_stepped_range!(lib, "range", INT);
|
||||||
let hash = lib.set_fn_3("range", get_step_range::<INT>);
|
|
||||||
lib.update_fn_metadata(hash, ["from: INT", "to: INT", "step: INT", "Iterator<Item=INT>"]);
|
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
#[cfg(not(feature = "only_i64"))]
|
||||||
{
|
{
|
||||||
reg_step!(lib, "range", i8, u8, i16, u16, i32, i64, u32, u64);
|
reg_stepped_range!(lib, "range", i8, u8, i16, u16, i32, u32, i64, u64);
|
||||||
|
|
||||||
if cfg!(not(target_arch = "wasm32")) {
|
if cfg!(not(target_arch = "wasm32")) {
|
||||||
reg_step!(lib, "range", i128, u128);
|
reg_stepped_range!(lib, "range", i128, u128);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -62,7 +62,7 @@ def_package!(crate:LogicPackage:"Logical operators.", lib, {
|
|||||||
{
|
{
|
||||||
reg_functions!(lib += numbers; i8, u8, i16, u16, i32, u32, u64);
|
reg_functions!(lib += numbers; i8, u8, i16, u16, i32, u32, u64);
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
reg_functions!(lib += num_128; i128, u128);
|
reg_functions!(lib += num_128; i128, u128);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ gen_cmp_functions!(numbers => i8, u8, i16, u16, i32, u32, u64);
|
|||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
#[cfg(not(feature = "only_i64"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
gen_cmp_functions!(num_128 => i128, u128);
|
gen_cmp_functions!(num_128 => i128, u128);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
|
@ -13,52 +13,54 @@ def_package!(crate:BasicMapPackage:"Basic object map utilities.", lib, {
|
|||||||
|
|
||||||
#[export_module]
|
#[export_module]
|
||||||
mod map_functions {
|
mod map_functions {
|
||||||
|
#[rhai_fn(pure)]
|
||||||
pub fn has(map: &mut Map, prop: ImmutableString) -> bool {
|
pub fn has(map: &mut Map, prop: ImmutableString) -> bool {
|
||||||
map.contains_key(&prop)
|
map.contains_key(&prop)
|
||||||
}
|
}
|
||||||
|
#[rhai_fn(pure)]
|
||||||
pub fn len(map: &mut Map) -> INT {
|
pub fn len(map: &mut Map) -> INT {
|
||||||
map.len() as INT
|
map.len() as INT
|
||||||
}
|
}
|
||||||
pub fn clear(map: &mut Map) {
|
pub fn clear(map: &mut Map) {
|
||||||
map.clear();
|
map.clear();
|
||||||
}
|
}
|
||||||
pub fn remove(x: &mut Map, name: ImmutableString) -> Dynamic {
|
pub fn remove(map: &mut Map, name: ImmutableString) -> Dynamic {
|
||||||
x.remove(&name).unwrap_or_else(|| ().into())
|
map.remove(&name).unwrap_or_else(|| ().into())
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "mixin", name = "+=")]
|
#[rhai_fn(name = "mixin", name = "+=")]
|
||||||
pub fn mixin(map1: &mut Map, map2: Map) {
|
pub fn mixin(map: &mut Map, map2: Map) {
|
||||||
map2.into_iter().for_each(|(key, value)| {
|
map2.into_iter().for_each(|(key, value)| {
|
||||||
map1.insert(key, value);
|
map.insert(key, value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(name = "+")]
|
||||||
pub fn merge(mut map1: Map, map2: Map) -> Map {
|
pub fn merge(mut map: Map, map2: Map) -> Map {
|
||||||
map2.into_iter().for_each(|(key, value)| {
|
map2.into_iter().for_each(|(key, value)| {
|
||||||
map1.insert(key, value);
|
map.insert(key, value);
|
||||||
});
|
});
|
||||||
map1
|
map
|
||||||
}
|
}
|
||||||
pub fn fill_with(map1: &mut Map, map2: Map) {
|
pub fn fill_with(map: &mut Map, map2: Map) {
|
||||||
map2.into_iter().for_each(|(key, value)| {
|
map2.into_iter().for_each(|(key, value)| {
|
||||||
map1.entry(key).or_insert(value);
|
map.entry(key).or_insert(value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "==", return_raw)]
|
#[rhai_fn(name = "==", return_raw, pure)]
|
||||||
pub fn equals(
|
pub fn equals(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
map1: &mut Map,
|
map: &mut Map,
|
||||||
mut map2: Map,
|
mut map2: Map,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
if map1.len() != map2.len() {
|
if map.len() != map2.len() {
|
||||||
return Ok(false.into());
|
return Ok(false.into());
|
||||||
}
|
}
|
||||||
if map1.is_empty() {
|
if map.is_empty() {
|
||||||
return Ok(true.into());
|
return Ok(true.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let def_value = Some(false.into());
|
let def_value = Some(false.into());
|
||||||
|
|
||||||
for (m1, v1) in map1.iter_mut() {
|
for (m1, v1) in map.iter_mut() {
|
||||||
if let Some(v2) = map2.get_mut(m1) {
|
if let Some(v2) = map2.get_mut(m1) {
|
||||||
let equals = ctx
|
let equals = ctx
|
||||||
.call_fn_dynamic_raw(OP_EQUALS, true, false, &mut [v1, v2], def_value.as_ref())
|
.call_fn_dynamic_raw(OP_EQUALS, true, false, &mut [v1, v2], def_value.as_ref())
|
||||||
@ -74,20 +76,22 @@ mod map_functions {
|
|||||||
|
|
||||||
Ok(true.into())
|
Ok(true.into())
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "!=", return_raw)]
|
#[rhai_fn(name = "!=", return_raw, pure)]
|
||||||
pub fn not_equals(
|
pub fn not_equals(
|
||||||
ctx: NativeCallContext,
|
ctx: NativeCallContext,
|
||||||
map1: &mut Map,
|
map: &mut Map,
|
||||||
map2: Map,
|
map2: Map,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
equals(ctx, map1, map2).map(|r| (!r.as_bool().unwrap()).into())
|
equals(ctx, map, map2).map(|r| (!r.as_bool().unwrap()).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
pub mod indexing {
|
pub mod indexing {
|
||||||
|
#[rhai_fn(pure)]
|
||||||
pub fn keys(map: &mut Map) -> Array {
|
pub fn keys(map: &mut Map) -> Array {
|
||||||
map.iter().map(|(k, _)| k.clone().into()).collect()
|
map.iter().map(|(k, _)| k.clone().into()).collect()
|
||||||
}
|
}
|
||||||
|
#[rhai_fn(pure)]
|
||||||
pub fn values(map: &mut Map) -> Array {
|
pub fn values(map: &mut Map) -> Array {
|
||||||
map.iter().map(|(_, v)| v.clone()).collect()
|
map.iter().map(|(_, v)| v.clone()).collect()
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ def_package!(crate:BasicMathPackage:"Basic mathematic functions.", lib, {
|
|||||||
{
|
{
|
||||||
reg_functions!(lib += numbers_to_int::to_int(i8, u8, i16, u16, i32, u32, i64, u64));
|
reg_functions!(lib += numbers_to_int::to_int(i8, u8, i16, u16, i32, u32, i64, u64));
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
reg_functions!(lib += num_128_to_int::to_int(i128, u128));
|
reg_functions!(lib += num_128_to_int::to_int(i128, u128));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ def_package!(crate:BasicMathPackage:"Basic mathematic functions.", lib, {
|
|||||||
{
|
{
|
||||||
reg_functions!(lib += numbers_to_float::to_float(i8, u8, i16, u16, i32, u32, i64, u32));
|
reg_functions!(lib += numbers_to_float::to_float(i8, u8, i16, u16, i32, u32, i64, u32));
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
reg_functions!(lib += num_128_to_float::to_float(i128, u128));
|
reg_functions!(lib += num_128_to_float::to_float(i128, u128));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -452,7 +452,7 @@ gen_conversion_as_functions!(numbers_to_float => to_float (i8, u8, i16, u16, i32
|
|||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
#[cfg(not(feature = "only_i64"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
gen_conversion_as_functions!(num_128_to_float => to_float (i128, u128) -> FLOAT);
|
gen_conversion_as_functions!(num_128_to_float => to_float (i128, u128) -> FLOAT);
|
||||||
|
|
||||||
gen_conversion_as_functions!(basic_to_int => to_int (char) -> INT);
|
gen_conversion_as_functions!(basic_to_int => to_int (char) -> INT);
|
||||||
@ -463,7 +463,7 @@ gen_conversion_as_functions!(numbers_to_int => to_int (i8, u8, i16, u16, i32, u3
|
|||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
#[cfg(not(feature = "only_i64"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
gen_conversion_as_functions!(num_128_to_int => to_int (i128, u128) -> INT);
|
gen_conversion_as_functions!(num_128_to_int => to_int (i128, u128) -> INT);
|
||||||
|
|
||||||
#[cfg(feature = "decimal")]
|
#[cfg(feature = "decimal")]
|
||||||
|
@ -28,7 +28,7 @@ macro_rules! gen_functions {
|
|||||||
pub mod $root { $(pub mod $arg_type {
|
pub mod $root { $(pub mod $arg_type {
|
||||||
use super::super::*;
|
use super::super::*;
|
||||||
|
|
||||||
#[export_fn]
|
#[export_fn(pure)]
|
||||||
pub fn to_string_func(x: &mut $arg_type) -> ImmutableString {
|
pub fn to_string_func(x: &mut $arg_type) -> ImmutableString {
|
||||||
super::super::$fn_name(x)
|
super::super::$fn_name(x)
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ def_package!(crate:BasicStringPackage:"Basic string utilities, including printin
|
|||||||
reg_print_functions!(lib += print_numbers; i8, u8, i16, u16, i32, u32, i64, u64);
|
reg_print_functions!(lib += print_numbers; i8, u8, i16, u16, i32, u32, i64, u64);
|
||||||
reg_debug_functions!(lib += debug_numbers; i8, u8, i16, u16, i32, u32, i64, u64);
|
reg_debug_functions!(lib += debug_numbers; i8, u8, i16, u16, i32, u32, i64, u64);
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
{
|
{
|
||||||
reg_print_functions!(lib += print_num_128; i128, u128);
|
reg_print_functions!(lib += print_num_128; i128, u128);
|
||||||
reg_debug_functions!(lib += debug_num_128; i128, u128);
|
reg_debug_functions!(lib += debug_num_128; i128, u128);
|
||||||
@ -128,12 +128,12 @@ gen_functions!(debug_numbers => to_debug(i8, u8, i16, u16, i32, u32, i64, u64));
|
|||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
#[cfg(not(feature = "only_i64"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
gen_functions!(print_num_128 => to_string(i128, u128));
|
gen_functions!(print_num_128 => to_string(i128, u128));
|
||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
#[cfg(not(feature = "only_i64"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
gen_functions!(debug_num_128 => to_debug(i128, u128));
|
gen_functions!(debug_num_128 => to_debug(i128, u128));
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
@ -174,7 +174,7 @@ mod print_debug_functions {
|
|||||||
pub fn print_string(s: ImmutableString) -> ImmutableString {
|
pub fn print_string(s: ImmutableString) -> ImmutableString {
|
||||||
s
|
s
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "debug")]
|
#[rhai_fn(name = "debug", pure)]
|
||||||
pub fn debug_fn_ptr(f: &mut FnPtr) -> ImmutableString {
|
pub fn debug_fn_ptr(f: &mut FnPtr) -> ImmutableString {
|
||||||
to_string(f)
|
to_string(f)
|
||||||
}
|
}
|
||||||
@ -183,14 +183,20 @@ mod print_debug_functions {
|
|||||||
pub mod array_functions {
|
pub mod array_functions {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[rhai_fn(name = "print", name = "to_string", name = "to_debug", name = "debug")]
|
#[rhai_fn(
|
||||||
pub fn format_array(ctx: NativeCallContext, arr: &mut Array) -> ImmutableString {
|
name = "print",
|
||||||
|
name = "to_string",
|
||||||
|
name = "to_debug",
|
||||||
|
name = "debug",
|
||||||
|
pure
|
||||||
|
)]
|
||||||
|
pub fn format_array(ctx: NativeCallContext, array: &mut Array) -> ImmutableString {
|
||||||
let mut result = crate::stdlib::string::String::with_capacity(16);
|
let mut result = crate::stdlib::string::String::with_capacity(16);
|
||||||
result.push_str("[");
|
result.push_str("[");
|
||||||
|
|
||||||
let len = arr.len();
|
let len = array.len();
|
||||||
|
|
||||||
arr.iter_mut().enumerate().for_each(|(i, x)| {
|
array.iter_mut().enumerate().for_each(|(i, x)| {
|
||||||
result.push_str(&print_with_func(FUNC_TO_DEBUG, &ctx, x));
|
result.push_str(&print_with_func(FUNC_TO_DEBUG, &ctx, x));
|
||||||
if i < len - 1 {
|
if i < len - 1 {
|
||||||
result.push_str(", ");
|
result.push_str(", ");
|
||||||
@ -205,7 +211,13 @@ mod print_debug_functions {
|
|||||||
pub mod map_functions {
|
pub mod map_functions {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[rhai_fn(name = "print", name = "to_string", name = "to_debug", name = "debug")]
|
#[rhai_fn(
|
||||||
|
name = "print",
|
||||||
|
name = "to_string",
|
||||||
|
name = "to_debug",
|
||||||
|
name = "debug",
|
||||||
|
pure
|
||||||
|
)]
|
||||||
pub fn format_map(ctx: NativeCallContext, map: &mut Map) -> ImmutableString {
|
pub fn format_map(ctx: NativeCallContext, map: &mut Map) -> ImmutableString {
|
||||||
let mut result = crate::stdlib::string::String::with_capacity(16);
|
let mut result = crate::stdlib::string::String::with_capacity(16);
|
||||||
result.push_str("#{");
|
result.push_str("#{");
|
||||||
|
@ -14,13 +14,13 @@ macro_rules! gen_concat_functions {
|
|||||||
#[export_module]
|
#[export_module]
|
||||||
pub mod functions {
|
pub mod functions {
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(name = "+")]
|
||||||
pub fn append_func(x: &str, y: $arg_type) -> String {
|
pub fn append_func(string: &str, arg: $arg_type) -> String {
|
||||||
format!("{}{}", x, y)
|
format!("{}{}", string, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(name = "+", pure)]
|
||||||
pub fn prepend_func(x: &mut $arg_type, y: &str) -> String {
|
pub fn prepend_func(arg: &mut $arg_type, string: &str) -> String {
|
||||||
format!("{}{}", x, y)
|
format!("{}{}", arg, string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} )* }
|
} )* }
|
||||||
@ -41,7 +41,7 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str
|
|||||||
{
|
{
|
||||||
reg_functions!(lib += numbers; i8, u8, i16, u16, i32, i64, u32, u64);
|
reg_functions!(lib += numbers; i8, u8, i16, u16, i32, i64, u32, u64);
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
reg_functions!(lib += num_128; i128, u128);
|
reg_functions!(lib += num_128; i128, u128);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str
|
|||||||
// Register string iterator
|
// Register string iterator
|
||||||
lib.set_iter(
|
lib.set_iter(
|
||||||
TypeId::of::<ImmutableString>(),
|
TypeId::of::<ImmutableString>(),
|
||||||
|s: Dynamic| Box::new(s.cast::<ImmutableString>().chars().collect::<Vec<_>>().into_iter().map(Into::into))
|
|string: Dynamic| Box::new(string.cast::<ImmutableString>().chars().collect::<Vec<_>>().into_iter().map(Into::into))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -65,7 +65,7 @@ gen_concat_functions!(numbers => i8, u8, i16, u16, i32, i64, u32, u64);
|
|||||||
|
|
||||||
#[cfg(not(feature = "only_i32"))]
|
#[cfg(not(feature = "only_i32"))]
|
||||||
#[cfg(not(feature = "only_i64"))]
|
#[cfg(not(feature = "only_i64"))]
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
gen_concat_functions!(num_128 => i128, u128);
|
gen_concat_functions!(num_128 => i128, u128);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
@ -73,104 +73,116 @@ gen_concat_functions!(float => f32, f64);
|
|||||||
|
|
||||||
#[export_module]
|
#[export_module]
|
||||||
mod string_functions {
|
mod string_functions {
|
||||||
|
use crate::ImmutableString;
|
||||||
|
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(name = "+")]
|
||||||
pub fn add_append_unit(s: ImmutableString, _x: ()) -> ImmutableString {
|
pub fn add_append_unit(string: ImmutableString, _x: ()) -> ImmutableString {
|
||||||
s
|
string
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(name = "+")]
|
||||||
pub fn add_prepend_unit(_x: (), s: ImmutableString) -> ImmutableString {
|
pub fn add_prepend_unit(_x: (), string: ImmutableString) -> ImmutableString {
|
||||||
s
|
string
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(name = "len", get = "len")]
|
#[rhai_fn(name = "len", get = "len")]
|
||||||
pub fn len(s: &str) -> INT {
|
pub fn len(string: &str) -> INT {
|
||||||
s.chars().count() as INT
|
string.chars().count() as INT
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(s: &mut ImmutableString) {
|
pub fn clear(string: &mut ImmutableString) {
|
||||||
s.make_mut().clear();
|
string.make_mut().clear();
|
||||||
}
|
}
|
||||||
pub fn truncate(s: &mut ImmutableString, len: INT) {
|
pub fn truncate(string: &mut ImmutableString, len: INT) {
|
||||||
if len > 0 {
|
if len > 0 {
|
||||||
let chars: StaticVec<_> = s.chars().collect();
|
let chars: StaticVec<_> = string.chars().collect();
|
||||||
let copy = s.make_mut();
|
let copy = string.make_mut();
|
||||||
copy.clear();
|
copy.clear();
|
||||||
copy.extend(chars.into_iter().take(len as usize));
|
copy.extend(chars.into_iter().take(len as usize));
|
||||||
} else {
|
} else {
|
||||||
s.make_mut().clear();
|
string.make_mut().clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn trim(s: &mut ImmutableString) {
|
pub fn trim(string: &mut ImmutableString) {
|
||||||
let trimmed = s.trim();
|
let trimmed = string.trim();
|
||||||
|
|
||||||
if trimmed.len() < s.len() {
|
if trimmed.len() < string.len() {
|
||||||
*s = trimmed.to_string().into();
|
*string = trimmed.to_string().into();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(name = "contains")]
|
#[rhai_fn(name = "contains")]
|
||||||
pub fn contains_char(s: &str, ch: char) -> bool {
|
pub fn contains_char(string: &str, ch: char) -> bool {
|
||||||
s.contains(ch)
|
string.contains(ch)
|
||||||
}
|
}
|
||||||
pub fn contains(s: &str, find: ImmutableString) -> bool {
|
pub fn contains(string: &str, find_string: &str) -> bool {
|
||||||
s.contains(find.as_str())
|
string.contains(find_string)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(name = "index_of")]
|
#[rhai_fn(name = "index_of")]
|
||||||
pub fn index_of_char_starting_from(s: &str, ch: char, start: INT) -> INT {
|
pub fn index_of_char_starting_from(string: &str, ch: char, start: INT) -> INT {
|
||||||
let start = if start < 0 {
|
let start = if start < 0 {
|
||||||
0
|
0
|
||||||
} else if start as usize >= s.chars().count() {
|
} else if start as usize >= string.chars().count() {
|
||||||
return -1 as INT;
|
return -1 as INT;
|
||||||
} else {
|
} else {
|
||||||
s.chars().take(start as usize).collect::<String>().len()
|
string
|
||||||
|
.chars()
|
||||||
|
.take(start as usize)
|
||||||
|
.collect::<String>()
|
||||||
|
.len()
|
||||||
};
|
};
|
||||||
|
|
||||||
s[start..]
|
string[start..]
|
||||||
.find(ch)
|
.find(ch)
|
||||||
.map(|index| s[0..start + index].chars().count() as INT)
|
.map(|index| string[0..start + index].chars().count() as INT)
|
||||||
.unwrap_or(-1 as INT)
|
.unwrap_or(-1 as INT)
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "index_of")]
|
#[rhai_fn(name = "index_of")]
|
||||||
pub fn index_of_char(s: &str, ch: char) -> INT {
|
pub fn index_of_char(string: &str, ch: char) -> INT {
|
||||||
s.find(ch)
|
string
|
||||||
.map(|index| s[0..index].chars().count() as INT)
|
.find(ch)
|
||||||
|
.map(|index| string[0..index].chars().count() as INT)
|
||||||
.unwrap_or(-1 as INT)
|
.unwrap_or(-1 as INT)
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "index_of")]
|
#[rhai_fn(name = "index_of")]
|
||||||
pub fn index_of_string_starting_from(s: &str, find: ImmutableString, start: INT) -> INT {
|
pub fn index_of_string_starting_from(string: &str, find_string: &str, start: INT) -> INT {
|
||||||
let start = if start < 0 {
|
let start = if start < 0 {
|
||||||
0
|
0
|
||||||
} else if start as usize >= s.chars().count() {
|
} else if start as usize >= string.chars().count() {
|
||||||
return -1 as INT;
|
return -1 as INT;
|
||||||
} else {
|
} else {
|
||||||
s.chars().take(start as usize).collect::<String>().len()
|
string
|
||||||
|
.chars()
|
||||||
|
.take(start as usize)
|
||||||
|
.collect::<String>()
|
||||||
|
.len()
|
||||||
};
|
};
|
||||||
|
|
||||||
s[start..]
|
string[start..]
|
||||||
.find(find.as_str())
|
.find(find_string)
|
||||||
.map(|index| s[0..start + index].chars().count() as INT)
|
.map(|index| string[0..start + index].chars().count() as INT)
|
||||||
.unwrap_or(-1 as INT)
|
.unwrap_or(-1 as INT)
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "index_of")]
|
#[rhai_fn(name = "index_of")]
|
||||||
pub fn index_of(s: &str, find: ImmutableString) -> INT {
|
pub fn index_of(string: &str, find_string: &str) -> INT {
|
||||||
s.find(find.as_str())
|
string
|
||||||
.map(|index| s[0..index].chars().count() as INT)
|
.find(find_string)
|
||||||
|
.map(|index| string[0..index].chars().count() as INT)
|
||||||
.unwrap_or(-1 as INT)
|
.unwrap_or(-1 as INT)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sub_string(s: &str, start: INT, len: INT) -> ImmutableString {
|
pub fn sub_string(string: &str, start: INT, len: INT) -> ImmutableString {
|
||||||
let offset = if s.is_empty() || len <= 0 {
|
let offset = if string.is_empty() || len <= 0 {
|
||||||
return "".to_string().into();
|
return "".to_string().into();
|
||||||
} else if start < 0 {
|
} else if start < 0 {
|
||||||
0
|
0
|
||||||
} else if start as usize >= s.chars().count() {
|
} else if start as usize >= string.chars().count() {
|
||||||
return "".to_string().into();
|
return "".to_string().into();
|
||||||
} else {
|
} else {
|
||||||
start as usize
|
start as usize
|
||||||
};
|
};
|
||||||
|
|
||||||
let chars: StaticVec<_> = s.chars().collect();
|
let chars: StaticVec<_> = string.chars().collect();
|
||||||
|
|
||||||
let len = if offset + len as usize > chars.len() {
|
let len = if offset + len as usize > chars.len() {
|
||||||
chars.len() - offset
|
chars.len() - offset
|
||||||
@ -187,26 +199,26 @@ mod string_functions {
|
|||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "sub_string")]
|
#[rhai_fn(name = "sub_string")]
|
||||||
pub fn sub_string_starting_from(s: &str, start: INT) -> ImmutableString {
|
pub fn sub_string_starting_from(string: &str, start: INT) -> ImmutableString {
|
||||||
let len = s.len() as INT;
|
let len = string.len() as INT;
|
||||||
sub_string(s, start, len)
|
sub_string(string, start, len)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(name = "crop")]
|
#[rhai_fn(name = "crop")]
|
||||||
pub fn crop(s: &mut ImmutableString, start: INT, len: INT) {
|
pub fn crop(string: &mut ImmutableString, start: INT, len: INT) {
|
||||||
let offset = if s.is_empty() || len <= 0 {
|
let offset = if string.is_empty() || len <= 0 {
|
||||||
s.make_mut().clear();
|
string.make_mut().clear();
|
||||||
return;
|
return;
|
||||||
} else if start < 0 {
|
} else if start < 0 {
|
||||||
0
|
0
|
||||||
} else if start as usize >= s.chars().count() {
|
} else if start as usize >= string.chars().count() {
|
||||||
s.make_mut().clear();
|
string.make_mut().clear();
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
start as usize
|
start as usize
|
||||||
};
|
};
|
||||||
|
|
||||||
let chars: StaticVec<_> = s.chars().collect();
|
let chars: StaticVec<_> = string.chars().collect();
|
||||||
|
|
||||||
let len = if offset + len as usize > chars.len() {
|
let len = if offset + len as usize > chars.len() {
|
||||||
chars.len() - offset
|
chars.len() - offset
|
||||||
@ -214,36 +226,50 @@ mod string_functions {
|
|||||||
len as usize
|
len as usize
|
||||||
};
|
};
|
||||||
|
|
||||||
let copy = s.make_mut();
|
let copy = string.make_mut();
|
||||||
copy.clear();
|
copy.clear();
|
||||||
copy.extend(chars.iter().skip(offset).take(len));
|
copy.extend(chars.iter().skip(offset).take(len));
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "crop")]
|
#[rhai_fn(name = "crop")]
|
||||||
pub fn crop_string_starting_from(s: &mut ImmutableString, start: INT) {
|
pub fn crop_string_starting_from(string: &mut ImmutableString, start: INT) {
|
||||||
crop(s, start, s.len() as INT);
|
crop(string, start, string.len() as INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(name = "replace")]
|
#[rhai_fn(name = "replace")]
|
||||||
pub fn replace(s: &mut ImmutableString, find: ImmutableString, sub: ImmutableString) {
|
pub fn replace(string: &mut ImmutableString, find_string: &str, substitute_string: &str) {
|
||||||
*s = s.replace(find.as_str(), sub.as_str()).into();
|
*string = string.replace(find_string, substitute_string).into();
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "replace")]
|
#[rhai_fn(name = "replace")]
|
||||||
pub fn replace_string_with_char(s: &mut ImmutableString, find: ImmutableString, sub: char) {
|
pub fn replace_string_with_char(
|
||||||
*s = s.replace(find.as_str(), &sub.to_string()).into();
|
string: &mut ImmutableString,
|
||||||
|
find_string: &str,
|
||||||
|
substitute_char: char,
|
||||||
|
) {
|
||||||
|
*string = string
|
||||||
|
.replace(find_string, &substitute_char.to_string())
|
||||||
|
.into();
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "replace")]
|
#[rhai_fn(name = "replace")]
|
||||||
pub fn replace_char_with_string(s: &mut ImmutableString, find: char, sub: ImmutableString) {
|
pub fn replace_char_with_string(
|
||||||
*s = s.replace(&find.to_string(), sub.as_str()).into();
|
string: &mut ImmutableString,
|
||||||
|
find_char: char,
|
||||||
|
substitute_string: &str,
|
||||||
|
) {
|
||||||
|
*string = string
|
||||||
|
.replace(&find_char.to_string(), substitute_string)
|
||||||
|
.into();
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "replace")]
|
#[rhai_fn(name = "replace")]
|
||||||
pub fn replace_char(s: &mut ImmutableString, find: char, sub: char) {
|
pub fn replace_char(string: &mut ImmutableString, find_char: char, substitute_char: char) {
|
||||||
*s = s.replace(&find.to_string(), &sub.to_string()).into();
|
*string = string
|
||||||
|
.replace(&find_char.to_string(), &substitute_char.to_string())
|
||||||
|
.into();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(return_raw)]
|
#[rhai_fn(return_raw)]
|
||||||
pub fn pad(
|
pub fn pad(
|
||||||
_ctx: NativeCallContext,
|
_ctx: NativeCallContext,
|
||||||
s: &mut ImmutableString,
|
string: &mut ImmutableString,
|
||||||
len: INT,
|
len: INT,
|
||||||
ch: char,
|
ch: char,
|
||||||
) -> Result<Dynamic, Box<crate::EvalAltResult>> {
|
) -> Result<Dynamic, Box<crate::EvalAltResult>> {
|
||||||
@ -258,17 +284,18 @@ mod string_functions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len > 0 {
|
if len > 0 {
|
||||||
let orig_len = s.chars().count();
|
let orig_len = string.chars().count();
|
||||||
|
|
||||||
if len as usize > orig_len {
|
if len as usize > orig_len {
|
||||||
let p = s.make_mut();
|
let p = string.make_mut();
|
||||||
|
|
||||||
for _ in 0..(len as usize - orig_len) {
|
for _ in 0..(len as usize - orig_len) {
|
||||||
p.push(ch);
|
p.push(ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
if _ctx.engine().max_string_size() > 0 && s.len() > _ctx.engine().max_string_size()
|
if _ctx.engine().max_string_size() > 0
|
||||||
|
&& string.len() > _ctx.engine().max_string_size()
|
||||||
{
|
{
|
||||||
return crate::EvalAltResult::ErrorDataTooLarge(
|
return crate::EvalAltResult::ErrorDataTooLarge(
|
||||||
"Length of string".to_string(),
|
"Length of string".to_string(),
|
||||||
@ -284,7 +311,7 @@ mod string_functions {
|
|||||||
#[rhai_fn(name = "pad", return_raw)]
|
#[rhai_fn(name = "pad", return_raw)]
|
||||||
pub fn pad_with_string(
|
pub fn pad_with_string(
|
||||||
_ctx: NativeCallContext,
|
_ctx: NativeCallContext,
|
||||||
s: &mut ImmutableString,
|
string: &mut ImmutableString,
|
||||||
len: INT,
|
len: INT,
|
||||||
padding: &str,
|
padding: &str,
|
||||||
) -> Result<Dynamic, Box<crate::EvalAltResult>> {
|
) -> Result<Dynamic, Box<crate::EvalAltResult>> {
|
||||||
@ -299,11 +326,11 @@ mod string_functions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len > 0 {
|
if len > 0 {
|
||||||
let mut str_len = s.chars().count();
|
let mut str_len = string.chars().count();
|
||||||
let padding_len = padding.chars().count();
|
let padding_len = padding.chars().count();
|
||||||
|
|
||||||
if len as usize > str_len {
|
if len as usize > str_len {
|
||||||
let p = s.make_mut();
|
let p = string.make_mut();
|
||||||
|
|
||||||
while str_len < len as usize {
|
while str_len < len as usize {
|
||||||
if str_len + padding_len <= len as usize {
|
if str_len + padding_len <= len as usize {
|
||||||
@ -316,7 +343,8 @@ mod string_functions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "unchecked"))]
|
#[cfg(not(feature = "unchecked"))]
|
||||||
if _ctx.engine().max_string_size() > 0 && s.len() > _ctx.engine().max_string_size()
|
if _ctx.engine().max_string_size() > 0
|
||||||
|
&& string.len() > _ctx.engine().max_string_size()
|
||||||
{
|
{
|
||||||
return crate::EvalAltResult::ErrorDataTooLarge(
|
return crate::EvalAltResult::ErrorDataTooLarge(
|
||||||
"Length of string".to_string(),
|
"Length of string".to_string(),
|
||||||
@ -335,21 +363,19 @@ mod string_functions {
|
|||||||
use crate::Array;
|
use crate::Array;
|
||||||
|
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(name = "+")]
|
||||||
pub fn append(x: &str, y: Array) -> String {
|
pub fn append(string: &str, array: Array) -> String {
|
||||||
format!("{}{:?}", x, y)
|
format!("{}{:?}", string, array)
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(name = "+", pure)]
|
||||||
pub fn prepend(x: &mut Array, y: &str) -> String {
|
pub fn prepend(array: &mut Array, string: &str) -> String {
|
||||||
format!("{:?}{}", x, y)
|
format!("{:?}{}", array, string)
|
||||||
}
|
}
|
||||||
pub fn split(s: &str, delimiter: ImmutableString) -> Array {
|
pub fn split(string: &str, delimiter: &str) -> Array {
|
||||||
s.split(delimiter.as_str())
|
string.split(delimiter).map(Into::<Dynamic>::into).collect()
|
||||||
.map(Into::<Dynamic>::into)
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "split")]
|
#[rhai_fn(name = "split")]
|
||||||
pub fn split_char(s: &str, delimiter: char) -> Array {
|
pub fn split_char(string: &str, delimiter: char) -> Array {
|
||||||
s.split(delimiter).map(Into::<Dynamic>::into).collect()
|
string.split(delimiter).map(Into::<Dynamic>::into).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,12 +384,12 @@ mod string_functions {
|
|||||||
use crate::Map;
|
use crate::Map;
|
||||||
|
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(name = "+")]
|
||||||
pub fn append(x: &str, y: Map) -> String {
|
pub fn append(string: &str, map: Map) -> String {
|
||||||
format!("{}#{:?}", x, y)
|
format!("{}#{:?}", string, map)
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "+")]
|
#[rhai_fn(name = "+", pure)]
|
||||||
pub fn prepend(x: &mut Map, y: &str) -> String {
|
pub fn prepend(map: &mut Map, string: &str) -> String {
|
||||||
format!("#{:?}{}", x, y)
|
format!("#{:?}{}", map, string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,10 @@ use crate::{def_package, Dynamic, EvalAltResult, INT};
|
|||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
use crate::FLOAT;
|
use crate::FLOAT;
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
use crate::stdlib::time::{Duration, Instant};
|
use crate::stdlib::time::{Duration, Instant};
|
||||||
|
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))]
|
||||||
use instant::{Duration, Instant};
|
use instant::{Duration, Instant};
|
||||||
|
|
||||||
def_package!(crate:BasicTimePackage:"Basic timing utilities.", lib, {
|
def_package!(crate:BasicTimePackage:"Basic timing utilities.", lib, {
|
||||||
@ -26,15 +26,13 @@ mod time_functions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(name = "elapsed", get = "elapsed", return_raw)]
|
#[rhai_fn(name = "elapsed", get = "elapsed", return_raw)]
|
||||||
pub fn elapsed(timestamp: &mut Instant) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn elapsed(timestamp: Instant) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
{
|
if timestamp > Instant::now() {
|
||||||
if *timestamp > Instant::now() {
|
|
||||||
Err(make_arithmetic_err("Time-stamp is later than now"))
|
Err(make_arithmetic_err("Time-stamp is later than now"))
|
||||||
} else {
|
} else {
|
||||||
Ok((timestamp.elapsed().as_secs_f64() as FLOAT).into())
|
Ok((timestamp.elapsed().as_secs_f64() as FLOAT).into())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "no_float")]
|
#[cfg(feature = "no_float")]
|
||||||
{
|
{
|
||||||
@ -45,7 +43,7 @@ mod time_functions {
|
|||||||
"Integer overflow for timestamp.elapsed: {}",
|
"Integer overflow for timestamp.elapsed: {}",
|
||||||
seconds
|
seconds
|
||||||
)))
|
)))
|
||||||
} else if *timestamp > Instant::now() {
|
} else if timestamp > Instant::now() {
|
||||||
Err(make_arithmetic_err("Time-stamp is later than now"))
|
Err(make_arithmetic_err("Time-stamp is later than now"))
|
||||||
} else {
|
} else {
|
||||||
Ok((seconds as INT).into())
|
Ok((seconds as INT).into())
|
||||||
@ -54,20 +52,21 @@ mod time_functions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(return_raw, name = "-")]
|
#[rhai_fn(return_raw, name = "-")]
|
||||||
pub fn time_diff(ts1: Instant, ts2: Instant) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn time_diff(
|
||||||
|
timestamp: Instant,
|
||||||
|
timestamp2: Instant,
|
||||||
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
{
|
return Ok(if timestamp2 > timestamp {
|
||||||
Ok(if ts2 > ts1 {
|
-(timestamp2 - timestamp).as_secs_f64() as FLOAT
|
||||||
-(ts2 - ts1).as_secs_f64() as FLOAT
|
|
||||||
} else {
|
} else {
|
||||||
(ts1 - ts2).as_secs_f64() as FLOAT
|
(timestamp - timestamp2).as_secs_f64() as FLOAT
|
||||||
}
|
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
.into());
|
||||||
|
|
||||||
#[cfg(feature = "no_float")]
|
#[cfg(feature = "no_float")]
|
||||||
if ts2 > ts1 {
|
if timestamp2 > timestamp {
|
||||||
let seconds = (ts2 - ts1).as_secs();
|
let seconds = (timestamp2 - timestamp).as_secs();
|
||||||
|
|
||||||
if cfg!(not(feature = "unchecked")) && seconds > (MAX_INT as u64) {
|
if cfg!(not(feature = "unchecked")) && seconds > (MAX_INT as u64) {
|
||||||
Err(make_arithmetic_err(format!(
|
Err(make_arithmetic_err(format!(
|
||||||
@ -78,7 +77,7 @@ mod time_functions {
|
|||||||
Ok((-(seconds as INT)).into())
|
Ok((-(seconds as INT)).into())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let seconds = (ts1 - ts2).as_secs();
|
let seconds = (timestamp - timestamp2).as_secs();
|
||||||
|
|
||||||
if cfg!(not(feature = "unchecked")) && seconds > (MAX_INT as u64) {
|
if cfg!(not(feature = "unchecked")) && seconds > (MAX_INT as u64) {
|
||||||
Err(make_arithmetic_err(format!(
|
Err(make_arithmetic_err(format!(
|
||||||
@ -93,9 +92,9 @@ mod time_functions {
|
|||||||
|
|
||||||
#[cfg(not(feature = "no_float"))]
|
#[cfg(not(feature = "no_float"))]
|
||||||
pub mod float_functions {
|
pub mod float_functions {
|
||||||
fn add_impl(x: Instant, seconds: FLOAT) -> Result<Instant, Box<EvalAltResult>> {
|
fn add_impl(timestamp: Instant, seconds: FLOAT) -> Result<Instant, Box<EvalAltResult>> {
|
||||||
if seconds < 0.0 {
|
if seconds < 0.0 {
|
||||||
subtract_impl(x, -seconds)
|
subtract_impl(timestamp, -seconds)
|
||||||
} else if cfg!(not(feature = "unchecked")) {
|
} else if cfg!(not(feature = "unchecked")) {
|
||||||
if seconds > (MAX_INT as FLOAT) {
|
if seconds > (MAX_INT as FLOAT) {
|
||||||
Err(make_arithmetic_err(format!(
|
Err(make_arithmetic_err(format!(
|
||||||
@ -103,7 +102,8 @@ mod time_functions {
|
|||||||
seconds
|
seconds
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
x.checked_add(Duration::from_millis((seconds * 1000.0) as u64))
|
timestamp
|
||||||
|
.checked_add(Duration::from_millis((seconds * 1000.0) as u64))
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
make_arithmetic_err(format!(
|
make_arithmetic_err(format!(
|
||||||
"Timestamp overflow when adding {} second(s)",
|
"Timestamp overflow when adding {} second(s)",
|
||||||
@ -112,12 +112,15 @@ mod time_functions {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(x + Duration::from_millis((seconds * 1000.0) as u64))
|
Ok(timestamp + Duration::from_millis((seconds * 1000.0) as u64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn subtract_impl(x: Instant, seconds: FLOAT) -> Result<Instant, Box<EvalAltResult>> {
|
fn subtract_impl(
|
||||||
|
timestamp: Instant,
|
||||||
|
seconds: FLOAT,
|
||||||
|
) -> Result<Instant, Box<EvalAltResult>> {
|
||||||
if seconds < 0.0 {
|
if seconds < 0.0 {
|
||||||
add_impl(x, -seconds)
|
add_impl(timestamp, -seconds)
|
||||||
} else if cfg!(not(feature = "unchecked")) {
|
} else if cfg!(not(feature = "unchecked")) {
|
||||||
if seconds > (MAX_INT as FLOAT) {
|
if seconds > (MAX_INT as FLOAT) {
|
||||||
Err(make_arithmetic_err(format!(
|
Err(make_arithmetic_err(format!(
|
||||||
@ -125,7 +128,8 @@ mod time_functions {
|
|||||||
seconds
|
seconds
|
||||||
)))
|
)))
|
||||||
} else {
|
} else {
|
||||||
x.checked_sub(Duration::from_millis((seconds * 1000.0) as u64))
|
timestamp
|
||||||
|
.checked_sub(Duration::from_millis((seconds * 1000.0) as u64))
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
make_arithmetic_err(format!(
|
make_arithmetic_err(format!(
|
||||||
"Timestamp overflow when adding {} second(s)",
|
"Timestamp overflow when adding {} second(s)",
|
||||||
@ -134,38 +138,42 @@ mod time_functions {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Ok(x - Duration::from_millis((seconds * 1000.0) as u64))
|
Ok(timestamp - Duration::from_millis((seconds * 1000.0) as u64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(return_raw, name = "+")]
|
#[rhai_fn(return_raw, name = "+")]
|
||||||
pub fn add(x: Instant, seconds: FLOAT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn add(timestamp: Instant, seconds: FLOAT) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
add_impl(x, seconds).map(Into::<Dynamic>::into)
|
add_impl(timestamp, seconds).map(Into::<Dynamic>::into)
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, name = "+=")]
|
#[rhai_fn(return_raw, name = "+=")]
|
||||||
pub fn add_assign(x: &mut Instant, seconds: FLOAT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn add_assign(
|
||||||
*x = add_impl(*x, seconds)?;
|
timestamp: &mut Instant,
|
||||||
|
seconds: FLOAT,
|
||||||
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
|
*timestamp = add_impl(*timestamp, seconds)?;
|
||||||
Ok(Dynamic::UNIT)
|
Ok(Dynamic::UNIT)
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, name = "-")]
|
#[rhai_fn(return_raw, name = "-")]
|
||||||
pub fn subtract(x: Instant, seconds: FLOAT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn subtract(timestamp: Instant, seconds: FLOAT) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
subtract_impl(x, seconds).map(Into::<Dynamic>::into)
|
subtract_impl(timestamp, seconds).map(Into::<Dynamic>::into)
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, name = "-=")]
|
#[rhai_fn(return_raw, name = "-=")]
|
||||||
pub fn subtract_assign(
|
pub fn subtract_assign(
|
||||||
x: &mut Instant,
|
timestamp: &mut Instant,
|
||||||
seconds: FLOAT,
|
seconds: FLOAT,
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
*x = subtract_impl(*x, seconds)?;
|
*timestamp = subtract_impl(*timestamp, seconds)?;
|
||||||
Ok(Dynamic::UNIT)
|
Ok(Dynamic::UNIT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_impl(x: Instant, seconds: INT) -> Result<Instant, Box<EvalAltResult>> {
|
fn add_impl(timestamp: Instant, seconds: INT) -> Result<Instant, Box<EvalAltResult>> {
|
||||||
if seconds < 0 {
|
if seconds < 0 {
|
||||||
subtract_impl(x, -seconds)
|
subtract_impl(timestamp, -seconds)
|
||||||
} else if cfg!(not(feature = "unchecked")) {
|
} else if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_add(Duration::from_secs(seconds as u64))
|
timestamp
|
||||||
|
.checked_add(Duration::from_secs(seconds as u64))
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
make_arithmetic_err(format!(
|
make_arithmetic_err(format!(
|
||||||
"Timestamp overflow when adding {} second(s)",
|
"Timestamp overflow when adding {} second(s)",
|
||||||
@ -173,14 +181,15 @@ mod time_functions {
|
|||||||
))
|
))
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Ok(x + Duration::from_secs(seconds as u64))
|
Ok(timestamp + Duration::from_secs(seconds as u64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn subtract_impl(x: Instant, seconds: INT) -> Result<Instant, Box<EvalAltResult>> {
|
fn subtract_impl(timestamp: Instant, seconds: INT) -> Result<Instant, Box<EvalAltResult>> {
|
||||||
if seconds < 0 {
|
if seconds < 0 {
|
||||||
add_impl(x, -seconds)
|
add_impl(timestamp, -seconds)
|
||||||
} else if cfg!(not(feature = "unchecked")) {
|
} else if cfg!(not(feature = "unchecked")) {
|
||||||
x.checked_sub(Duration::from_secs(seconds as u64))
|
timestamp
|
||||||
|
.checked_sub(Duration::from_secs(seconds as u64))
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
make_arithmetic_err(format!(
|
make_arithmetic_err(format!(
|
||||||
"Timestamp overflow when adding {} second(s)",
|
"Timestamp overflow when adding {} second(s)",
|
||||||
@ -188,51 +197,57 @@ mod time_functions {
|
|||||||
))
|
))
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Ok(x - Duration::from_secs(seconds as u64))
|
Ok(timestamp - Duration::from_secs(seconds as u64))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(return_raw, name = "+")]
|
#[rhai_fn(return_raw, name = "+")]
|
||||||
pub fn add(x: Instant, seconds: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn add(timestamp: Instant, seconds: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
add_impl(x, seconds).map(Into::<Dynamic>::into)
|
add_impl(timestamp, seconds).map(Into::<Dynamic>::into)
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, name = "+=")]
|
#[rhai_fn(return_raw, name = "+=")]
|
||||||
pub fn add_assign(x: &mut Instant, seconds: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn add_assign(
|
||||||
*x = add_impl(*x, seconds)?;
|
timestamp: &mut Instant,
|
||||||
|
seconds: INT,
|
||||||
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
|
*timestamp = add_impl(*timestamp, seconds)?;
|
||||||
Ok(Dynamic::UNIT)
|
Ok(Dynamic::UNIT)
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, name = "-")]
|
#[rhai_fn(return_raw, name = "-")]
|
||||||
pub fn subtract(x: Instant, seconds: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn subtract(timestamp: Instant, seconds: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
subtract_impl(x, seconds).map(Into::<Dynamic>::into)
|
subtract_impl(timestamp, seconds).map(Into::<Dynamic>::into)
|
||||||
}
|
}
|
||||||
#[rhai_fn(return_raw, name = "-=")]
|
#[rhai_fn(return_raw, name = "-=")]
|
||||||
pub fn subtract_assign(x: &mut Instant, seconds: INT) -> Result<Dynamic, Box<EvalAltResult>> {
|
pub fn subtract_assign(
|
||||||
*x = subtract_impl(*x, seconds)?;
|
timestamp: &mut Instant,
|
||||||
|
seconds: INT,
|
||||||
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
|
*timestamp = subtract_impl(*timestamp, seconds)?;
|
||||||
Ok(Dynamic::UNIT)
|
Ok(Dynamic::UNIT)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rhai_fn(name = "==")]
|
#[rhai_fn(name = "==")]
|
||||||
pub fn eq(x: Instant, y: Instant) -> bool {
|
pub fn eq(timestamp: Instant, timestamp2: Instant) -> bool {
|
||||||
x == y
|
timestamp == timestamp2
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "!=")]
|
#[rhai_fn(name = "!=")]
|
||||||
pub fn ne(x: Instant, y: Instant) -> bool {
|
pub fn ne(timestamp: Instant, timestamp2: Instant) -> bool {
|
||||||
x != y
|
timestamp != timestamp2
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "<")]
|
#[rhai_fn(name = "<")]
|
||||||
pub fn lt(x: Instant, y: Instant) -> bool {
|
pub fn lt(timestamp: Instant, timestamp2: Instant) -> bool {
|
||||||
x < y
|
timestamp < timestamp2
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "<=")]
|
#[rhai_fn(name = "<=")]
|
||||||
pub fn lte(x: Instant, y: Instant) -> bool {
|
pub fn lte(timestamp: Instant, timestamp2: Instant) -> bool {
|
||||||
x <= y
|
timestamp <= timestamp2
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = ">")]
|
#[rhai_fn(name = ">")]
|
||||||
pub fn gt(x: Instant, y: Instant) -> bool {
|
pub fn gt(timestamp: Instant, timestamp2: Instant) -> bool {
|
||||||
x > y
|
timestamp > timestamp2
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = ">=")]
|
#[rhai_fn(name = ">=")]
|
||||||
pub fn gte(x: Instant, y: Instant) -> bool {
|
pub fn gte(timestamp: Instant, timestamp2: Instant) -> bool {
|
||||||
x >= y
|
timestamp >= timestamp2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ pub use crate::fn_native::{CallableFunction, FnCallArgs};
|
|||||||
pub use crate::stdlib::{any::TypeId, boxed::Box, format, mem, string::ToString, vec as new_vec};
|
pub use crate::stdlib::{any::TypeId, boxed::Box, format, mem, string::ToString, vec as new_vec};
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
Dynamic, Engine, EvalAltResult, FnAccess, FnNamespace, ImmutableString, Module,
|
Dynamic, Engine, EvalAltResult, FnAccess, FnNamespace, ImmutableString, Module,
|
||||||
NativeCallContext, RegisterFn, RegisterResultFn,
|
NativeCallContext, Position, RegisterFn, RegisterResultFn,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(features = "no_module"))]
|
#[cfg(not(features = "no_module"))]
|
||||||
|
@ -120,7 +120,7 @@ impl EvalAltResult {
|
|||||||
Self::ErrorVariableNotFound(_, _) => "Variable not found",
|
Self::ErrorVariableNotFound(_, _) => "Variable not found",
|
||||||
Self::ErrorModuleNotFound(_, _) => "Module not found",
|
Self::ErrorModuleNotFound(_, _) => "Module not found",
|
||||||
Self::ErrorDataRace(_, _) => "Data race detected when accessing variable",
|
Self::ErrorDataRace(_, _) => "Data race detected when accessing variable",
|
||||||
Self::ErrorAssignmentToConstant(_, _) => "Cannot assign to a constant",
|
Self::ErrorAssignmentToConstant(_, _) => "Cannot modify a constant",
|
||||||
Self::ErrorMismatchOutputType(_, _, _) => "Output type is incorrect",
|
Self::ErrorMismatchOutputType(_, _, _) => "Output type is incorrect",
|
||||||
Self::ErrorInExpr(_) => "Malformed 'in' expression",
|
Self::ErrorInExpr(_) => "Malformed 'in' expression",
|
||||||
Self::ErrorDotExpr(_, _) => "Malformed dot expression",
|
Self::ErrorDotExpr(_, _) => "Malformed dot expression",
|
||||||
@ -196,7 +196,7 @@ impl fmt::Display for EvalAltResult {
|
|||||||
Self::ErrorRuntime(d, _) if d.is::<()>() => f.write_str(desc)?,
|
Self::ErrorRuntime(d, _) if d.is::<()>() => f.write_str(desc)?,
|
||||||
Self::ErrorRuntime(d, _) => write!(f, "{}: {}", desc, d)?,
|
Self::ErrorRuntime(d, _) => write!(f, "{}: {}", desc, d)?,
|
||||||
|
|
||||||
Self::ErrorAssignmentToConstant(s, _) => write!(f, "Cannot assign to constant {}", s)?,
|
Self::ErrorAssignmentToConstant(s, _) => write!(f, "Cannot modify constant {}", s)?,
|
||||||
Self::ErrorMismatchOutputType(s, r, _) => {
|
Self::ErrorMismatchOutputType(s, r, _) => {
|
||||||
write!(f, "Output type is incorrect: {} (expecting {})", r, s)?
|
write!(f, "Output type is incorrect: {} (expecting {})", r, s)?
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ use crate::Map;
|
|||||||
///
|
///
|
||||||
/// The reference is necessary because the deserialized type may hold references
|
/// The reference is necessary because the deserialized type may hold references
|
||||||
/// (especially `&str`) to the source [`Dynamic`][crate::Dynamic].
|
/// (especially `&str`) to the source [`Dynamic`][crate::Dynamic].
|
||||||
pub struct DynamicDeserializer<'a> {
|
struct DynamicDeserializer<'a> {
|
||||||
value: &'a Dynamic,
|
value: &'a Dynamic,
|
||||||
}
|
}
|
||||||
|
|
14
src/serde/mod.rs
Normal file
14
src/serde/mod.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
//! _(SERDE)_ Serialization and deserialization support for [`serde`](https://crates.io/crates/serde).
|
||||||
|
//! Exported under the `serde` feature only.
|
||||||
|
|
||||||
|
mod de;
|
||||||
|
mod deserialize;
|
||||||
|
mod ser;
|
||||||
|
mod serialize;
|
||||||
|
mod str;
|
||||||
|
|
||||||
|
#[cfg(feature = "metadata")]
|
||||||
|
mod metadata;
|
||||||
|
|
||||||
|
pub use de::from_dynamic;
|
||||||
|
pub use ser::to_dynamic;
|
@ -14,7 +14,7 @@ use crate::Array;
|
|||||||
use crate::Map;
|
use crate::Map;
|
||||||
|
|
||||||
/// Serializer for [`Dynamic`][crate::Dynamic] which is kept as a reference.
|
/// Serializer for [`Dynamic`][crate::Dynamic] which is kept as a reference.
|
||||||
pub struct DynamicSerializer {
|
struct DynamicSerializer {
|
||||||
/// Buffer to hold a temporary key.
|
/// Buffer to hold a temporary key.
|
||||||
_key: Dynamic,
|
_key: Dynamic,
|
||||||
/// Buffer to hold a temporary value.
|
/// Buffer to hold a temporary value.
|
||||||
@ -639,7 +639,7 @@ impl SerializeStruct for DynamicSerializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(feature = "no_object", feature = "no_index")))]
|
#[cfg(not(any(feature = "no_object", feature = "no_index")))]
|
||||||
pub struct TupleVariantSerializer {
|
struct TupleVariantSerializer {
|
||||||
variant: &'static str,
|
variant: &'static str,
|
||||||
array: Array,
|
array: Array,
|
||||||
}
|
}
|
||||||
@ -664,7 +664,7 @@ impl serde::ser::SerializeTupleVariant for TupleVariantSerializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
pub struct StructVariantSerializer {
|
struct StructVariantSerializer {
|
||||||
variant: &'static str,
|
variant: &'static str,
|
||||||
map: Map,
|
map: Map,
|
||||||
}
|
}
|
@ -1,10 +0,0 @@
|
|||||||
//! Helper module defining serialization/deserialization support for [`serde`].
|
|
||||||
|
|
||||||
pub mod de;
|
|
||||||
mod deserialize;
|
|
||||||
pub mod ser;
|
|
||||||
mod serialize;
|
|
||||||
mod str;
|
|
||||||
|
|
||||||
#[cfg(feature = "metadata")]
|
|
||||||
pub mod metadata;
|
|
@ -8,7 +8,7 @@ mod inner {
|
|||||||
pin, prelude, ptr, result, slice, str, task, time, u16, u32, u64, u8, usize,
|
pin, prelude, ptr, result, slice, str, task, time, u16, u32, u64, u8, usize,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
||||||
pub use core::{i128, u128};
|
pub use core::{i128, u128};
|
||||||
|
|
||||||
#[cfg(feature = "sync")]
|
#[cfg(feature = "sync")]
|
||||||
|
Loading…
Reference in New Issue
Block a user