rhai/src/fn_native.rs

684 lines
21 KiB
Rust
Raw Normal View History

//! Module defining interfaces to native-Rust functions.
2020-11-16 16:25:19 +01:00
use crate::ast::{FnAccess, ScriptFnDef};
2020-11-16 16:10:14 +01:00
use crate::engine::Imports;
2020-07-26 10:10:38 +02:00
use crate::plugin::PluginFunction;
2020-12-26 06:05:57 +01:00
use crate::stdlib::{
boxed::Box,
convert::{TryFrom, TryInto},
fmt,
iter::empty,
mem,
string::String,
2021-01-02 06:37:40 +01:00
vec::Vec,
2020-12-26 06:05:57 +01:00
};
2020-11-16 16:10:14 +01:00
use crate::token::is_valid_identifier;
use crate::{
2020-11-16 16:25:19 +01:00
calc_script_fn_hash, Dynamic, Engine, EvalAltResult, EvalContext, ImmutableString, Module,
2021-03-02 08:02:28 +01:00
Position, RhaiResult,
2020-11-16 16:10:14 +01:00
};
2020-07-26 04:03:59 +02:00
2020-11-16 09:28:04 +01:00
#[cfg(not(feature = "sync"))]
use crate::stdlib::rc::Rc;
2020-07-26 04:03:59 +02:00
#[cfg(feature = "sync")]
2020-11-16 09:28:04 +01:00
use crate::stdlib::sync::Arc;
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 {}
/// 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 {}
/// 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
/// Immutable reference-counted container.
2020-05-12 10:32:22 +02:00
#[cfg(not(feature = "sync"))]
2020-05-21 11:11:01 +02:00
pub type Shared<T> = Rc<T>;
/// Immutable reference-counted container.
2020-05-12 10:32:22 +02:00
#[cfg(feature = "sync")]
2020-05-21 11:11:01 +02:00
pub type Shared<T> = Arc<T>;
2020-05-12 10:32:22 +02:00
/// Synchronized shared object.
2020-11-27 16:37:59 +01:00
#[cfg(not(feature = "no_closure"))]
#[cfg(not(feature = "sync"))]
pub type Locked<T> = crate::stdlib::cell::RefCell<T>;
/// Synchronized shared object.
2020-11-27 16:37:59 +01:00
#[cfg(not(feature = "no_closure"))]
#[cfg(feature = "sync")]
pub type Locked<T> = crate::stdlib::sync::RwLock<T>;
2020-11-25 02:36:06 +01:00
/// Context of a native Rust function call.
#[derive(Debug, Copy, Clone)]
2021-02-17 12:28:07 +01:00
pub struct NativeCallContext<'e, 'n, 's, 'a, 'm> {
engine: &'e Engine,
fn_name: &'n str,
2020-12-21 16:12:45 +01:00
source: Option<&'s str>,
2020-11-22 08:41:55 +01:00
pub(crate) mods: Option<&'a Imports>,
2021-02-17 12:28:07 +01:00
pub(crate) lib: &'m [&'m Module],
}
2021-02-17 12:28:07 +01:00
impl<'e, 'n, 's, 'a, 'm, M: AsRef<[&'m Module]> + ?Sized>
From<(&'e Engine, &'n str, Option<&'s str>, &'a Imports, &'m M)>
2021-02-17 12:28:07 +01:00
for NativeCallContext<'e, 'n, 's, 'a, 'm>
2020-11-07 16:33:21 +01:00
{
2020-12-29 03:41:20 +01:00
#[inline(always)]
fn from(value: (&'e Engine, &'n str, Option<&'s str>, &'a Imports, &'m M)) -> Self {
2020-11-07 16:33:21 +01:00
Self {
engine: value.0,
fn_name: value.1,
source: value.2,
mods: Some(value.3),
lib: value.4.as_ref(),
2020-11-07 16:33:21 +01:00
}
}
}
2021-02-17 12:28:07 +01:00
impl<'e, 'n, 'm, M: AsRef<[&'m Module]> + ?Sized> From<(&'e Engine, &'n str, &'m M)>
for NativeCallContext<'e, 'n, '_, '_, 'm>
2020-10-20 04:54:32 +02:00
{
2020-12-29 03:41:20 +01:00
#[inline(always)]
fn from(value: (&'e Engine, &'n str, &'m M)) -> Self {
Self {
engine: value.0,
fn_name: value.1,
2020-12-21 16:12:45 +01:00
source: None,
2020-11-07 16:33:21 +01:00
mods: None,
lib: value.2.as_ref(),
}
}
}
2021-02-17 12:28:07 +01:00
impl<'e, 'n, 's, 'a, 'm> NativeCallContext<'e, 'n, 's, 'a, 'm> {
2020-11-20 09:52:28 +01:00
/// Create a new [`NativeCallContext`].
2020-11-08 11:15:23 +01:00
#[inline(always)]
pub fn new(engine: &'e Engine, fn_name: &'n str, lib: &'m [&'m Module]) -> Self {
2020-11-08 11:15:23 +01:00
Self {
engine,
fn_name,
2020-12-21 16:12:45 +01:00
source: None,
2020-11-08 11:15:23 +01:00
mods: None,
lib,
2020-11-08 11:15:23 +01:00
}
}
2020-11-20 09:52:28 +01:00
/// _(INTERNALS)_ Create a new [`NativeCallContext`].
2020-11-08 11:15:23 +01:00
/// Available under the `internals` feature only.
#[cfg(feature = "internals")]
#[cfg(not(feature = "no_module"))]
#[inline(always)]
2020-12-21 16:12:45 +01:00
pub fn new_with_all_fields(
2020-11-08 11:15:23 +01:00
engine: &'e Engine,
fn_name: &'n str,
source: &'s Option<&str>,
2020-12-29 16:01:34 +01:00
imports: &'a mut Imports,
lib: &'m [&'m Module],
2020-11-08 11:15:23 +01:00
) -> Self {
Self {
engine,
2021-01-23 03:34:38 +01:00
fn_name,
source: source.clone(),
2020-12-29 16:01:34 +01:00
mods: Some(imports),
lib,
2020-11-08 11:15:23 +01:00
}
}
2020-11-20 09:52:28 +01:00
/// The current [`Engine`].
#[inline(always)]
2021-01-01 10:05:06 +01:00
pub fn engine(&self) -> &Engine {
self.engine
}
/// Name of the function called.
#[inline(always)]
pub fn fn_name(&self) -> &str {
self.fn_name
}
2020-12-21 16:12:45 +01:00
/// The current source.
#[inline(always)]
2021-01-01 10:05:06 +01:00
pub 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.
#[cfg(not(feature = "no_module"))]
#[inline(always)]
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
}
2020-11-20 09:52:28 +01:00
/// _(INTERNALS)_ The current set of modules imported via `import` statements.
2020-11-07 16:33:21 +01:00
/// Available under the `internals` feature only.
#[cfg(feature = "internals")]
#[cfg(not(feature = "no_module"))]
#[inline(always)]
pub fn imports(&self) -> Option<&Imports> {
self.mods
}
2021-01-01 10:05:06 +01:00
/// Get an iterator over the namespaces containing definitions of all script-defined functions.
#[inline(always)]
2021-01-01 10:05:06 +01:00
pub fn iter_namespaces(&self) -> impl Iterator<Item = &Module> {
self.lib.iter().cloned()
}
2021-01-01 10:05:06 +01:00
/// _(INTERNALS)_ The current set of namespaces containing definitions of all script-defined functions.
/// Available under the `internals` feature only.
#[cfg(feature = "internals")]
#[inline(always)]
pub fn namespaces(&self) -> &[&Module] {
self.lib
}
2020-11-08 16:00:37 +01:00
/// Call a function inside the call context.
///
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.
///
2020-11-20 09:52:28 +01:00
/// If `is_method` is [`true`], the first argument is assumed to be passed
2020-11-08 16:00:37 +01:00
/// by reference and is not consumed.
2020-12-29 03:41:20 +01:00
#[inline(always)]
2020-11-08 16:00:37 +01:00
pub fn call_fn_dynamic_raw(
2020-11-30 04:20:51 +01:00
&self,
2020-11-08 16:00:37 +01:00
fn_name: &str,
is_method: bool,
args: &mut [&mut Dynamic],
2021-03-02 08:02:28 +01:00
) -> RhaiResult {
2020-11-08 16:00:37 +01:00
self.engine()
.exec_fn_call(
2020-12-26 06:05:57 +01:00
&mut self.mods.cloned().unwrap_or_default(),
2020-11-08 16:00:37 +01:00
&mut Default::default(),
self.lib,
fn_name,
2020-12-26 06:05:57 +01:00
calc_script_fn_hash(empty(), fn_name, args.len() - if is_method { 1 } else { 0 }),
2020-11-08 16:00:37 +01:00
args,
is_method,
is_method,
2020-12-12 04:15:09 +01:00
Position::NONE,
2020-11-08 16:00:37 +01:00
None,
0,
)
.map(|(r, _)| r)
}
}
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)]
2020-05-25 11:01:39 +02:00
pub fn shared_make_mut<T: Clone>(value: &mut Shared<T>) -> &mut T {
#[cfg(not(feature = "sync"))]
2020-07-04 16:53:00 +02:00
return Rc::make_mut(value);
2020-05-25 11:01:39 +02:00
#[cfg(feature = "sync")]
2020-07-04 16:53:00 +02:00
return Arc::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.
2020-11-09 15:44:20 +01:00
#[inline(always)]
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>> {
2020-08-08 10:24:10 +02:00
#[cfg(not(feature = "sync"))]
return Rc::try_unwrap(value);
#[cfg(feature = "sync")]
return Arc::try_unwrap(value);
}
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).
2020-11-09 15:44:20 +01:00
#[inline(always)]
2020-08-08 11:04:21 +02:00
pub fn shared_take<T>(value: Shared<T>) -> T {
2020-08-08 10:24:10 +02:00
shared_try_take(value).map_err(|_| ()).unwrap()
2020-05-25 11:01:39 +02:00
}
2020-11-25 02:36:06 +01:00
/// Arguments to a function call, which is a list of [`&mut Dynamic`][Dynamic].
2020-05-21 11:11:01 +02:00
pub type FnCallArgs<'a> = [&'a mut Dynamic];
2020-05-12 10:32:22 +02:00
2020-07-23 09:49:09 +02:00
/// A general function pointer, which may carry additional (i.e. curried) argument values
/// to be passed onto a function during a call.
2020-12-26 06:05:57 +01:00
#[derive(Debug, Clone)]
2021-01-02 06:37:40 +01:00
pub struct FnPtr(ImmutableString, Vec<Dynamic>);
2020-06-25 12:07:57 +02:00
impl FnPtr {
/// Create a new function pointer.
2020-12-29 03:41:20 +01:00
#[inline(always)]
2020-12-26 06:05:57 +01:00
pub fn new(name: impl Into<ImmutableString>) -> Result<Self, Box<EvalAltResult>> {
name.into().try_into()
}
/// Create a new function pointer without checking its parameters.
2020-10-08 16:25:50 +02:00
#[inline(always)]
2021-01-02 06:37:40 +01:00
pub(crate) fn new_unchecked(name: impl Into<ImmutableString>, curry: Vec<Dynamic>) -> Self {
2020-07-22 17:12:09 +02:00
Self(name.into(), curry)
}
2020-06-25 12:07:57 +02:00
/// Get the name of the function.
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-06-25 12:07:57 +02:00
pub fn fn_name(&self) -> &str {
self.get_fn_name().as_ref()
}
/// Get the name of the function.
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-06-25 12:07:57 +02:00
pub(crate) fn get_fn_name(&self) -> &ImmutableString {
&self.0
}
2020-07-23 04:12:51 +02:00
/// Get the underlying data of the function pointer.
2020-10-08 16:25:50 +02:00
#[inline(always)]
2021-01-02 06:37:40 +01:00
pub(crate) fn take_data(self) -> (ImmutableString, Vec<Dynamic>) {
2020-07-23 04:12:51 +02:00
(self.0, self.1)
2020-06-29 17:55:28 +02:00
}
2020-07-23 09:49:09 +02:00
/// Get the curried arguments.
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-07-23 09:49:09 +02:00
pub fn curry(&self) -> &[Dynamic] {
self.1.as_ref()
2020-07-22 17:12:09 +02:00
}
2020-12-26 06:05:57 +01:00
/// Add a new curried argument.
#[inline(always)]
pub fn add_curry(&mut self, value: Dynamic) -> &mut Self {
self.1.push(value);
self
}
/// Set curried arguments to the function pointer.
#[inline(always)]
pub fn set_curry(&mut self, values: impl IntoIterator<Item = Dynamic>) -> &mut Self {
self.1 = values.into_iter().collect();
self
}
/// Is the function pointer curried?
#[inline(always)]
pub fn is_curried(&self) -> bool {
!self.1.is_empty()
}
/// Does the function pointer refer to an anonymous function?
2020-10-18 11:29:11 +02:00
#[cfg(not(feature = "no_function"))]
#[inline(always)]
pub fn is_anonymous(&self) -> bool {
2020-11-16 09:28:04 +01:00
self.0.starts_with(crate::engine::FN_ANONYMOUS)
}
2020-07-23 09:49:09 +02:00
/// Call the function pointer with curried arguments (if any).
///
/// If this function is a script-defined function, it must not be marked private.
2020-07-26 07:51:09 +02:00
///
2021-01-02 16:30:10 +01:00
/// # WARNING
2020-07-23 09:49:09 +02:00
///
/// All the arguments are _consumed_, meaning that they're replaced by `()`.
/// This is to avoid unnecessarily cloning the arguments.
/// Do not use the arguments after this call. If they are needed afterwards,
/// clone them _before_ calling this function.
2020-12-29 03:41:20 +01:00
#[inline(always)]
pub fn call_dynamic(
&self,
2020-11-30 04:20:51 +01:00
ctx: NativeCallContext,
2020-07-23 09:49:09 +02:00
this_ptr: Option<&mut Dynamic>,
mut arg_values: impl AsMut<[Dynamic]>,
2021-03-02 08:02:28 +01:00
) -> RhaiResult {
let arg_values = arg_values.as_mut();
let mut args_data = self
.curry()
.iter()
.cloned()
.chain(arg_values.iter_mut().map(mem::take))
2021-01-02 06:37:40 +01:00
.collect::<Vec<_>>();
2021-01-02 06:37:40 +01:00
let mut args = args_data.iter_mut().collect::<Vec<_>>();
2020-11-08 16:00:37 +01:00
2020-12-29 03:41:20 +01:00
let is_method = this_ptr.is_some();
if let Some(obj) = this_ptr {
args.insert(0, obj);
}
2021-03-01 08:39:49 +01:00
ctx.call_fn_dynamic_raw(self.fn_name(), is_method, args.as_mut())
2020-06-29 17:55:28 +02:00
}
2020-06-25 12:07:57 +02:00
}
impl fmt::Display for FnPtr {
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-06-25 12:07:57 +02:00
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Fn({})", self.0)
}
}
impl TryFrom<ImmutableString> for FnPtr {
type Error = Box<EvalAltResult>;
2020-10-08 16:25:50 +02:00
#[inline(always)]
fn try_from(value: ImmutableString) -> Result<Self, Self::Error> {
if is_valid_identifier(value.chars()) {
2020-07-22 17:12:09 +02:00
Ok(Self(value, Default::default()))
} else {
2020-11-20 09:52:28 +01:00
EvalAltResult::ErrorFunctionNotFound(value.into(), Position::NONE).into()
}
}
}
impl TryFrom<String> for FnPtr {
type Error = Box<EvalAltResult>;
2020-10-08 16:25:50 +02:00
#[inline(always)]
fn try_from(value: String) -> Result<Self, Self::Error> {
let s: ImmutableString = value.into();
Self::try_from(s)
}
}
impl TryFrom<&str> for FnPtr {
type Error = Box<EvalAltResult>;
2020-10-08 16:25:50 +02:00
#[inline(always)]
fn try_from(value: &str) -> Result<Self, Self::Error> {
let s: ImmutableString = value.into();
Self::try_from(s)
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"))]
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.
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.
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-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
/// A standard callback function for variable access.
2020-10-11 15:58:11 +02:00
#[cfg(not(feature = "sync"))]
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<
dyn Fn(&str, usize, &EvalContext) -> Result<Option<Dynamic>, Box<EvalAltResult>>
2020-10-11 15:58:11 +02:00
+ Send
+ Sync
+ 'static,
>;
/// A type encapsulating a function callable by Rhai.
2020-05-19 16:25:57 +02:00
#[derive(Clone)]
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>),
/// 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>),
/// An iterator function.
2020-05-20 13:27:23 +02:00
Iterator(IteratorFn),
/// A plugin function,
Plugin(Shared<FnPlugin>),
/// A script-defined function.
2020-07-04 10:21:15 +02:00
#[cfg(not(feature = "no_function"))]
Script(Shared<ScriptFnDef>),
}
impl fmt::Debug for CallableFunction {
2020-12-29 03:41:20 +01:00
#[inline(always)]
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),
}
}
}
impl fmt::Display for CallableFunction {
2020-12-29 03:41:20 +01:00
#[inline(always)]
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"))]
CallableFunction::Script(s) => fmt::Display::fmt(s, f),
}
}
}
impl CallableFunction {
/// Is this a pure native Rust function?
2020-12-29 03:41:20 +01:00
#[inline(always)]
pub fn is_pure(&self) -> bool {
match self {
2020-05-19 16:25:57 +02:00
Self::Pure(_) => true,
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-06-26 04:39:18 +02:00
/// Is this a native Rust method function?
2020-12-29 03:41:20 +01:00
#[inline(always)]
pub fn is_method(&self) -> bool {
match self {
2020-05-19 16:25:57 +02:00
Self::Method(_) => true,
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-11 07:36:50 +02:00
}
/// Is this an iterator function?
2020-12-29 03:41:20 +01:00
#[inline(always)]
pub fn is_iter(&self) -> bool {
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-11 07:36:50 +02:00
}
/// Is this a Rhai-scripted function?
2020-12-29 03:41:20 +01:00
#[inline(always)]
pub fn is_script(&self) -> bool {
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,
}
}
/// Is this a plugin function?
2020-12-29 03:41:20 +01:00
#[inline(always)]
2020-07-02 06:47:24 +02:00
pub fn is_plugin_fn(&self) -> bool {
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-07-31 06:11:16 +02:00
/// Is this a native Rust function?
2020-12-29 03:41:20 +01:00
#[inline(always)]
2020-07-31 06:11:16 +02:00
pub fn is_native(&self) -> bool {
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,
}
}
/// Get the access mode.
2020-12-29 03:41:20 +01:00
#[inline(always)]
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-11-07 16:33:21 +01:00
/// Get a shared reference to a native Rust function.
///
/// # Panics
///
2020-11-20 09:52:28 +01:00
/// Panics if the [`CallableFunction`] is not [`Pure`][CallableFunction::Pure] or
/// [`Method`][CallableFunction::Method].
2020-12-29 03:41:20 +01:00
#[inline(always)]
2020-11-25 02:36:06 +01:00
pub fn get_native_fn(&self) -> &FnAny {
match self {
2020-11-25 02:36:06 +01:00
Self::Pure(f) | Self::Method(f) => f.as_ref(),
Self::Iterator(_) | Self::Plugin(_) => panic!("function should be native"),
2020-07-04 10:21:15 +02:00
#[cfg(not(feature = "no_function"))]
Self::Script(_) => panic!("function should be native"),
}
}
/// Get a shared reference to a script-defined function definition.
///
/// # Panics
///
2020-11-20 09:52:28 +01:00
/// Panics if the [`CallableFunction`] is not [`Script`][CallableFunction::Script].
2020-07-04 10:21:15 +02:00
#[cfg(not(feature = "no_function"))]
2020-12-29 03:41:20 +01:00
#[inline(always)]
2020-11-25 02:36:06 +01:00
pub fn get_fn_def(&self) -> &ScriptFnDef {
match self {
Self::Pure(_) | Self::Method(_) | Self::Iterator(_) | Self::Plugin(_) => {
panic!("function should be scripted")
}
2020-11-25 02:36:06 +01:00
Self::Script(f) => f.as_ref(),
}
}
/// Get a reference to an iterator function.
///
/// # Panics
///
2020-11-20 09:52:28 +01:00
/// Panics if the [`CallableFunction`] is not [`Iterator`][CallableFunction::Iterator].
2020-12-29 03:41:20 +01:00
#[inline(always)]
2020-05-20 13:27:23 +02:00
pub fn get_iter_fn(&self) -> IteratorFn {
match self {
2020-05-20 13:27:23 +02:00
Self::Iterator(f) => *f,
Self::Pure(_) | Self::Method(_) | Self::Plugin(_) => {
panic!("function should an iterator")
}
2020-07-05 12:12:35 +02:00
#[cfg(not(feature = "no_function"))]
Self::Script(_) => panic!("function should be an iterator"),
2020-07-02 06:47:24 +02:00
}
}
2020-11-07 16:33:21 +01:00
/// Get a shared reference to a plugin function.
2020-07-02 06:47:24 +02:00
///
/// # Panics
///
2020-11-20 09:52:28 +01:00
/// Panics if the [`CallableFunction`] is not [`Plugin`][CallableFunction::Plugin].
2020-12-29 03:41:20 +01:00
#[inline(always)]
2020-11-25 02:36:06 +01:00
pub fn get_plugin_fn<'s>(&'s self) -> &FnPlugin {
2020-07-02 06:47:24 +02:00
match self {
2020-11-25 02:36:06 +01:00
Self::Plugin(f) => f.as_ref(),
Self::Pure(_) | Self::Method(_) | Self::Iterator(_) => {
panic!("function should a plugin")
}
2020-07-04 10:21:15 +02:00
#[cfg(not(feature = "no_function"))]
Self::Script(_) => panic!("function should a plugin"),
}
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)]
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)]
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)]
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
}
impl From<IteratorFn> for CallableFunction {
2020-10-08 16:25:50 +02:00
#[inline(always)]
fn from(func: IteratorFn) -> Self {
Self::Iterator(func)
}
}
impl From<ScriptFnDef> for CallableFunction {
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-08-05 16:53:01 +02:00
fn from(_func: ScriptFnDef) -> Self {
#[cfg(feature = "no_function")]
unreachable!("no_function active");
2020-08-05 16:53:01 +02:00
#[cfg(not(feature = "no_function"))]
Self::Script(_func.into())
}
}
impl From<Shared<ScriptFnDef>> for CallableFunction {
2020-10-08 16:25:50 +02:00
#[inline(always)]
2020-08-05 16:53:01 +02:00
fn from(_func: Shared<ScriptFnDef>) -> Self {
#[cfg(feature = "no_function")]
unreachable!("no_function active");
2020-08-05 16:53:01 +02:00
#[cfg(not(feature = "no_function"))]
Self::Script(_func)
}
}
impl<T: PluginFunction + 'static + SendSync> From<T> for CallableFunction {
2020-10-08 16:25:50 +02:00
#[inline(always)]
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)]
fn from(func: Shared<FnPlugin>) -> Self {
Self::Plugin(func.into())
}
}