rhai/src/module/mod.rs

1702 lines
55 KiB
Rust
Raw Normal View History

//! Module defining external-loaded modules for Rhai.
2020-12-22 09:45:56 +01:00
use crate::ast::{FnAccess, Ident};
2020-11-16 16:10:14 +01:00
use crate::dynamic::Variant;
2020-11-21 15:18:32 +01:00
use crate::fn_native::{shared_take_or_clone, CallableFunction, FnCallArgs, IteratorFn, SendSync};
2021-03-15 05:39:06 +01:00
use crate::fn_register::RegisterNativeFunction;
2020-05-05 17:57:25 +02:00
use crate::stdlib::{
any::TypeId,
boxed::Box,
2021-03-24 06:17:52 +01:00
collections::BTreeMap,
2020-06-26 17:24:47 +02:00
fmt, format,
2020-11-27 16:37:59 +01:00
iter::empty,
num::NonZeroUsize,
ops::{Add, AddAssign, Deref, DerefMut},
string::String,
vec::Vec,
2020-05-05 17:57:25 +02:00
};
2020-11-16 16:10:14 +01:00
use crate::token::Token;
2021-03-24 06:17:52 +01:00
use crate::utils::StringInterner;
2020-11-16 16:10:14 +01:00
use crate::{
2021-03-08 08:30:32 +01:00
calc_fn_hash, calc_fn_params_hash, combine_hashes, Dynamic, EvalAltResult, ImmutableString,
NativeCallContext, Position, Shared, StaticVec,
2020-11-16 16:10:14 +01:00
};
#[cfg(not(feature = "no_index"))]
use crate::Array;
#[cfg(not(feature = "no_index"))]
#[cfg(not(feature = "no_object"))]
use crate::Map;
2020-05-05 17:57:25 +02:00
2020-11-17 05:23:53 +01:00
/// A type representing the namespace of a function.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum FnNamespace {
2020-12-26 06:05:57 +01:00
/// Expose to global namespace.
2020-11-17 05:23:53 +01:00
Global,
2020-12-26 06:05:57 +01:00
/// Module namespace only.
2020-11-17 05:23:53 +01:00
Internal,
}
impl Default for FnNamespace {
#[inline(always)]
fn default() -> Self {
Self::Internal
}
}
2020-11-04 07:37:46 +01:00
/// Data structure containing a single registered function.
#[derive(Debug, Clone)]
pub struct FuncInfo {
/// Function instance.
pub func: CallableFunction,
2020-11-17 05:23:53 +01:00
/// Function namespace.
pub namespace: FnNamespace,
2020-11-04 07:37:46 +01:00
/// Function access mode.
pub access: FnAccess,
/// Function name.
2021-03-24 02:56:25 +01:00
pub name: ImmutableString,
2020-11-04 07:37:46 +01:00
/// Number of parameters.
pub params: usize,
/// Parameter types (if applicable).
2020-12-23 16:29:19 +01:00
pub param_types: StaticVec<TypeId>,
2020-11-22 10:21:34 +01:00
/// Parameter names (if available).
#[cfg(feature = "metadata")]
2020-12-23 16:29:19 +01:00
pub param_names: StaticVec<ImmutableString>,
2020-11-22 10:21:34 +01:00
}
impl FuncInfo {
/// Generate a signature of the function.
/// Available under the `metadata` feature only.
#[cfg(feature = "metadata")]
2020-11-22 10:21:34 +01:00
pub fn gen_signature(&self) -> String {
let mut sig = format!("{}(", self.name);
2020-12-23 16:29:19 +01:00
if !self.param_names.is_empty() {
let mut params: crate::stdlib::vec::Vec<String> =
self.param_names.iter().map(|s| s.as_str().into()).collect();
let return_type = params.pop().unwrap_or_else(|| "()".into());
2020-11-22 10:21:34 +01:00
sig.push_str(&params.join(", "));
2020-11-22 15:15:17 +01:00
if return_type != "()" {
sig.push_str(") -> ");
sig.push_str(&return_type);
} else {
sig.push_str(")");
}
2020-11-22 10:21:34 +01:00
} else {
for x in 0..self.params {
sig.push_str("_");
if x < self.params - 1 {
sig.push_str(", ");
}
}
2020-12-23 16:29:19 +01:00
if self.func.is_script() {
2020-12-28 02:49:54 +01:00
sig.push_str(")");
2020-12-23 16:29:19 +01:00
} else {
sig.push_str(") -> ?");
}
2020-11-22 10:21:34 +01:00
}
sig
}
2020-11-04 07:37:46 +01:00
}
2021-03-08 08:30:32 +01:00
/// _(INTERNALS)_ Calculate a [`u64`] hash key from a namespace-qualified function name and
/// parameter types.
/// Exported under the `internals` feature only.
///
/// Module names are passed in via `&str` references from an iterator.
/// Parameter types are passed in via [`TypeId`] values from an iterator.
///
/// # Note
///
/// The first module name is skipped. Hashing starts from the _second_ module in the chain.
#[inline(always)]
fn calc_native_fn_hash<'a>(
modules: impl Iterator<Item = &'a str>,
2021-03-24 06:17:52 +01:00
fn_name: impl AsRef<str>,
2021-03-08 08:30:32 +01:00
params: &[TypeId],
) -> u64 {
let hash_script = calc_fn_hash(modules, fn_name, params.len());
let hash_params = calc_fn_params_hash(params.iter().cloned());
combine_hashes(hash_script, hash_params)
}
2020-11-10 16:26:50 +01:00
/// A module which may contain variables, sub-modules, external Rust functions,
/// and/or script-defined functions.
2020-11-15 05:07:35 +01:00
#[derive(Clone)]
2020-05-05 09:00:10 +02:00
pub struct Module {
2020-12-21 15:04:46 +01:00
/// ID identifying the module.
id: Option<ImmutableString>,
2020-05-05 09:00:10 +02:00
/// Sub-modules.
2021-03-23 05:13:53 +01:00
modules: BTreeMap<ImmutableString, Shared<Module>>,
2021-01-02 16:30:10 +01:00
/// [`Module`] variables.
2021-03-23 05:13:53 +01:00
variables: BTreeMap<ImmutableString, Dynamic>,
2021-01-02 16:30:10 +01:00
/// Flattened collection of all [`Module`] variables, including those in sub-modules.
2021-03-23 05:13:53 +01:00
all_variables: BTreeMap<u64, Dynamic>,
2020-05-05 09:00:10 +02:00
/// External Rust functions.
2021-03-23 05:13:53 +01:00
functions: BTreeMap<u64, Box<FuncInfo>>,
/// Flattened collection of all external Rust functions, native or scripted.
/// including those in sub-modules.
2021-03-23 05:13:53 +01:00
all_functions: BTreeMap<u64, CallableFunction>,
2020-11-15 05:07:35 +01:00
/// Iterator functions, keyed by the type producing the iterator.
2021-03-23 05:13:53 +01:00
type_iterators: BTreeMap<TypeId, IteratorFn>,
/// Flattened collection of iterator functions, including those in sub-modules.
2021-03-23 05:13:53 +01:00
all_type_iterators: BTreeMap<TypeId, IteratorFn>,
2021-01-02 16:30:10 +01:00
/// Is the [`Module`] indexed?
indexed: bool,
/// Does the [`Module`] contain indexed functions that have been exposed to the global namespace?
contains_indexed_global_functions: bool,
2021-03-24 02:56:25 +01:00
/// Interned strings
2021-03-24 06:17:52 +01:00
interned_strings: StringInterner,
2020-05-05 09:00:10 +02:00
}
2020-11-15 05:07:35 +01:00
impl Default for Module {
#[inline(always)]
2020-11-15 05:07:35 +01:00
fn default() -> Self {
Self {
2020-12-21 15:04:46 +01:00
id: None,
2020-11-15 06:49:54 +01:00
modules: Default::default(),
variables: Default::default(),
all_variables: Default::default(),
2021-03-23 05:13:53 +01:00
functions: Default::default(),
all_functions: Default::default(),
2020-11-15 06:49:54 +01:00
type_iterators: Default::default(),
all_type_iterators: Default::default(),
2020-11-15 05:07:35 +01:00
indexed: false,
contains_indexed_global_functions: false,
2021-03-24 02:56:25 +01:00
interned_strings: Default::default(),
2020-11-15 05:07:35 +01:00
}
}
}
2020-05-05 09:00:10 +02:00
impl fmt::Debug for Module {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
2021-01-09 16:26:50 +01:00
"Module({}\n{}{}{})",
2021-03-24 02:56:25 +01:00
self.id
.as_ref()
.map(|id| format!("id: {:?},", id))
.unwrap_or_default(),
2021-01-09 16:26:50 +01:00
if !self.modules.is_empty() {
format!(
" modules: {}\n",
self.modules
.keys()
.map(|m| m.as_str())
.collect::<Vec<_>>()
.join(", ")
)
} else {
Default::default()
2021-01-09 16:26:50 +01:00
},
if !self.variables.is_empty() {
format!(
" vars: {}\n",
self.variables
.iter()
.map(|(k, v)| format!("{}={:?}", k, v))
.collect::<Vec<_>>()
.join(", ")
)
} else {
Default::default()
2021-01-09 16:26:50 +01:00
},
if !self.functions.is_empty() {
format!(
" functions: {}\n",
self.functions
.values()
.map(|f| crate::stdlib::string::ToString::to_string(&f.func))
2021-01-09 16:26:50 +01:00
.collect::<Vec<_>>()
.join(", ")
)
} else {
Default::default()
2021-01-09 16:26:50 +01:00
}
2020-05-05 09:00:10 +02:00
)
}
}
2020-07-06 07:01:57 +02:00
impl AsRef<Module> for Module {
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-07-06 07:01:57 +02:00
fn as_ref(&self) -> &Module {
self
}
}
2021-01-11 16:09:33 +01:00
impl<M: AsRef<Module>> Add<M> for &Module {
type Output = Module;
#[inline(always)]
2021-01-11 16:09:33 +01:00
fn add(self, rhs: M) -> Self::Output {
let mut module = self.clone();
module.merge(rhs.as_ref());
module
}
}
impl<M: AsRef<Module>> Add<M> for Module {
type Output = Self;
#[inline(always)]
2021-01-11 16:09:33 +01:00
fn add(mut self, rhs: M) -> Self::Output {
self.merge(rhs.as_ref());
self
}
}
impl<M: Into<Module>> AddAssign<M> for Module {
#[inline(always)]
2021-01-11 16:09:33 +01:00
fn add_assign(&mut self, rhs: M) {
self.combine(rhs.into());
}
}
impl Module {
2021-01-02 16:30:10 +01:00
/// Create a new [`Module`].
///
2020-10-27 04:30:38 +01:00
/// # Example
///
/// ```
/// use rhai::Module;
///
/// let mut module = Module::new();
/// module.set_var("answer", 42_i64);
/// assert_eq!(module.get_var_value::<i64>("answer").unwrap(), 42);
/// ```
2020-10-08 16:25:50 +02:00
#[inline(always)]
pub fn new() -> Self {
2020-05-05 09:00:10 +02:00
Default::default()
}
2021-01-02 16:30:10 +01:00
/// Get the ID of the [`Module`], if any.
2020-12-21 15:04:46 +01:00
///
/// # Example
///
/// ```
/// use rhai::Module;
///
/// let mut module = Module::new();
/// module.set_id(Some("hello"));
/// assert_eq!(module.id(), Some("hello"));
/// ```
2021-01-03 06:29:42 +01:00
#[inline(always)]
2020-12-21 15:04:46 +01:00
pub fn id(&self) -> Option<&str> {
2021-01-03 06:29:42 +01:00
self.id_raw().map(|s| s.as_str())
2020-12-21 15:04:46 +01:00
}
2021-01-03 03:08:22 +01:00
/// Get the ID of the [`Module`] as an [`ImmutableString`], if any.
2021-01-03 06:29:42 +01:00
///
/// # Example
///
/// ```
/// use rhai::Module;
///
/// let mut module = Module::new();
/// module.set_id(Some("hello"));
/// assert_eq!(module.id_raw().map(|s| s.as_str()), Some("hello"));
/// ```
#[inline(always)]
pub fn id_raw(&self) -> Option<&ImmutableString> {
self.id.as_ref()
2020-12-21 15:04:46 +01:00
}
2021-01-02 16:30:10 +01:00
/// Set the ID of the [`Module`].
2020-12-21 15:04:46 +01:00
///
/// # Example
///
/// ```
/// use rhai::Module;
///
/// let mut module = Module::new();
/// module.set_id(Some("hello"));
/// assert_eq!(module.id(), Some("hello"));
/// ```
2021-01-03 06:29:42 +01:00
#[inline(always)]
2020-12-21 15:04:46 +01:00
pub fn set_id<S: Into<ImmutableString>>(&mut self, id: Option<S>) {
self.id = id.map(|s| s.into());
}
2021-01-02 16:30:10 +01:00
/// Is the [`Module`] empty?
2020-09-30 03:57:21 +02:00
///
2020-10-27 04:30:38 +01:00
/// # Example
2020-09-30 03:57:21 +02:00
///
/// ```
/// use rhai::Module;
///
/// let module = Module::new();
/// assert!(module.is_empty());
/// ```
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-09-30 03:57:21 +02:00
pub fn is_empty(&self) -> bool {
self.functions.is_empty()
&& self.all_functions.is_empty()
&& self.variables.is_empty()
&& self.all_variables.is_empty()
&& self.modules.is_empty()
&& self.type_iterators.is_empty()
&& self.all_type_iterators.is_empty()
2020-09-30 03:57:21 +02:00
}
2021-01-02 16:30:10 +01:00
/// Is the [`Module`] indexed?
///
/// # Example
///
/// ```
/// use rhai::Module;
///
/// let mut module = Module::new();
/// assert!(!module.is_indexed());
///
2020-11-08 09:49:59 +01:00
/// # #[cfg(not(feature = "no_module"))]
/// # {
/// module.build_index();
/// assert!(module.is_indexed());
2020-11-08 09:49:59 +01:00
/// # }
/// ```
2021-01-03 06:29:42 +01:00
#[inline(always)]
pub fn is_indexed(&self) -> bool {
self.indexed
}
/// Generate signatures for all the non-private functions in the [`Module`].
/// Available under the `metadata` feature only.
#[cfg(feature = "metadata")]
2021-01-03 06:29:42 +01:00
#[inline(always)]
2021-02-09 07:22:55 +01:00
pub fn gen_fn_signatures(&self) -> impl Iterator<Item = String> + '_ {
2020-11-22 10:21:34 +01:00
self.functions
.values()
2021-03-12 07:11:08 +01:00
.filter(|f| match f.access {
FnAccess::Public => true,
FnAccess::Private => false,
})
2021-03-12 07:11:08 +01:00
.map(|f| f.gen_signature())
2020-11-22 10:21:34 +01:00
}
2021-01-02 16:30:10 +01:00
/// Does a variable exist in the [`Module`]?
///
2020-10-27 04:30:38 +01:00
/// # Example
///
/// ```
/// use rhai::Module;
///
/// let mut module = Module::new();
/// module.set_var("answer", 42_i64);
/// assert!(module.contains_var("answer"));
/// ```
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-05-05 11:51:40 +02:00
pub fn contains_var(&self, name: &str) -> bool {
2020-05-05 09:00:10 +02:00
self.variables.contains_key(name)
}
2021-01-02 16:30:10 +01:00
/// Get the value of a [`Module`] variable.
///
2020-10-27 04:30:38 +01:00
/// # Example
///
/// ```
/// use rhai::Module;
///
/// let mut module = Module::new();
/// module.set_var("answer", 42_i64);
/// assert_eq!(module.get_var_value::<i64>("answer").unwrap(), 42);
/// ```
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-05-05 11:51:40 +02:00
pub fn get_var_value<T: Variant + Clone>(&self, name: &str) -> Option<T> {
self.get_var(name).and_then(Dynamic::try_cast::<T>)
2020-05-05 09:00:10 +02:00
}
2021-01-02 16:30:10 +01:00
/// Get a [`Module`] variable as a [`Dynamic`].
///
2020-10-27 04:30:38 +01:00
/// # Example
///
/// ```
/// use rhai::Module;
///
/// let mut module = Module::new();
/// module.set_var("answer", 42_i64);
/// assert_eq!(module.get_var("answer").unwrap().cast::<i64>(), 42);
/// ```
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-05-05 11:51:40 +02:00
pub fn get_var(&self, name: &str) -> Option<Dynamic> {
2020-05-05 09:00:10 +02:00
self.variables.get(name).cloned()
}
2021-01-02 16:30:10 +01:00
/// Set a variable into the [`Module`].
2020-05-05 09:00:10 +02:00
///
/// If there is an existing variable of the same name, it is replaced.
///
2020-10-27 04:30:38 +01:00
/// # Example
///
/// ```
/// use rhai::Module;
///
/// let mut module = Module::new();
/// module.set_var("answer", 42_i64);
/// assert_eq!(module.get_var_value::<i64>("answer").unwrap(), 42);
/// ```
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-12-11 05:57:07 +01:00
pub fn set_var(
&mut self,
name: impl Into<ImmutableString>,
value: impl Variant + Clone,
) -> &mut Self {
2020-05-13 13:21:42 +02:00
self.variables.insert(name.into(), Dynamic::from(value));
self.indexed = false;
2020-07-12 05:46:53 +02:00
self
2020-05-05 09:00:10 +02:00
}
2020-11-10 16:26:50 +01:00
/// Get a reference to a namespace-qualified variable.
2021-01-02 06:29:16 +01:00
/// Name and Position in [`EvalAltResult`] are [`None`] and [`NONE`][Position::NONE] and must be set afterwards.
2020-10-08 16:25:50 +02:00
#[inline(always)]
2021-03-08 08:30:32 +01:00
pub(crate) fn get_qualified_var(&self, hash_var: u64) -> Result<&Dynamic, Box<EvalAltResult>> {
2020-12-24 09:32:43 +01:00
self.all_variables.get(&hash_var).ok_or_else(|| {
EvalAltResult::ErrorVariableNotFound(String::new(), Position::NONE).into()
})
2020-05-05 09:00:10 +02:00
}
2021-01-02 16:30:10 +01:00
/// Set a script-defined function into the [`Module`].
///
/// If there is an existing function of the same name and number of arguments, it is replaced.
2020-09-24 17:32:54 +02:00
#[cfg(not(feature = "no_function"))]
2020-10-08 16:25:50 +02:00
#[inline]
2021-03-07 15:10:54 +01:00
pub(crate) fn set_script_fn(
&mut self,
fn_def: impl Into<Shared<crate::ast::ScriptFnDef>>,
2021-03-08 08:30:32 +01:00
) -> u64 {
2020-11-25 02:36:06 +01:00
let fn_def = fn_def.into();
// None + function name + number of arguments.
2020-09-24 16:50:28 +02:00
let num_params = fn_def.params.len();
2021-03-08 08:30:32 +01:00
let hash_script = crate::calc_fn_hash(empty(), &fn_def.name, num_params);
2021-03-24 02:56:25 +01:00
let mut param_names = fn_def.params.clone();
2020-11-27 16:37:59 +01:00
param_names.push("Dynamic".into());
self.functions.insert(
2020-06-11 12:13:33 +02:00
hash_script,
2021-03-12 07:11:08 +01:00
Box::new(FuncInfo {
2021-03-24 02:56:25 +01:00
name: fn_def.name.clone(),
2020-11-17 05:23:53 +01:00
namespace: FnNamespace::Internal,
2020-11-04 07:37:46 +01:00
access: fn_def.access,
params: num_params,
2020-12-23 16:29:19 +01:00
param_types: Default::default(),
#[cfg(feature = "metadata")]
2020-12-23 16:29:19 +01:00
param_names,
2020-11-04 07:37:46 +01:00
func: fn_def.into(),
2021-03-12 07:11:08 +01:00
}),
);
self.indexed = false;
self.contains_indexed_global_functions = false;
2020-09-24 16:50:28 +02:00
hash_script
}
2021-03-12 07:11:08 +01:00
/// Get a shared reference to the script-defined function in the [`Module`] based on name
/// and number of parameters.
2020-10-05 06:09:45 +02:00
#[cfg(not(feature = "no_function"))]
2020-10-08 16:25:50 +02:00
#[inline(always)]
pub fn get_script_fn(
&self,
name: &str,
num_params: usize,
2021-03-12 07:11:08 +01:00
) -> Option<&Shared<crate::ast::ScriptFnDef>> {
self.functions
.values()
2021-03-17 02:58:08 +01:00
.find(|f| f.params == num_params && f.name == name)
2021-03-12 07:11:08 +01:00
.map(|f| f.func.get_fn_def())
}
2021-03-23 05:13:53 +01:00
/// Get a mutable reference to the underlying [`BTreeMap`] of sub-modules.
2020-12-26 16:21:16 +01:00
///
2021-01-02 16:30:10 +01:00
/// # WARNING
2020-12-26 16:21:16 +01:00
///
/// By taking a mutable reference, it is assumed that some sub-modules will be modified.
2021-01-02 16:30:10 +01:00
/// Thus the [`Module`] is automatically set to be non-indexed.
2020-12-28 02:49:54 +01:00
#[cfg(not(feature = "no_module"))]
2020-12-26 06:05:57 +01:00
#[inline(always)]
2021-03-23 05:13:53 +01:00
pub(crate) fn sub_modules_mut(&mut self) -> &mut BTreeMap<ImmutableString, Shared<Module>> {
2020-12-26 06:05:57 +01:00
// We must assume that the user has changed the sub-modules
// (otherwise why take a mutable reference?)
2020-12-26 16:21:16 +01:00
self.all_functions.clear();
self.all_variables.clear();
self.all_type_iterators.clear();
2020-12-26 06:05:57 +01:00
self.indexed = false;
self.contains_indexed_global_functions = false;
2020-12-26 06:05:57 +01:00
&mut self.modules
}
2021-01-02 16:30:10 +01:00
/// Does a sub-module exist in the [`Module`]?
///
2020-10-27 04:30:38 +01:00
/// # Example
///
/// ```
/// use rhai::Module;
///
/// let mut module = Module::new();
/// let sub_module = Module::new();
/// module.set_sub_module("question", sub_module);
/// assert!(module.contains_sub_module("question"));
/// ```
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-05-05 09:00:10 +02:00
pub fn contains_sub_module(&self, name: &str) -> bool {
self.modules.contains_key(name)
}
2021-01-02 16:30:10 +01:00
/// Get a sub-module in the [`Module`].
///
2020-10-27 04:30:38 +01:00
/// # Example
///
/// ```
/// use rhai::Module;
///
/// let mut module = Module::new();
/// let sub_module = Module::new();
/// module.set_sub_module("question", sub_module);
/// assert!(module.get_sub_module("question").is_some());
/// ```
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-05-05 09:00:10 +02:00
pub fn get_sub_module(&self, name: &str) -> Option<&Module> {
2020-11-09 15:44:20 +01:00
self.modules.get(name).map(|m| m.as_ref())
2020-05-05 09:00:10 +02:00
}
2021-01-02 16:30:10 +01:00
/// Set a sub-module into the [`Module`].
2020-05-05 09:00:10 +02:00
///
/// If there is an existing sub-module of the same name, it is replaced.
///
2020-10-27 04:30:38 +01:00
/// # Example
///
/// ```
/// use rhai::Module;
///
/// let mut module = Module::new();
/// let sub_module = Module::new();
/// module.set_sub_module("question", sub_module);
/// assert!(module.get_sub_module("question").is_some());
/// ```
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-11-09 15:44:20 +01:00
pub fn set_sub_module(
&mut self,
2020-12-11 05:57:07 +01:00
name: impl Into<ImmutableString>,
2020-11-09 15:44:20 +01:00
sub_module: impl Into<Shared<Module>>,
) -> &mut Self {
2020-05-05 09:00:10 +02:00
self.modules.insert(name.into(), sub_module.into());
self.indexed = false;
self.contains_indexed_global_functions = false;
2020-07-12 05:46:53 +02:00
self
2020-05-05 09:00:10 +02:00
}
2021-01-02 16:30:10 +01:00
/// Does the particular Rust function exist in the [`Module`]?
2020-05-05 11:51:40 +02:00
///
2021-03-15 05:39:06 +01:00
/// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
///
2020-10-27 04:30:38 +01:00
/// # Example
///
/// ```
/// use rhai::Module;
///
/// let mut module = Module::new();
2021-03-15 05:39:06 +01:00
/// let hash = module.set_native_fn("calc", || Ok(42_i64));
2021-03-17 02:58:08 +01:00
/// assert!(module.contains_fn(hash));
/// ```
2021-03-04 11:13:47 +01:00
#[inline(always)]
2021-03-17 02:58:08 +01:00
pub fn contains_fn(&self, hash_fn: u64) -> bool {
self.functions.contains_key(&hash_fn)
2020-05-05 11:51:40 +02:00
}
2020-11-22 15:15:17 +01:00
/// Update the metadata (parameter names/types and return type) of a registered function.
/// Available under the `metadata` feature only.
2020-11-22 10:21:34 +01:00
///
2021-03-15 05:39:06 +01:00
/// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
2021-01-02 16:30:10 +01:00
///
/// ## Parameter Names and Types
2020-11-22 15:15:17 +01:00
///
/// Each parameter name/type pair should be a single string of the format: `var_name: type`.
///
2021-01-02 16:30:10 +01:00
/// ## Return Type
///
/// The _last entry_ in the list should be the _return type_ of the function.
2020-11-22 15:15:17 +01:00
/// In other words, the number of entries should be one larger than the number of parameters.
#[cfg(feature = "metadata")]
2021-01-03 06:29:42 +01:00
#[inline(always)]
2021-03-08 08:30:32 +01:00
pub fn update_fn_metadata(&mut self, hash_fn: u64, arg_names: &[&str]) -> &mut Self {
2021-03-24 02:56:25 +01:00
let param_names = arg_names
.iter()
2021-03-24 06:17:52 +01:00
.map(|&name| self.interned_strings.get(name))
2021-03-24 02:56:25 +01:00
.collect();
2020-11-22 10:21:34 +01:00
if let Some(f) = self.functions.get_mut(&hash_fn) {
2021-03-24 02:56:25 +01:00
f.param_names = param_names;
2020-11-22 10:21:34 +01:00
}
self
}
2020-12-07 14:54:52 +01:00
/// Update the namespace of a registered function.
///
2021-03-15 05:39:06 +01:00
/// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
2021-01-03 06:29:42 +01:00
#[inline(always)]
2021-03-08 08:30:32 +01:00
pub fn update_fn_namespace(&mut self, hash_fn: u64, namespace: FnNamespace) -> &mut Self {
2020-12-07 14:54:52 +01:00
if let Some(f) = self.functions.get_mut(&hash_fn) {
f.namespace = namespace;
2021-03-24 02:56:25 +01:00
self.indexed = false;
self.contains_indexed_global_functions = false;
2020-12-07 14:54:52 +01:00
}
self
}
2021-01-02 16:30:10 +01:00
/// Set a Rust function into the [`Module`], returning a hash key.
2020-05-05 11:51:40 +02:00
///
/// If there is an existing Rust function of the same hash, it is replaced.
2020-07-11 09:09:17 +02:00
///
2021-01-02 16:30:10 +01:00
/// # WARNING - Low Level API
2020-07-11 09:09:17 +02:00
///
/// This function is very low level.
2021-01-03 06:29:42 +01:00
#[inline]
2020-07-11 09:09:17 +02:00
pub fn set_fn(
2020-05-22 15:50:24 +02:00
&mut self,
2021-03-24 06:17:52 +01:00
name: impl AsRef<str> + Into<ImmutableString>,
2020-11-17 05:23:53 +01:00
namespace: FnNamespace,
2020-05-22 15:50:24 +02:00
access: FnAccess,
_arg_names: Option<&[&str]>,
2020-07-07 16:59:23 +02:00
arg_types: &[TypeId],
func: CallableFunction,
2021-03-08 08:30:32 +01:00
) -> u64 {
let is_method = func.is_method();
2020-09-11 16:32:59 +02:00
2020-12-23 16:29:19 +01:00
let param_types = arg_types
2021-03-08 08:30:32 +01:00
.iter()
.cloned()
2021-03-08 08:30:32 +01:00
.enumerate()
.map(|(i, type_id)| {
if !is_method || i > 0 {
if type_id == TypeId::of::<&str>() {
// Map &str to ImmutableString
TypeId::of::<ImmutableString>()
} else if type_id == TypeId::of::<String>() {
// Map String to ImmutableString
TypeId::of::<ImmutableString>()
} else {
type_id
}
} else {
2021-03-08 08:30:32 +01:00
// Do not map &mut parameter
type_id
}
})
2020-10-28 15:18:44 +01:00
.collect::<StaticVec<_>>();
2020-05-17 16:19:49 +02:00
2021-03-08 08:30:32 +01:00
let hash_fn = calc_native_fn_hash(empty(), &name, &param_types);
2021-03-24 06:17:52 +01:00
let name = self.interned_strings.get(name);
#[cfg(feature = "metadata")]
let param_names = _arg_names
2021-03-24 02:56:25 +01:00
.iter()
.flat_map(|p| p.iter())
2021-03-24 06:17:52 +01:00
.map(|&arg| self.interned_strings.get(arg))
2021-03-24 02:56:25 +01:00
.collect();
2020-10-28 15:18:44 +01:00
self.functions.insert(
hash_fn,
2021-03-12 07:11:08 +01:00
Box::new(FuncInfo {
2020-11-04 07:37:46 +01:00
name,
2020-11-17 05:23:53 +01:00
namespace,
2020-11-04 07:37:46 +01:00
access,
2020-12-23 16:29:19 +01:00
params: param_types.len(),
param_types,
#[cfg(feature = "metadata")]
2021-03-24 02:56:25 +01:00
param_names,
2020-11-04 07:37:46 +01:00
func: func.into(),
2021-03-12 07:11:08 +01:00
}),
2020-10-28 15:18:44 +01:00
);
2020-05-05 17:57:25 +02:00
self.indexed = false;
self.contains_indexed_global_functions = false;
2020-05-11 17:48:50 +02:00
hash_fn
2020-05-05 11:51:40 +02:00
}
2020-11-20 09:52:28 +01:00
/// Set a Rust function taking a reference to the scripting [`Engine`][crate::Engine],
2020-12-26 16:21:16 +01:00
/// the current set of functions, plus a list of mutable [`Dynamic`] references
2021-01-02 16:30:10 +01:00
/// into the [`Module`], returning a hash key.
///
/// Use this to register a built-in function which must reference settings on the scripting
2020-11-20 09:52:28 +01:00
/// [`Engine`][crate::Engine] (e.g. to prevent growing an array beyond the allowed maximum size),
/// or to call a script-defined function in the current evaluation context.
///
/// If there is a similar existing Rust function, it is replaced.
2020-07-07 16:59:23 +02:00
///
2021-01-02 16:30:10 +01:00
/// # WARNING - Low Level API
2020-07-07 16:59:23 +02:00
///
/// This function is very low level.
///
/// # Arguments
///
2020-11-20 09:52:28 +01:00
/// A list of [`TypeId`]'s is taken as the argument types.
2020-07-07 16:59:23 +02:00
///
2021-01-02 16:30:10 +01:00
/// Arguments are simply passed in as a mutable array of [`&mut Dynamic`][Dynamic],
2020-07-07 16:59:23 +02:00
/// which is guaranteed to contain enough arguments of the correct types.
///
2020-10-03 10:25:58 +02:00
/// The function is assumed to be a _method_, meaning that the first argument should not be consumed.
/// All other arguments can be consumed.
///
/// To access a primary argument value (i.e. cloning is cheap), use: `args[n].as_xxx().unwrap()`
2020-07-07 16:59:23 +02:00
///
/// To access an argument value and avoid cloning, use `std::mem::take(args[n]).cast::<T>()`.
2020-07-07 16:59:23 +02:00
/// Notice that this will _consume_ the argument, replacing it with `()`.
///
/// To access the first mutable argument, use `args.get_mut(0).unwrap()`
2020-07-07 16:59:23 +02:00
///
2020-11-22 15:15:17 +01:00
/// # Function Metadata
///
/// No metadata for the function is registered. Use `update_fn_metadata` to add metadata.
///
2020-10-27 04:30:38 +01:00
/// # Example
2020-07-07 16:59:23 +02:00
///
/// ```
2020-11-17 05:23:53 +01:00
/// use rhai::{Module, FnNamespace, FnAccess};
2020-07-07 16:59:23 +02:00
///
/// let mut module = Module::new();
/// let hash = module.set_raw_fn("double_or_not", FnNamespace::Internal, FnAccess::Public,
2020-07-07 16:59:23 +02:00
/// // Pass parameter types via a slice with TypeId's
2020-07-28 04:25:57 +02:00
/// &[std::any::TypeId::of::<i64>(), std::any::TypeId::of::<bool>()],
2020-07-07 16:59:23 +02:00
/// // Fixed closure signature
2020-10-18 11:08:57 +02:00
/// |context, args| {
2020-07-07 16:59:23 +02:00
/// // 'args' is guaranteed to be the right length and of the correct types
///
/// // Get the second parameter by 'consuming' it
/// let double = std::mem::take(args[1]).cast::<bool>();
/// // Since it is a primary type, it can also be cheaply copied
/// let double = args[1].clone().cast::<bool>();
/// // Get a mutable reference to the first argument.
/// let mut x = args[0].write_lock::<i64>().unwrap();
2020-07-07 16:59:23 +02:00
///
/// let orig = *x;
///
/// if double {
/// *x *= 2; // the first argument can be mutated
/// }
///
/// Ok(orig) // return Result<T, Box<EvalAltResult>>
/// });
///
2021-03-17 07:45:40 +01:00
/// assert!(module.contains_fn(hash));
2020-07-07 16:59:23 +02:00
/// ```
2021-01-03 06:29:42 +01:00
#[inline(always)]
2021-03-24 06:17:52 +01:00
pub fn set_raw_fn<N, T, F>(
&mut self,
2021-03-24 06:17:52 +01:00
name: N,
2020-11-17 05:23:53 +01:00
namespace: FnNamespace,
access: FnAccess,
2020-07-07 16:59:23 +02:00
arg_types: &[TypeId],
2021-03-24 06:17:52 +01:00
func: F,
) -> u64
where
N: AsRef<str> + Into<ImmutableString>,
T: Variant + Clone,
F: Fn(NativeCallContext, &mut FnCallArgs) -> Result<T, Box<EvalAltResult>>
+ SendSync
+ 'static,
2021-03-24 06:17:52 +01:00
{
2020-11-02 04:04:45 +01:00
let f =
move |ctx: NativeCallContext, args: &mut FnCallArgs| func(ctx, args).map(Dynamic::from);
2020-11-17 05:23:53 +01:00
self.set_fn(
name,
2020-11-17 05:23:53 +01:00
namespace,
access,
2020-11-22 10:21:34 +01:00
None,
arg_types,
CallableFunction::from_method(Box::new(f)),
)
}
2021-03-15 05:39:06 +01:00
/// Set a Rust function into the [`Module`], returning a hash key.
2020-05-05 11:51:40 +02:00
///
/// If there is a similar existing Rust function, it is replaced.
///
2021-03-15 05:39:06 +01:00
/// # Function Namespace
2020-11-22 15:15:17 +01:00
///
2021-03-15 05:39:06 +01:00
/// The default function namespace is [`FnNamespace::Internal`].
/// Use [`update_fn_namespace`][Module::update_fn_namespace] to change it.
///
2020-11-22 15:15:17 +01:00
/// # Function Metadata
///
2021-03-15 05:39:06 +01:00
/// No metadata for the function is registered.
/// Use [`update_fn_metadata`][Module::update_fn_metadata] to add metadata.
2020-11-22 15:15:17 +01:00
///
2020-10-27 04:30:38 +01:00
/// # Example
///
/// ```
/// use rhai::Module;
///
/// let mut module = Module::new();
2021-03-15 05:39:06 +01:00
/// let hash = module.set_native_fn("calc", || Ok(42_i64));
2021-03-17 07:45:40 +01:00
/// assert!(module.contains_fn(hash));
/// ```
2021-01-03 06:29:42 +01:00
#[inline(always)]
2021-03-24 06:17:52 +01:00
pub fn set_native_fn<ARGS, N, T, F>(&mut self, name: N, func: F) -> u64
2021-03-15 05:39:06 +01:00
where
2021-03-24 06:17:52 +01:00
N: AsRef<str> + Into<ImmutableString>,
2021-03-15 05:39:06 +01:00
T: Variant + Clone,
F: RegisterNativeFunction<ARGS, Result<T, Box<EvalAltResult>>>,
{
self.set_fn(
name,
2020-11-17 05:23:53 +01:00
FnNamespace::Internal,
2020-10-01 17:31:27 +02:00
FnAccess::Public,
2020-11-22 10:21:34 +01:00
None,
2021-03-15 05:39:06 +01:00
&F::param_types(),
func.into_callable_function(),
)
2020-05-05 11:51:40 +02:00
}
/// Set a Rust getter function taking one mutable parameter, returning a hash key.
/// This function is automatically exposed to the global namespace.
///
/// If there is a similar existing Rust getter function, it is replaced.
///
2020-11-22 15:15:17 +01:00
/// # Function Metadata
///
/// No metadata for the function is registered. Use `update_fn_metadata` to add metadata.
///
2020-10-27 04:30:38 +01:00
/// # Example
///
/// ```
/// use rhai::Module;
///
/// let mut module = Module::new();
/// let hash = module.set_getter_fn("value", |x: &mut i64| { Ok(*x) });
2021-03-17 07:45:40 +01:00
/// assert!(module.contains_fn(hash));
/// ```
#[cfg(not(feature = "no_object"))]
2021-01-03 06:29:42 +01:00
#[inline(always)]
2021-03-24 02:56:25 +01:00
pub fn set_getter_fn<ARGS, A, T, F>(&mut self, name: &str, func: F) -> u64
2021-03-15 05:39:06 +01:00
where
A: Variant + Clone,
T: Variant + Clone,
F: RegisterNativeFunction<ARGS, Result<T, Box<EvalAltResult>>>,
F: Fn(&mut A) -> Result<T, Box<EvalAltResult>> + SendSync + 'static,
{
self.set_fn(
2021-03-24 02:56:25 +01:00
&crate::engine::make_getter(name),
FnNamespace::Global,
2020-10-01 17:31:27 +02:00
FnAccess::Public,
2020-11-22 10:21:34 +01:00
None,
2021-03-15 05:39:06 +01:00
&F::param_types(),
func.into_callable_function(),
)
2020-05-05 11:51:40 +02:00
}
2021-01-02 16:30:10 +01:00
/// Set a Rust setter function taking two parameters (the first one mutable) into the [`Module`],
/// returning a hash key.
/// This function is automatically exposed to the global namespace.
///
/// If there is a similar existing setter Rust function, it is replaced.
///
2020-11-22 15:15:17 +01:00
/// # Function Metadata
///
/// No metadata for the function is registered. Use `update_fn_metadata` to add metadata.
///
2020-10-27 04:30:38 +01:00
/// # Example
///
/// ```
/// use rhai::{Module, ImmutableString};
///
/// let mut module = Module::new();
/// let hash = module.set_setter_fn("value", |x: &mut i64, y: ImmutableString| {
/// *x = y.len() as i64;
/// Ok(())
/// });
2021-03-17 07:45:40 +01:00
/// assert!(module.contains_fn(hash));
/// ```
#[cfg(not(feature = "no_object"))]
2021-01-03 06:29:42 +01:00
#[inline(always)]
2021-03-24 02:56:25 +01:00
pub fn set_setter_fn<ARGS, A, B, F>(&mut self, name: &str, func: F) -> u64
2021-03-15 05:39:06 +01:00
where
A: Variant + Clone,
B: Variant + Clone,
F: RegisterNativeFunction<ARGS, Result<(), Box<EvalAltResult>>>,
F: Fn(&mut A, B) -> Result<(), Box<EvalAltResult>> + SendSync + 'static,
{
self.set_fn(
2021-03-24 02:56:25 +01:00
&crate::engine::make_setter(name),
FnNamespace::Global,
2021-03-15 05:39:06 +01:00
FnAccess::Public,
None,
&F::param_types(),
func.into_callable_function(),
)
}
2021-01-02 16:30:10 +01:00
/// Set a Rust index getter taking two parameters (the first one mutable) into the [`Module`],
/// returning a hash key.
/// This function is automatically exposed to the global namespace.
///
/// If there is a similar existing setter Rust function, it is replaced.
///
/// # Panics
///
2020-11-20 09:52:28 +01:00
/// Panics if the type is [`Array`] or [`Map`].
/// Indexers for arrays, object maps and strings cannot be registered.
///
2020-11-22 15:15:17 +01:00
/// # Function Metadata
///
/// No metadata for the function is registered. Use `update_fn_metadata` to add metadata.
///
2020-10-27 04:30:38 +01:00
/// # Example
///
/// ```
/// use rhai::{Module, ImmutableString};
///
/// let mut module = Module::new();
2020-06-06 07:06:00 +02:00
/// let hash = module.set_indexer_get_fn(|x: &mut i64, y: ImmutableString| {
/// Ok(*x + y.len() as i64)
/// });
2021-03-17 07:45:40 +01:00
/// assert!(module.contains_fn(hash));
/// ```
#[cfg(not(feature = "no_index"))]
2021-01-03 06:29:42 +01:00
#[inline(always)]
2021-03-15 05:39:06 +01:00
pub fn set_indexer_get_fn<ARGS, A, B, T, F>(&mut self, func: F) -> u64
where
A: Variant + Clone,
B: Variant + Clone,
T: Variant + Clone,
F: RegisterNativeFunction<ARGS, Result<T, Box<EvalAltResult>>>,
F: Fn(&mut A, B) -> Result<T, Box<EvalAltResult>> + SendSync + 'static,
{
if TypeId::of::<A>() == TypeId::of::<Array>() {
panic!("Cannot register indexer for arrays.");
}
#[cfg(not(feature = "no_object"))]
if TypeId::of::<A>() == TypeId::of::<Map>() {
panic!("Cannot register indexer for object maps.");
}
if TypeId::of::<A>() == TypeId::of::<String>()
|| TypeId::of::<A>() == TypeId::of::<&str>()
|| TypeId::of::<A>() == TypeId::of::<ImmutableString>()
{
panic!("Cannot register indexer for strings.");
}
self.set_fn(
2021-03-15 05:39:06 +01:00
crate::engine::FN_IDX_GET,
FnNamespace::Global,
2020-10-01 17:31:27 +02:00
FnAccess::Public,
2020-11-22 10:21:34 +01:00
None,
2021-03-15 05:39:06 +01:00
&F::param_types(),
func.into_callable_function(),
)
2020-05-05 11:51:40 +02:00
}
2021-01-02 16:30:10 +01:00
/// Set a Rust index setter taking three parameters (the first one mutable) into the [`Module`],
2020-06-06 07:06:00 +02:00
/// returning a hash key.
/// This function is automatically exposed to the global namespace.
2020-06-06 07:06:00 +02:00
///
/// If there is a similar existing Rust function, it is replaced.
///
/// # Panics
///
2020-11-20 09:52:28 +01:00
/// Panics if the type is [`Array`] or [`Map`].
/// Indexers for arrays, object maps and strings cannot be registered.
///
2020-11-22 15:15:17 +01:00
/// # Function Metadata
///
/// No metadata for the function is registered. Use `update_fn_metadata` to add metadata.
///
2020-10-27 04:30:38 +01:00
/// # Example
2020-06-06 07:06:00 +02:00
///
/// ```
/// use rhai::{Module, ImmutableString};
///
/// let mut module = Module::new();
/// let hash = module.set_indexer_set_fn(|x: &mut i64, y: ImmutableString, value: i64| {
/// *x = y.len() as i64 + value;
/// Ok(())
/// });
2021-03-17 07:45:40 +01:00
/// assert!(module.contains_fn(hash));
2020-06-06 07:06:00 +02:00
/// ```
2020-07-26 09:53:22 +02:00
#[cfg(not(feature = "no_index"))]
2021-01-03 06:29:42 +01:00
#[inline(always)]
2021-03-15 05:39:06 +01:00
pub fn set_indexer_set_fn<ARGS, A, B, C, F>(&mut self, func: F) -> u64
where
A: Variant + Clone,
B: Variant + Clone,
C: Variant + Clone,
F: RegisterNativeFunction<ARGS, Result<(), Box<EvalAltResult>>>,
F: Fn(&mut A, B, C) -> Result<(), Box<EvalAltResult>> + SendSync + 'static,
{
if TypeId::of::<A>() == TypeId::of::<Array>() {
panic!("Cannot register indexer for arrays.");
}
#[cfg(not(feature = "no_object"))]
if TypeId::of::<A>() == TypeId::of::<Map>() {
panic!("Cannot register indexer for object maps.");
}
if TypeId::of::<A>() == TypeId::of::<String>()
|| TypeId::of::<A>() == TypeId::of::<&str>()
|| TypeId::of::<A>() == TypeId::of::<ImmutableString>()
{
panic!("Cannot register indexer for strings.");
}
2020-06-06 07:06:00 +02:00
self.set_fn(
2020-11-16 09:28:04 +01:00
crate::engine::FN_IDX_SET,
2021-03-15 05:39:06 +01:00
FnNamespace::Global,
2020-10-01 17:31:27 +02:00
FnAccess::Public,
2020-11-22 10:21:34 +01:00
None,
2021-03-15 05:39:06 +01:00
&F::param_types(),
func.into_callable_function(),
2020-06-06 07:06:00 +02:00
)
}
2020-07-24 17:16:54 +02:00
/// Set a pair of Rust index getter and setter functions, returning both hash keys.
2020-11-20 09:52:28 +01:00
/// This is a short-hand for [`set_indexer_get_fn`][Module::set_indexer_get_fn] and
/// [`set_indexer_set_fn`][Module::set_indexer_set_fn].
2020-07-24 17:16:54 +02:00
///
/// If there are similar existing Rust functions, they are replaced.
///
/// # Panics
///
2020-11-20 09:52:28 +01:00
/// Panics if the type is [`Array`] or [`Map`].
/// Indexers for arrays, object maps and strings cannot be registered.
///
2020-11-22 15:15:17 +01:00
/// # Function Metadata
///
/// No metadata for the function is registered. Use `update_fn_metadata` to add metadata.
///
2020-10-27 04:30:38 +01:00
/// # Example
2020-07-24 17:16:54 +02:00
///
/// ```
/// use rhai::{Module, ImmutableString};
///
/// let mut module = Module::new();
/// let (hash_get, hash_set) = module.set_indexer_get_set_fn(
/// |x: &mut i64, y: ImmutableString| {
/// Ok(*x + y.len() as i64)
/// },
/// |x: &mut i64, y: ImmutableString, value: i64| {
/// *x = y.len() as i64 + value;
/// Ok(())
/// }
/// );
2021-03-17 07:45:40 +01:00
/// assert!(module.contains_fn(hash_get));
/// assert!(module.contains_fn(hash_set));
2020-07-24 17:16:54 +02:00
/// ```
2020-07-26 09:53:22 +02:00
#[cfg(not(feature = "no_index"))]
2021-01-03 06:29:42 +01:00
#[inline(always)]
2021-03-24 06:17:52 +01:00
pub fn set_indexer_get_set_fn<A, B, T>(
2020-07-24 17:16:54 +02:00
&mut self,
2021-02-13 03:56:09 +01:00
get_fn: impl Fn(&mut A, B) -> Result<T, Box<EvalAltResult>> + SendSync + 'static,
set_fn: impl Fn(&mut A, B, T) -> Result<(), Box<EvalAltResult>> + SendSync + 'static,
2021-03-24 06:17:52 +01:00
) -> (u64, u64)
where
A: Variant + Clone,
B: Variant + Clone,
T: Variant + Clone,
{
2020-07-24 17:16:54 +02:00
(
2021-02-13 03:56:09 +01:00
self.set_indexer_get_fn(get_fn),
self.set_indexer_set_fn(set_fn),
2020-07-24 17:16:54 +02:00
)
}
2020-05-05 11:51:40 +02:00
/// Get a Rust function.
///
2021-03-15 05:39:06 +01:00
/// The [`u64`] hash is returned by the [`set_native_fn`][Module::set_native_fn] call.
2020-10-08 16:25:50 +02:00
#[inline(always)]
2021-03-17 02:58:08 +01:00
pub(crate) fn get_fn(&self, hash_fn: u64) -> Option<&CallableFunction> {
self.functions.get(&hash_fn).map(|f| &f.func)
2020-05-05 11:51:40 +02:00
}
2021-01-02 16:30:10 +01:00
/// Does the particular namespace-qualified function exist in the [`Module`]?
///
2021-03-08 08:30:32 +01:00
/// The [`u64`] hash is calculated by [`build_index`][Module::build_index].
2020-12-24 09:32:43 +01:00
#[inline(always)]
2021-03-08 08:30:32 +01:00
pub fn contains_qualified_fn(&self, hash_fn: u64) -> bool {
2020-12-24 09:32:43 +01:00
self.all_functions.contains_key(&hash_fn)
}
2020-11-10 16:26:50 +01:00
/// Get a namespace-qualified function.
2020-05-05 11:51:40 +02:00
///
2021-03-08 08:30:32 +01:00
/// The [`u64`] hash is calculated by [`build_index`][Module::build_index].
2020-10-08 16:25:50 +02:00
#[inline(always)]
2021-03-08 08:30:32 +01:00
pub(crate) fn get_qualified_fn(&self, hash_qualified_fn: u64) -> Option<&CallableFunction> {
2020-12-24 09:32:43 +01:00
self.all_functions.get(&hash_qualified_fn)
2020-05-05 11:51:40 +02:00
}
2020-05-05 17:57:25 +02:00
2021-01-02 16:30:10 +01:00
/// Combine another [`Module`] into this [`Module`].
/// The other [`Module`] is _consumed_ to merge into this [`Module`].
2020-10-08 16:25:50 +02:00
#[inline]
2020-08-14 18:04:10 +02:00
pub fn combine(&mut self, other: Self) -> &mut Self {
2020-10-24 18:39:47 +02:00
self.modules.extend(other.modules.into_iter());
self.variables.extend(other.variables.into_iter());
self.functions.extend(other.functions.into_iter());
self.type_iterators.extend(other.type_iterators.into_iter());
self.all_functions.clear();
self.all_variables.clear();
self.all_type_iterators.clear();
self.indexed = false;
self.contains_indexed_global_functions = false;
self
}
2021-01-02 16:30:10 +01:00
/// Combine another [`Module`] into this [`Module`].
/// The other [`Module`] is _consumed_ to merge into this [`Module`].
/// Sub-modules are flattened onto the root [`Module`], with higher level overriding lower level.
2020-10-08 16:25:50 +02:00
#[inline]
pub fn combine_flatten(&mut self, other: Self) -> &mut Self {
2020-10-24 18:39:47 +02:00
other.modules.into_iter().for_each(|(_, m)| {
2020-11-09 15:44:20 +01:00
self.combine_flatten(shared_take_or_clone(m));
2020-10-24 18:39:47 +02:00
});
self.variables.extend(other.variables.into_iter());
self.functions.extend(other.functions.into_iter());
self.type_iterators.extend(other.type_iterators.into_iter());
self.all_functions.clear();
self.all_variables.clear();
self.all_type_iterators.clear();
2020-10-24 18:39:47 +02:00
self.indexed = false;
self.contains_indexed_global_functions = false;
2020-10-24 18:39:47 +02:00
self
}
2021-01-02 16:30:10 +01:00
/// Polyfill this [`Module`] with another [`Module`].
/// Only items not existing in this [`Module`] are added.
2020-10-24 18:39:47 +02:00
#[inline]
pub fn fill_with(&mut self, other: &Self) -> &mut Self {
other.modules.iter().for_each(|(k, v)| {
if !self.modules.contains_key(k) {
self.modules.insert(k.clone(), v.clone());
}
});
other.variables.iter().for_each(|(k, v)| {
if !self.variables.contains_key(k) {
self.variables.insert(k.clone(), v.clone());
}
});
other.functions.iter().for_each(|(&k, v)| {
self.functions.entry(k).or_insert_with(|| v.clone());
});
other.type_iterators.iter().for_each(|(&k, &v)| {
self.type_iterators.entry(k).or_insert(v);
});
2020-08-14 18:04:10 +02:00
self.all_functions.clear();
self.all_variables.clear();
self.all_type_iterators.clear();
2020-08-14 18:04:10 +02:00
self.indexed = false;
self.contains_indexed_global_functions = false;
2020-08-14 18:04:10 +02:00
self
}
2021-01-02 16:30:10 +01:00
/// Merge another [`Module`] into this [`Module`].
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-07-12 05:46:53 +02:00
pub fn merge(&mut self, other: &Self) -> &mut Self {
2020-11-17 05:23:53 +01:00
self.merge_filtered(other, &mut |_, _, _, _, _| true)
}
2021-01-02 16:30:10 +01:00
/// Merge another [`Module`] into this [`Module`] based on a filter predicate.
pub(crate) fn merge_filtered(
&mut self,
other: &Self,
2021-02-13 03:56:09 +01:00
_filter: &impl Fn(FnNamespace, FnAccess, bool, &str, usize) -> bool,
2020-07-12 05:46:53 +02:00
) -> &mut Self {
#[cfg(not(feature = "no_function"))]
2020-10-24 18:39:47 +02:00
other.modules.iter().for_each(|(k, v)| {
let mut m = Self::new();
m.merge_filtered(v, _filter);
2020-12-11 05:57:07 +01:00
self.set_sub_module(k.clone(), m);
2020-10-24 18:39:47 +02:00
});
#[cfg(feature = "no_function")]
2020-10-24 18:39:47 +02:00
self.modules
.extend(other.modules.iter().map(|(k, v)| (k.clone(), v.clone())));
self.variables
.extend(other.variables.iter().map(|(k, v)| (k.clone(), v.clone())));
self.functions.extend(
other
.functions
.iter()
2021-03-12 07:11:08 +01:00
.filter(|(_, f)| {
_filter(
f.namespace,
f.access,
f.func.is_script(),
f.name.as_str(),
f.params,
)
})
2020-10-24 18:39:47 +02:00
.map(|(&k, v)| (k, v.clone())),
);
2020-10-24 18:39:47 +02:00
self.type_iterators.extend(other.type_iterators.iter());
self.all_functions.clear();
self.all_variables.clear();
self.all_type_iterators.clear();
self.indexed = false;
self.contains_indexed_global_functions = false;
2020-07-12 05:46:53 +02:00
self
}
2020-11-17 05:23:53 +01:00
/// Filter out the functions, retaining only some script-defined functions based on a filter predicate.
2020-07-04 10:21:15 +02:00
#[cfg(not(feature = "no_function"))]
2020-10-08 16:25:50 +02:00
#[inline]
2020-11-17 05:23:53 +01:00
pub(crate) fn retain_script_functions(
2020-07-12 05:46:53 +02:00
&mut self,
2021-02-13 03:56:09 +01:00
filter: impl Fn(FnNamespace, FnAccess, &str, usize) -> bool,
2020-07-12 05:46:53 +02:00
) -> &mut Self {
2021-03-23 05:13:53 +01:00
self.functions = crate::stdlib::mem::take(&mut self.functions)
.into_iter()
.filter(|(_, f)| {
if f.func.is_script() {
filter(f.namespace, f.access, f.name.as_str(), f.params)
} else {
false
}
})
.collect();
self.all_functions.clear();
self.all_variables.clear();
self.all_type_iterators.clear();
self.indexed = false;
self.contains_indexed_global_functions = false;
2020-07-12 05:46:53 +02:00
self
}
2021-01-02 16:30:10 +01:00
/// Get the number of variables, functions and type iterators in the [`Module`].
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-10-05 15:52:39 +02:00
pub fn count(&self) -> (usize, usize, usize) {
(
self.variables.len(),
2020-11-09 15:44:20 +01:00
self.functions.len(),
self.type_iterators.len(),
2020-10-05 15:52:39 +02:00
)
}
2021-01-02 16:30:10 +01:00
/// Get an iterator to the sub-modules in the [`Module`].
2020-11-23 12:11:32 +01:00
#[inline(always)]
pub fn iter_sub_modules(&self) -> impl Iterator<Item = (&str, Shared<Module>)> {
self.modules.iter().map(|(k, m)| (k.as_str(), m.clone()))
}
2021-01-02 16:30:10 +01:00
/// Get an iterator to the variables in the [`Module`].
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-11-23 12:11:32 +01:00
pub fn iter_var(&self) -> impl Iterator<Item = (&str, &Dynamic)> {
self.variables.iter().map(|(k, v)| (k.as_str(), v))
}
2021-01-02 16:30:10 +01:00
/// Get an iterator to the functions in the [`Module`].
2020-10-08 16:25:50 +02:00
#[inline(always)]
2021-01-18 03:56:42 +01:00
#[allow(dead_code)]
pub(crate) fn iter_fn(&self) -> impl Iterator<Item = &FuncInfo> {
2021-03-12 07:11:08 +01:00
self.functions.values().map(Box::as_ref)
}
2021-01-02 16:30:10 +01:00
/// Get an iterator over all script-defined functions in the [`Module`].
2020-10-05 15:52:39 +02:00
///
/// Function metadata includes:
2020-11-20 09:52:28 +01:00
/// 1) Namespace ([`FnNamespace::Global`] or [`FnNamespace::Internal`]).
/// 2) Access mode ([`FnAccess::Public`] or [`FnAccess::Private`]).
/// 3) Function name (as string slice).
/// 4) Number of parameters.
2020-11-25 02:36:06 +01:00
/// 5) Shared reference to function definition [`ScriptFnDef`][crate::ast::ScriptFnDef].
2020-07-04 10:21:15 +02:00
#[cfg(not(feature = "no_function"))]
2020-10-08 16:25:50 +02:00
#[inline(always)]
2021-02-09 07:22:55 +01:00
pub(crate) fn iter_script_fn(
&self,
2021-03-12 07:11:08 +01:00
) -> impl Iterator<
Item = (
FnNamespace,
FnAccess,
&str,
usize,
&Shared<crate::ast::ScriptFnDef>,
),
> + '_ {
self.functions
.values()
.filter(|f| f.func.is_script())
.map(|f| {
2020-11-17 05:23:53 +01:00
(
2021-03-12 07:11:08 +01:00
f.namespace,
f.access,
f.name.as_str(),
f.params,
f.func.get_fn_def(),
2020-11-17 05:23:53 +01:00
)
2021-03-12 07:11:08 +01:00
})
}
2021-01-02 16:30:10 +01:00
/// Get an iterator over all script-defined functions in the [`Module`].
2020-10-05 15:52:39 +02:00
///
/// Function metadata includes:
2020-11-20 09:52:28 +01:00
/// 1) Namespace ([`FnNamespace::Global`] or [`FnNamespace::Internal`]).
/// 2) Access mode ([`FnAccess::Public`] or [`FnAccess::Private`]).
/// 3) Function name (as string slice).
/// 4) Number of parameters.
2020-10-05 15:52:39 +02:00
#[cfg(not(feature = "no_function"))]
#[cfg(not(feature = "internals"))]
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-11-17 05:23:53 +01:00
pub fn iter_script_fn_info(
&self,
) -> impl Iterator<Item = (FnNamespace, FnAccess, &str, usize)> {
2021-03-12 07:11:08 +01:00
self.functions
.values()
.filter(|f| f.func.is_script())
.map(|f| (f.namespace, f.access, f.name.as_str(), f.params))
2020-10-05 15:52:39 +02:00
}
2021-02-21 07:26:31 +01:00
/// _(INTERNALS)_ Get an iterator over all script-defined functions in the [`Module`].
/// Exported under the `internals` feature only.
2020-10-05 15:52:39 +02:00
///
/// Function metadata includes:
2020-11-20 09:52:28 +01:00
/// 1) Namespace ([`FnNamespace::Global`] or [`FnNamespace::Internal`]).
/// 2) Access mode ([`FnAccess::Public`] or [`FnAccess::Private`]).
/// 3) Function name (as string slice).
/// 4) Number of parameters.
2020-11-25 02:36:06 +01:00
/// 5) _(INTERNALS)_ Shared reference to function definition [`ScriptFnDef`][crate::ast::ScriptFnDef].
2020-10-05 15:52:39 +02:00
#[cfg(not(feature = "no_function"))]
#[cfg(feature = "internals")]
#[inline(always)]
pub fn iter_script_fn_info(
&self,
2021-03-12 12:33:22 +01:00
) -> impl Iterator<
Item = (
FnNamespace,
FnAccess,
&str,
usize,
&Shared<crate::ast::ScriptFnDef>,
),
> {
2020-10-05 15:52:39 +02:00
self.iter_script_fn()
}
2021-01-02 16:30:10 +01:00
/// Create a new [`Module`] by evaluating an [`AST`][crate::AST].
///
2020-11-20 09:52:28 +01:00
/// The entire [`AST`][crate::AST] is encapsulated into each function, allowing functions
/// to cross-call each other. Functions in the global namespace, plus all functions
2021-01-02 16:30:10 +01:00
/// defined in the [`Module`], are _merged_ into a _unified_ namespace before each call.
/// Therefore, all functions will be found.
///
2020-10-27 04:30:38 +01:00
/// # Example
///
/// ```
/// # fn main() -> Result<(), Box<rhai::EvalAltResult>> {
/// use rhai::{Engine, Module, Scope};
///
/// let engine = Engine::new();
/// let ast = engine.compile("let answer = 42; export answer;")?;
/// let module = Module::eval_ast_as_new(Scope::new(), &ast, &engine)?;
/// assert!(module.contains_var("answer"));
/// assert_eq!(module.get_var_value::<i64>("answer").unwrap(), 42);
/// # Ok(())
/// # }
/// ```
2020-05-13 13:21:42 +02:00
#[cfg(not(feature = "no_module"))]
pub fn eval_ast_as_new(
2020-11-16 09:28:04 +01:00
mut scope: crate::Scope,
ast: &crate::AST,
engine: &crate::Engine,
) -> Result<Self, Box<EvalAltResult>> {
2021-03-01 07:54:20 +01:00
let mut mods: crate::engine::Imports = Default::default();
2020-11-15 16:14:16 +01:00
let orig_mods_len = mods.len();
// Run the script
2020-12-29 05:29:45 +01:00
engine.eval_ast_with_scope_raw(&mut scope, &mut mods, &ast, 0)?;
// Create new module
let mut module = Module::new();
2020-12-08 15:47:38 +01:00
scope.into_iter().for_each(|(_, value, mut aliases)| {
2020-11-01 15:46:46 +01:00
// Variables with an alias left in the scope become module variables
2021-03-17 06:30:47 +01:00
match aliases.len() {
0 => (),
1 => {
module.variables.insert(aliases.pop().unwrap(), value);
}
_ => aliases.into_iter().for_each(|alias| {
2020-11-09 07:38:33 +01:00
module.variables.insert(alias, value.clone());
2021-03-17 06:30:47 +01:00
}),
2020-11-01 15:46:46 +01:00
}
});
2020-11-15 16:14:16 +01:00
// Extra modules left in the scope become sub-modules
2020-11-16 09:28:04 +01:00
let mut func_mods: crate::engine::Imports = Default::default();
2020-11-15 16:14:16 +01:00
2020-11-17 05:23:53 +01:00
mods.into_iter().skip(orig_mods_len).for_each(|(alias, m)| {
func_mods.push(alias.clone(), m.clone());
module.set_sub_module(alias, m);
});
// Non-private functions defined become module functions
#[cfg(not(feature = "no_function"))]
2021-03-01 09:53:03 +01:00
ast.lib()
.functions
.values()
2021-03-12 07:11:08 +01:00
.filter(|f| match f.access {
FnAccess::Public => true,
FnAccess::Private => false,
})
2021-03-12 07:11:08 +01:00
.filter(|f| f.func.is_script())
.for_each(|f| {
2021-03-01 09:53:03 +01:00
// Encapsulate AST environment
2021-03-12 07:11:08 +01:00
let mut func = crate::fn_native::shared_take_or_clone(f.func.get_fn_def().clone());
2021-03-01 09:53:03 +01:00
func.lib = Some(ast.shared_lib());
func.mods = func_mods.clone();
module.set_script_fn(func);
});
2020-12-21 15:04:46 +01:00
module.set_id(ast.clone_source());
2020-11-21 15:18:32 +01:00
module.build_index();
Ok(module)
}
/// Does the [`Module`] contain indexed functions that have been exposed to the global namespace?
///
/// # Panics
///
/// Panics if the [`Module`] is not yet indexed via [`build_index`][Module::build_index].
#[inline(always)]
pub fn contains_indexed_global_functions(&self) -> bool {
self.contains_indexed_global_functions
}
2021-01-02 16:30:10 +01:00
/// Scan through all the sub-modules in the [`Module`] and build a hash index of all
/// variables and functions as one flattened namespace.
///
2021-01-02 16:30:10 +01:00
/// If the [`Module`] is already indexed, this method has no effect.
2020-11-21 15:18:32 +01:00
pub fn build_index(&mut self) -> &mut Self {
// Collect a particular module.
2020-05-09 04:00:59 +02:00
fn index_module<'a>(
2020-05-17 16:19:49 +02:00
module: &'a Module,
2021-03-12 15:30:08 +01:00
path: &mut Vec<&'a str>,
2021-03-23 05:13:53 +01:00
variables: &mut BTreeMap<u64, Dynamic>,
functions: &mut BTreeMap<u64, CallableFunction>,
type_iterators: &mut BTreeMap<TypeId, IteratorFn>,
) -> bool {
let mut contains_indexed_global_functions = false;
2020-10-01 17:31:27 +02:00
module.modules.iter().for_each(|(name, m)| {
2020-05-09 04:00:59 +02:00
// Index all the sub-modules first.
2021-03-12 15:30:08 +01:00
path.push(name);
if index_module(m, path, variables, functions, type_iterators) {
contains_indexed_global_functions = true;
}
2021-03-12 15:30:08 +01:00
path.pop();
2020-10-01 17:31:27 +02:00
});
2020-05-09 04:00:59 +02:00
// Index all variables
2020-10-01 17:31:27 +02:00
module.variables.iter().for_each(|(var_name, value)| {
2021-03-12 15:30:08 +01:00
let hash_var = crate::calc_fn_hash(path.iter().map(|&v| v), var_name, 0);
variables.insert(hash_var, value.clone());
});
// Index type iterators
module.type_iterators.iter().for_each(|(&type_id, func)| {
type_iterators.insert(type_id, func.clone());
contains_indexed_global_functions = true;
2020-10-01 17:31:27 +02:00
});
2020-05-09 04:00:59 +02:00
// Index all Rust functions
2021-03-12 07:11:08 +01:00
module.functions.iter().for_each(|(&hash, f)| {
match f.namespace {
FnNamespace::Global => {
// Flatten all functions with global namespace
functions.insert(hash, f.func.clone());
contains_indexed_global_functions = true;
}
2021-03-12 07:11:08 +01:00
FnNamespace::Internal => (),
}
match f.access {
FnAccess::Public => (),
FnAccess::Private => return, // Do not index private functions
}
2021-03-12 07:11:08 +01:00
if !f.func.is_script() {
2021-03-12 15:30:08 +01:00
let hash_qualified_fn =
calc_native_fn_hash(path.iter().cloned(), f.name.as_str(), &f.param_types);
2021-03-12 07:11:08 +01:00
functions.insert(hash_qualified_fn, f.func.clone());
} else if cfg!(not(feature = "no_function")) {
let hash_qualified_script =
2021-03-12 15:30:08 +01:00
crate::calc_fn_hash(path.iter().cloned(), f.name.as_str(), f.params);
2021-03-12 07:11:08 +01:00
functions.insert(hash_qualified_script, f.func.clone());
}
});
contains_indexed_global_functions
}
2020-10-01 17:31:27 +02:00
if !self.indexed {
2021-03-12 15:30:08 +01:00
let mut path = Vec::with_capacity(4);
2021-03-23 05:13:53 +01:00
let mut variables = Default::default();
let mut functions = Default::default();
let mut type_iterators = Default::default();
2020-07-26 09:53:22 +02:00
2021-03-12 15:30:08 +01:00
path.push("root");
self.contains_indexed_global_functions = index_module(
self,
2021-03-12 15:30:08 +01:00
&mut path,
&mut variables,
&mut functions,
&mut type_iterators,
);
self.all_variables = variables;
self.all_functions = functions;
self.all_type_iterators = type_iterators;
2020-10-01 17:31:27 +02:00
self.indexed = true;
}
2020-11-21 15:18:32 +01:00
self
}
2020-05-13 13:21:42 +02:00
/// Does a type iterator exist in the entire module tree?
#[inline(always)]
pub fn contains_qualified_iter(&self, id: TypeId) -> bool {
self.all_type_iterators.contains_key(&id)
}
2020-05-13 13:21:42 +02:00
/// Does a type iterator exist in the module?
#[inline(always)]
2020-05-13 14:22:05 +02:00
pub fn contains_iter(&self, id: TypeId) -> bool {
2020-05-13 13:21:42 +02:00
self.type_iterators.contains_key(&id)
}
2021-01-02 16:30:10 +01:00
/// Set a type iterator into the [`Module`].
#[inline(always)]
2020-07-12 05:46:53 +02:00
pub fn set_iter(&mut self, typ: TypeId, func: IteratorFn) -> &mut Self {
2020-05-20 13:27:23 +02:00
self.type_iterators.insert(typ, func);
self.indexed = false;
self.contains_indexed_global_functions = false;
2020-07-12 05:46:53 +02:00
self
2020-05-13 13:21:42 +02:00
}
2021-01-02 16:30:10 +01:00
/// Set a type iterator into the [`Module`].
#[inline(always)]
2020-10-15 16:11:18 +02:00
pub fn set_iterable<T>(&mut self) -> &mut Self
where
T: Variant + Clone + IntoIterator,
<T as IntoIterator>::Item: Variant + Clone,
{
2020-10-14 17:22:10 +02:00
self.set_iter(TypeId::of::<T>(), |obj: Dynamic| {
Box::new(obj.cast::<T>().into_iter().map(Dynamic::from))
})
}
2021-01-02 16:30:10 +01:00
/// Set an iterator type into the [`Module`] as a type iterator.
#[inline(always)]
2020-10-15 16:11:18 +02:00
pub fn set_iterator<T>(&mut self) -> &mut Self
where
T: Variant + Clone + Iterator,
<T as Iterator>::Item: Variant + Clone,
{
2020-10-14 17:22:10 +02:00
self.set_iter(TypeId::of::<T>(), |obj: Dynamic| {
Box::new(obj.cast::<T>().map(Dynamic::from))
})
}
/// Get the specified type iterator.
#[inline(always)]
pub(crate) fn get_qualified_iter(&self, id: TypeId) -> Option<IteratorFn> {
self.all_type_iterators.get(&id).cloned()
}
2020-05-13 13:21:42 +02:00
/// Get the specified type iterator.
#[inline(always)]
2020-06-20 04:49:15 +02:00
pub(crate) fn get_iter(&self, id: TypeId) -> Option<IteratorFn> {
2020-05-20 13:27:23 +02:00
self.type_iterators.get(&id).cloned()
2020-05-13 13:21:42 +02:00
}
}
2020-11-25 02:36:06 +01:00
/// _(INTERNALS)_ A chain of [module][Module] names to namespace-qualify a variable or function call.
/// Exported under the `internals` feature only.
///
2021-03-08 08:30:32 +01:00
/// A [`u64`] offset to the current [`Scope`][crate::Scope] is cached for quick search purposes.
2020-05-13 13:21:42 +02:00
///
2020-11-20 09:52:28 +01:00
/// A [`StaticVec`] is used because most namespace-qualified access contains only one level,
/// and it is wasteful to always allocate a [`Vec`] with one element.
///
2021-01-16 07:46:03 +01:00
/// # Volatile Data Structure
///
/// This type is volatile and may change.
2020-07-19 11:14:55 +02:00
#[derive(Clone, Eq, PartialEq, Default, Hash)]
2021-01-11 16:09:33 +01:00
pub struct NamespaceRef {
index: Option<NonZeroUsize>,
path: StaticVec<Ident>,
}
2020-05-13 13:21:42 +02:00
2020-11-10 16:26:50 +01:00
impl fmt::Debug for NamespaceRef {
#[inline(always)]
2020-05-13 13:21:42 +02:00
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2021-01-11 16:09:33 +01:00
if let Some(index) = self.index {
2021-03-09 07:00:21 +01:00
write!(f, "{} -> ", index)?;
2020-05-13 13:21:42 +02:00
}
2021-03-09 07:00:21 +01:00
f.write_str(
&self
.path
.iter()
.map(|Ident { name, .. }| name.as_str())
.collect::<Vec<_>>()
.join("::"),
)
2020-05-13 13:21:42 +02:00
}
}
2020-11-10 16:26:50 +01:00
impl Deref for NamespaceRef {
2020-12-22 09:45:56 +01:00
type Target = StaticVec<Ident>;
2020-05-13 13:21:42 +02:00
#[inline(always)]
2020-05-13 13:21:42 +02:00
fn deref(&self) -> &Self::Target {
2021-01-11 16:09:33 +01:00
&self.path
2020-05-13 13:21:42 +02:00
}
}
2020-11-10 16:26:50 +01:00
impl DerefMut for NamespaceRef {
#[inline(always)]
2020-05-13 13:21:42 +02:00
fn deref_mut(&mut self) -> &mut Self::Target {
2021-01-11 16:09:33 +01:00
&mut self.path
2020-05-13 13:21:42 +02:00
}
}
2020-11-10 16:26:50 +01:00
impl fmt::Display for NamespaceRef {
#[inline(always)]
2020-05-13 13:21:42 +02:00
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2021-01-11 16:09:33 +01:00
for Ident { name, .. } in self.path.iter() {
2020-10-31 17:04:02 +01:00
write!(f, "{}{}", name, Token::DoubleColon.syntax())?;
2020-05-13 13:21:42 +02:00
}
Ok(())
}
}
2020-12-22 09:45:56 +01:00
impl From<StaticVec<Ident>> for NamespaceRef {
#[inline(always)]
2021-01-11 16:09:33 +01:00
fn from(path: StaticVec<Ident>) -> Self {
Self { index: None, path }
}
}
2020-11-10 16:26:50 +01:00
impl NamespaceRef {
2020-12-24 16:22:50 +01:00
/// Get the [`Scope`][crate::Scope] index offset.
#[inline(always)]
2020-05-13 13:21:42 +02:00
pub(crate) fn index(&self) -> Option<NonZeroUsize> {
2021-01-11 16:09:33 +01:00
self.index
2020-05-13 13:21:42 +02:00
}
2020-12-24 16:22:50 +01:00
/// Set the [`Scope`][crate::Scope] index offset.
2020-10-18 16:10:08 +02:00
#[cfg(not(feature = "no_module"))]
#[inline(always)]
2020-05-13 13:21:42 +02:00
pub(crate) fn set_index(&mut self, index: Option<NonZeroUsize>) {
2021-01-11 16:09:33 +01:00
self.index = index
2020-05-13 13:21:42 +02:00
}
}
#[cfg(not(feature = "no_module"))]
pub use resolvers::ModuleResolver;
2021-01-02 16:30:10 +01:00
/// Module containing all built-in [module resolvers][ModuleResolver].
2020-07-07 17:44:23 +02:00
#[cfg(not(feature = "no_module"))]
pub mod resolvers;