feature_method_to_disable_builtin_function

This commit is contained in:
Codex Yore 2023-05-18 23:16:47 +05:45 committed by Sebastian Schmidt
parent 9a53ce9893
commit 50532c5db5
4 changed files with 46 additions and 1 deletions

View File

@ -22,6 +22,12 @@ pub trait Context {
/// Calls the function that is linked to the given identifier with the given argument. /// 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`. /// If no function with the given identifier is found, this method returns `EvalexprError::FunctionIdentifierNotFound`.
fn call_function(&self, identifier: &str, argument: &Value) -> EvalexprResult<Value>; fn call_function(&self, identifier: &str, argument: &Value) -> EvalexprResult<Value>;
/// 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. /// A context that allows to assign to variables.
@ -79,6 +85,12 @@ impl Context for EmptyContext {
identifier.to_string(), 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 { impl<'a> IterateVariablesContext<'a> for EmptyContext {
@ -105,6 +117,7 @@ pub struct HashMapContext {
variables: HashMap<String, Value>, variables: HashMap<String, Value>,
#[cfg_attr(feature = "serde_support", serde(skip))] #[cfg_attr(feature = "serde_support", serde(skip))]
functions: HashMap<String, Function>, functions: HashMap<String, Function>,
without_builtin_fn: bool,
} }
impl HashMapContext { 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 { impl ContextWithMutableVariables for HashMapContext {

View File

@ -252,6 +252,8 @@
//! When assigning to variables, the assignment is stored in a context. //! When assigning to variables, the assignment is stored in a context.
//! When the variable is read later on, it is read from the 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. //! 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: //! Here is a simple example to show the difference between preserving and not preserving context between evaluations:
//! //!
//! ```rust //! ```rust
@ -270,6 +272,12 @@
//! Err(EvalexprError::ExpectedInt { actual: Value::from(5.5) })); //! Err(EvalexprError::ExpectedInt { actual: Value::from(5.5) }));
//! // Reading a variable does not require a mutable context //! // Reading a variable does not require a mutable context
//! assert_eq!(eval_with_context("a", &context), Ok(Value::from(5))); //! 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. //! Otherwise, a float is returned.
//! //!
//! The regex functions require the feature flag `regex_support`. //! 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 //! ### Values
//! //!

View File

@ -459,7 +459,9 @@ impl Operator {
let arguments = &arguments[0]; let arguments = &arguments[0];
match context.call_function(identifier, arguments) { 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) { if let Some(builtin_function) = builtin_function(identifier) {
builtin_function.call(arguments) builtin_function.call(arguments)
} else { } else {

View File

@ -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)));
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"))));
}