cala_cel_interpreter/context/
mod.rs1mod 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 debug_context(&self) -> String {
31 let vars: Vec<_> = self
32 .idents
33 .iter()
34 .filter_map(|(name, item)| match item {
35 ContextItem::Value(val) => Some(format!("{}={:?}", name, val)),
36 _ => None,
37 })
38 .collect();
39
40 if vars.is_empty() {
41 String::new()
42 } else {
43 vars.join(", ")
44 }
45 }
46
47 pub fn new() -> Self {
48 let mut idents = HashMap::new();
49 idents.insert(
50 Cow::Borrowed("date"),
51 ContextItem::Function(Box::new(builtins::date)),
52 );
53 idents.insert(
54 Cow::Borrowed("uuid"),
55 ContextItem::Function(Box::new(builtins::uuid)),
56 );
57 idents.insert(
58 Cow::Borrowed("decimal"),
59 ContextItem::Package(&decimal::CEL_PACKAGE),
60 );
61
62 idents.insert(
63 Cow::Borrowed("timestamp"),
64 ContextItem::Package(×tamp::CEL_PACKAGE),
65 );
66
67 Self { idents }
68 }
69
70 pub(crate) fn lookup_ident(&self, name: &str) -> Result<&ContextItem, CelError> {
71 self.idents
72 .get(name)
73 .ok_or_else(|| CelError::UnknownIdent(name.to_string()))
74 }
75
76 pub(crate) fn lookup_member_fn(
77 &self,
78 value: &CelValue,
79 name: &str,
80 ) -> Result<&CelMemberFunction, CelError> {
81 let package_name = CelType::from(value).package_name();
82 let package = if let Some(ContextItem::Package(package)) = self.idents.get(package_name) {
83 package
84 } else {
85 return Err(CelError::UnknownPackage(package_name));
86 };
87
88 package.lookup_member(value, name)
89 }
90}
91impl Default for CelContext {
92 fn default() -> Self {
93 Self::new()
94 }
95}
96
97pub(crate) enum ContextItem {
98 Value(CelValue),
99 Function(CelFunction),
100 Package(&'static CelPackage),
101}
102
103impl std::fmt::Debug for ContextItem {
104 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105 match self {
106 ContextItem::Value(val) => write!(f, "Value({val:?})"),
107 ContextItem::Function(_) => write!(f, "Function"),
108 ContextItem::Package(_) => write!(f, "Package"),
109 }
110 }
111}