diff --git a/src/context/mod.rs b/src/context/mod.rs index e05f893..5cbf88d 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -22,6 +22,12 @@ pub trait Context { /// Calls the function that is linked to the given identifier with the given argument. /// If no function with the given identifier is found, this method returns `EvalexprError::FunctionIdentifierNotFound`. fn call_function(&self, identifier: &str, argument: &Value) -> EvalexprResult; + + /// Checks if builtin function has been disabled. + fn is_builtin_fn_disabled(&self) -> bool; + + /// Disables Builtin function. + fn disable_builtin_fn(&mut self); } /// A context that allows to assign to variables. @@ -79,6 +85,12 @@ impl Context for EmptyContext { identifier.to_string(), )) } + /// Builtin functions can't be disbaled for Empty Context. + fn disable_builtin_fn(&mut self) {} + /// Builtin functions are always disabled for Empty Context. + fn is_builtin_fn_disabled(&self) -> bool { + true + } } impl<'a> IterateVariablesContext<'a> for EmptyContext { @@ -105,6 +117,7 @@ pub struct HashMapContext { variables: HashMap, #[cfg_attr(feature = "serde_support", serde(skip))] functions: HashMap, + without_builtin_fn: bool, } impl HashMapContext { @@ -128,6 +141,14 @@ impl Context for HashMapContext { )) } } + + fn disable_builtin_fn(&mut self) { + self.without_builtin_fn = true; + } + + fn is_builtin_fn_disabled(&self) -> bool { + self.without_builtin_fn + } } impl ContextWithMutableVariables for HashMapContext { diff --git a/src/lib.rs b/src/lib.rs index cfd5c40..fe3e703 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -252,6 +252,8 @@ //! When assigning to variables, the assignment is stored in a context. //! When the variable is read later on, it is read from the context. //! Contexts can be preserved between multiple calls to eval by creating them yourself. +//! By default, Builtin functions are diabled. +//! Builtin functions can be disabled by calling Context::disable_builtin_fn(). //! Here is a simple example to show the difference between preserving and not preserving context between evaluations: //! //! ```rust @@ -270,6 +272,12 @@ //! Err(EvalexprError::ExpectedInt { actual: Value::from(5.5) })); //! // Reading a variable does not require a mutable context //! assert_eq!(eval_with_context("a", &context), Ok(Value::from(5))); +//! // Builtin functions are enabled by default. +//! assert_eq!(eval_with_context("max(1,3)",&context),Ok(Value::from(3))); +//! //Disabling builtin function in Context. +//! context.disable_builtin_fn(); +//! // Builtin functions are disabled and using them returns Error. +//! assert_eq!(eval_with_context("max(1,3)",&context),Err(EvalexprError::FunctionIdentifierNotFound(String::from("max")))); //! //! ``` //! @@ -377,6 +385,9 @@ //! Otherwise, a float is returned. //! //! The regex functions require the feature flag `regex_support`. +//! +//! Builtin functions are enabled by Default. +//! It can be disabled by calling Context::disable_builtin_fn(). //! //! ### Values //! diff --git a/src/operator/mod.rs b/src/operator/mod.rs index 218e7ad..8ddda53 100644 --- a/src/operator/mod.rs +++ b/src/operator/mod.rs @@ -459,7 +459,9 @@ impl Operator { let arguments = &arguments[0]; match context.call_function(identifier, arguments) { - Err(EvalexprError::FunctionIdentifierNotFound(_)) => { + Err(EvalexprError::FunctionIdentifierNotFound(_)) + if !context.is_builtin_fn_disabled() => + { if let Some(builtin_function) = builtin_function(identifier) { builtin_function.call(arguments) } else { diff --git a/tests/integration.rs b/tests/integration.rs index e6c114e..598d7c2 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -2243,3 +2243,14 @@ fn test_negative_power() { assert_eq!(eval("(-3)^-2"), Ok(Value::Float(1.0 / 9.0))); assert_eq!(eval("-(3^-2)"), Ok(Value::Float(-1.0 / 9.0))); } + +#[test] +fn test_disabling_builtin_fn() { + let mut context = HashMapContext::new(); + // Built in functions are enabled by default. + assert_eq!(eval_with_context("max(1,3)",&context),Ok(Value::from(3))); + // Disabling builtin function in Context. + context.disable_builtin_fn(); + // Builting functions are disabled and using them returns Error. + assert_eq!(eval_with_context("max(1,3)",&context),Err(EvalexprError::FunctionIdentifierNotFound(String::from("max")))); +} \ No newline at end of file