From 5a4dcf95163f948e35a899349e2b628885840ee7 Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Sun, 21 May 2023 10:19:26 +0300 Subject: [PATCH] Fix docs and error types. --- README.md | 26 ++++++++++++-------------- src/context/mod.rs | 35 ++++++++++++++++++++++------------- src/error/display.rs | 7 ++++++- src/error/mod.rs | 7 +++++-- src/lib.rs | 26 ++++++++++++-------------- tests/integration.rs | 13 +++++++++---- 6 files changed, 66 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 8c79758..9682dc0 100644 --- a/README.md +++ b/README.md @@ -287,10 +287,6 @@ assert_eq!(eval_with_context_mut("a = 5.5", &mut context), 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))); -context.set_builtin_functions_disabled(true); -assert_eq!(eval_with_context("max(1,3)",&context),Err(EvalexprError::FunctionIdentifierNotFound(String::from("max")))); ``` @@ -304,8 +300,6 @@ This means that assigning to `a` again with a different type yields an error. Type unsafe contexts may be implemented if requested. For reading `a`, it is enough to pass an immutable reference. -EmptyContext have builtin functions disabled and can't be enabled. -EmptyContextWithBuiltinFunctions have builtin functions enabled and can't be disabled. Contexts can also be manipulated in code. Take a look at the following example: @@ -339,14 +333,21 @@ assert_eq!(eval_int_with_context("f 5", &context), Ok(10)); For more information about user-defined functions, refer to the respective [section](#user-defined-functions). ### Builtin Functions -Builtin functions are enabled by default for HashMap Context. It can be disabled by calling Context:: -set_builtin_functions_disabled -It's disabled for EmptyContext. It can't be enabled for EmptyContext +This crate offers a set of builtin functions (see below for a full list). +They can be disabled if needed as follows: -It's enabled for EmptyContextWithBuiltinfunctions. It can't be disabled. +```rust +use evalexpr::*; +let mut context = HashMapContext::new(); +assert_eq!(eval_with_context("max(1,3)",&context),Ok(Value::from(3))); +context.set_builtin_functions_disabled(true).unwrap(); // Do proper error handling here +assert_eq!(eval_with_context("max(1,3)",&context),Err(EvalexprError::FunctionIdentifierNotFound(String::from("max")))); +``` -This crate offers a set of builtin functions. +Not all contexts support enabling or disabling builtin functions. +Specifically the `EmptyContext` has builtin functions disabled by default, and they cannot be enabled. +Symmetrically, the `EmptyContextWithBuiltinFunctions` has builtin functions enabled by default, and they cannot be disabled. | Identifier | Argument Amount | Argument Types | Description | |----------------------|-----------------|-------------------------------|-------------| @@ -407,9 +408,6 @@ 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 Operators take values as arguments and produce values as results. diff --git a/src/context/mod.rs b/src/context/mod.rs index cc79f17..63dc379 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -23,10 +23,11 @@ pub trait Context { /// 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. + /// Checks if builtin functions are disabled. fn are_builtin_functions_disabled(&self) -> bool; - /// Disables Builtin function. + /// Disables builtin functions if `disabled` is `true`, and enables them otherwise. + /// If the context does not support enabling or disabling builtin functions, an error is returned. fn set_builtin_functions_disabled(&mut self, disabled: bool) -> EvalexprResult<()>; } @@ -72,7 +73,7 @@ pub trait GetFunctionContext: Context { }*/ /// A context that returns `None` for each identifier. -/// Builtin functiions are disabled. +/// Builtin functions are disabled and cannot be enabled. #[derive(Debug, Default)] pub struct EmptyContext; @@ -86,14 +87,16 @@ impl Context for EmptyContext { identifier.to_string(), )) } - /// Builtin functions can't be enabled for Empty Context. - fn set_builtin_functions_disabled(&mut self, _disabled: bool) -> EvalexprResult<()> { - Err(EvalexprError::InvalidBuiltinFunctionsContext) - } - /// Builtin functions are always disabled for Empty Context. + + /// Builtin functions are always disabled for `EmptyContext`. fn are_builtin_functions_disabled(&self) -> bool { true } + + /// Builtin functions can't be enabled for `EmptyContext`. + fn set_builtin_functions_disabled(&mut self, _disabled: bool) -> EvalexprResult<()> { + Err(EvalexprError::BuiltinFunctionsCannotBeEnabled) + } } impl<'a> IterateVariablesContext<'a> for EmptyContext { @@ -109,7 +112,8 @@ impl<'a> IterateVariablesContext<'a> for EmptyContext { } } -/// Same as Empty Context except Builtin functions are enabled. +/// A context that returns `None` for each identifier. +/// Builtin functions are enabled and cannot be disabled. #[derive(Debug, Default)] pub struct EmptyContextWithBuiltinFunctions; @@ -123,14 +127,16 @@ impl Context for EmptyContextWithBuiltinFunctions { identifier.to_string(), )) } - /// Builtin functions can't be disbaled for EmptyContextWithBuiltinFunctions. - fn set_builtin_functions_disabled(&mut self, _disabled: bool) -> EvalexprResult<()> { - Err(EvalexprError::InvalidBuiltinFunctionsContext) - } + /// Builtin functions are always enabled for EmptyContextWithBuiltinFunctions. fn are_builtin_functions_disabled(&self) -> bool { false } + + /// Builtin functions can't be disabled for EmptyContextWithBuiltinFunctions. + fn set_builtin_functions_disabled(&mut self, _disabled: bool) -> EvalexprResult<()> { + Err(EvalexprError::BuiltinFunctionsCannotBeDisabled) + } } impl<'a> IterateVariablesContext<'a> for EmptyContextWithBuiltinFunctions { @@ -145,6 +151,7 @@ impl<'a> IterateVariablesContext<'a> for EmptyContextWithBuiltinFunctions { iter::empty() } } + /// A context that stores its mappings in hash maps. /// /// *Value and function mappings are stored independently, meaning that there can be a function and a value with the same identifier.* @@ -156,6 +163,8 @@ pub struct HashMapContext { variables: HashMap, #[cfg_attr(feature = "serde_support", serde(skip))] functions: HashMap, + + /// True if builtin functions are disabled. without_builtin_functions: bool, } diff --git a/src/error/display.rs b/src/error/display.rs index bb3d418..d7a4e75 100644 --- a/src/error/display.rs +++ b/src/error/display.rs @@ -113,7 +113,12 @@ impl fmt::Display for EvalexprError { regex, message ), ContextNotMutable => write!(f, "Cannot manipulate context"), - InvalidBuiltinFunctionsContext => write!(f, "Invalid Builtin Functions Context"), + BuiltinFunctionsCannotBeEnabled => { + write!(f, "This context does not allow enabling builtin functions") + }, + BuiltinFunctionsCannotBeDisabled => { + write!(f, "This context does not allow disabling builtin functions") + }, IllegalEscapeSequence(string) => write!(f, "Illegal escape sequence: {}", string), CustomMessage(message) => write!(f, "Error: {}", message), } diff --git a/src/error/mod.rs b/src/error/mod.rs index 87a9e64..e896973 100644 --- a/src/error/mod.rs +++ b/src/error/mod.rs @@ -203,8 +203,11 @@ pub enum EvalexprError { /// An escape sequence within a string literal is illegal. IllegalEscapeSequence(String), - /// Empty Context can't have builtin functions enabled - InvalidBuiltinFunctionsContext, + /// This context does not allow enabling builtin functions. + BuiltinFunctionsCannotBeEnabled, + + /// This context does not allow disabling builtin functions. + BuiltinFunctionsCannotBeDisabled, /// A custom error explained by its message. CustomMessage(String), diff --git a/src/lib.rs b/src/lib.rs index 2d40af8..673443b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -270,10 +270,6 @@ //! 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))); -//! context.set_builtin_functions_disabled(true); -//! assert_eq!(eval_with_context("max(1,3)",&context),Err(EvalexprError::FunctionIdentifierNotFound(String::from("max")))); //! //! ``` //! @@ -287,8 +283,6 @@ //! Type unsafe contexts may be implemented if requested. //! For reading `a`, it is enough to pass an immutable reference. //! -//! EmptyContext have builtin functions disabled and can't be enabled. -//! EmptyContextWithBuiltinFunctions have builtin functions enabled and can't be disabled. //! Contexts can also be manipulated in code. //! Take a look at the following example: //! @@ -322,14 +316,21 @@ //! For more information about user-defined functions, refer to the respective [section](#user-defined-functions). //! //! ### Builtin Functions -//! Builtin functions are enabled by default for HashMap Context. It can be disabled by calling Context:: -//! set_builtin_functions_disabled //! -//! It's disabled for EmptyContext. It can't be enabled for EmptyContext +//! This crate offers a set of builtin functions (see below for a full list). +//! They can be disabled if needed as follows: //! -//! It's enabled for EmptyContextWithBuiltinfunctions. It can't be disabled. +//! ```rust +//! use evalexpr::*; +//! let mut context = HashMapContext::new(); +//! assert_eq!(eval_with_context("max(1,3)",&context),Ok(Value::from(3))); +//! context.set_builtin_functions_disabled(true).unwrap(); // Do proper error handling here +//! assert_eq!(eval_with_context("max(1,3)",&context),Err(EvalexprError::FunctionIdentifierNotFound(String::from("max")))); +//! ``` //! -//! This crate offers a set of builtin functions. +//! Not all contexts support enabling or disabling builtin functions. +//! Specifically the `EmptyContext` has builtin functions disabled by default, and they cannot be enabled. +//! Symmetrically, the `EmptyContextWithBuiltinFunctions` has builtin functions enabled by default, and they cannot be disabled. //! //! | Identifier | Argument Amount | Argument Types | Description | //! |----------------------|-----------------|-------------------------------|-------------| @@ -390,9 +391,6 @@ //! //! 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 //! //! Operators take values as arguments and produce values as results. diff --git a/tests/integration.rs b/tests/integration.rs index b592c50..37158ae 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -1529,17 +1529,22 @@ fn test_empty_context() { ); assert_eq!( context.set_builtin_functions_disabled(false), - Err(EvalexprError::InvalidBuiltinFunctionsContext) + Err(EvalexprError::BuiltinFunctionsCannotBeEnabled) ) } #[test] fn test_empty_context_with_builtin_functions() { let mut context = EmptyContextWithBuiltinFunctions; + assert_eq!(context.get_value("abc"), None); + assert_eq!( + context.call_function("abc", &Value::Empty), + Err(EvalexprError::FunctionIdentifierNotFound("abc".to_owned())) + ); assert_eq!(eval_with_context("max(1,3)", &context), Ok(Value::Int(3))); assert_eq!( context.set_builtin_functions_disabled(true), - Err(EvalexprError::InvalidBuiltinFunctionsContext) + Err(EvalexprError::BuiltinFunctionsCannotBeEnabled) ); } @@ -2270,8 +2275,8 @@ fn test_builtin_functions_context() { // Builtin functions are enabled by default for HashMapContext. assert_eq!(eval_with_context("max(1,3)", &context), Ok(Value::from(3))); // Disabling builtin function in Context. - context.set_builtin_functions_disabled(true); - // Builting functions are disabled and using them returns Error. + context.set_builtin_functions_disabled(true).unwrap(); + // Builtin functions are disabled and using them returns an error. assert_eq!( eval_with_context("max(1,3)", &context), Err(EvalexprError::FunctionIdentifierNotFound(String::from(