cala_cel_interpreter/context/
mod.rs

1mod decimal;
2mod package;
3mod timestamp;
4
5use std::{borrow::Cow, collections::HashMap};
6
7use crate::{builtins, cel_type::CelType, error::*, value::*};
8
9use package::CelPackage;
10
11const SELF_PACKAGE_NAME: Cow<'static, str> = Cow::Borrowed("self");
12
13type CelFunction = Box<dyn Fn(Vec<CelValue>) -> Result<CelValue, CelError> + Sync>;
14pub(crate) type CelMemberFunction =
15    Box<dyn Fn(&CelValue, Vec<CelValue>) -> Result<CelValue, CelError> + Sync>;
16
17#[derive(Debug)]
18pub struct CelContext {
19    idents: HashMap<Cow<'static, str>, ContextItem>,
20}
21
22impl CelContext {
23    pub fn add_variable(&mut self, name: impl Into<Cow<'static, str>>, value: impl Into<CelValue>) {
24        self.idents
25            .insert(name.into(), ContextItem::Value(value.into()));
26    }
27
28    pub fn new() -> Self {
29        let mut idents = HashMap::new();
30        idents.insert(
31            Cow::Borrowed("date"),
32            ContextItem::Function(Box::new(builtins::date)),
33        );
34        idents.insert(
35            Cow::Borrowed("uuid"),
36            ContextItem::Function(Box::new(builtins::uuid)),
37        );
38        idents.insert(
39            Cow::Borrowed("decimal"),
40            ContextItem::Package(&decimal::CEL_PACKAGE),
41        );
42
43        idents.insert(
44            Cow::Borrowed("timestamp"),
45            ContextItem::Package(&timestamp::CEL_PACKAGE),
46        );
47
48        Self { idents }
49    }
50
51    pub(crate) fn lookup_ident(&self, name: &str) -> Result<&ContextItem, CelError> {
52        self.idents
53            .get(name)
54            .ok_or_else(|| CelError::UnknownIdent(name.to_string()))
55    }
56
57    pub(crate) fn lookup_member_fn(
58        &self,
59        value: &CelValue,
60        name: &str,
61    ) -> Result<&CelMemberFunction, CelError> {
62        let package_name = CelType::from(value).package_name();
63        let package = if let Some(ContextItem::Package(package)) = self.idents.get(package_name) {
64            package
65        } else {
66            return Err(CelError::UnknownPackage(package_name));
67        };
68
69        package.lookup_member(value, name)
70    }
71}
72impl Default for CelContext {
73    fn default() -> Self {
74        Self::new()
75    }
76}
77
78pub(crate) enum ContextItem {
79    Value(CelValue),
80    Function(CelFunction),
81    Package(&'static CelPackage),
82}
83
84impl std::fmt::Debug for ContextItem {
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        match self {
87            ContextItem::Value(val) => write!(f, "Value({val:?})"),
88            ContextItem::Function(_) => write!(f, "Function"),
89            ContextItem::Package(_) => write!(f, "Package"),
90        }
91    }
92}