rhai/src/api/register.rs

755 lines
26 KiB
Rust
Raw Normal View History

2021-11-20 14:57:21 +08:00
//! Module that defines the public function/module registration API of [`Engine`].
use crate::func::register::Mut;
2021-11-20 14:57:21 +08:00
use crate::func::{FnCallArgs, RegisterNativeFunction, SendSync};
use crate::types::dynamic::Variant;
use crate::{
2021-12-25 23:49:14 +08:00
Engine, FnAccess, FnNamespace, Identifier, Module, NativeCallContext, RhaiResultOf, Shared,
2021-11-20 14:57:21 +08:00
};
use std::any::{type_name, TypeId};
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
impl Engine {
/// Get the global namespace module (which is the fist module in `global_modules`).
2021-11-20 14:57:21 +08:00
#[inline(always)]
#[allow(dead_code)]
pub(crate) fn global_namespace(&self) -> &Module {
2022-01-06 11:07:52 +08:00
self.global_modules.first().unwrap()
2021-11-20 14:57:21 +08:00
}
/// Get a mutable reference to the global namespace module
/// (which is the first module in `global_modules`).
#[inline(always)]
pub(crate) fn global_namespace_mut(&mut self) -> &mut Module {
2022-01-06 11:07:52 +08:00
let module = self.global_modules.first_mut().unwrap();
Shared::get_mut(module).expect("not shared")
2021-11-20 14:57:21 +08:00
}
/// Register a custom function with the [`Engine`].
///
/// # Example
///
/// ```
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
/// use rhai::Engine;
///
/// // Normal function
/// fn add(x: i64, y: i64) -> i64 {
/// x + y
/// }
///
/// let mut engine = Engine::new();
///
/// engine.register_fn("add", add);
///
/// assert_eq!(engine.eval::<i64>("add(40, 2)")?, 42);
///
/// // You can also register a closure.
/// engine.register_fn("sub", |x: i64, y: i64| x - y );
///
/// assert_eq!(engine.eval::<i64>("sub(44, 2)")?, 42);
/// # Ok(())
/// # }
/// ```
#[inline]
pub fn register_fn<N, A, F, R, S>(&mut self, name: N, func: F) -> &mut Self
2021-11-20 14:57:21 +08:00
where
N: AsRef<str> + Into<Identifier>,
F: RegisterNativeFunction<A, R, S>,
2021-11-20 14:57:21 +08:00
{
let param_types = F::param_types();
#[cfg(feature = "metadata")]
let mut param_type_names: crate::StaticVec<_> = F::param_names()
.iter()
2022-01-17 21:51:04 +08:00
.map(|ty| format!("_: {}", self.format_type_name(ty)))
2021-11-20 14:57:21 +08:00
.collect();
#[cfg(feature = "metadata")]
if F::return_type() != TypeId::of::<()>() {
2022-01-17 21:51:04 +08:00
param_type_names.push(self.format_type_name(F::return_type_name()).into());
2021-11-20 14:57:21 +08:00
}
#[cfg(feature = "metadata")]
2022-01-06 11:07:52 +08:00
let param_type_names: crate::StaticVec<_> =
2022-07-27 18:04:59 +08:00
param_type_names.iter().map(String::as_str).collect();
2022-01-06 11:07:52 +08:00
#[cfg(feature = "metadata")]
let param_type_names = Some(param_type_names.as_ref());
2021-11-20 14:57:21 +08:00
#[cfg(not(feature = "metadata"))]
2022-01-06 11:07:52 +08:00
let param_type_names: Option<&[&str]> = None;
2021-11-20 14:57:21 +08:00
self.global_namespace_mut().set_fn(
name,
FnNamespace::Global,
FnAccess::Public,
2022-01-06 11:07:52 +08:00
param_type_names,
param_types,
2021-11-20 14:57:21 +08:00
func.into_callable_function(),
);
self
}
/// Register a function of the [`Engine`].
///
/// # WARNING - Low Level API
///
/// This function is very low level. It takes a list of [`TypeId`][std::any::TypeId]'s
/// indicating the actual types of the parameters.
2021-11-20 14:57:21 +08:00
///
2021-12-27 11:43:11 +08:00
/// # Arguments
2021-11-29 12:43:59 +08:00
///
/// Arguments are simply passed in as a mutable array of [`&mut Dynamic`][crate::Dynamic].
2021-11-20 14:57:21 +08:00
/// The arguments are guaranteed to be of the correct types matching the [`TypeId`][std::any::TypeId]'s.
///
/// To access a primary argument value (i.e. cloning is cheap), use: `args[n].as_xxx().unwrap()`
///
/// To access an argument value and avoid cloning, use `std::mem::take(args[n]).cast::<T>()`.
/// Notice that this will _consume_ the argument, replacing it with `()`.
///
/// To access the first mutable parameter, use `args.get_mut(0).unwrap()`
#[inline(always)]
pub fn register_raw_fn<N, T>(
&mut self,
name: N,
2022-01-04 15:22:48 +08:00
arg_types: impl AsRef<[TypeId]>,
2021-12-25 23:49:14 +08:00
func: impl Fn(NativeCallContext, &mut FnCallArgs) -> RhaiResultOf<T> + SendSync + 'static,
2021-11-20 14:57:21 +08:00
) -> &mut Self
where
N: AsRef<str> + Into<Identifier>,
T: Variant + Clone,
{
self.global_namespace_mut().set_raw_fn(
name,
FnNamespace::Global,
FnAccess::Public,
arg_types,
func,
);
self
}
/// Register a custom type for use with the [`Engine`].
/// The type must implement [`Clone`].
///
/// # Example
///
/// ```
/// #[derive(Debug, Clone, Eq, PartialEq)]
/// struct TestStruct {
/// field: i64
/// }
///
/// impl TestStruct {
2021-12-27 21:56:50 +08:00
/// fn new() -> Self {
/// Self { field: 1 }
/// }
/// fn update(&mut self, offset: i64) {
/// self.field += offset;
/// }
2021-11-20 14:57:21 +08:00
/// }
///
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
/// use rhai::Engine;
///
/// let mut engine = Engine::new();
///
/// // Register API for the custom type.
/// engine
/// .register_type::<TestStruct>()
/// .register_fn("new_ts", TestStruct::new)
/// // Use `register_fn` to register methods on the type.
/// .register_fn("update", TestStruct::update);
///
/// # #[cfg(not(feature = "no_object"))]
/// assert_eq!(
/// engine.eval::<TestStruct>("let x = new_ts(); x.update(41); x")?,
/// TestStruct { field: 42 }
/// );
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub fn register_type<T: Variant + Clone>(&mut self) -> &mut Self {
self.register_type_with_name::<T>(type_name::<T>())
}
/// Register a custom type for use with the [`Engine`], with a pretty-print name
/// for the `type_of` function. The type must implement [`Clone`].
///
/// # Example
///
/// ```
/// #[derive(Clone)]
/// struct TestStruct {
/// field: i64
/// }
///
/// impl TestStruct {
2021-12-27 21:56:50 +08:00
/// fn new() -> Self {
/// Self { field: 1 }
/// }
2021-11-20 14:57:21 +08:00
/// }
///
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
/// use rhai::Engine;
///
/// let mut engine = Engine::new();
///
/// // Register API for the custom type.
/// engine
/// .register_type::<TestStruct>()
/// .register_fn("new_ts", TestStruct::new);
///
/// assert_eq!(
/// engine.eval::<String>("let x = new_ts(); type_of(x)")?,
/// "rust_out::TestStruct"
/// );
///
/// // Re-register the custom type with a name.
/// engine.register_type_with_name::<TestStruct>("Hello");
///
/// assert_eq!(
/// engine.eval::<String>("let x = new_ts(); type_of(x)")?,
/// "Hello"
/// );
/// # Ok(())
/// # }
/// ```
#[inline(always)]
pub fn register_type_with_name<T: Variant + Clone>(&mut self, name: &str) -> &mut Self {
2022-03-29 08:18:20 +08:00
self.global_namespace_mut().set_custom_type::<T>(name);
self
}
/// Register a custom type for use with the [`Engine`], with a pretty-print name
/// for the `type_of` function. The type must implement [`Clone`].
///
/// # WARNING - Low Level API
///
/// This function is low level.
#[inline(always)]
pub fn register_type_with_name_raw(
&mut self,
2022-01-06 11:07:52 +08:00
fully_qualified_type_path: impl Into<Identifier>,
name: impl Into<Identifier>,
) -> &mut Self {
2021-11-20 14:57:21 +08:00
// Add the pretty-print type name into the map
2022-03-29 08:18:20 +08:00
self.global_namespace_mut()
.set_custom_type_raw(fully_qualified_type_path, name);
2021-11-20 14:57:21 +08:00
self
}
2022-08-22 14:02:24 +08:00
/// Register a type iterator for an iterable type with the [`Engine`].
2022-03-09 09:25:55 +08:00
/// This is an advanced API.
2021-11-20 14:57:21 +08:00
#[inline(always)]
pub fn register_iterator<T>(&mut self) -> &mut Self
where
T: Variant + Clone + IntoIterator,
<T as IntoIterator>::Item: Variant + Clone,
{
self.global_namespace_mut().set_iterable::<T>();
self
}
2022-08-22 14:02:24 +08:00
/// Register a fallible type iterator for an iterable type with the [`Engine`].
/// This is an advanced API.
#[inline(always)]
pub fn register_iterator_result<T, X>(&mut self) -> &mut Self
where
T: Variant + Clone + IntoIterator<Item = RhaiResultOf<X>>,
X: Variant + Clone,
{
self.global_namespace_mut().set_iterable_result::<T, X>();
self
}
2021-11-20 14:57:21 +08:00
/// Register a getter function for a member of a registered type with the [`Engine`].
///
/// The function signature must start with `&mut self` and not `&self`.
///
/// Not available under `no_object`.
///
/// # Example
///
/// ```
/// #[derive(Clone)]
/// struct TestStruct {
/// field: i64
/// }
///
/// impl TestStruct {
2021-12-27 21:56:50 +08:00
/// fn new() -> Self {
/// Self { field: 1 }
/// }
2021-11-20 14:57:21 +08:00
/// // Even a getter must start with `&mut self` and not `&self`.
2021-12-27 21:56:50 +08:00
/// fn get_field(&mut self) -> i64 {
/// self.field
/// }
2021-11-20 14:57:21 +08:00
/// }
///
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
/// use rhai::Engine;
///
/// let mut engine = Engine::new();
///
/// // Register API for the custom type.
/// engine
/// .register_type::<TestStruct>()
/// .register_fn("new_ts", TestStruct::new)
/// // Register a getter on a property (notice it doesn't have to be the same name).
/// .register_get("xyz", TestStruct::get_field);
///
/// assert_eq!(engine.eval::<i64>("let a = new_ts(); a.xyz")?, 1);
/// # Ok(())
/// # }
/// ```
#[cfg(not(feature = "no_object"))]
#[inline(always)]
pub fn register_get<T: Variant + Clone, V: Variant + Clone, S>(
2021-11-20 14:57:21 +08:00
&mut self,
2021-11-27 23:04:45 +08:00
name: impl AsRef<str>,
get_fn: impl RegisterNativeFunction<(Mut<T>,), V, S> + SendSync + 'static,
2021-11-20 14:57:21 +08:00
) -> &mut Self {
2022-01-04 15:22:48 +08:00
self.register_fn(crate::engine::make_getter(name.as_ref()).as_str(), get_fn)
2021-11-20 14:57:21 +08:00
}
/// Register a setter function for a member of a registered type with the [`Engine`].
///
/// Not available under `no_object`.
///
/// # Example
///
/// ```
/// #[derive(Debug, Clone, Eq, PartialEq)]
/// struct TestStruct {
/// field: i64
/// }
///
/// impl TestStruct {
2021-12-27 21:56:50 +08:00
/// fn new() -> Self {
/// Self { field: 1 }
/// }
/// fn set_field(&mut self, new_val: i64) {
/// self.field = new_val;
/// }
2021-11-20 14:57:21 +08:00
/// }
///
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
/// use rhai::Engine;
///
/// let mut engine = Engine::new();
///
/// // Register API for the custom type.
/// engine
/// .register_type::<TestStruct>()
/// .register_fn("new_ts", TestStruct::new)
/// // Register a setter on a property (notice it doesn't have to be the same name)
/// .register_set("xyz", TestStruct::set_field);
///
/// // Notice that, with a getter, there is no way to get the property value
/// assert_eq!(
/// engine.eval::<TestStruct>("let a = new_ts(); a.xyz = 42; a")?,
/// TestStruct { field: 42 }
/// );
/// # Ok(())
/// # }
/// ```
#[cfg(not(feature = "no_object"))]
#[inline(always)]
pub fn register_set<T: Variant + Clone, V: Variant + Clone, S>(
2021-11-20 14:57:21 +08:00
&mut self,
2021-11-27 23:04:45 +08:00
name: impl AsRef<str>,
set_fn: impl RegisterNativeFunction<(Mut<T>, V), (), S> + SendSync + 'static,
2021-11-20 14:57:21 +08:00
) -> &mut Self {
2022-01-04 15:22:48 +08:00
self.register_fn(crate::engine::make_setter(name.as_ref()).as_str(), set_fn)
2021-11-20 14:57:21 +08:00
}
/// Short-hand for registering both getter and setter functions
/// of a registered type with the [`Engine`].
///
/// All function signatures must start with `&mut self` and not `&self`.
///
/// Not available under `no_object`.
///
/// # Example
///
/// ```
/// #[derive(Clone)]
/// struct TestStruct {
/// field: i64
/// }
///
/// impl TestStruct {
2021-12-27 21:56:50 +08:00
/// fn new() -> Self {
/// Self { field: 1 }
/// }
2021-11-20 14:57:21 +08:00
/// // Even a getter must start with `&mut self` and not `&self`.
2021-12-27 21:56:50 +08:00
/// fn get_field(&mut self) -> i64 {
/// self.field
/// }
/// fn set_field(&mut self, new_val: i64) {
/// self.field = new_val;
/// }
2021-11-20 14:57:21 +08:00
/// }
///
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
/// use rhai::Engine;
///
/// let mut engine = Engine::new();
///
/// // Register API for the custom type.
/// engine
/// .register_type::<TestStruct>()
/// .register_fn("new_ts", TestStruct::new)
/// // Register both a getter and a setter on a property
/// // (notice it doesn't have to be the same name)
/// .register_get_set("xyz", TestStruct::get_field, TestStruct::set_field);
///
/// assert_eq!(engine.eval::<i64>("let a = new_ts(); a.xyz = 42; a.xyz")?, 42);
/// # Ok(())
/// # }
/// ```
#[cfg(not(feature = "no_object"))]
#[inline(always)]
2022-08-22 00:15:00 +08:00
pub fn register_get_set<T: Variant + Clone, V: Variant + Clone, S1, S2>(
2021-11-20 14:57:21 +08:00
&mut self,
2021-11-27 23:04:45 +08:00
name: impl AsRef<str>,
2022-08-22 00:15:00 +08:00
get_fn: impl RegisterNativeFunction<(Mut<T>,), V, S1> + SendSync + 'static,
set_fn: impl RegisterNativeFunction<(Mut<T>, V), (), S2> + SendSync + 'static,
2021-11-20 14:57:21 +08:00
) -> &mut Self {
2021-11-27 23:04:45 +08:00
self.register_get(&name, get_fn).register_set(&name, set_fn)
2021-11-20 14:57:21 +08:00
}
/// Register an index getter for a custom type with the [`Engine`].
///
/// The function signature must start with `&mut self` and not `&self`.
///
/// Not available under both `no_index` and `no_object`.
///
/// # Panics
///
2021-12-06 20:52:47 +08:00
/// Panics if the type is [`Array`][crate::Array], [`Map`][crate::Map], [`String`],
2021-11-20 14:57:21 +08:00
/// [`ImmutableString`][crate::ImmutableString], `&str` or [`INT`][crate::INT].
/// Indexers for arrays, object maps, strings and integers cannot be registered.
///
/// # Example
///
/// ```
/// #[derive(Clone)]
/// struct TestStruct {
/// fields: Vec<i64>
/// }
///
/// impl TestStruct {
2021-12-27 21:56:50 +08:00
/// fn new() -> Self {
/// Self { fields: vec![1, 2, 3, 4, 5] }
/// }
2021-11-20 14:57:21 +08:00
/// // Even a getter must start with `&mut self` and not `&self`.
2021-12-27 21:56:50 +08:00
/// fn get_field(&mut self, index: i64) -> i64 {
/// self.fields[index as usize]
/// }
2021-11-20 14:57:21 +08:00
/// }
///
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
/// use rhai::Engine;
///
/// let mut engine = Engine::new();
///
/// // Register API for the custom type.
/// # #[cfg(not(feature = "no_object"))]
/// engine.register_type::<TestStruct>();
///
/// engine
/// .register_fn("new_ts", TestStruct::new)
/// // Register an indexer.
/// .register_indexer_get(TestStruct::get_field);
///
/// # #[cfg(not(feature = "no_index"))]
/// assert_eq!(engine.eval::<i64>("let a = new_ts(); a[2]")?, 3);
/// # Ok(())
/// # }
/// ```
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
#[inline]
pub fn register_indexer_get<T: Variant + Clone, X: Variant + Clone, V: Variant + Clone, S>(
2021-11-20 14:57:21 +08:00
&mut self,
get_fn: impl RegisterNativeFunction<(Mut<T>, X), V, S> + SendSync + 'static,
2021-11-20 14:57:21 +08:00
) -> &mut Self {
#[cfg(not(feature = "no_index"))]
2021-12-06 20:52:47 +08:00
if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
2021-11-20 14:57:21 +08:00
panic!("Cannot register indexer for arrays.");
}
#[cfg(not(feature = "no_object"))]
2021-12-06 20:52:47 +08:00
if TypeId::of::<T>() == TypeId::of::<crate::Map>() {
2021-11-20 14:57:21 +08:00
panic!("Cannot register indexer for object maps.");
}
if TypeId::of::<T>() == TypeId::of::<String>()
|| TypeId::of::<T>() == TypeId::of::<&str>()
|| TypeId::of::<T>() == TypeId::of::<crate::ImmutableString>()
{
panic!("Cannot register indexer for strings.");
}
if TypeId::of::<T>() == TypeId::of::<crate::INT>() {
panic!("Cannot register indexer for integers.");
}
self.register_fn(crate::engine::FN_IDX_GET, get_fn)
}
/// Register an index setter for a custom type with the [`Engine`].
///
/// Not available under both `no_index` and `no_object`.
///
/// # Panics
///
2021-12-06 20:52:47 +08:00
/// Panics if the type is [`Array`][crate::Array], [`Map`][crate::Map], [`String`],
2021-11-20 14:57:21 +08:00
/// [`ImmutableString`][crate::ImmutableString], `&str` or [`INT`][crate::INT].
/// Indexers for arrays, object maps, strings and integers cannot be registered.
///
/// # Example
///
/// ```
/// #[derive(Clone)]
/// struct TestStruct {
/// fields: Vec<i64>
/// }
///
/// impl TestStruct {
2021-12-27 21:56:50 +08:00
/// fn new() -> Self {
/// Self { fields: vec![1, 2, 3, 4, 5] }
/// }
/// fn set_field(&mut self, index: i64, value: i64) {
/// self.fields[index as usize] = value;
/// }
2021-11-20 14:57:21 +08:00
/// }
///
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
/// use rhai::Engine;
///
/// let mut engine = Engine::new();
///
/// // Register API for the custom type.
/// # #[cfg(not(feature = "no_object"))]
/// engine.register_type::<TestStruct>();
///
/// engine
/// .register_fn("new_ts", TestStruct::new)
/// // Register an indexer.
/// .register_indexer_set(TestStruct::set_field);
///
/// # #[cfg(not(feature = "no_index"))]
2021-12-27 21:56:50 +08:00
/// let result = engine.eval::<TestStruct>("let a = new_ts(); a[2] = 42; a")?;
///
/// # #[cfg(not(feature = "no_index"))]
/// assert_eq!(result.fields[2], 42);
2021-11-20 14:57:21 +08:00
/// # Ok(())
/// # }
/// ```
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
#[inline]
pub fn register_indexer_set<T: Variant + Clone, X: Variant + Clone, V: Variant + Clone, S>(
2021-11-20 14:57:21 +08:00
&mut self,
set_fn: impl RegisterNativeFunction<(Mut<T>, X, V), (), S> + SendSync + 'static,
2021-11-20 14:57:21 +08:00
) -> &mut Self {
#[cfg(not(feature = "no_index"))]
2021-12-06 20:52:47 +08:00
if TypeId::of::<T>() == TypeId::of::<crate::Array>() {
2021-11-20 14:57:21 +08:00
panic!("Cannot register indexer for arrays.");
}
#[cfg(not(feature = "no_object"))]
2021-12-06 20:52:47 +08:00
if TypeId::of::<T>() == TypeId::of::<crate::Map>() {
2021-11-20 14:57:21 +08:00
panic!("Cannot register indexer for object maps.");
}
if TypeId::of::<T>() == TypeId::of::<String>()
|| TypeId::of::<T>() == TypeId::of::<&str>()
|| TypeId::of::<T>() == TypeId::of::<crate::ImmutableString>()
{
panic!("Cannot register indexer for strings.");
}
if TypeId::of::<T>() == TypeId::of::<crate::INT>() {
panic!("Cannot register indexer for integers.");
}
self.register_fn(crate::engine::FN_IDX_SET, set_fn)
}
/// Short-hand for registering both index getter and setter functions for a custom type with the [`Engine`].
///
/// Not available under both `no_index` and `no_object`.
///
/// # Panics
///
2021-12-06 20:52:47 +08:00
/// Panics if the type is [`Array`][crate::Array], [`Map`][crate::Map], [`String`],
2021-11-20 14:57:21 +08:00
/// [`ImmutableString`][crate::ImmutableString], `&str` or [`INT`][crate::INT].
/// Indexers for arrays, object maps, strings and integers cannot be registered.
///
/// # Example
///
/// ```
/// #[derive(Clone)]
/// struct TestStruct {
/// fields: Vec<i64>
/// }
///
/// impl TestStruct {
2021-12-27 21:56:50 +08:00
/// fn new() -> Self {
/// Self { fields: vec![1, 2, 3, 4, 5] }
/// }
2021-11-20 14:57:21 +08:00
/// // Even a getter must start with `&mut self` and not `&self`.
2021-12-27 21:56:50 +08:00
/// fn get_field(&mut self, index: i64) -> i64 {
/// self.fields[index as usize]
/// }
/// fn set_field(&mut self, index: i64, value: i64) {
/// self.fields[index as usize] = value;
/// }
2021-11-20 14:57:21 +08:00
/// }
///
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
/// use rhai::Engine;
///
/// let mut engine = Engine::new();
///
/// // Register API for the custom type.
/// # #[cfg(not(feature = "no_object"))]
/// engine.register_type::<TestStruct>();
///
/// engine
/// .register_fn("new_ts", TestStruct::new)
/// // Register an indexer.
/// .register_indexer_get_set(TestStruct::get_field, TestStruct::set_field);
///
/// # #[cfg(not(feature = "no_index"))]
/// assert_eq!(engine.eval::<i64>("let a = new_ts(); a[2] = 42; a[2]")?, 42);
/// # Ok(())
/// # }
/// ```
#[cfg(any(not(feature = "no_index"), not(feature = "no_object")))]
#[inline(always)]
pub fn register_indexer_get_set<
T: Variant + Clone,
X: Variant + Clone,
V: Variant + Clone,
2022-08-22 00:15:00 +08:00
S1,
S2,
>(
2021-11-20 14:57:21 +08:00
&mut self,
2022-08-22 00:15:00 +08:00
get_fn: impl RegisterNativeFunction<(Mut<T>, X), V, S1> + SendSync + 'static,
set_fn: impl RegisterNativeFunction<(Mut<T>, X, V), (), S2> + SendSync + 'static,
2021-11-20 14:57:21 +08:00
) -> &mut Self {
self.register_indexer_get(get_fn)
.register_indexer_set(set_fn)
}
/// Register a shared [`Module`] into the global namespace of [`Engine`].
///
/// All functions and type iterators are automatically available to scripts without namespace
/// qualifications.
///
/// Sub-modules and variables are **ignored**.
///
/// When searching for functions, modules loaded later are preferred. In other words, loaded
/// modules are searched in reverse order.
#[inline(always)]
pub fn register_global_module(&mut self, module: Shared<Module>) -> &mut Self {
// Insert the module into the front.
// The first module is always the global namespace.
self.global_modules.insert(1, module);
self
}
/// Register a shared [`Module`] as a static module namespace with the [`Engine`].
///
/// Functions marked [`FnNamespace::Global`] and type iterators are exposed to scripts without
/// namespace qualifications.
///
/// Not available under `no_module`.
///
/// # Example
///
/// ```
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
/// use rhai::{Engine, Shared, Module};
///
/// let mut engine = Engine::new();
///
/// // Create the module
/// let mut module = Module::new();
/// module.set_native_fn("calc", |x: i64| Ok(x + 1));
///
/// let module: Shared<Module> = module.into();
///
/// engine
/// // Register the module as a fixed sub-module
/// .register_static_module("foo::bar::baz", module.clone())
/// // Multiple registrations to the same partial path is also OK!
/// .register_static_module("foo::bar::hello", module.clone())
/// .register_static_module("CalcService", module);
///
/// assert_eq!(engine.eval::<i64>("foo::bar::baz::calc(41)")?, 42);
/// assert_eq!(engine.eval::<i64>("foo::bar::hello::calc(41)")?, 42);
/// assert_eq!(engine.eval::<i64>("CalcService::calc(41)")?, 42);
/// # Ok(())
/// # }
/// ```
#[cfg(not(feature = "no_module"))]
pub fn register_static_module(
&mut self,
2022-01-04 15:22:48 +08:00
name: impl AsRef<str>,
2021-11-20 14:57:21 +08:00
module: Shared<Module>,
) -> &mut Self {
fn register_static_module_raw(
root: &mut std::collections::BTreeMap<Identifier, Shared<Module>>,
2022-01-04 15:22:48 +08:00
name: &str,
2021-11-20 14:57:21 +08:00
module: Shared<Module>,
) {
let separator = crate::tokenizer::Token::DoubleColon.syntax();
2022-07-05 16:26:38 +08:00
let separator = separator.as_ref();
2021-11-20 14:57:21 +08:00
2022-07-27 18:04:59 +08:00
if name.contains(separator) {
2022-07-05 16:26:38 +08:00
let mut iter = name.splitn(2, separator);
2021-11-20 14:57:21 +08:00
let sub_module = iter.next().expect("contains separator").trim();
let remainder = iter.next().expect("contains separator").trim();
2022-03-03 13:02:57 +08:00
if root.is_empty() || !root.contains_key(sub_module) {
2021-11-20 14:57:21 +08:00
let mut m = Module::new();
register_static_module_raw(m.sub_modules_mut(), remainder, module);
m.build_index();
root.insert(sub_module.into(), m.into());
} else {
let m = root.remove(sub_module).expect("contains sub-module");
2022-06-26 14:10:09 +08:00
let mut m = crate::func::shared_take_or_clone(m);
2021-11-20 14:57:21 +08:00
register_static_module_raw(m.sub_modules_mut(), remainder, module);
m.build_index();
root.insert(sub_module.into(), m.into());
}
2022-07-27 18:04:59 +08:00
} else if module.is_indexed() {
root.insert(name.into(), module);
} else {
// Index the module (making a clone copy if necessary) if it is not indexed
let mut module = crate::func::shared_take_or_clone(module);
module.build_index();
root.insert(name.into(), module.into());
2021-11-20 14:57:21 +08:00
}
}
2022-01-04 15:22:48 +08:00
register_static_module_raw(&mut self.global_sub_modules, name.as_ref(), module);
2021-11-20 14:57:21 +08:00
self
}
/// _(metadata)_ Generate a list of all registered functions.
/// Exported under the `metadata` feature only.
///
/// Functions from the following sources are included, in order:
/// 1) Functions registered into the global namespace
/// 2) Functions in registered sub-modules
/// 3) Functions in registered packages
/// 4) Functions in standard packages (optional)
2021-11-20 14:57:21 +08:00
#[cfg(feature = "metadata")]
#[inline]
#[must_use]
pub fn gen_fn_signatures(&self, include_packages: bool) -> Vec<String> {
let mut signatures = Vec::with_capacity(64);
signatures.extend(self.global_namespace().gen_fn_signatures());
2022-01-29 11:09:43 +08:00
#[cfg(not(feature = "no_module"))]
2022-01-28 18:59:18 +08:00
for (name, m) in &self.global_sub_modules {
2022-08-11 19:01:23 +08:00
signatures.extend(m.gen_fn_signatures().map(|f| format!("{name}::{f}")));
2022-01-28 18:59:18 +08:00
}
2021-11-20 14:57:21 +08:00
signatures.extend(
self.global_modules
.iter()
.skip(1)
.filter(|m| !m.internal && (include_packages || !m.standard))
.flat_map(|m| m.gen_fn_signatures()),
);
2021-11-20 14:57:21 +08:00
signatures
}
}