commit
b8366bd8a4
@ -22,6 +22,11 @@ New features
|
|||||||
|
|
||||||
* For very special needs, the ability to register fallible type iterators is added.
|
* For very special needs, the ability to register fallible type iterators is added.
|
||||||
|
|
||||||
|
Enhancements
|
||||||
|
------------
|
||||||
|
|
||||||
|
* `is_empty` method is added to arrays, BLOB's, object maps, strings and ranges.
|
||||||
|
|
||||||
|
|
||||||
Version 1.9.0
|
Version 1.9.0
|
||||||
=============
|
=============
|
||||||
|
@ -18,7 +18,7 @@ keywords = ["scripting", "scripting-engine", "scripting-language", "embedded"]
|
|||||||
categories = ["no-std", "embedded", "wasm", "parser-implementations"]
|
categories = ["no-std", "embedded", "wasm", "parser-implementations"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
smallvec = { version = "1.7", default-features = false, features = ["union", "const_new" ] }
|
smallvec = { version = "1.7", default-features = false, features = ["union", "const_new", "const_generics"] }
|
||||||
ahash = { version = "0.8", default-features = false }
|
ahash = { version = "0.8", default-features = false }
|
||||||
num-traits = { version = "0.2", default-features = false }
|
num-traits = { version = "0.2", default-features = false }
|
||||||
bitflags = { version = "1", default-features = false }
|
bitflags = { version = "1", default-features = false }
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
error[E0277]: the trait bound `NonClonable: Clone` is not satisfied
|
error[E0277]: the trait bound `NonClonable: Clone` is not satisfied
|
||||||
--> ui_tests/non_clonable.rs:11:23
|
--> ui_tests/non_clonable.rs:11:23
|
||||||
|
|
|
|
||||||
10 | #[export_fn]
|
|
||||||
| ------------ in this procedural macro expansion
|
|
||||||
11 | pub fn test_fn(input: NonClonable) -> bool {
|
11 | pub fn test_fn(input: NonClonable) -> bool {
|
||||||
| ^^^^^^^^^^^ the trait `Clone` is not implemented for `NonClonable`
|
| ^^^^^^^^^^^ the trait `Clone` is not implemented for `NonClonable`
|
||||||
|
|
|
|
||||||
@ -11,7 +9,6 @@ note: required by a bound in `rhai::Dynamic::cast`
|
|||||||
|
|
|
|
||||||
| pub fn cast<T: Any + Clone>(self) -> T {
|
| pub fn cast<T: Any + Clone>(self) -> T {
|
||||||
| ^^^^^ required by this bound in `rhai::Dynamic::cast`
|
| ^^^^^ required by this bound in `rhai::Dynamic::cast`
|
||||||
= note: this error originates in the attribute macro `export_fn` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
help: consider annotating `NonClonable` with `#[derive(Clone)]`
|
help: consider annotating `NonClonable` with `#[derive(Clone)]`
|
||||||
|
|
|
|
||||||
3 | #[derive(Clone)]
|
3 | #[derive(Clone)]
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
error[E0277]: the trait bound `NonClonable: Clone` is not satisfied
|
error[E0277]: the trait bound `NonClonable: Clone` is not satisfied
|
||||||
--> ui_tests/non_clonable_second.rs:11:27
|
--> ui_tests/non_clonable_second.rs:11:27
|
||||||
|
|
|
|
||||||
10 | #[export_fn]
|
|
||||||
| ------------ in this procedural macro expansion
|
|
||||||
11 | pub fn test_fn(a: u32, b: NonClonable) -> bool {
|
11 | pub fn test_fn(a: u32, b: NonClonable) -> bool {
|
||||||
| ^^^^^^^^^^^ the trait `Clone` is not implemented for `NonClonable`
|
| ^^^^^^^^^^^ the trait `Clone` is not implemented for `NonClonable`
|
||||||
|
|
|
|
||||||
@ -11,7 +9,6 @@ note: required by a bound in `rhai::Dynamic::cast`
|
|||||||
|
|
|
|
||||||
| pub fn cast<T: Any + Clone>(self) -> T {
|
| pub fn cast<T: Any + Clone>(self) -> T {
|
||||||
| ^^^^^ required by this bound in `rhai::Dynamic::cast`
|
| ^^^^^ required by this bound in `rhai::Dynamic::cast`
|
||||||
= note: this error originates in the attribute macro `export_fn` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
help: consider annotating `NonClonable` with `#[derive(Clone)]`
|
help: consider annotating `NonClonable` with `#[derive(Clone)]`
|
||||||
|
|
|
|
||||||
3 | #[derive(Clone)]
|
3 | #[derive(Clone)]
|
||||||
|
@ -785,6 +785,12 @@ op +(u8, u8) -> u8;
|
|||||||
/// ```
|
/// ```
|
||||||
op +=(Map, Map) -> ();
|
op +=(Map, Map) -> ();
|
||||||
|
|
||||||
|
op +=(String, String) -> ();
|
||||||
|
|
||||||
|
op +=(String, char) -> ();
|
||||||
|
|
||||||
|
op +=(String, ()) -> ();
|
||||||
|
|
||||||
op +=(String, ?) -> ();
|
op +=(String, ?) -> ();
|
||||||
|
|
||||||
op +=(String, Blob) -> ();
|
op +=(String, Blob) -> ();
|
||||||
@ -2368,6 +2374,21 @@ fn get int(x: float) -> float;
|
|||||||
/// ```
|
/// ```
|
||||||
fn get is_anonymous(fn_ptr: FnPtr) -> bool;
|
fn get is_anonymous(fn_ptr: FnPtr) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the array is empty.
|
||||||
|
fn get is_empty(array: Array) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the BLOB is empty.
|
||||||
|
fn get is_empty(blob: Blob) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the range contains no items.
|
||||||
|
fn get is_empty(range: ExclusiveRange) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the range contains no items.
|
||||||
|
fn get is_empty(range: InclusiveRange) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the string is empty.
|
||||||
|
fn get is_empty(string: String) -> bool;
|
||||||
|
|
||||||
/// Return true if the number is even.
|
/// Return true if the number is even.
|
||||||
fn get is_even(x: int) -> bool;
|
fn get is_even(x: int) -> bool;
|
||||||
|
|
||||||
@ -2913,6 +2934,24 @@ fn int(x: float) -> float;
|
|||||||
/// ```
|
/// ```
|
||||||
fn is_anonymous(fn_ptr: FnPtr) -> bool;
|
fn is_anonymous(fn_ptr: FnPtr) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the array is empty.
|
||||||
|
fn is_empty(array: Array) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the BLOB is empty.
|
||||||
|
fn is_empty(blob: Blob) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the map is empty.
|
||||||
|
fn is_empty(map: Map) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the range contains no items.
|
||||||
|
fn is_empty(range: ExclusiveRange) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the range contains no items.
|
||||||
|
fn is_empty(range: InclusiveRange) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the string is empty.
|
||||||
|
fn is_empty(string: String) -> bool;
|
||||||
|
|
||||||
/// Return true if the number is even.
|
/// Return true if the number is even.
|
||||||
fn is_even(x: int) -> bool;
|
fn is_even(x: int) -> bool;
|
||||||
|
|
||||||
@ -3047,9 +3086,6 @@ fn keys(map: Map) -> Array;
|
|||||||
/// Number of elements in the array.
|
/// Number of elements in the array.
|
||||||
fn len(array: Array) -> int;
|
fn len(array: Array) -> int;
|
||||||
|
|
||||||
/// Return true if the array is empty.
|
|
||||||
fn is_empty(array: Array) -> bool;
|
|
||||||
|
|
||||||
/// Return the length of the BLOB.
|
/// Return the length of the BLOB.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -3063,15 +3099,9 @@ fn is_empty(array: Array) -> bool;
|
|||||||
/// ```
|
/// ```
|
||||||
fn len(blob: Blob) -> int;
|
fn len(blob: Blob) -> int;
|
||||||
|
|
||||||
/// Return true if the blob is empty.
|
|
||||||
fn is_empty(blob: Blob) -> bool;
|
|
||||||
|
|
||||||
/// Return the number of properties in the object map.
|
/// Return the number of properties in the object map.
|
||||||
fn len(map: Map) -> int;
|
fn len(map: Map) -> int;
|
||||||
|
|
||||||
/// Return true if the map is empty.
|
|
||||||
fn is_empty(map: Map) -> bool;
|
|
||||||
|
|
||||||
/// Return the length of the string, in number of characters.
|
/// Return the length of the string, in number of characters.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -3083,9 +3113,6 @@ fn is_empty(map: Map) -> bool;
|
|||||||
/// ```
|
/// ```
|
||||||
fn len(string: String) -> int;
|
fn len(string: String) -> int;
|
||||||
|
|
||||||
/// Return true if the string is empty.
|
|
||||||
fn is_empty(string: String) -> bool;
|
|
||||||
|
|
||||||
/// Return the natural log of the decimal number.
|
/// Return the natural log of the decimal number.
|
||||||
fn ln(x: Decimal) -> Decimal;
|
fn ln(x: Decimal) -> Decimal;
|
||||||
|
|
||||||
@ -5738,6 +5765,16 @@ fn tan(x: float) -> float;
|
|||||||
fn tanh(x: float) -> float;
|
fn tanh(x: float) -> float;
|
||||||
|
|
||||||
/// Create a timestamp containing the current system time.
|
/// Create a timestamp containing the current system time.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rhai
|
||||||
|
/// let now = timestamp();
|
||||||
|
///
|
||||||
|
/// sleep(10.0); // sleep for 10 seconds
|
||||||
|
///
|
||||||
|
/// print(now.elapsed); // prints 10.???
|
||||||
|
/// ```
|
||||||
fn timestamp() -> Instant;
|
fn timestamp() -> Instant;
|
||||||
|
|
||||||
/// Convert the BLOB into an array of integers.
|
/// Convert the BLOB into an array of integers.
|
||||||
|
@ -267,6 +267,12 @@ op +(u8, u8) -> u8;
|
|||||||
/// ```
|
/// ```
|
||||||
op +=(Map, Map) -> ();
|
op +=(Map, Map) -> ();
|
||||||
|
|
||||||
|
op +=(String, String) -> ();
|
||||||
|
|
||||||
|
op +=(String, char) -> ();
|
||||||
|
|
||||||
|
op +=(String, ()) -> ();
|
||||||
|
|
||||||
op +=(String, ?) -> ();
|
op +=(String, ?) -> ();
|
||||||
|
|
||||||
op +=(String, Blob) -> ();
|
op +=(String, Blob) -> ();
|
||||||
@ -1850,6 +1856,21 @@ fn get int(x: float) -> float;
|
|||||||
/// ```
|
/// ```
|
||||||
fn get is_anonymous(fn_ptr: FnPtr) -> bool;
|
fn get is_anonymous(fn_ptr: FnPtr) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the array is empty.
|
||||||
|
fn get is_empty(array: Array) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the BLOB is empty.
|
||||||
|
fn get is_empty(blob: Blob) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the range contains no items.
|
||||||
|
fn get is_empty(range: ExclusiveRange) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the range contains no items.
|
||||||
|
fn get is_empty(range: InclusiveRange) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the string is empty.
|
||||||
|
fn get is_empty(string: String) -> bool;
|
||||||
|
|
||||||
/// Return true if the number is even.
|
/// Return true if the number is even.
|
||||||
fn get is_even(x: int) -> bool;
|
fn get is_even(x: int) -> bool;
|
||||||
|
|
||||||
@ -1973,9 +1994,6 @@ fn get is_zero(x: u8) -> bool;
|
|||||||
/// Number of elements in the array.
|
/// Number of elements in the array.
|
||||||
fn get len(array: Array) -> int;
|
fn get len(array: Array) -> int;
|
||||||
|
|
||||||
/// Return true if the array is empty.
|
|
||||||
fn get empty(array: Array) -> bool;
|
|
||||||
|
|
||||||
/// Return the length of the BLOB.
|
/// Return the length of the BLOB.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -2398,6 +2416,24 @@ fn int(x: float) -> float;
|
|||||||
/// ```
|
/// ```
|
||||||
fn is_anonymous(fn_ptr: FnPtr) -> bool;
|
fn is_anonymous(fn_ptr: FnPtr) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the array is empty.
|
||||||
|
fn is_empty(array: Array) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the BLOB is empty.
|
||||||
|
fn is_empty(blob: Blob) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the map is empty.
|
||||||
|
fn is_empty(map: Map) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the range contains no items.
|
||||||
|
fn is_empty(range: ExclusiveRange) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the range contains no items.
|
||||||
|
fn is_empty(range: InclusiveRange) -> bool;
|
||||||
|
|
||||||
|
/// Return true if the string is empty.
|
||||||
|
fn is_empty(string: String) -> bool;
|
||||||
|
|
||||||
/// Return true if the number is even.
|
/// Return true if the number is even.
|
||||||
fn is_even(x: int) -> bool;
|
fn is_even(x: int) -> bool;
|
||||||
|
|
||||||
@ -2532,9 +2568,6 @@ fn keys(map: Map) -> Array;
|
|||||||
/// Number of elements in the array.
|
/// Number of elements in the array.
|
||||||
fn len(array: Array) -> int;
|
fn len(array: Array) -> int;
|
||||||
|
|
||||||
/// Return true if the array is empty.
|
|
||||||
fn is_empty(array: Array) -> bool;
|
|
||||||
|
|
||||||
/// Return the length of the BLOB.
|
/// Return the length of the BLOB.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -2548,15 +2581,9 @@ fn is_empty(array: Array) -> bool;
|
|||||||
/// ```
|
/// ```
|
||||||
fn len(blob: Blob) -> int;
|
fn len(blob: Blob) -> int;
|
||||||
|
|
||||||
/// Return true if the blob is empty.
|
|
||||||
fn is_empty(blob: Blob) -> bool;
|
|
||||||
|
|
||||||
/// Return the number of properties in the object map.
|
/// Return the number of properties in the object map.
|
||||||
fn len(map: Map) -> int;
|
fn len(map: Map) -> int;
|
||||||
|
|
||||||
/// Return true if the map is empty.
|
|
||||||
fn is_empty(map: Map) -> bool;
|
|
||||||
|
|
||||||
/// Return the length of the string, in number of characters.
|
/// Return the length of the string, in number of characters.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
@ -2568,9 +2595,6 @@ fn is_empty(map: Map) -> bool;
|
|||||||
/// ```
|
/// ```
|
||||||
fn len(string: String) -> int;
|
fn len(string: String) -> int;
|
||||||
|
|
||||||
/// Return true if the string is empty.
|
|
||||||
fn is_empty(string: String) -> bool;
|
|
||||||
|
|
||||||
/// Return the natural log of the decimal number.
|
/// Return the natural log of the decimal number.
|
||||||
fn ln(x: Decimal) -> Decimal;
|
fn ln(x: Decimal) -> Decimal;
|
||||||
|
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
"general_kenobi": {
|
"general_kenobi": {
|
||||||
"functions": [
|
"functions": [
|
||||||
{
|
{
|
||||||
"baseHash": 2647973605745432570,
|
"baseHash": 14798413363692662073,
|
||||||
"fullHash": 14052888716942083368,
|
"fullHash": 2039416761244929762,
|
||||||
"namespace": "internal",
|
"namespace": "internal",
|
||||||
"access": "public",
|
"access": "public",
|
||||||
"name": "hello_there",
|
"name": "hello_there",
|
||||||
@ -27,8 +27,8 @@
|
|||||||
},
|
},
|
||||||
"functions": [
|
"functions": [
|
||||||
{
|
{
|
||||||
"baseHash": 6399059862174416123,
|
"baseHash": 17487674894006547092,
|
||||||
"fullHash": 15886705420394126404,
|
"fullHash": 13058993152904417424,
|
||||||
"namespace": "global",
|
"namespace": "global",
|
||||||
"access": "public",
|
"access": "public",
|
||||||
"name": "minus",
|
"name": "minus",
|
||||||
|
@ -128,11 +128,11 @@ impl<'a, T: Variant + Clone> TypeBuilder<'a, T> {
|
|||||||
|
|
||||||
/// Register a custom function.
|
/// Register a custom function.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn with_fn<N, A, F, R, S>(&mut self, name: N, method: F) -> &mut Self
|
pub fn with_fn<A, R, S>(
|
||||||
where
|
&mut self,
|
||||||
N: AsRef<str> + Into<Identifier>,
|
name: impl AsRef<str> + Into<Identifier>,
|
||||||
F: RegisterNativeFunction<A, R, S>,
|
method: impl RegisterNativeFunction<A, R, S>,
|
||||||
{
|
) -> &mut Self {
|
||||||
self.engine.register_fn(name, method);
|
self.engine.register_fn(name, method);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -143,11 +143,11 @@ impl Engine {
|
|||||||
/// This method will be removed in the next major version.
|
/// This method will be removed in the next major version.
|
||||||
#[deprecated(since = "1.9.1", note = "use `register_fn` instead")]
|
#[deprecated(since = "1.9.1", note = "use `register_fn` instead")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn register_result_fn<N, A, F, R, S>(&mut self, name: N, func: F) -> &mut Self
|
pub fn register_result_fn<A, R, S>(
|
||||||
where
|
&mut self,
|
||||||
N: AsRef<str> + Into<Identifier>,
|
name: impl AsRef<str> + Into<Identifier>,
|
||||||
F: RegisterNativeFunction<A, R, RhaiResultOf<S>>,
|
func: impl RegisterNativeFunction<A, R, RhaiResultOf<S>>,
|
||||||
{
|
) -> &mut Self {
|
||||||
self.register_fn(name, func)
|
self.register_fn(name, func)
|
||||||
}
|
}
|
||||||
/// Register a getter function for a member of a registered type with the [`Engine`].
|
/// Register a getter function for a member of a registered type with the [`Engine`].
|
||||||
|
@ -53,11 +53,11 @@ impl Engine {
|
|||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn register_fn<N, A, F, R, S>(&mut self, name: N, func: F) -> &mut Self
|
pub fn register_fn<A, R, S, F: RegisterNativeFunction<A, R, S>>(
|
||||||
where
|
&mut self,
|
||||||
N: AsRef<str> + Into<Identifier>,
|
name: impl AsRef<str> + Into<Identifier>,
|
||||||
F: RegisterNativeFunction<A, R, S>,
|
func: F,
|
||||||
{
|
) -> &mut Self {
|
||||||
let param_types = F::param_types();
|
let param_types = F::param_types();
|
||||||
|
|
||||||
#[cfg(feature = "metadata")]
|
#[cfg(feature = "metadata")]
|
||||||
@ -109,16 +109,12 @@ impl Engine {
|
|||||||
///
|
///
|
||||||
/// To access the first mutable parameter, use `args.get_mut(0).unwrap()`
|
/// To access the first mutable parameter, use `args.get_mut(0).unwrap()`
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn register_raw_fn<N, T>(
|
pub fn register_raw_fn<T: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: N,
|
name: impl AsRef<str> + Into<Identifier>,
|
||||||
arg_types: impl AsRef<[TypeId]>,
|
arg_types: impl AsRef<[TypeId]>,
|
||||||
func: impl Fn(NativeCallContext, &mut FnCallArgs) -> RhaiResultOf<T> + SendSync + 'static,
|
func: impl Fn(NativeCallContext, &mut FnCallArgs) -> RhaiResultOf<T> + SendSync + 'static,
|
||||||
) -> &mut Self
|
) -> &mut Self {
|
||||||
where
|
|
||||||
N: AsRef<str> + Into<Identifier>,
|
|
||||||
T: Variant + Clone,
|
|
||||||
{
|
|
||||||
self.global_namespace_mut().set_raw_fn(
|
self.global_namespace_mut().set_raw_fn(
|
||||||
name,
|
name,
|
||||||
FnNamespace::Global,
|
FnNamespace::Global,
|
||||||
|
@ -36,7 +36,7 @@ pub struct ScriptFnDef {
|
|||||||
/// Encapsulated AST environment, if any.
|
/// Encapsulated AST environment, if any.
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
pub environ: Option<EncapsulatedEnviron>,
|
pub environ: Option<crate::Shared<EncapsulatedEnviron>>,
|
||||||
/// Function name.
|
/// Function name.
|
||||||
pub name: ImmutableString,
|
pub name: ImmutableString,
|
||||||
/// Function access mode.
|
/// Function access mode.
|
||||||
|
@ -11,20 +11,23 @@ use crate::{reify, Dynamic, NativeCallContext, RhaiResultOf};
|
|||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
use std::{any::TypeId, mem};
|
use std::{any::TypeId, mem};
|
||||||
|
|
||||||
// These types are used to build a unique _marker_ tuple type for each combination
|
/// These types are used to build a unique _marker_ tuple type for each combination
|
||||||
// of function parameter types in order to make each trait implementation unique.
|
/// of function parameter types in order to make each trait implementation unique.
|
||||||
// That is because stable Rust currently does not allow distinguishing implementations
|
///
|
||||||
// based purely on parameter types of traits (`Fn`, `FnOnce` and `FnMut`).
|
/// That is because stable Rust currently does not allow distinguishing implementations
|
||||||
//
|
/// based purely on parameter types of traits (`Fn`, `FnOnce` and `FnMut`).
|
||||||
// For example:
|
///
|
||||||
//
|
/// # Examples
|
||||||
// `NativeFunction<(Mut<A>, B, Ref<C>), R>`
|
///
|
||||||
//
|
/// `RegisterNativeFunction<(Mut<A>, B, Ref<C>), R, ()>` = `Fn(&mut A, B, &C) -> R`
|
||||||
// will have the function prototype constraint to:
|
///
|
||||||
//
|
/// `RegisterNativeFunction<(Mut<A>, B, Ref<C>), R, NativeCallContext>` = `Fn(NativeCallContext, &mut A, B, &C) -> R`
|
||||||
// `FN: (&mut A, B, &C) -> R`
|
///
|
||||||
//
|
/// `RegisterNativeFunction<(Mut<A>, B, Ref<C>), R, RhaiResultOf<()>>` = `Fn(&mut A, B, &C) -> Result<R, Box<EvalAltResult>>`
|
||||||
// These types are not actually used anywhere.
|
///
|
||||||
|
/// `RegisterNativeFunction<(Mut<A>, B, Ref<C>), R, RhaiResultOf<NativeCallContext>>` = `Fn(NativeCallContext, &mut A, B, &C) -> Result<R, Box<EvalAltResult>>`
|
||||||
|
///
|
||||||
|
/// These types are not actually used anywhere.
|
||||||
pub struct Mut<T>(T);
|
pub struct Mut<T>(T);
|
||||||
//pub struct Ref<T>(T);
|
//pub struct Ref<T>(T);
|
||||||
|
|
||||||
@ -60,6 +63,11 @@ pub fn by_value<T: Variant + Clone>(data: &mut Dynamic) -> T {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Trait to register custom Rust functions.
|
/// Trait to register custom Rust functions.
|
||||||
|
///
|
||||||
|
/// # Type Parameters
|
||||||
|
///
|
||||||
|
/// * `ARGS` - a tuple containing parameter types, with `&mut T` represented by [`Mut<T>`].
|
||||||
|
/// * `RET` - return type of the function; if the function returns `Result`, it is the unwrapped inner value type.
|
||||||
pub trait RegisterNativeFunction<ARGS, RET, RESULT> {
|
pub trait RegisterNativeFunction<ARGS, RET, RESULT> {
|
||||||
/// Convert this function into a [`CallableFunction`].
|
/// Convert this function into a [`CallableFunction`].
|
||||||
#[must_use]
|
#[must_use]
|
||||||
|
@ -111,12 +111,13 @@ impl Engine {
|
|||||||
let mut lib_merged = crate::StaticVec::with_capacity(lib.len() + 1);
|
let mut lib_merged = crate::StaticVec::with_capacity(lib.len() + 1);
|
||||||
|
|
||||||
#[cfg(not(feature = "no_module"))]
|
#[cfg(not(feature = "no_module"))]
|
||||||
let (lib, constants) = if let Some(crate::ast::EncapsulatedEnviron {
|
let (lib, constants) = if let Some(ref environ) = fn_def.environ {
|
||||||
lib: ref fn_lib,
|
let crate::ast::EncapsulatedEnviron {
|
||||||
ref imports,
|
lib: fn_lib,
|
||||||
ref constants,
|
imports,
|
||||||
}) = fn_def.environ
|
constants,
|
||||||
{
|
} = environ.as_ref();
|
||||||
|
|
||||||
imports
|
imports
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.cloned()
|
||||||
|
@ -1245,18 +1245,14 @@ impl Module {
|
|||||||
/// assert!(module.contains_fn(hash));
|
/// assert!(module.contains_fn(hash));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_raw_fn<T, F>(
|
pub fn set_raw_fn<T: Variant + Clone>(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: impl AsRef<str>,
|
name: impl AsRef<str>,
|
||||||
namespace: FnNamespace,
|
namespace: FnNamespace,
|
||||||
access: FnAccess,
|
access: FnAccess,
|
||||||
arg_types: impl AsRef<[TypeId]>,
|
arg_types: impl AsRef<[TypeId]>,
|
||||||
func: F,
|
func: impl Fn(NativeCallContext, &mut FnCallArgs) -> RhaiResultOf<T> + SendSync + 'static,
|
||||||
) -> u64
|
) -> u64 {
|
||||||
where
|
|
||||||
T: Variant + Clone,
|
|
||||||
F: Fn(NativeCallContext, &mut FnCallArgs) -> RhaiResultOf<T> + SendSync + 'static,
|
|
||||||
{
|
|
||||||
let f =
|
let f =
|
||||||
move |ctx: NativeCallContext, args: &mut FnCallArgs| func(ctx, args).map(Dynamic::from);
|
move |ctx: NativeCallContext, args: &mut FnCallArgs| func(ctx, args).map(Dynamic::from);
|
||||||
|
|
||||||
@ -1293,11 +1289,14 @@ impl Module {
|
|||||||
/// assert!(module.contains_fn(hash));
|
/// assert!(module.contains_fn(hash));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_native_fn<ARGS, N, T, F, S>(&mut self, name: N, func: F) -> u64
|
pub fn set_native_fn<A, T, F, S>(
|
||||||
|
&mut self,
|
||||||
|
name: impl AsRef<str> + Into<Identifier>,
|
||||||
|
func: F,
|
||||||
|
) -> u64
|
||||||
where
|
where
|
||||||
N: AsRef<str> + Into<Identifier>,
|
|
||||||
T: Variant + Clone,
|
T: Variant + Clone,
|
||||||
F: RegisterNativeFunction<ARGS, T, RhaiResultOf<S>>,
|
F: RegisterNativeFunction<A, T, RhaiResultOf<S>>,
|
||||||
{
|
{
|
||||||
self.set_fn(
|
self.set_fn(
|
||||||
name,
|
name,
|
||||||
@ -1587,16 +1586,17 @@ impl Module {
|
|||||||
/// ```
|
/// ```
|
||||||
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn set_indexer_get_set_fn<A, B, T, S1, S2>(
|
pub fn set_indexer_get_set_fn<
|
||||||
&mut self,
|
|
||||||
get_fn: impl RegisterNativeFunction<(Mut<A>, B), T, RhaiResultOf<S1>> + SendSync + 'static,
|
|
||||||
set_fn: impl RegisterNativeFunction<(Mut<A>, B, T), (), RhaiResultOf<S2>> + SendSync + 'static,
|
|
||||||
) -> (u64, u64)
|
|
||||||
where
|
|
||||||
A: Variant + Clone,
|
A: Variant + Clone,
|
||||||
B: Variant + Clone,
|
B: Variant + Clone,
|
||||||
T: Variant + Clone,
|
T: Variant + Clone,
|
||||||
{
|
S1,
|
||||||
|
S2,
|
||||||
|
>(
|
||||||
|
&mut self,
|
||||||
|
get_fn: impl RegisterNativeFunction<(Mut<A>, B), T, RhaiResultOf<S1>> + SendSync + 'static,
|
||||||
|
set_fn: impl RegisterNativeFunction<(Mut<A>, B, T), (), RhaiResultOf<S2>> + SendSync + 'static,
|
||||||
|
) -> (u64, u64) {
|
||||||
(
|
(
|
||||||
self.set_indexer_get_fn(get_fn),
|
self.set_indexer_get_fn(get_fn),
|
||||||
self.set_indexer_set_fn(set_fn),
|
self.set_indexer_set_fn(set_fn),
|
||||||
@ -2086,6 +2086,12 @@ impl Module {
|
|||||||
// Non-private functions defined become module functions
|
// Non-private functions defined become module functions
|
||||||
#[cfg(not(feature = "no_function"))]
|
#[cfg(not(feature = "no_function"))]
|
||||||
{
|
{
|
||||||
|
let environ = Shared::new(crate::ast::EncapsulatedEnviron {
|
||||||
|
lib: ast.shared_lib().clone(),
|
||||||
|
imports: imports.into_boxed_slice(),
|
||||||
|
constants,
|
||||||
|
});
|
||||||
|
|
||||||
ast.shared_lib()
|
ast.shared_lib()
|
||||||
.iter_fn()
|
.iter_fn()
|
||||||
.filter(|&f| match f.metadata.access {
|
.filter(|&f| match f.metadata.access {
|
||||||
@ -2102,11 +2108,7 @@ impl Module {
|
|||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
// Encapsulate AST environment
|
// Encapsulate AST environment
|
||||||
func.environ = Some(crate::ast::EncapsulatedEnviron {
|
func.environ = Some(environ.clone());
|
||||||
lib: ast.shared_lib().clone(),
|
|
||||||
imports: imports.clone().into_boxed_slice(),
|
|
||||||
constants: constants.clone(),
|
|
||||||
});
|
|
||||||
|
|
||||||
module.set_script_fn(func);
|
module.set_script_fn(func);
|
||||||
});
|
});
|
||||||
|
@ -140,7 +140,7 @@ pub mod blob_functions {
|
|||||||
pub fn len(blob: &mut Blob) -> INT {
|
pub fn len(blob: &mut Blob) -> INT {
|
||||||
blob.len() as INT
|
blob.len() as INT
|
||||||
}
|
}
|
||||||
/// Return true if the blob is empty.
|
/// Return true if the BLOB is empty.
|
||||||
#[rhai_fn(name = "is_empty", get = "is_empty", pure)]
|
#[rhai_fn(name = "is_empty", get = "is_empty", pure)]
|
||||||
pub fn is_empty(blob: &mut Blob) -> bool {
|
pub fn is_empty(blob: &mut Blob) -> bool {
|
||||||
blob.len() == 0
|
blob.len() == 0
|
||||||
|
@ -666,7 +666,7 @@ mod range_functions {
|
|||||||
let _ = range;
|
let _ = range;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
/// Returns true if the range contains no items.
|
/// Return true if the range contains no items.
|
||||||
#[rhai_fn(get = "is_empty", name = "is_empty", pure)]
|
#[rhai_fn(get = "is_empty", name = "is_empty", pure)]
|
||||||
pub fn is_empty_exclusive(range: &mut ExclusiveRange) -> bool {
|
pub fn is_empty_exclusive(range: &mut ExclusiveRange) -> bool {
|
||||||
range.is_empty()
|
range.is_empty()
|
||||||
@ -693,7 +693,7 @@ mod range_functions {
|
|||||||
let _ = range;
|
let _ = range;
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
/// Returns true if the range contains no items.
|
/// Return true if the range contains no items.
|
||||||
#[rhai_fn(get = "is_empty", name = "is_empty", pure)]
|
#[rhai_fn(get = "is_empty", name = "is_empty", pure)]
|
||||||
pub fn is_empty_inclusive(range: &mut InclusiveRange) -> bool {
|
pub fn is_empty_inclusive(range: &mut InclusiveRange) -> bool {
|
||||||
range.is_empty()
|
range.is_empty()
|
||||||
|
@ -26,7 +26,7 @@ mod map_functions {
|
|||||||
map.len() as INT
|
map.len() as INT
|
||||||
}
|
}
|
||||||
/// Return true if the map is empty.
|
/// Return true if the map is empty.
|
||||||
#[rhai_fn(name = "is_empty", get = "is_empty", pure)]
|
#[rhai_fn(pure)]
|
||||||
pub fn is_empty(map: &mut Map) -> bool {
|
pub fn is_empty(map: &mut Map) -> bool {
|
||||||
map.len() == 0
|
map.len() == 0
|
||||||
}
|
}
|
||||||
|
@ -515,41 +515,31 @@ impl<'a: 'de, 'de, ITER: Iterator<Item = &'a Dynamic>> serde::de::SeqAccess<'de>
|
|||||||
|
|
||||||
/// `MapAccess` implementation for maps.
|
/// `MapAccess` implementation for maps.
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
struct IterateMap<'a, KEYS, VALUES>
|
struct IterateMap<'a, K: Iterator<Item = &'a str>, V: Iterator<Item = &'a Dynamic>> {
|
||||||
where
|
|
||||||
KEYS: Iterator<Item = &'a str>,
|
|
||||||
VALUES: Iterator<Item = &'a Dynamic>,
|
|
||||||
{
|
|
||||||
// Iterator for a stream of [`Dynamic`][crate::Dynamic] keys.
|
// Iterator for a stream of [`Dynamic`][crate::Dynamic] keys.
|
||||||
keys: KEYS,
|
keys: K,
|
||||||
// Iterator for a stream of [`Dynamic`][crate::Dynamic] values.
|
// Iterator for a stream of [`Dynamic`][crate::Dynamic] values.
|
||||||
values: VALUES,
|
values: V,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
impl<'a, KEYS, VALUES> IterateMap<'a, KEYS, VALUES>
|
impl<'a, K: Iterator<Item = &'a str>, V: Iterator<Item = &'a Dynamic>> IterateMap<'a, K, V> {
|
||||||
where
|
|
||||||
KEYS: Iterator<Item = &'a str>,
|
|
||||||
VALUES: Iterator<Item = &'a Dynamic>,
|
|
||||||
{
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(keys: KEYS, values: VALUES) -> Self {
|
pub fn new(keys: K, values: V) -> Self {
|
||||||
Self { keys, values }
|
Self { keys, values }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
impl<'a: 'de, 'de, KEYS, VALUES> serde::de::MapAccess<'de> for IterateMap<'a, KEYS, VALUES>
|
impl<'a: 'de, 'de, K: Iterator<Item = &'a str>, V: Iterator<Item = &'a Dynamic>>
|
||||||
where
|
serde::de::MapAccess<'de> for IterateMap<'a, K, V>
|
||||||
KEYS: Iterator<Item = &'a str>,
|
|
||||||
VALUES: Iterator<Item = &'a Dynamic>,
|
|
||||||
{
|
{
|
||||||
type Error = RhaiError;
|
type Error = RhaiError;
|
||||||
|
|
||||||
fn next_key_seed<K: serde::de::DeserializeSeed<'de>>(
|
fn next_key_seed<S: serde::de::DeserializeSeed<'de>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
seed: K,
|
seed: S,
|
||||||
) -> RhaiResultOf<Option<K::Value>> {
|
) -> RhaiResultOf<Option<S::Value>> {
|
||||||
// Deserialize each `Identifier` key coming out of the keys iterator.
|
// Deserialize each `Identifier` key coming out of the keys iterator.
|
||||||
match self.keys.next() {
|
match self.keys.next() {
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
@ -559,10 +549,10 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_value_seed<V: serde::de::DeserializeSeed<'de>>(
|
fn next_value_seed<S: serde::de::DeserializeSeed<'de>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
seed: V,
|
seed: S,
|
||||||
) -> RhaiResultOf<V::Value> {
|
) -> RhaiResultOf<S::Value> {
|
||||||
// Deserialize each value item coming out of the iterator.
|
// Deserialize each value item coming out of the iterator.
|
||||||
seed.deserialize(&mut DynamicDeserializer::from_dynamic(
|
seed.deserialize(&mut DynamicDeserializer::from_dynamic(
|
||||||
self.values.next().unwrap(),
|
self.values.next().unwrap(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user