From e59f6939f78a31ad65d02e9eb602b44c550ff94b Mon Sep 17 00:00:00 2001 From: jhwgh1968 Date: Sat, 25 Apr 2020 18:50:10 -0500 Subject: [PATCH] Added basic Plugin trait and test --- Cargo.toml | 1 + src/fn_register.rs | 59 ++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ 3 files changed, 62 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index a50bc0b0..431473e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ num-traits = { version = "0.2.11", default-features = false } [features] #default = ["no_stdlib", "no_function", "no_index", "no_object", "no_float", "only_i32", "unchecked", "no_optimize", "sync"] default = [] +plugins = [] unchecked = [] # unchecked arithmetic no_index = [] # no arrays and indexing no_float = [] # no floating-point diff --git a/src/fn_register.rs b/src/fn_register.rs index e711ee54..90289784 100644 --- a/src/fn_register.rs +++ b/src/fn_register.rs @@ -9,6 +9,49 @@ use crate::token::Position; use crate::stdlib::{any::TypeId, boxed::Box, string::ToString}; +/// A trait to register custom plugins with the `Engine`. +/// +/// A plugin consists of a number of functions. All functions will be registered with the engine. +#[cfg(feature = "plugins")] +pub trait RegisterPlugin { + /// Register a custom function with the `Engine`. + /// + /// # Example + /// + /// ``` + /// use rhai::{Dynamic, Engine, INT, Plugin, RegisterDynamicFn, RegisterPlugin}; + /// + /// // A simple custom plugin type. This should not usually be done with hand-written code. + /// struct AddOffsetPlugin(INT); + /// impl AddOffsetPlugin { + /// fn add_offset(&self, x: INT) -> Dynamic { + /// Dynamic::from(x + self.0) + /// } + /// } + /// impl Plugin for AddOffsetPlugin { + /// fn name(&self) -> &str { + /// "My Plugin" + /// } + /// fn register_contents(self, engine: &mut Engine) { + /// let add_offset_fn: Box Dynamic> = { + /// Box::new(move |x| self.add_offset(x)) + /// }; + /// engine.register_dynamic_fn("add_offset", add_offset_fn); + /// } + /// } + /// + /// # fn main() -> Result<(), Box> { + /// + /// let mut engine = Engine::new(); + /// engine.register_plugin(AddOffsetPlugin(50)); + /// + /// assert_eq!(engine.eval::("add_offset(42)")?, 92); + /// # Ok(()) + /// # } + /// ``` + fn register_plugin(&mut self, plugin: PL); +} + /// A trait to register custom functions with the `Engine`. pub trait RegisterFn { /// Register a custom function with the `Engine`. @@ -98,6 +141,15 @@ pub trait RegisterResultFn { fn register_result_fn(&mut self, name: &str, f: FN); } +/// Represents an externally-written plugin for the Rhai interpreter. +/// +/// This should not be used directly. Use the `plugin_module!` macro instead. +#[cfg(feature = "plugins")] +pub trait Plugin { + fn register_contents(self, engine: &mut Engine); + fn name(&self) -> &str; +} + // These types are used to build a unique _marker_ tuple type for each combination // of function parameter types in order to make each trait implementation unique. // That is because stable Rust currently does not allow distinguishing implementations @@ -127,6 +179,13 @@ pub fn cloned(data: &mut T) -> T { data.clone() } +#[cfg(feature = "plugins")] +impl RegisterPlugin for Engine { + fn register_plugin(&mut self, plugin: PL) { + plugin.register_contents(self) + } +} + /// This macro counts the number of arguments via recursion. macro_rules! count_args { () => { 0_usize }; diff --git a/src/lib.rs b/src/lib.rs index e13eaf0f..d442ae9a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -89,6 +89,8 @@ pub use engine::{calc_fn_spec as calc_fn_hash, Engine}; pub use error::{ParseError, ParseErrorType}; pub use fn_call::FuncArgs; pub use fn_register::{RegisterDynamicFn, RegisterFn, RegisterResultFn}; +#[cfg(feature = "plugins")] +pub use fn_register::{Plugin, RegisterPlugin}; pub use parser::{AST, INT}; pub use result::EvalAltResult; pub use scope::Scope;