1use std::collections::HashMap;
2
3use crate::{Error, expr::{BoxedExprFn, ExprValue}};
4
5#[macro_export]
18macro_rules! simple_context {
19 () => {
21 $crate::SimpleContext::new(std::collections::HashMap::new())
22 };
23
24 ($key:literal : $value:expr $(,)?) => {
26 $crate::SimpleContext::new(std::collections::HashMap::from([
27 ($key.to_string(), ($value).into()),
28 ]))
29 };
30
31 ($key:literal : $value:expr, $($rest_key:literal : $rest_value:expr),* $(,)?) => {
33 $crate::SimpleContext::new(std::collections::HashMap::from([
34 ($key.to_string(), ($value).into()),
35 $(($rest_key.to_string(), ($rest_value).into())),*
36 ]))
37 };
38}
39
40#[async_trait::async_trait]
42pub trait Context: Send + Sync {
43 async fn get_var(&self, name: &str) -> Result<ExprValue, Error>;
44 async fn get_fn(&self, name: &str) -> Result<Option<&BoxedExprFn>, Error> {
45 Err(Error::NoSuchFunction(name.to_string()))
46 }
47}
48
49pub struct SimpleContext {
54 vars: HashMap<String, ExprValue>,
55 fns: HashMap<String, BoxedExprFn>,
56}
57
58impl SimpleContext {
59 pub fn new(vars: HashMap<String, ExprValue>) -> Self {
60 Self {
61 vars,
62 fns: HashMap::new(),
63 }
64 }
65
66 pub fn add_fn(&mut self, name: String, func: BoxedExprFn) {
67 self.fns.insert(name, func);
68 }
69}
70
71#[async_trait::async_trait]
72impl Context for SimpleContext {
73 async fn get_var(&self, name: &str) -> Result<ExprValue, Error> {
74 self.vars
75 .get(name)
76 .cloned()
77 .ok_or(Error::NoSuchVar(name.to_string()))
78 }
79
80 async fn get_fn(&self, name: &str) -> Result<Option<&BoxedExprFn>, Error> {
81 Ok(self.fns.get(name))
82 }
83}