2020-07-23 12:40:42 +02:00
|
|
|
//! Module defining interfaces to native-Rust functions.
|
|
|
|
|
2021-04-20 16:26:08 +02:00
|
|
|
use crate::ast::{FnAccess, FnCallHashes};
|
2021-11-07 11:12:37 +01:00
|
|
|
use crate::engine::{EvalState, Imports};
|
2021-06-17 03:50:32 +02:00
|
|
|
use crate::fn_call::FnCallArgs;
|
2020-07-26 10:10:38 +02:00
|
|
|
use crate::plugin::PluginFunction;
|
2021-09-24 16:44:39 +02:00
|
|
|
use crate::token::{Token, TokenizeState};
|
2020-11-16 16:10:14 +01:00
|
|
|
use crate::{
|
2021-06-17 03:50:32 +02:00
|
|
|
calc_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, Module, Position, RhaiResult,
|
2020-11-16 16:10:14 +01:00
|
|
|
};
|
2021-06-17 03:50:32 +02:00
|
|
|
use std::fmt;
|
2021-04-17 09:15:54 +02:00
|
|
|
#[cfg(feature = "no_std")]
|
|
|
|
use std::prelude::v1::*;
|
2020-07-26 04:03:59 +02:00
|
|
|
|
2020-06-18 12:39:28 +02:00
|
|
|
/// Trait that maps to `Send + Sync` only under the `sync` feature.
|
2020-05-12 10:32:22 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2020-05-21 11:11:01 +02:00
|
|
|
pub trait SendSync: Send + Sync {}
|
2020-07-31 10:03:08 +02:00
|
|
|
/// Trait that maps to `Send + Sync` only under the `sync` feature.
|
2020-05-12 10:32:22 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2020-05-21 11:11:01 +02:00
|
|
|
impl<T: Send + Sync> SendSync for T {}
|
2020-05-12 10:32:22 +02:00
|
|
|
|
2020-06-18 12:39:28 +02:00
|
|
|
/// Trait that maps to `Send + Sync` only under the `sync` feature.
|
2020-05-12 10:32:22 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2020-05-21 11:11:01 +02:00
|
|
|
pub trait SendSync {}
|
2020-07-31 10:03:08 +02:00
|
|
|
/// Trait that maps to `Send + Sync` only under the `sync` feature.
|
2020-05-12 10:32:22 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2020-05-21 11:11:01 +02:00
|
|
|
impl<T> SendSync for T {}
|
2020-05-12 10:32:22 +02:00
|
|
|
|
2020-10-16 17:41:56 +02:00
|
|
|
/// Immutable reference-counted container.
|
2020-05-12 10:32:22 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2021-04-17 09:15:54 +02:00
|
|
|
pub use std::rc::Rc as Shared;
|
2020-10-16 17:41:56 +02:00
|
|
|
/// Immutable reference-counted container.
|
2020-05-12 10:32:22 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2021-04-17 09:15:54 +02:00
|
|
|
pub use std::sync::Arc as Shared;
|
2020-05-12 10:32:22 +02:00
|
|
|
|
2020-10-16 17:41:56 +02:00
|
|
|
/// Synchronized shared object.
|
2021-05-10 05:07:19 +02:00
|
|
|
///
|
|
|
|
/// Not available under `no_closure`.
|
2020-11-27 16:37:59 +01:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-10-16 17:41:56 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2021-04-17 09:15:54 +02:00
|
|
|
pub use std::cell::RefCell as Locked;
|
2020-10-16 17:41:56 +02:00
|
|
|
/// Synchronized shared object.
|
2021-05-10 05:07:19 +02:00
|
|
|
///
|
|
|
|
/// Not available under `no_closure`.
|
2020-11-27 16:37:59 +01:00
|
|
|
#[cfg(not(feature = "no_closure"))]
|
2020-10-16 17:41:56 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2021-04-17 09:15:54 +02:00
|
|
|
pub use std::sync::RwLock as Locked;
|
2020-10-16 17:41:56 +02:00
|
|
|
|
2020-11-25 02:36:06 +01:00
|
|
|
/// Context of a native Rust function call.
|
2021-03-15 04:36:30 +01:00
|
|
|
#[derive(Debug)]
|
2021-03-03 15:49:57 +01:00
|
|
|
pub struct NativeCallContext<'a> {
|
|
|
|
engine: &'a Engine,
|
|
|
|
fn_name: &'a str,
|
|
|
|
source: Option<&'a str>,
|
|
|
|
mods: Option<&'a Imports>,
|
|
|
|
lib: &'a [&'a Module],
|
2021-11-05 12:35:33 +01:00
|
|
|
pos: Position,
|
2020-10-18 11:02:17 +02:00
|
|
|
}
|
|
|
|
|
2021-03-03 15:49:57 +01:00
|
|
|
impl<'a, M: AsRef<[&'a Module]> + ?Sized>
|
2021-11-05 12:35:33 +01:00
|
|
|
From<(
|
|
|
|
&'a Engine,
|
|
|
|
&'a str,
|
|
|
|
Option<&'a str>,
|
|
|
|
&'a Imports,
|
|
|
|
&'a M,
|
|
|
|
Position,
|
|
|
|
)> for NativeCallContext<'a>
|
2020-11-07 16:33:21 +01:00
|
|
|
{
|
2020-12-29 03:41:20 +01:00
|
|
|
#[inline(always)]
|
2021-11-05 12:35:33 +01:00
|
|
|
fn from(
|
|
|
|
value: (
|
|
|
|
&'a Engine,
|
|
|
|
&'a str,
|
|
|
|
Option<&'a str>,
|
|
|
|
&'a Imports,
|
|
|
|
&'a M,
|
|
|
|
Position,
|
|
|
|
),
|
|
|
|
) -> Self {
|
2020-11-07 16:33:21 +01:00
|
|
|
Self {
|
|
|
|
engine: value.0,
|
2021-01-21 14:49:25 +01:00
|
|
|
fn_name: value.1,
|
|
|
|
source: value.2,
|
|
|
|
mods: Some(value.3),
|
|
|
|
lib: value.4.as_ref(),
|
2021-11-05 12:35:33 +01:00
|
|
|
pos: value.5,
|
2020-11-07 16:33:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-07 11:12:37 +01:00
|
|
|
impl<'a, M: AsRef<[&'a Module]> + ?Sized> From<(&'a Engine, &'a str, &'a M)>
|
2021-03-03 15:49:57 +01:00
|
|
|
for NativeCallContext<'a>
|
2020-10-20 04:54:32 +02:00
|
|
|
{
|
2020-12-29 03:41:20 +01:00
|
|
|
#[inline(always)]
|
2021-11-07 11:12:37 +01:00
|
|
|
fn from(value: (&'a Engine, &'a str, &'a M)) -> Self {
|
2020-10-18 11:02:17 +02:00
|
|
|
Self {
|
|
|
|
engine: value.0,
|
2021-01-21 14:49:25 +01:00
|
|
|
fn_name: value.1,
|
2020-12-21 16:12:45 +01:00
|
|
|
source: None,
|
2020-11-07 16:33:21 +01:00
|
|
|
mods: None,
|
2021-01-21 14:49:25 +01:00
|
|
|
lib: value.2.as_ref(),
|
2021-11-07 11:12:37 +01:00
|
|
|
pos: Position::NONE,
|
2020-10-18 11:02:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-03 15:49:57 +01:00
|
|
|
impl<'a> NativeCallContext<'a> {
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Create a new [`NativeCallContext`].
|
2020-11-08 11:15:23 +01:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-11-07 11:12:37 +01:00
|
|
|
pub const fn new(engine: &'a Engine, fn_name: &'a str, lib: &'a [&Module]) -> Self {
|
2020-11-08 11:15:23 +01:00
|
|
|
Self {
|
|
|
|
engine,
|
2021-01-21 14:49:25 +01:00
|
|
|
fn_name,
|
2020-12-21 16:12:45 +01:00
|
|
|
source: None,
|
2020-11-08 11:15:23 +01:00
|
|
|
mods: None,
|
2021-03-01 08:58:11 +01:00
|
|
|
lib,
|
2021-11-07 11:12:37 +01:00
|
|
|
pos: Position::NONE,
|
2020-11-08 11:15:23 +01:00
|
|
|
}
|
|
|
|
}
|
2021-07-25 16:56:05 +02:00
|
|
|
/// _(internals)_ Create a new [`NativeCallContext`].
|
2021-04-02 06:34:39 +02:00
|
|
|
/// Exported under the `internals` feature only.
|
2021-05-10 05:07:19 +02:00
|
|
|
///
|
|
|
|
/// Not available under `no_module`.
|
2020-11-08 11:15:23 +01:00
|
|
|
#[cfg(feature = "internals")]
|
|
|
|
#[cfg(not(feature = "no_module"))]
|
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const fn new_with_all_fields(
|
2021-03-03 15:49:57 +01:00
|
|
|
engine: &'a Engine,
|
|
|
|
fn_name: &'a str,
|
2021-06-28 12:29:53 +02:00
|
|
|
source: Option<&'a str>,
|
2021-03-03 15:49:57 +01:00
|
|
|
imports: &'a Imports,
|
|
|
|
lib: &'a [&Module],
|
2021-11-05 12:35:33 +01:00
|
|
|
pos: Position,
|
2020-11-08 11:15:23 +01:00
|
|
|
) -> Self {
|
|
|
|
Self {
|
|
|
|
engine,
|
2021-01-23 03:34:38 +01:00
|
|
|
fn_name,
|
2021-06-28 12:29:53 +02:00
|
|
|
source,
|
2020-12-29 16:01:34 +01:00
|
|
|
mods: Some(imports),
|
2021-03-01 08:58:11 +01:00
|
|
|
lib,
|
2021-11-05 12:35:33 +01:00
|
|
|
pos,
|
2020-11-08 11:15:23 +01:00
|
|
|
}
|
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// The current [`Engine`].
|
2020-10-18 11:02:17 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const fn engine(&self) -> &Engine {
|
2020-10-18 11:02:17 +02:00
|
|
|
self.engine
|
|
|
|
}
|
2021-01-21 14:49:25 +01:00
|
|
|
/// Name of the function called.
|
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const fn fn_name(&self) -> &str {
|
2021-01-21 14:49:25 +01:00
|
|
|
self.fn_name
|
|
|
|
}
|
2021-11-05 12:35:33 +01:00
|
|
|
/// [Position][`Position`] of the function call.
|
|
|
|
#[inline(always)]
|
|
|
|
#[must_use]
|
|
|
|
pub const fn position(&self) -> Position {
|
|
|
|
self.pos
|
|
|
|
}
|
2020-12-21 16:12:45 +01:00
|
|
|
/// The current source.
|
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const fn source(&self) -> Option<&str> {
|
2020-12-21 16:12:45 +01:00
|
|
|
self.source
|
|
|
|
}
|
2021-01-01 10:05:06 +01:00
|
|
|
/// Get an iterator over the current set of modules imported via `import` statements.
|
2021-05-10 05:07:19 +02:00
|
|
|
///
|
|
|
|
/// Not available under `no_module`.
|
2021-01-01 10:05:06 +01:00
|
|
|
#[cfg(not(feature = "no_module"))]
|
2021-10-21 11:26:43 +02:00
|
|
|
#[inline]
|
2021-01-01 10:05:06 +01:00
|
|
|
pub fn iter_imports(&self) -> impl Iterator<Item = (&str, &Module)> {
|
2021-01-02 16:30:10 +01:00
|
|
|
self.mods.iter().flat_map(|&m| m.iter())
|
2021-01-01 10:05:06 +01:00
|
|
|
}
|
2021-03-03 15:49:57 +01:00
|
|
|
/// Get an iterator over the current set of modules imported via `import` statements.
|
|
|
|
#[cfg(not(feature = "no_module"))]
|
2021-03-07 15:10:54 +01:00
|
|
|
#[allow(dead_code)]
|
2021-10-21 11:26:43 +02:00
|
|
|
#[inline]
|
2021-03-31 04:16:38 +02:00
|
|
|
pub(crate) fn iter_imports_raw(
|
|
|
|
&self,
|
|
|
|
) -> impl Iterator<Item = (&crate::Identifier, &Shared<Module>)> {
|
2021-03-03 15:49:57 +01:00
|
|
|
self.mods.iter().flat_map(|&m| m.iter_raw())
|
|
|
|
}
|
2021-07-25 16:56:05 +02:00
|
|
|
/// _(internals)_ The current set of modules imported via `import` statements.
|
2021-04-02 06:34:39 +02:00
|
|
|
/// Exported under the `internals` feature only.
|
2021-05-10 05:07:19 +02:00
|
|
|
///
|
|
|
|
/// Not available under `no_module`.
|
2020-11-07 16:33:21 +01:00
|
|
|
#[cfg(feature = "internals")]
|
|
|
|
#[cfg(not(feature = "no_module"))]
|
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const fn imports(&self) -> Option<&Imports> {
|
2020-11-07 16:33:21 +01:00
|
|
|
self.mods
|
|
|
|
}
|
2021-01-01 10:05:06 +01:00
|
|
|
/// Get an iterator over the namespaces containing definitions of all script-defined functions.
|
2021-10-21 11:26:43 +02:00
|
|
|
#[inline]
|
2021-01-01 10:05:06 +01:00
|
|
|
pub fn iter_namespaces(&self) -> impl Iterator<Item = &Module> {
|
2020-10-20 12:09:26 +02:00
|
|
|
self.lib.iter().cloned()
|
2020-10-18 11:02:17 +02:00
|
|
|
}
|
2021-07-25 16:56:05 +02:00
|
|
|
/// _(internals)_ The current set of namespaces containing definitions of all script-defined functions.
|
2021-04-02 06:34:39 +02:00
|
|
|
/// Exported under the `internals` feature only.
|
2021-01-01 10:05:06 +01:00
|
|
|
#[cfg(feature = "internals")]
|
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const fn namespaces(&self) -> &[&Module] {
|
2021-01-01 10:05:06 +01:00
|
|
|
self.lib
|
|
|
|
}
|
2020-11-08 16:00:37 +01:00
|
|
|
/// Call a function inside the call context.
|
|
|
|
///
|
2021-10-19 17:52:58 +02:00
|
|
|
/// If `is_method_call` is [`true`], the first argument is assumed to be the
|
|
|
|
/// `this` pointer for a script-defined function (or the object of a method call).
|
|
|
|
///
|
2021-01-02 16:30:10 +01:00
|
|
|
/// # WARNING
|
2020-11-08 16:00:37 +01:00
|
|
|
///
|
|
|
|
/// All arguments may be _consumed_, meaning that they may be replaced by `()`.
|
|
|
|
/// This is to avoid unnecessarily cloning the arguments.
|
2020-11-20 09:52:28 +01:00
|
|
|
///
|
2020-11-08 16:00:37 +01:00
|
|
|
/// Do not use the arguments after this call. If they are needed afterwards,
|
|
|
|
/// clone them _before_ calling this function.
|
|
|
|
///
|
2021-10-19 13:57:15 +02:00
|
|
|
/// If `is_ref_mut` is [`true`], the first argument is assumed to be passed
|
2020-11-08 16:00:37 +01:00
|
|
|
/// by reference and is not consumed.
|
2021-10-19 13:57:15 +02:00
|
|
|
pub fn call_fn_raw(
|
2020-11-30 04:20:51 +01:00
|
|
|
&self,
|
2021-10-19 13:57:15 +02:00
|
|
|
fn_name: &str,
|
|
|
|
is_ref_mut: bool,
|
2021-06-17 03:50:32 +02:00
|
|
|
is_method_call: bool,
|
2020-11-08 16:00:37 +01:00
|
|
|
args: &mut [&mut Dynamic],
|
2021-10-19 13:57:15 +02:00
|
|
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
|
|
let hash = if is_method_call {
|
|
|
|
FnCallHashes::from_script_and_native(
|
|
|
|
calc_fn_hash(fn_name, args.len() - 1),
|
|
|
|
calc_fn_hash(fn_name, args.len()),
|
|
|
|
)
|
|
|
|
} else {
|
|
|
|
FnCallHashes::from_script(calc_fn_hash(fn_name, args.len()))
|
|
|
|
};
|
2021-03-08 08:30:32 +01:00
|
|
|
|
2021-10-19 13:57:15 +02:00
|
|
|
self.engine()
|
|
|
|
.exec_fn_call(
|
2021-11-07 11:12:37 +01:00
|
|
|
&mut self.mods.cloned().unwrap_or_else(|| Imports::new()),
|
|
|
|
&mut EvalState::new(),
|
2021-10-19 13:57:15 +02:00
|
|
|
self.lib,
|
|
|
|
fn_name,
|
|
|
|
hash,
|
|
|
|
args,
|
|
|
|
is_ref_mut,
|
|
|
|
is_method_call,
|
|
|
|
Position::NONE,
|
|
|
|
None,
|
|
|
|
0,
|
|
|
|
)
|
|
|
|
.map(|(r, _)| r)
|
2020-11-08 16:00:37 +01:00
|
|
|
}
|
2020-10-18 11:02:17 +02:00
|
|
|
}
|
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Consume a [`Shared`] resource and return a mutable reference to the wrapped value.
|
2020-05-26 08:14:03 +02:00
|
|
|
/// If the resource is shared (i.e. has other outstanding references), a cloned copy is used.
|
2020-11-09 15:44:20 +01:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-05-25 11:01:39 +02:00
|
|
|
pub fn shared_make_mut<T: Clone>(value: &mut Shared<T>) -> &mut T {
|
2021-03-04 07:08:11 +01:00
|
|
|
Shared::make_mut(value)
|
2020-05-25 11:01:39 +02:00
|
|
|
}
|
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Consume a [`Shared`] resource if is unique (i.e. not shared), or clone it otherwise.
|
2021-10-21 11:26:43 +02:00
|
|
|
#[inline]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-11-09 15:44:20 +01:00
|
|
|
pub fn shared_take_or_clone<T: Clone>(value: Shared<T>) -> T {
|
|
|
|
shared_try_take(value).unwrap_or_else(|v| v.as_ref().clone())
|
|
|
|
}
|
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Consume a [`Shared`] resource if is unique (i.e. not shared).
|
2020-11-09 15:44:20 +01:00
|
|
|
#[inline(always)]
|
2020-08-08 11:04:21 +02:00
|
|
|
pub fn shared_try_take<T>(value: Shared<T>) -> Result<T, Shared<T>> {
|
2021-03-04 07:08:11 +01:00
|
|
|
Shared::try_unwrap(value)
|
2020-08-08 10:24:10 +02:00
|
|
|
}
|
|
|
|
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Consume a [`Shared`] resource, assuming that it is unique (i.e. not shared).
|
2020-05-26 08:14:03 +02:00
|
|
|
///
|
|
|
|
/// # Panics
|
|
|
|
///
|
|
|
|
/// Panics if the resource is shared (i.e. has other outstanding references).
|
2021-10-21 11:26:43 +02:00
|
|
|
#[inline]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-08-08 11:04:21 +02:00
|
|
|
pub fn shared_take<T>(value: Shared<T>) -> T {
|
2021-05-22 13:14:24 +02:00
|
|
|
shared_try_take(value)
|
|
|
|
.ok()
|
2021-08-26 17:58:41 +02:00
|
|
|
.expect("no outstanding references")
|
2020-05-25 11:01:39 +02:00
|
|
|
}
|
|
|
|
|
2020-06-25 12:07:57 +02:00
|
|
|
/// A general function trail object.
|
2020-05-19 16:25:57 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2021-03-02 08:02:28 +01:00
|
|
|
pub type FnAny = dyn Fn(NativeCallContext, &mut FnCallArgs) -> RhaiResult;
|
2020-06-25 12:07:57 +02:00
|
|
|
/// A general function trail object.
|
2020-05-19 16:25:57 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2021-03-02 08:02:28 +01:00
|
|
|
pub type FnAny = dyn Fn(NativeCallContext, &mut FnCallArgs) -> RhaiResult + Send + Sync;
|
2020-05-19 16:25:57 +02:00
|
|
|
|
2020-06-18 12:39:28 +02:00
|
|
|
/// A standard function that gets an iterator from a type.
|
2020-05-21 11:11:01 +02:00
|
|
|
pub type IteratorFn = fn(Dynamic) -> Box<dyn Iterator<Item = Dynamic>>;
|
2020-05-19 16:25:57 +02:00
|
|
|
|
2020-07-02 06:47:24 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2020-09-29 07:06:48 +02:00
|
|
|
pub type FnPlugin = dyn PluginFunction;
|
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
pub type FnPlugin = dyn PluginFunction + Send + Sync;
|
2020-07-02 06:47:24 +02:00
|
|
|
|
2020-12-12 03:10:27 +01:00
|
|
|
/// A standard callback function for progress reporting.
|
2021-04-25 09:27:58 +02:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2020-06-02 07:33:16 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2020-12-12 03:10:27 +01:00
|
|
|
pub type OnProgressCallback = Box<dyn Fn(u64) -> Option<Dynamic> + 'static>;
|
|
|
|
/// A standard callback function for progress reporting.
|
2021-04-25 09:27:58 +02:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2020-06-02 07:33:16 +02:00
|
|
|
#[cfg(feature = "sync")]
|
2020-12-12 03:10:27 +01:00
|
|
|
pub type OnProgressCallback = Box<dyn Fn(u64) -> Option<Dynamic> + Send + Sync + 'static>;
|
2020-06-03 04:44:26 +02:00
|
|
|
|
2020-12-12 03:10:27 +01:00
|
|
|
/// A standard callback function for printing.
|
|
|
|
#[cfg(not(feature = "sync"))]
|
|
|
|
pub type OnPrintCallback = Box<dyn Fn(&str) + 'static>;
|
|
|
|
/// A standard callback function for printing.
|
|
|
|
#[cfg(feature = "sync")]
|
2020-12-12 04:47:18 +01:00
|
|
|
pub type OnPrintCallback = Box<dyn Fn(&str) + Send + Sync + 'static>;
|
|
|
|
|
|
|
|
/// A standard callback function for debugging.
|
|
|
|
#[cfg(not(feature = "sync"))]
|
2020-12-21 15:04:46 +01:00
|
|
|
pub type OnDebugCallback = Box<dyn Fn(&str, Option<&str>, Position) + 'static>;
|
2020-12-12 04:47:18 +01:00
|
|
|
/// A standard callback function for debugging.
|
|
|
|
#[cfg(feature = "sync")]
|
2020-12-21 15:04:46 +01:00
|
|
|
pub type OnDebugCallback = Box<dyn Fn(&str, Option<&str>, Position) + Send + Sync + 'static>;
|
2020-12-12 03:10:27 +01:00
|
|
|
|
2021-09-24 12:00:48 +02:00
|
|
|
/// A standard callback function for mapping tokens during parsing.
|
|
|
|
#[cfg(not(feature = "sync"))]
|
2021-09-24 16:44:39 +02:00
|
|
|
pub type OnParseTokenCallback = dyn Fn(Token, Position, &TokenizeState) -> Token;
|
2021-09-24 12:00:48 +02:00
|
|
|
/// A standard callback function for mapping tokens during parsing.
|
|
|
|
#[cfg(feature = "sync")]
|
2021-09-24 16:44:39 +02:00
|
|
|
pub type OnParseTokenCallback =
|
|
|
|
dyn Fn(Token, Position, &TokenizeState) -> Token + Send + Sync + 'static;
|
2021-09-24 12:00:48 +02:00
|
|
|
|
2020-12-12 03:10:27 +01:00
|
|
|
/// A standard callback function for variable access.
|
2020-10-11 15:58:11 +02:00
|
|
|
#[cfg(not(feature = "sync"))]
|
2020-10-19 13:11:55 +02:00
|
|
|
pub type OnVarCallback =
|
|
|
|
Box<dyn Fn(&str, usize, &EvalContext) -> Result<Option<Dynamic>, Box<EvalAltResult>> + 'static>;
|
2020-12-12 03:10:27 +01:00
|
|
|
/// A standard callback function for variable access.
|
2020-10-11 15:58:11 +02:00
|
|
|
#[cfg(feature = "sync")]
|
|
|
|
pub type OnVarCallback = Box<
|
2020-10-19 13:11:55 +02:00
|
|
|
dyn Fn(&str, usize, &EvalContext) -> Result<Option<Dynamic>, Box<EvalAltResult>>
|
2020-10-11 15:58:11 +02:00
|
|
|
+ Send
|
|
|
|
+ Sync
|
|
|
|
+ 'static,
|
|
|
|
>;
|
|
|
|
|
2020-05-19 13:03:06 +02:00
|
|
|
/// A type encapsulating a function callable by Rhai.
|
2020-05-19 16:25:57 +02:00
|
|
|
#[derive(Clone)]
|
2020-05-19 13:03:06 +02:00
|
|
|
pub enum CallableFunction {
|
|
|
|
/// A pure native Rust function with all arguments passed by value.
|
2020-05-21 11:11:01 +02:00
|
|
|
Pure(Shared<FnAny>),
|
2020-05-19 13:03:06 +02:00
|
|
|
/// A native Rust object method with the first argument passed by reference,
|
|
|
|
/// and the rest passed by value.
|
2020-05-21 11:11:01 +02:00
|
|
|
Method(Shared<FnAny>),
|
2020-05-19 13:03:06 +02:00
|
|
|
/// An iterator function.
|
2020-05-20 13:27:23 +02:00
|
|
|
Iterator(IteratorFn),
|
2020-09-30 16:55:40 +02:00
|
|
|
/// A plugin function,
|
2020-09-29 07:06:48 +02:00
|
|
|
Plugin(Shared<FnPlugin>),
|
2020-05-19 13:03:06 +02:00
|
|
|
/// A script-defined function.
|
2021-05-10 05:07:19 +02:00
|
|
|
///
|
|
|
|
/// Not available under `no_function`.
|
2020-07-04 10:21:15 +02:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
2021-03-07 15:10:54 +01:00
|
|
|
Script(Shared<crate::ast::ScriptFnDef>),
|
2020-06-05 09:14:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for CallableFunction {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
match self {
|
|
|
|
Self::Pure(_) => write!(f, "NativePureFunction"),
|
|
|
|
Self::Method(_) => write!(f, "NativeMethod"),
|
|
|
|
Self::Iterator(_) => write!(f, "NativeIterator"),
|
2020-07-02 06:47:24 +02:00
|
|
|
Self::Plugin(_) => write!(f, "PluginFunction"),
|
2020-07-04 10:21:15 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
2020-06-11 16:18:30 +02:00
|
|
|
Self::Script(fn_def) => fmt::Debug::fmt(fn_def, f),
|
2020-06-27 17:56:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for CallableFunction {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
match self {
|
|
|
|
Self::Pure(_) => write!(f, "NativePureFunction"),
|
|
|
|
Self::Method(_) => write!(f, "NativeMethod"),
|
|
|
|
Self::Iterator(_) => write!(f, "NativeIterator"),
|
2020-07-02 06:47:24 +02:00
|
|
|
Self::Plugin(_) => write!(f, "PluginFunction"),
|
2020-07-04 10:21:15 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
2020-06-27 17:56:24 +02:00
|
|
|
CallableFunction::Script(s) => fmt::Display::fmt(s, f),
|
2020-06-05 09:14:42 +02:00
|
|
|
}
|
|
|
|
}
|
2020-05-11 12:55:58 +02:00
|
|
|
}
|
|
|
|
|
2020-05-19 13:03:06 +02:00
|
|
|
impl CallableFunction {
|
|
|
|
/// Is this a pure native Rust function?
|
2021-07-10 05:06:13 +02:00
|
|
|
#[inline]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-05-19 13:03:06 +02:00
|
|
|
pub fn is_pure(&self) -> bool {
|
|
|
|
match self {
|
2020-05-19 16:25:57 +02:00
|
|
|
Self::Pure(_) => true,
|
2020-08-19 06:50:23 +02:00
|
|
|
Self::Method(_) | Self::Iterator(_) => false,
|
|
|
|
|
|
|
|
Self::Plugin(p) => !p.is_method_call(),
|
2020-07-04 10:21:15 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
Self::Script(_) => false,
|
2020-05-19 13:03:06 +02:00
|
|
|
}
|
2020-05-11 12:55:58 +02:00
|
|
|
}
|
2020-06-26 04:39:18 +02:00
|
|
|
/// Is this a native Rust method function?
|
2021-07-10 05:06:13 +02:00
|
|
|
#[inline]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-05-19 13:03:06 +02:00
|
|
|
pub fn is_method(&self) -> bool {
|
|
|
|
match self {
|
2020-05-19 16:25:57 +02:00
|
|
|
Self::Method(_) => true,
|
2020-08-19 06:50:23 +02:00
|
|
|
Self::Pure(_) | Self::Iterator(_) => false,
|
|
|
|
|
|
|
|
Self::Plugin(p) => p.is_method_call(),
|
2020-07-04 10:21:15 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
Self::Script(_) => false,
|
2020-05-19 13:03:06 +02:00
|
|
|
}
|
2020-05-11 07:36:50 +02:00
|
|
|
}
|
2020-05-19 13:03:06 +02:00
|
|
|
/// Is this an iterator function?
|
2021-07-10 05:06:13 +02:00
|
|
|
#[inline]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-07-04 10:40:15 +02:00
|
|
|
pub const fn is_iter(&self) -> bool {
|
2020-05-19 13:03:06 +02:00
|
|
|
match self {
|
2020-05-19 16:25:57 +02:00
|
|
|
Self::Iterator(_) => true,
|
2020-07-05 12:12:35 +02:00
|
|
|
Self::Pure(_) | Self::Method(_) | Self::Plugin(_) => false,
|
2020-07-04 10:21:15 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
Self::Script(_) => false,
|
2020-05-19 13:03:06 +02:00
|
|
|
}
|
2020-05-11 07:36:50 +02:00
|
|
|
}
|
2020-05-19 13:03:06 +02:00
|
|
|
/// Is this a Rhai-scripted function?
|
2021-07-10 05:06:13 +02:00
|
|
|
#[inline]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-07-04 10:40:15 +02:00
|
|
|
pub const fn is_script(&self) -> bool {
|
2020-05-19 13:03:06 +02:00
|
|
|
match self {
|
2020-08-05 16:53:01 +02:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
2020-05-19 16:25:57 +02:00
|
|
|
Self::Script(_) => true,
|
2020-08-05 16:53:01 +02:00
|
|
|
|
2020-07-02 06:47:24 +02:00
|
|
|
Self::Pure(_) | Self::Method(_) | Self::Iterator(_) | Self::Plugin(_) => false,
|
|
|
|
}
|
|
|
|
}
|
2020-09-30 16:55:40 +02:00
|
|
|
/// Is this a plugin function?
|
2021-07-10 05:06:13 +02:00
|
|
|
#[inline]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-07-04 10:40:15 +02:00
|
|
|
pub const fn is_plugin_fn(&self) -> bool {
|
2020-07-02 06:47:24 +02:00
|
|
|
match self {
|
|
|
|
Self::Plugin(_) => true,
|
2020-05-19 16:25:57 +02:00
|
|
|
Self::Pure(_) | Self::Method(_) | Self::Iterator(_) => false,
|
2020-08-06 04:31:15 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
Self::Script(_) => false,
|
2020-05-19 13:03:06 +02:00
|
|
|
}
|
|
|
|
}
|
2020-07-31 06:11:16 +02:00
|
|
|
/// Is this a native Rust function?
|
2021-07-10 05:06:13 +02:00
|
|
|
#[inline]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-07-04 10:40:15 +02:00
|
|
|
pub const fn is_native(&self) -> bool {
|
2020-07-31 06:11:16 +02:00
|
|
|
match self {
|
|
|
|
Self::Pure(_) | Self::Method(_) => true,
|
2020-08-06 04:31:15 +02:00
|
|
|
Self::Plugin(_) => true,
|
2020-07-31 06:11:16 +02:00
|
|
|
Self::Iterator(_) => true,
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
Self::Script(_) => false,
|
|
|
|
}
|
|
|
|
}
|
2020-07-27 06:52:32 +02:00
|
|
|
/// Get the access mode.
|
2021-07-10 05:06:13 +02:00
|
|
|
#[inline]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-07-27 06:52:32 +02:00
|
|
|
pub fn access(&self) -> FnAccess {
|
|
|
|
match self {
|
2020-07-29 08:17:40 +02:00
|
|
|
Self::Plugin(_) => FnAccess::Public,
|
2020-07-28 13:11:37 +02:00
|
|
|
Self::Pure(_) | Self::Method(_) | Self::Iterator(_) => FnAccess::Public,
|
2020-08-05 16:53:01 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
2020-07-28 13:11:37 +02:00
|
|
|
Self::Script(f) => f.access,
|
2020-07-27 06:52:32 +02:00
|
|
|
}
|
|
|
|
}
|
2020-11-07 16:33:21 +01:00
|
|
|
/// Get a shared reference to a native Rust function.
|
2021-07-10 05:06:13 +02:00
|
|
|
#[inline]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-06-28 12:06:05 +02:00
|
|
|
pub fn get_native_fn(&self) -> Option<&Shared<FnAny>> {
|
2020-05-19 13:03:06 +02:00
|
|
|
match self {
|
2021-06-28 12:06:05 +02:00
|
|
|
Self::Pure(f) | Self::Method(f) => Some(f),
|
|
|
|
Self::Iterator(_) | Self::Plugin(_) => None,
|
2020-07-04 10:21:15 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
2021-06-28 12:06:05 +02:00
|
|
|
Self::Script(_) => None,
|
2020-05-19 13:03:06 +02:00
|
|
|
}
|
|
|
|
}
|
2020-06-05 09:14:42 +02:00
|
|
|
/// Get a shared reference to a script-defined function definition.
|
|
|
|
///
|
2021-05-10 05:07:19 +02:00
|
|
|
/// Not available under `no_function`.
|
2020-07-04 10:21:15 +02:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
2021-07-10 05:06:13 +02:00
|
|
|
#[inline]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-06-28 12:06:05 +02:00
|
|
|
pub const fn get_script_fn_def(&self) -> Option<&Shared<crate::ast::ScriptFnDef>> {
|
2020-06-05 09:14:42 +02:00
|
|
|
match self {
|
2021-06-28 12:06:05 +02:00
|
|
|
Self::Pure(_) | Self::Method(_) | Self::Iterator(_) | Self::Plugin(_) => None,
|
|
|
|
Self::Script(f) => Some(f),
|
2020-06-05 09:14:42 +02:00
|
|
|
}
|
|
|
|
}
|
2020-05-19 13:03:06 +02:00
|
|
|
/// Get a reference to an iterator function.
|
2021-07-10 05:06:13 +02:00
|
|
|
#[inline]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-06-28 12:06:05 +02:00
|
|
|
pub fn get_iter_fn(&self) -> Option<IteratorFn> {
|
2020-05-19 13:03:06 +02:00
|
|
|
match self {
|
2021-06-28 12:06:05 +02:00
|
|
|
Self::Iterator(f) => Some(*f),
|
|
|
|
Self::Pure(_) | Self::Method(_) | Self::Plugin(_) => None,
|
2020-07-05 12:12:35 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
2021-06-28 12:06:05 +02:00
|
|
|
Self::Script(_) => None,
|
2020-07-02 06:47:24 +02:00
|
|
|
}
|
|
|
|
}
|
2020-11-07 16:33:21 +01:00
|
|
|
/// Get a shared reference to a plugin function.
|
2021-07-10 05:06:13 +02:00
|
|
|
#[inline]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2021-07-24 08:11:16 +02:00
|
|
|
pub fn get_plugin_fn(&self) -> Option<&Shared<FnPlugin>> {
|
2020-07-02 06:47:24 +02:00
|
|
|
match self {
|
2021-06-28 12:06:05 +02:00
|
|
|
Self::Plugin(f) => Some(f),
|
|
|
|
Self::Pure(_) | Self::Method(_) | Self::Iterator(_) => None,
|
2020-07-04 10:21:15 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_function"))]
|
2021-06-28 12:06:05 +02:00
|
|
|
Self::Script(_) => None,
|
2020-05-19 13:03:06 +02:00
|
|
|
}
|
2020-05-11 07:36:50 +02:00
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Create a new [`CallableFunction::Pure`].
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-05-19 16:25:57 +02:00
|
|
|
pub fn from_pure(func: Box<FnAny>) -> Self {
|
|
|
|
Self::Pure(func.into())
|
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Create a new [`CallableFunction::Method`].
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-05-19 16:25:57 +02:00
|
|
|
pub fn from_method(func: Box<FnAny>) -> Self {
|
|
|
|
Self::Method(func.into())
|
|
|
|
}
|
2020-11-20 09:52:28 +01:00
|
|
|
/// Create a new [`CallableFunction::Plugin`].
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2021-06-12 16:47:43 +02:00
|
|
|
#[must_use]
|
2020-09-29 07:06:48 +02:00
|
|
|
pub fn from_plugin(func: impl PluginFunction + 'static + SendSync) -> Self {
|
|
|
|
Self::Plugin((Box::new(func) as Box<FnPlugin>).into())
|
2020-07-02 06:47:24 +02:00
|
|
|
}
|
2020-05-11 07:36:50 +02:00
|
|
|
}
|
2020-06-05 09:14:42 +02:00
|
|
|
|
|
|
|
impl From<IteratorFn> for CallableFunction {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-06-05 09:14:42 +02:00
|
|
|
fn from(func: IteratorFn) -> Self {
|
|
|
|
Self::Iterator(func)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-07 15:10:54 +01:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
impl From<crate::ast::ScriptFnDef> for CallableFunction {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2021-03-07 15:10:54 +01:00
|
|
|
fn from(_func: crate::ast::ScriptFnDef) -> Self {
|
2020-08-05 16:53:01 +02:00
|
|
|
Self::Script(_func.into())
|
2020-06-05 09:14:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-07 15:10:54 +01:00
|
|
|
#[cfg(not(feature = "no_function"))]
|
|
|
|
impl From<Shared<crate::ast::ScriptFnDef>> for CallableFunction {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2021-03-07 15:10:54 +01:00
|
|
|
fn from(_func: Shared<crate::ast::ScriptFnDef>) -> Self {
|
2020-08-05 16:53:01 +02:00
|
|
|
Self::Script(_func)
|
2020-06-05 09:14:42 +02:00
|
|
|
}
|
|
|
|
}
|
2020-09-29 07:06:48 +02:00
|
|
|
|
|
|
|
impl<T: PluginFunction + 'static + SendSync> From<T> for CallableFunction {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-09-29 07:06:48 +02:00
|
|
|
fn from(func: T) -> Self {
|
|
|
|
Self::from_plugin(func)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<Shared<FnPlugin>> for CallableFunction {
|
2020-10-08 16:25:50 +02:00
|
|
|
#[inline(always)]
|
2020-09-29 07:06:48 +02:00
|
|
|
fn from(func: Shared<FnPlugin>) -> Self {
|
2021-07-24 08:11:16 +02:00
|
|
|
Self::Plugin(func)
|
2020-09-29 07:06:48 +02:00
|
|
|
}
|
|
|
|
}
|