rhai/src/func/callable_function.rs

281 lines
8.7 KiB
Rust
Raw Normal View History

2021-12-20 15:13:00 +01:00
//! Module defining the standard Rhai function type.
2022-11-17 11:05:52 +01:00
use super::native::{FnAny, FnPlugin, IteratorFn, SendSync};
2021-12-20 15:13:00 +01:00
use crate::ast::FnAccess;
use crate::plugin::PluginFunction;
use crate::Shared;
use std::fmt;
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
/// _(internals)_ Encapsulated AST environment.
/// Exported under the `internals` feature only.
///
/// 1) functions defined within the same AST
/// 2) the stack of imported [modules][crate::Module]
/// 3) global constants
#[derive(Debug, Clone)]
pub struct EncapsulatedEnviron {
/// Functions defined within the same [`AST`][crate::AST].
#[cfg(not(feature = "no_function"))]
pub lib: crate::SharedModule,
/// Imported [modules][crate::Module].
#[cfg(not(feature = "no_module"))]
pub imports: Box<[(crate::ImmutableString, crate::SharedModule)]>,
/// Globally-defined constants.
#[cfg(not(feature = "no_module"))]
#[cfg(not(feature = "no_function"))]
pub constants: Option<crate::eval::SharedGlobalConstants>,
}
2022-11-17 11:05:52 +01:00
/// _(internals)_ A type encapsulating a function callable by Rhai.
/// Exported under the `internals` feature only.
2021-12-20 15:13:00 +01:00
#[derive(Clone)]
2022-04-26 10:36:24 +02:00
#[non_exhaustive]
2021-12-20 15:13:00 +01:00
pub enum CallableFunction {
/// A pure native Rust function with all arguments passed by value.
2022-12-03 09:20:13 +01:00
Pure(Shared<FnAny>, bool),
2021-12-20 15:13:00 +01:00
/// A native Rust object method with the first argument passed by reference,
/// and the rest passed by value.
2022-12-03 09:20:13 +01:00
Method(Shared<FnAny>, bool),
2021-12-20 15:13:00 +01:00
/// An iterator function.
2022-01-27 16:55:32 +01:00
Iterator(Shared<IteratorFn>),
2021-12-20 15:13:00 +01:00
/// A plugin function,
Plugin(Shared<FnPlugin>),
/// A script-defined function.
#[cfg(not(feature = "no_function"))]
Script(
Shared<crate::ast::ScriptFnDef>,
Option<Shared<EncapsulatedEnviron>>,
),
2021-12-20 15:13:00 +01:00
}
impl fmt::Debug for CallableFunction {
2022-09-27 02:52:39 +02:00
#[cold]
#[inline(never)]
2021-12-20 15:13:00 +01:00
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Pure(..) => f.write_str("NativePureFunction"),
Self::Method(..) => f.write_str("NativeMethod"),
Self::Iterator(..) => f.write_str("NativeIterator"),
Self::Plugin(..) => f.write_str("PluginFunction"),
2021-12-20 15:13:00 +01:00
#[cfg(not(feature = "no_function"))]
Self::Script(fn_def, ..) => fmt::Debug::fmt(fn_def, f),
2021-12-20 15:13:00 +01:00
}
}
}
impl fmt::Display for CallableFunction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Pure(..) => f.write_str("NativePureFunction"),
Self::Method(..) => f.write_str("NativeMethod"),
Self::Iterator(..) => f.write_str("NativeIterator"),
Self::Plugin(..) => f.write_str("PluginFunction"),
2021-12-20 15:13:00 +01:00
#[cfg(not(feature = "no_function"))]
Self::Script(fn_def, ..) => fmt::Display::fmt(fn_def, f),
2021-12-20 15:13:00 +01:00
}
}
}
impl CallableFunction {
/// Is this a pure native Rust function?
#[inline]
#[must_use]
pub fn is_pure(&self) -> bool {
match self {
2022-02-08 02:46:14 +01:00
Self::Pure(..) => true,
Self::Method(..) | Self::Iterator(..) => false,
2021-12-20 15:13:00 +01:00
Self::Plugin(p) => !p.is_method_call(),
#[cfg(not(feature = "no_function"))]
2022-02-08 02:46:14 +01:00
Self::Script(..) => false,
2021-12-20 15:13:00 +01:00
}
}
/// Is this a native Rust method function?
#[inline]
#[must_use]
pub fn is_method(&self) -> bool {
match self {
2022-02-08 02:46:14 +01:00
Self::Method(..) => true,
Self::Pure(..) | Self::Iterator(..) => false,
2021-12-20 15:13:00 +01:00
Self::Plugin(p) => p.is_method_call(),
#[cfg(not(feature = "no_function"))]
2022-02-08 02:46:14 +01:00
Self::Script(..) => false,
2021-12-20 15:13:00 +01:00
}
}
/// Is this an iterator function?
#[inline]
#[must_use]
pub const fn is_iter(&self) -> bool {
match self {
2022-02-08 02:46:14 +01:00
Self::Iterator(..) => true,
Self::Pure(..) | Self::Method(..) | Self::Plugin(..) => false,
2021-12-20 15:13:00 +01:00
#[cfg(not(feature = "no_function"))]
2022-02-08 02:46:14 +01:00
Self::Script(..) => false,
2021-12-20 15:13:00 +01:00
}
}
/// Is this a script-defined function?
#[inline]
#[must_use]
pub const fn is_script(&self) -> bool {
2021-12-21 06:03:39 +01:00
#[cfg(feature = "no_function")]
return false;
#[cfg(not(feature = "no_function"))]
2021-12-20 15:13:00 +01:00
match self {
2022-02-08 02:46:14 +01:00
Self::Script(..) => true,
Self::Pure(..) | Self::Method(..) | Self::Iterator(..) | Self::Plugin(..) => false,
2021-12-20 15:13:00 +01:00
}
}
/// Is this a plugin function?
#[inline]
#[must_use]
pub const fn is_plugin_fn(&self) -> bool {
match self {
2022-02-08 02:46:14 +01:00
Self::Plugin(..) => true,
Self::Pure(..) | Self::Method(..) | Self::Iterator(..) => false,
2021-12-20 15:13:00 +01:00
#[cfg(not(feature = "no_function"))]
2022-02-08 02:46:14 +01:00
Self::Script(..) => false,
2021-12-20 15:13:00 +01:00
}
}
/// Is this a native Rust function?
#[inline]
#[must_use]
pub const fn is_native(&self) -> bool {
2021-12-21 06:03:39 +01:00
#[cfg(feature = "no_function")]
return true;
#[cfg(not(feature = "no_function"))]
2021-12-20 15:13:00 +01:00
match self {
2022-11-23 06:24:14 +01:00
Self::Pure(..) | Self::Method(..) | Self::Plugin(..) | Self::Iterator(..) => true,
2022-02-08 02:46:14 +01:00
Self::Script(..) => false,
2021-12-20 15:13:00 +01:00
}
}
2022-12-04 07:06:54 +01:00
/// Is there a [`NativeCallContext`][crate::NativeCallContext] parameter?
2022-12-03 09:20:13 +01:00
#[inline]
#[must_use]
pub fn has_context(&self) -> bool {
match self {
Self::Pure(.., ctx) | Self::Method(.., ctx) => *ctx,
2022-12-03 10:03:15 +01:00
Self::Plugin(f) => f.has_context(),
Self::Iterator(..) => false,
2022-12-03 09:20:13 +01:00
#[cfg(not(feature = "no_function"))]
Self::Script(..) => false,
}
}
2021-12-20 15:13:00 +01:00
/// Get the access mode.
#[inline]
#[must_use]
pub fn access(&self) -> FnAccess {
2021-12-21 06:03:39 +01:00
#[cfg(feature = "no_function")]
return FnAccess::Public;
#[cfg(not(feature = "no_function"))]
2021-12-20 15:13:00 +01:00
match self {
2022-11-23 06:24:14 +01:00
Self::Plugin(..) | Self::Pure(..) | Self::Method(..) | Self::Iterator(..) => {
FnAccess::Public
}
Self::Script(f, ..) => f.access,
2021-12-20 15:13:00 +01:00
}
}
/// Get a shared reference to a native Rust function.
#[inline]
#[must_use]
pub fn get_native_fn(&self) -> Option<&Shared<FnAny>> {
match self {
2022-12-03 09:20:13 +01:00
Self::Pure(f, ..) | Self::Method(f, ..) => Some(f),
2022-02-08 02:46:14 +01:00
Self::Iterator(..) | Self::Plugin(..) => None,
2021-12-20 15:13:00 +01:00
#[cfg(not(feature = "no_function"))]
2022-02-08 02:46:14 +01:00
Self::Script(..) => None,
2021-12-20 15:13:00 +01:00
}
}
/// Get a shared reference to a script-defined function definition.
///
/// Not available under `no_function`.
#[cfg(not(feature = "no_function"))]
#[inline]
#[must_use]
pub const fn get_script_fn_def(&self) -> Option<&Shared<crate::ast::ScriptFnDef>> {
match self {
2022-02-08 02:46:14 +01:00
Self::Pure(..) | Self::Method(..) | Self::Iterator(..) | Self::Plugin(..) => None,
Self::Script(f, ..) => Some(f),
}
}
/// Get a reference to the shared encapsulated environment of the function definition.
///
/// Not available under `no_function` or `no_module`.
#[inline]
#[must_use]
pub fn get_encapsulated_environ(&self) -> Option<&EncapsulatedEnviron> {
match self {
Self::Pure(..) | Self::Method(..) | Self::Iterator(..) | Self::Plugin(..) => None,
#[cfg(not(feature = "no_function"))]
Self::Script(.., environ) => environ.as_deref(),
2021-12-20 15:13:00 +01:00
}
}
/// Get a reference to an iterator function.
#[inline]
#[must_use]
2022-01-27 16:55:32 +01:00
pub fn get_iter_fn(&self) -> Option<&IteratorFn> {
2021-12-20 15:13:00 +01:00
match self {
2022-07-05 10:26:38 +02:00
Self::Iterator(f) => Some(&**f),
2022-02-08 02:46:14 +01:00
Self::Pure(..) | Self::Method(..) | Self::Plugin(..) => None,
2021-12-20 15:13:00 +01:00
#[cfg(not(feature = "no_function"))]
2022-02-08 02:46:14 +01:00
Self::Script(..) => None,
2021-12-20 15:13:00 +01:00
}
}
/// Get a shared reference to a plugin function.
#[inline]
#[must_use]
pub fn get_plugin_fn(&self) -> Option<&Shared<FnPlugin>> {
match self {
Self::Plugin(f) => Some(f),
2022-02-08 02:46:14 +01:00
Self::Pure(..) | Self::Method(..) | Self::Iterator(..) => None,
2021-12-20 15:13:00 +01:00
#[cfg(not(feature = "no_function"))]
2022-02-08 02:46:14 +01:00
Self::Script(..) => None,
2021-12-20 15:13:00 +01:00
}
}
}
#[cfg(not(feature = "no_function"))]
impl From<crate::ast::ScriptFnDef> for CallableFunction {
#[inline(always)]
2022-11-29 08:50:58 +01:00
fn from(func: crate::ast::ScriptFnDef) -> Self {
Self::Script(func.into(), None)
2021-12-20 15:13:00 +01:00
}
}
#[cfg(not(feature = "no_function"))]
impl From<Shared<crate::ast::ScriptFnDef>> for CallableFunction {
#[inline(always)]
2022-11-29 08:50:58 +01:00
fn from(func: Shared<crate::ast::ScriptFnDef>) -> Self {
Self::Script(func, None)
2021-12-20 15:13:00 +01:00
}
}
impl<T: PluginFunction + 'static + SendSync> From<T> for CallableFunction {
#[inline(always)]
fn from(func: T) -> Self {
2022-11-17 11:05:52 +01:00
Self::Plugin(Shared::new(func))
2021-12-20 15:13:00 +01:00
}
}
impl From<Shared<FnPlugin>> for CallableFunction {
#[inline(always)]
fn from(func: Shared<FnPlugin>) -> Self {
Self::Plugin(func)
}
}