cel_eval/
models.rs

1use crate::DisplayableValue;
2use cel_interpreter::objects::{Key, Map};
3use cel_interpreter::Value;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use std::sync::Arc;
7
8#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
9pub(crate) struct ExecutionContext {
10    pub(crate) variables: PassableMap,
11    pub(crate) expression: String,
12    pub(crate) computed: Option<HashMap<String, Vec<PassableValue>>>,
13    pub(crate) device: Option<HashMap<String, Vec<PassableValue>>>
14}
15
16#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
17pub struct PassableMap {
18    pub map: HashMap<String, PassableValue>,
19}
20
21#[derive(Serialize, Deserialize, Debug, Clone)]
22#[serde(tag = "type", content = "value")]
23pub enum PassableValue {
24    #[serde(rename = "list")]
25    List(Vec<PassableValue>),
26    #[serde(rename = "map")]
27    PMap(HashMap<String, PassableValue>),
28    #[serde(rename = "function")]
29    Function(String, Option<Box<PassableValue>>),
30    #[serde(rename = "int")]
31    Int(i64),
32    #[serde(rename = "uint")]
33    UInt(u64),
34    #[serde(rename = "float")]
35    Float(f64),
36    #[serde(rename = "string")]
37    String(String),
38    #[serde(rename = "bytes")]
39    Bytes(Vec<u8>),
40    #[serde(rename = "bool")]
41    Bool(bool),
42    #[serde(rename = "timestamp")]
43    Timestamp(i64),
44    Null,
45}
46
47impl PartialEq for PassableValue {
48    fn eq(&self, other: &Self) -> bool {
49        match (self, other) {
50            (PassableValue::PMap(a), PassableValue::PMap(b)) => a == b,
51            (PassableValue::List(a), PassableValue::List(b)) => a == b,
52            (PassableValue::Function(a1, a2), PassableValue::Function(b1, b2)) => {
53                a1 == b1 && a2 == b2
54            }
55            (PassableValue::Int(a), PassableValue::Int(b)) => a == b,
56            (PassableValue::UInt(a), PassableValue::UInt(b)) => a == b,
57            (PassableValue::Float(a), PassableValue::Float(b)) => a == b,
58            (PassableValue::String(a), PassableValue::String(b)) => a == b,
59            (PassableValue::Bytes(a), PassableValue::Bytes(b)) => a == b,
60            (PassableValue::Bool(a), PassableValue::Bool(b)) => a == b,
61            (PassableValue::Null, PassableValue::Null) => true,
62            (PassableValue::Timestamp(a), PassableValue::Timestamp(b)) => a == b,
63            // Allow different numeric types to be compared without explicit casting.
64            (PassableValue::Int(a), PassableValue::UInt(b)) => a
65                .to_owned()
66                .try_into()
67                .map(|a: u64| a == *b)
68                .unwrap_or(false),
69            (PassableValue::Int(a), PassableValue::Float(b)) => (*a as f64) == *b,
70            (PassableValue::UInt(a), PassableValue::Int(b)) => a
71                .to_owned()
72                .try_into()
73                .map(|a: i64| a == *b)
74                .unwrap_or(false),
75            (PassableValue::UInt(a), PassableValue::Float(b)) => (*a as f64) == *b,
76            (PassableValue::Float(a), PassableValue::Int(b)) => *a == (*b as f64),
77            (PassableValue::Float(a), PassableValue::UInt(b)) => *a == (*b as f64),
78            (_, _) => false,
79        }
80    }
81}
82
83impl PassableValue {
84    pub fn to_cel(&self) -> Value {
85        match self {
86            PassableValue::List(list) => {
87                let mapped_list: Vec<Value> = list.iter().map(|item| item.to_cel()).collect();
88                Value::List(Arc::new(mapped_list))
89            }
90            PassableValue::PMap(map) => {
91                let mapped_map = map
92                    .iter()
93                    .map(|(k, v)| (Key::String(Arc::from(k.clone())), (*v).to_cel()))
94                    .collect();
95                Value::Map(Map {
96                    map: Arc::new(mapped_map),
97                })
98            }
99            PassableValue::Function(name, arg) => {
100                let mapped_arg = arg.as_ref().map(|arg| arg.to_cel());
101                Value::Function(Arc::from(name.clone()), mapped_arg.map(|v| Box::new(v)))
102            }
103            PassableValue::Int(i) => Value::Int(*i),
104            PassableValue::UInt(u) => Value::UInt(*u),
105            PassableValue::Float(f) => Value::Float(*f),
106            PassableValue::String(s) => Value::String(Arc::from(s.clone())),
107            PassableValue::Bytes(b) => Value::Bytes(Arc::from(b.clone())),
108            PassableValue::Bool(b) => Value::Bool(*b),
109            PassableValue::Timestamp(t) => Value::Int(*t),
110            PassableValue::Null => Value::Null,
111        }
112    }
113}
114
115fn key_to_string(key: Key) -> String {
116    match key {
117        Key::String(s) => (*s).clone(),
118        Key::Int(i) => i.to_string(),
119        Key::Uint(u) => u.to_string(),
120        Key::Bool(b) => b.to_string(),
121    }
122}
123impl DisplayableValue {
124    pub fn to_passable(&self) -> PassableValue {
125        match &self.0 {
126            Value::List(list) => {
127                let mapped_list: Vec<PassableValue> = list
128                    .iter()
129                    .map(|item| DisplayableValue(item.clone()).to_passable())
130                    .collect();
131                PassableValue::List(mapped_list)
132            }
133            Value::Map(map) => {
134                let mapped_map: HashMap<String, PassableValue> = map
135                    .map
136                    .iter()
137                    .map(|(k, v)| {
138                        (
139                            key_to_string(k.clone()),
140                            DisplayableValue(v.clone()).to_passable(),
141                        )
142                    })
143                    .collect();
144                PassableValue::PMap(mapped_map)
145            }
146            Value::Function(name, arg) => {
147                let mapped_arg = arg.as_ref().map(|arg| {
148                    let arg = *arg.clone();
149                    let arg = DisplayableValue(arg).to_passable();
150                    Box::new(arg)
151                });
152                PassableValue::Function((**name).clone(), mapped_arg)
153            }
154            Value::Int(i) => PassableValue::Int(*i),
155            Value::UInt(u) => PassableValue::UInt(*u),
156            Value::Float(f) => PassableValue::Float(*f),
157            Value::String(s) => PassableValue::String((**s).clone()),
158            Value::Bytes(b) => PassableValue::Bytes((**b).clone()),
159            Value::Bool(b) => PassableValue::Bool(*b),
160            Value::Duration(_) => PassableValue::Null,
161            Value::Timestamp(t) => PassableValue::Timestamp(t.timestamp()),
162            Value::Null => PassableValue::Null,
163        }
164    }
165}