use std::{collections::HashMap, iter, marker::PhantomData};
use crate::{
error::EvalexprResultValue,
function::Function,
value::{
numeric_types::{default_numeric_types::DefaultNumericTypes, EvalexprNumericTypes},
value_type::ValueType,
Value,
},
EvalexprError, EvalexprResult,
};
mod predefined;
pub trait Context {
type NumericTypes: EvalexprNumericTypes;
fn get_value(&self, identifier: &str) -> Option<&Value<Self::NumericTypes>>;
fn call_function(
&self,
identifier: &str,
argument: &Value<Self::NumericTypes>,
) -> EvalexprResultValue<Self::NumericTypes>;
fn are_builtin_functions_disabled(&self) -> bool;
fn set_builtin_functions_disabled(
&mut self,
disabled: bool,
) -> EvalexprResult<(), Self::NumericTypes>;
}
pub trait ContextWithMutableVariables: Context {
fn set_value(
&mut self,
_identifier: String,
_value: Value<Self::NumericTypes>,
) -> EvalexprResult<(), Self::NumericTypes> {
Err(EvalexprError::ContextNotMutable)
}
fn remove_value(
&mut self,
_identifier: &str,
) -> EvalexprResult<Option<Value<Self::NumericTypes>>, Self::NumericTypes> {
Err(EvalexprError::ContextNotMutable)
}
}
pub trait ContextWithMutableFunctions: Context {
fn set_function(
&mut self,
_identifier: String,
_function: Function<Self::NumericTypes>,
) -> EvalexprResult<(), Self::NumericTypes> {
Err(EvalexprError::ContextNotMutable)
}
}
pub trait IterateVariablesContext: Context {
type VariableIterator<'a>: Iterator<Item = (String, Value<Self::NumericTypes>)>
where
Self: 'a;
type VariableNameIterator<'a>: Iterator<Item = String>
where
Self: 'a;
fn iter_variables(&self) -> Self::VariableIterator<'_>;
fn iter_variable_names(&self) -> Self::VariableNameIterator<'_>;
}
#[derive(Debug)]
pub struct EmptyContext<NumericTypes>(PhantomData<NumericTypes>);
impl<NumericTypes: EvalexprNumericTypes> Context for EmptyContext<NumericTypes> {
type NumericTypes = NumericTypes;
fn get_value(&self, _identifier: &str) -> Option<&Value<Self::NumericTypes>> {
None
}
fn call_function(
&self,
identifier: &str,
_argument: &Value<Self::NumericTypes>,
) -> EvalexprResultValue<Self::NumericTypes> {
Err(EvalexprError::FunctionIdentifierNotFound(
identifier.to_string(),
))
}
fn are_builtin_functions_disabled(&self) -> bool {
true
}
fn set_builtin_functions_disabled(
&mut self,
disabled: bool,
) -> EvalexprResult<(), Self::NumericTypes> {
if disabled {
Ok(())
} else {
Err(EvalexprError::BuiltinFunctionsCannotBeEnabled)
}
}
}
impl<NumericTypes: EvalexprNumericTypes> IterateVariablesContext for EmptyContext<NumericTypes> {
type VariableIterator<'a>
= iter::Empty<(String, Value<Self::NumericTypes>)>
where
Self: 'a;
type VariableNameIterator<'a>
= iter::Empty<String>
where
Self: 'a;
fn iter_variables(&self) -> Self::VariableIterator<'_> {
iter::empty()
}
fn iter_variable_names(&self) -> Self::VariableNameIterator<'_> {
iter::empty()
}
}
impl<NumericTypes> Default for EmptyContext<NumericTypes> {
fn default() -> Self {
Self(PhantomData)
}
}
#[derive(Debug)]
pub struct EmptyContextWithBuiltinFunctions<NumericTypes>(PhantomData<NumericTypes>);
impl<NumericTypes: EvalexprNumericTypes> Context
for EmptyContextWithBuiltinFunctions<NumericTypes>
{
type NumericTypes = NumericTypes;
fn get_value(&self, _identifier: &str) -> Option<&Value<Self::NumericTypes>> {
None
}
fn call_function(
&self,
identifier: &str,
_argument: &Value<Self::NumericTypes>,
) -> EvalexprResultValue<Self::NumericTypes> {
Err(EvalexprError::FunctionIdentifierNotFound(
identifier.to_string(),
))
}
fn are_builtin_functions_disabled(&self) -> bool {
false
}
fn set_builtin_functions_disabled(
&mut self,
disabled: bool,
) -> EvalexprResult<(), Self::NumericTypes> {
if disabled {
Err(EvalexprError::BuiltinFunctionsCannotBeDisabled)
} else {
Ok(())
}
}
}
impl<NumericTypes: EvalexprNumericTypes> IterateVariablesContext
for EmptyContextWithBuiltinFunctions<NumericTypes>
{
type VariableIterator<'a>
= iter::Empty<(String, Value<Self::NumericTypes>)>
where
Self: 'a;
type VariableNameIterator<'a>
= iter::Empty<String>
where
Self: 'a;
fn iter_variables(&self) -> Self::VariableIterator<'_> {
iter::empty()
}
fn iter_variable_names(&self) -> Self::VariableNameIterator<'_> {
iter::empty()
}
}
impl<NumericTypes> Default for EmptyContextWithBuiltinFunctions<NumericTypes> {
fn default() -> Self {
Self(PhantomData)
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct HashMapContext<NumericTypes: EvalexprNumericTypes = DefaultNumericTypes> {
variables: HashMap<String, Value<NumericTypes>>,
#[cfg_attr(feature = "serde", serde(skip))]
functions: HashMap<String, Function<NumericTypes>>,
without_builtin_functions: bool,
}
impl<NumericTypes: EvalexprNumericTypes> HashMapContext<NumericTypes> {
pub fn new() -> Self {
Default::default()
}
pub fn clear_variables(&mut self) {
self.variables.clear()
}
pub fn clear_functions(&mut self) {
self.functions.clear()
}
pub fn clear(&mut self) {
self.clear_variables();
self.clear_functions();
}
}
impl<NumericTypes: EvalexprNumericTypes> Context for HashMapContext<NumericTypes> {
type NumericTypes = NumericTypes;
fn get_value(&self, identifier: &str) -> Option<&Value<Self::NumericTypes>> {
self.variables.get(identifier)
}
fn call_function(
&self,
identifier: &str,
argument: &Value<Self::NumericTypes>,
) -> EvalexprResultValue<Self::NumericTypes> {
if let Some(function) = self.functions.get(identifier) {
function.call(argument)
} else {
Err(EvalexprError::FunctionIdentifierNotFound(
identifier.to_string(),
))
}
}
fn are_builtin_functions_disabled(&self) -> bool {
self.without_builtin_functions
}
fn set_builtin_functions_disabled(
&mut self,
disabled: bool,
) -> EvalexprResult<(), NumericTypes> {
self.without_builtin_functions = disabled;
Ok(())
}
}
impl<NumericTypes: EvalexprNumericTypes> ContextWithMutableVariables
for HashMapContext<NumericTypes>
{
fn set_value(
&mut self,
identifier: String,
value: Value<Self::NumericTypes>,
) -> EvalexprResult<(), NumericTypes> {
if let Some(existing_value) = self.variables.get_mut(&identifier) {
if ValueType::from(&existing_value) == ValueType::from(&value) {
*existing_value = value;
return Ok(());
} else {
return Err(EvalexprError::expected_type(existing_value, value));
}
}
self.variables.insert(identifier, value);
Ok(())
}
fn remove_value(
&mut self,
identifier: &str,
) -> EvalexprResult<Option<Value<Self::NumericTypes>>, Self::NumericTypes> {
Ok(self.variables.remove(identifier))
}
}
impl<NumericTypes: EvalexprNumericTypes> ContextWithMutableFunctions
for HashMapContext<NumericTypes>
{
fn set_function(
&mut self,
identifier: String,
function: Function<NumericTypes>,
) -> EvalexprResult<(), Self::NumericTypes> {
self.functions.insert(identifier, function);
Ok(())
}
}
impl<NumericTypes: EvalexprNumericTypes> IterateVariablesContext for HashMapContext<NumericTypes> {
type VariableIterator<'a>
= std::iter::Map<
std::collections::hash_map::Iter<'a, String, Value<NumericTypes>>,
fn((&String, &Value<NumericTypes>)) -> (String, Value<NumericTypes>),
>
where
Self: 'a;
type VariableNameIterator<'a>
= std::iter::Cloned<std::collections::hash_map::Keys<'a, String, Value<NumericTypes>>>
where
Self: 'a;
fn iter_variables(&self) -> Self::VariableIterator<'_> {
self.variables
.iter()
.map(|(string, value)| (string.clone(), value.clone()))
}
fn iter_variable_names(&self) -> Self::VariableNameIterator<'_> {
self.variables.keys().cloned()
}
}
impl<NumericTypes: EvalexprNumericTypes> Default for HashMapContext<NumericTypes> {
fn default() -> Self {
Self {
variables: Default::default(),
functions: Default::default(),
without_builtin_functions: false,
}
}
}
#[macro_export]
macro_rules! context_map {
( ($ctx:expr) $k:expr => Function::new($($v:tt)*) ) =>
{ $crate::context_map!(($ctx) $k => Function::new($($v)*),) };
( ($ctx:expr) $k:expr => int $v:expr ) =>
{ $crate::context_map!(($ctx) $k => int $v,) };
( ($ctx:expr) $k:expr => float $v:expr ) =>
{ $crate::context_map!(($ctx) $k => float $v,) };
( ($ctx:expr) $k:expr => $v:expr ) =>
{ $crate::context_map!(($ctx) $k => $v,) };
( ($ctx:expr) ) => { Ok(()) };
( ($ctx:expr) $k:expr => Function::new($($v:tt)*) , $($tt:tt)*) => {{
$crate::ContextWithMutableFunctions::set_function($ctx, $k.into(), $crate::Function::new($($v)*))
.and($crate::context_map!(($ctx) $($tt)*))
}};
( ($ctx:expr) $k:expr => int $v:expr , $($tt:tt)*) => {{
$crate::ContextWithMutableVariables::set_value($ctx, $k.into(), $crate::Value::from_int($v.into()))
.and($crate::context_map!(($ctx) $($tt)*))
}};
( ($ctx:expr) $k:expr => float $v:expr , $($tt:tt)*) => {{
$crate::ContextWithMutableVariables::set_value($ctx, $k.into(), $crate::Value::from_float($v.into()))
.and($crate::context_map!(($ctx) $($tt)*))
}};
( ($ctx:expr) $k:expr => $v:expr , $($tt:tt)*) => {{
$crate::ContextWithMutableVariables::set_value($ctx, $k.into(), $v.into())
.and($crate::context_map!(($ctx) $($tt)*))
}};
( $($tt:tt)* ) => {{
let mut context = $crate::HashMapContext::new();
$crate::context_map!((&mut context) $($tt)*)
.map(|_| context)
}};
}