1use std::{collections::HashMap, iter, marker::PhantomData};
8
9use crate::{
10 error::EvalexprResultValue,
11 function::Function,
12 value::{
13 numeric_types::{default_numeric_types::DefaultNumericTypes, EvalexprNumericTypes},
14 value_type::ValueType,
15 Value,
16 },
17 EvalexprError, EvalexprResult,
18};
19
20mod predefined;
21
22pub trait Context {
24 type NumericTypes: EvalexprNumericTypes;
26
27 fn get_value(&self, identifier: &str) -> Option<&Value<Self::NumericTypes>>;
29
30 fn call_function(
33 &self,
34 identifier: &str,
35 argument: &Value<Self::NumericTypes>,
36 ) -> EvalexprResultValue<Self::NumericTypes>;
37
38 fn are_builtin_functions_disabled(&self) -> bool;
40
41 fn set_builtin_functions_disabled(
44 &mut self,
45 disabled: bool,
46 ) -> EvalexprResult<(), Self::NumericTypes>;
47}
48
49pub trait ContextWithMutableVariables: Context {
51 fn set_value(
53 &mut self,
54 _identifier: String,
55 _value: Value<Self::NumericTypes>,
56 ) -> EvalexprResult<(), Self::NumericTypes> {
57 Err(EvalexprError::ContextNotMutable)
58 }
59}
60
61pub trait ContextWithMutableFunctions: Context {
63 fn set_function(
65 &mut self,
66 _identifier: String,
67 _function: Function<Self::NumericTypes>,
68 ) -> EvalexprResult<(), Self::NumericTypes> {
69 Err(EvalexprError::ContextNotMutable)
70 }
71}
72
73pub trait IterateVariablesContext: Context {
75 type VariableIterator<'a>: Iterator<Item = (String, Value<Self::NumericTypes>)>
77 where
78 Self: 'a;
79 type VariableNameIterator<'a>: Iterator<Item = String>
81 where
82 Self: 'a;
83
84 fn iter_variables(&self) -> Self::VariableIterator<'_>;
86
87 fn iter_variable_names(&self) -> Self::VariableNameIterator<'_>;
89}
90
91#[derive(Debug)]
103pub struct EmptyContext<NumericTypes>(PhantomData<NumericTypes>);
104
105impl<NumericTypes: EvalexprNumericTypes> Context for EmptyContext<NumericTypes> {
106 type NumericTypes = NumericTypes;
107
108 fn get_value(&self, _identifier: &str) -> Option<&Value<Self::NumericTypes>> {
109 None
110 }
111
112 fn call_function(
113 &self,
114 identifier: &str,
115 _argument: &Value<Self::NumericTypes>,
116 ) -> EvalexprResultValue<Self::NumericTypes> {
117 Err(EvalexprError::FunctionIdentifierNotFound(
118 identifier.to_string(),
119 ))
120 }
121
122 fn are_builtin_functions_disabled(&self) -> bool {
124 true
125 }
126
127 fn set_builtin_functions_disabled(
129 &mut self,
130 disabled: bool,
131 ) -> EvalexprResult<(), Self::NumericTypes> {
132 if disabled {
133 Ok(())
134 } else {
135 Err(EvalexprError::BuiltinFunctionsCannotBeEnabled)
136 }
137 }
138}
139
140impl<NumericTypes: EvalexprNumericTypes> IterateVariablesContext for EmptyContext<NumericTypes> {
141 type VariableIterator<'a>
142 = iter::Empty<(String, Value<Self::NumericTypes>)>
143 where
144 Self: 'a;
145 type VariableNameIterator<'a>
146 = iter::Empty<String>
147 where
148 Self: 'a;
149
150 fn iter_variables(&self) -> Self::VariableIterator<'_> {
151 iter::empty()
152 }
153
154 fn iter_variable_names(&self) -> Self::VariableNameIterator<'_> {
155 iter::empty()
156 }
157}
158
159impl<NumericTypes> Default for EmptyContext<NumericTypes> {
160 fn default() -> Self {
161 Self(PhantomData)
162 }
163}
164
165#[derive(Debug)]
168pub struct EmptyContextWithBuiltinFunctions<NumericTypes>(PhantomData<NumericTypes>);
169
170impl<NumericTypes: EvalexprNumericTypes> Context
171 for EmptyContextWithBuiltinFunctions<NumericTypes>
172{
173 type NumericTypes = NumericTypes;
174
175 fn get_value(&self, _identifier: &str) -> Option<&Value<Self::NumericTypes>> {
176 None
177 }
178
179 fn call_function(
180 &self,
181 identifier: &str,
182 _argument: &Value<Self::NumericTypes>,
183 ) -> EvalexprResultValue<Self::NumericTypes> {
184 Err(EvalexprError::FunctionIdentifierNotFound(
185 identifier.to_string(),
186 ))
187 }
188
189 fn are_builtin_functions_disabled(&self) -> bool {
191 false
192 }
193
194 fn set_builtin_functions_disabled(
196 &mut self,
197 disabled: bool,
198 ) -> EvalexprResult<(), Self::NumericTypes> {
199 if disabled {
200 Err(EvalexprError::BuiltinFunctionsCannotBeDisabled)
201 } else {
202 Ok(())
203 }
204 }
205}
206
207impl<NumericTypes: EvalexprNumericTypes> IterateVariablesContext
208 for EmptyContextWithBuiltinFunctions<NumericTypes>
209{
210 type VariableIterator<'a>
211 = iter::Empty<(String, Value<Self::NumericTypes>)>
212 where
213 Self: 'a;
214 type VariableNameIterator<'a>
215 = iter::Empty<String>
216 where
217 Self: 'a;
218
219 fn iter_variables(&self) -> Self::VariableIterator<'_> {
220 iter::empty()
221 }
222
223 fn iter_variable_names(&self) -> Self::VariableNameIterator<'_> {
224 iter::empty()
225 }
226}
227
228impl<NumericTypes> Default for EmptyContextWithBuiltinFunctions<NumericTypes> {
229 fn default() -> Self {
230 Self(PhantomData)
231 }
232}
233
234#[derive(Clone, Debug)]
240#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
241pub struct HashMapContext<NumericTypes: EvalexprNumericTypes = DefaultNumericTypes> {
242 variables: HashMap<String, Value<NumericTypes>>,
243 #[cfg_attr(feature = "serde", serde(skip))]
244 functions: HashMap<String, Function<NumericTypes>>,
245
246 without_builtin_functions: bool,
248}
249
250impl<NumericTypes: EvalexprNumericTypes> HashMapContext<NumericTypes> {
251 pub fn new() -> Self {
253 Default::default()
254 }
255
256 pub fn clear_variables(&mut self) {
271 self.variables.clear()
272 }
273
274 pub fn clear_functions(&mut self) {
277 self.functions.clear()
278 }
279
280 pub fn clear(&mut self) {
295 self.clear_variables();
296 self.clear_functions();
297 }
298}
299
300impl<NumericTypes: EvalexprNumericTypes> Context for HashMapContext<NumericTypes> {
301 type NumericTypes = NumericTypes;
302
303 fn get_value(&self, identifier: &str) -> Option<&Value<Self::NumericTypes>> {
304 self.variables.get(identifier)
305 }
306
307 fn call_function(
308 &self,
309 identifier: &str,
310 argument: &Value<Self::NumericTypes>,
311 ) -> EvalexprResultValue<Self::NumericTypes> {
312 if let Some(function) = self.functions.get(identifier) {
313 function.call(argument)
314 } else {
315 Err(EvalexprError::FunctionIdentifierNotFound(
316 identifier.to_string(),
317 ))
318 }
319 }
320
321 fn are_builtin_functions_disabled(&self) -> bool {
322 self.without_builtin_functions
323 }
324
325 fn set_builtin_functions_disabled(
326 &mut self,
327 disabled: bool,
328 ) -> EvalexprResult<(), NumericTypes> {
329 self.without_builtin_functions = disabled;
330 Ok(())
331 }
332}
333
334impl<NumericTypes: EvalexprNumericTypes> ContextWithMutableVariables
335 for HashMapContext<NumericTypes>
336{
337 fn set_value(
338 &mut self,
339 identifier: String,
340 value: Value<Self::NumericTypes>,
341 ) -> EvalexprResult<(), NumericTypes> {
342 if let Some(existing_value) = self.variables.get_mut(&identifier) {
343 if ValueType::from(&existing_value) == ValueType::from(&value) {
344 *existing_value = value;
345 return Ok(());
346 } else {
347 return Err(EvalexprError::expected_type(existing_value, value));
348 }
349 }
350
351 self.variables.insert(identifier, value);
353 Ok(())
354 }
355}
356
357impl<NumericTypes: EvalexprNumericTypes> ContextWithMutableFunctions
358 for HashMapContext<NumericTypes>
359{
360 fn set_function(
361 &mut self,
362 identifier: String,
363 function: Function<NumericTypes>,
364 ) -> EvalexprResult<(), Self::NumericTypes> {
365 self.functions.insert(identifier, function);
366 Ok(())
367 }
368}
369
370impl<NumericTypes: EvalexprNumericTypes> IterateVariablesContext for HashMapContext<NumericTypes> {
371 type VariableIterator<'a>
372 = std::iter::Map<
373 std::collections::hash_map::Iter<'a, String, Value<NumericTypes>>,
374 fn((&String, &Value<NumericTypes>)) -> (String, Value<NumericTypes>),
375 >
376 where
377 Self: 'a;
378 type VariableNameIterator<'a>
379 = std::iter::Cloned<std::collections::hash_map::Keys<'a, String, Value<NumericTypes>>>
380 where
381 Self: 'a;
382
383 fn iter_variables(&self) -> Self::VariableIterator<'_> {
384 self.variables
385 .iter()
386 .map(|(string, value)| (string.clone(), value.clone()))
387 }
388
389 fn iter_variable_names(&self) -> Self::VariableNameIterator<'_> {
390 self.variables.keys().cloned()
391 }
392}
393
394impl<NumericTypes: EvalexprNumericTypes> Default for HashMapContext<NumericTypes> {
395 fn default() -> Self {
396 Self {
397 variables: Default::default(),
398 functions: Default::default(),
399 without_builtin_functions: false,
400 }
401 }
402}
403
404#[macro_export]
419macro_rules! context_map {
420 ( ($ctx:expr) $k:expr => Function::new($($v:tt)*) ) =>
422 { $crate::context_map!(($ctx) $k => Function::new($($v)*),) };
423 ( ($ctx:expr) $k:expr => int $v:expr ) =>
424 { $crate::context_map!(($ctx) $k => int $v,) };
425 ( ($ctx:expr) $k:expr => float $v:expr ) =>
426 { $crate::context_map!(($ctx) $k => float $v,) };
427 ( ($ctx:expr) $k:expr => $v:expr ) =>
428 { $crate::context_map!(($ctx) $k => $v,) };
429 ( ($ctx:expr) ) => { Ok(()) };
431
432 ( ($ctx:expr) $k:expr => Function::new($($v:tt)*) , $($tt:tt)*) => {{
434 $crate::ContextWithMutableFunctions::set_function($ctx, $k.into(), $crate::Function::new($($v)*))
435 .and($crate::context_map!(($ctx) $($tt)*))
436 }};
437 ( ($ctx:expr) $k:expr => int $v:expr , $($tt:tt)*) => {{
439 $crate::ContextWithMutableVariables::set_value($ctx, $k.into(), $crate::Value::from_int($v.into()))
440 .and($crate::context_map!(($ctx) $($tt)*))
441 }};
442 ( ($ctx:expr) $k:expr => float $v:expr , $($tt:tt)*) => {{
444 $crate::ContextWithMutableVariables::set_value($ctx, $k.into(), $crate::Value::from_float($v.into()))
445 .and($crate::context_map!(($ctx) $($tt)*))
446 }};
447 ( ($ctx:expr) $k:expr => $v:expr , $($tt:tt)*) => {{
449 $crate::ContextWithMutableVariables::set_value($ctx, $k.into(), $v.into())
450 .and($crate::context_map!(($ctx) $($tt)*))
451 }};
452
453 ( $($tt:tt)* ) => {{
455 let mut context = $crate::HashMapContext::new();
456 $crate::context_map!((&mut context) $($tt)*)
457 .map(|_| context)
458 }};
459}