cala_cel_interpreter/
value.rs

1use cel_parser::{ast::Literal, Expression};
2use chrono::{DateTime, NaiveDate, Utc};
3use rust_decimal::Decimal;
4use uuid::Uuid;
5
6use std::{collections::HashMap, sync::Arc};
7
8use crate::{cel_type::*, error::*};
9
10pub struct CelResult<'a> {
11    pub expr: &'a Expression,
12    pub val: CelValue,
13}
14
15#[derive(Debug, Clone, PartialEq)]
16pub enum CelValue {
17    // Builtins
18    Map(Arc<CelMap>),
19    List(Arc<CelArray>),
20    Int(i64),
21    UInt(u64),
22    Double(f64),
23    String(Arc<String>),
24    Bytes(Arc<Vec<u8>>),
25    Bool(bool),
26    Null,
27
28    // Abstract
29    Decimal(Decimal),
30    Date(NaiveDate),
31    Timestamp(DateTime<Utc>),
32    Uuid(Uuid),
33}
34
35impl CelValue {
36    pub(crate) fn try_bool(&self) -> Result<bool, CelError> {
37        if let CelValue::Bool(val) = self {
38            Ok(*val)
39        } else {
40            Err(CelError::BadType(CelType::Bool, CelType::from(self)))
41        }
42    }
43}
44
45#[derive(Debug, PartialEq)]
46pub struct CelMap {
47    inner: HashMap<CelKey, CelValue>,
48}
49
50impl CelMap {
51    pub fn new() -> Self {
52        Self {
53            inner: HashMap::new(),
54        }
55    }
56
57    pub fn insert(&mut self, k: impl Into<CelKey>, val: impl Into<CelValue>) {
58        self.inner.insert(k.into(), val.into());
59    }
60
61    pub fn get(&self, key: impl Into<CelKey>) -> CelValue {
62        self.inner
63            .get(&key.into())
64            .cloned()
65            .unwrap_or(CelValue::Null)
66    }
67
68    pub fn contains_key(&self, key: impl Into<CelKey>) -> bool {
69        self.inner.contains_key(&key.into())
70    }
71}
72
73impl Default for CelMap {
74    fn default() -> Self {
75        Self::new()
76    }
77}
78
79impl From<HashMap<String, CelValue>> for CelMap {
80    fn from(map: HashMap<String, CelValue>) -> Self {
81        let mut res = CelMap::new();
82        for (k, v) in map {
83            res.insert(CelKey::String(Arc::from(k)), v);
84        }
85        res
86    }
87}
88
89impl From<CelMap> for CelValue {
90    fn from(m: CelMap) -> Self {
91        CelValue::Map(Arc::from(m))
92    }
93}
94
95#[derive(Debug, PartialEq)]
96pub struct CelArray {
97    inner: Vec<CelValue>,
98}
99
100impl CelArray {
101    pub fn new() -> Self {
102        Self { inner: Vec::new() }
103    }
104
105    pub fn push(&mut self, elem: impl Into<CelValue>) {
106        self.inner.push(elem.into());
107    }
108}
109
110impl Default for CelArray {
111    fn default() -> Self {
112        Self::new()
113    }
114}
115
116impl From<i64> for CelValue {
117    fn from(i: i64) -> Self {
118        CelValue::Int(i)
119    }
120}
121
122impl From<Decimal> for CelValue {
123    fn from(d: Decimal) -> Self {
124        CelValue::Decimal(d)
125    }
126}
127
128impl From<bool> for CelValue {
129    fn from(b: bool) -> Self {
130        CelValue::Bool(b)
131    }
132}
133
134impl From<String> for CelValue {
135    fn from(s: String) -> Self {
136        CelValue::String(Arc::from(s))
137    }
138}
139
140impl From<NaiveDate> for CelValue {
141    fn from(d: NaiveDate) -> Self {
142        CelValue::Date(d)
143    }
144}
145
146impl From<Uuid> for CelValue {
147    fn from(id: Uuid) -> Self {
148        CelValue::Uuid(id)
149    }
150}
151
152impl From<&str> for CelValue {
153    fn from(s: &str) -> Self {
154        CelValue::String(Arc::from(s.to_string()))
155    }
156}
157
158impl From<serde_json::Value> for CelValue {
159    fn from(v: serde_json::Value) -> Self {
160        use serde_json::Value::*;
161        match v {
162            Null => CelValue::Null,
163            Bool(b) => CelValue::Bool(b),
164            Number(n) => {
165                if let Some(u) = n.as_u64() {
166                    CelValue::UInt(u)
167                } else if let Some(i) = n.as_i64() {
168                    CelValue::Int(i)
169                } else {
170                    unimplemented!()
171                }
172            }
173            String(s) => CelValue::String(Arc::from(s)),
174            Object(o) => {
175                let mut map = CelMap::new();
176                for (k, v) in o.into_iter() {
177                    map.insert(CelKey::String(Arc::from(k)), CelValue::from(v));
178                }
179                CelValue::Map(Arc::from(map))
180            }
181            Array(a) => {
182                let mut ar = CelArray::new();
183                for v in a.into_iter() {
184                    ar.push(CelValue::from(v));
185                }
186                CelValue::List(Arc::from(ar))
187            }
188        }
189    }
190}
191
192#[derive(Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
193pub enum CelKey {
194    Int(i64),
195    UInt(u64),
196    Bool(bool),
197    String(Arc<String>),
198}
199
200impl From<&str> for CelKey {
201    fn from(s: &str) -> Self {
202        CelKey::String(Arc::from(s.to_string()))
203    }
204}
205
206impl From<String> for CelKey {
207    fn from(s: String) -> Self {
208        CelKey::String(Arc::from(s))
209    }
210}
211
212impl From<&Arc<String>> for CelKey {
213    fn from(s: &Arc<String>) -> Self {
214        CelKey::String(s.clone())
215    }
216}
217
218impl From<&CelValue> for CelType {
219    fn from(v: &CelValue) -> Self {
220        match v {
221            CelValue::Map(_) => CelType::Map,
222            CelValue::List(_) => CelType::List,
223            CelValue::Int(_) => CelType::Int,
224            CelValue::UInt(_) => CelType::UInt,
225            CelValue::Double(_) => CelType::Double,
226            CelValue::String(_) => CelType::String,
227            CelValue::Bytes(_) => CelType::Bytes,
228            CelValue::Bool(_) => CelType::Bool,
229            CelValue::Null => CelType::Null,
230
231            CelValue::Decimal(_) => CelType::Decimal,
232            CelValue::Date(_) => CelType::Date,
233            CelValue::Uuid(_) => CelType::Uuid,
234            CelValue::Timestamp(_) => CelType::Timestamp,
235        }
236    }
237}
238
239impl From<&Literal> for CelValue {
240    fn from(l: &Literal) -> Self {
241        use Literal::*;
242        match l {
243            Int(i) => CelValue::Int(*i),
244            UInt(u) => CelValue::UInt(*u),
245            Double(d) => CelValue::Double(d.parse().expect("Couldn't parse Decimal")),
246            String(s) => CelValue::String(s.clone()),
247            Bytes(b) => CelValue::Bytes(b.clone()),
248            Bool(b) => CelValue::Bool(*b),
249            Null => CelValue::Null,
250        }
251    }
252}
253
254impl From<DateTime<Utc>> for CelValue {
255    fn from(d: DateTime<Utc>) -> Self {
256        CelValue::Timestamp(d)
257    }
258}
259
260impl TryFrom<&CelValue> for Arc<String> {
261    type Error = CelError;
262
263    fn try_from(v: &CelValue) -> Result<Self, Self::Error> {
264        if let CelValue::String(s) = v {
265            Ok(s.clone())
266        } else {
267            Err(CelError::BadType(CelType::String, CelType::from(v)))
268        }
269    }
270}
271
272impl<'a> TryFrom<&'a CelValue> for &'a Decimal {
273    type Error = CelError;
274
275    fn try_from(v: &'a CelValue) -> Result<Self, Self::Error> {
276        if let CelValue::Decimal(d) = v {
277            Ok(d)
278        } else {
279            Err(CelError::BadType(CelType::Decimal, CelType::from(v)))
280        }
281    }
282}
283
284impl TryFrom<CelResult<'_>> for bool {
285    type Error = ResultCoercionError;
286
287    fn try_from(CelResult { expr, val }: CelResult) -> Result<Self, Self::Error> {
288        if let CelValue::Bool(b) = val {
289            Ok(b)
290        } else {
291            Err(ResultCoercionError::BadCoreTypeCoercion(
292                format!("{expr:?}"),
293                CelType::from(&val),
294                CelType::Bool,
295            ))
296        }
297    }
298}
299
300impl TryFrom<CelResult<'_>> for NaiveDate {
301    type Error = ResultCoercionError;
302
303    fn try_from(CelResult { expr, val }: CelResult) -> Result<Self, Self::Error> {
304        if let CelValue::Date(d) = val {
305            Ok(d)
306        } else {
307            Err(ResultCoercionError::BadCoreTypeCoercion(
308                format!("{expr:?}"),
309                CelType::from(&val),
310                CelType::Date,
311            ))
312        }
313    }
314}
315
316impl TryFrom<CelResult<'_>> for DateTime<Utc> {
317    type Error = ResultCoercionError;
318
319    fn try_from(CelResult { expr, val }: CelResult) -> Result<Self, Self::Error> {
320        if let CelValue::Timestamp(d) = val {
321            Ok(d)
322        } else {
323            Err(ResultCoercionError::BadCoreTypeCoercion(
324                format!("{expr:?}"),
325                CelType::from(&val),
326                CelType::Timestamp,
327            ))
328        }
329    }
330}
331
332impl TryFrom<CelResult<'_>> for Uuid {
333    type Error = ResultCoercionError;
334
335    fn try_from(CelResult { expr, val }: CelResult) -> Result<Self, Self::Error> {
336        if let CelValue::Uuid(id) = val {
337            Ok(id)
338        } else {
339            Err(ResultCoercionError::BadCoreTypeCoercion(
340                format!("{expr:?}"),
341                CelType::from(&val),
342                CelType::Uuid,
343            ))
344        }
345    }
346}
347
348impl TryFrom<CelResult<'_>> for String {
349    type Error = ResultCoercionError;
350
351    fn try_from(CelResult { expr, val }: CelResult) -> Result<Self, Self::Error> {
352        if let CelValue::String(s) = val {
353            Ok(s.to_string())
354        } else {
355            Err(ResultCoercionError::BadCoreTypeCoercion(
356                format!("{expr:?}"),
357                CelType::from(&val),
358                CelType::String,
359            ))
360        }
361    }
362}
363
364impl TryFrom<CelResult<'_>> for Decimal {
365    type Error = ResultCoercionError;
366
367    fn try_from(CelResult { expr, val }: CelResult) -> Result<Self, Self::Error> {
368        match val {
369            CelValue::Decimal(n) => Ok(n),
370            _ => Err(ResultCoercionError::BadCoreTypeCoercion(
371                format!("{expr:?}"),
372                CelType::from(&val),
373                CelType::Decimal,
374            )),
375        }
376    }
377}
378
379impl From<&CelKey> for CelType {
380    fn from(v: &CelKey) -> Self {
381        match v {
382            CelKey::Int(_) => CelType::Int,
383            CelKey::UInt(_) => CelType::UInt,
384            CelKey::Bool(_) => CelType::Bool,
385            CelKey::String(_) => CelType::String,
386        }
387    }
388}
389
390impl TryFrom<&CelKey> for String {
391    type Error = ResultCoercionError;
392
393    fn try_from(v: &CelKey) -> Result<Self, Self::Error> {
394        if let CelKey::String(s) = v {
395            Ok(s.to_string())
396        } else {
397            Err(ResultCoercionError::BadCoreTypeCoercion(
398                format!("{v:?}"),
399                CelType::from(v),
400                CelType::String,
401            ))
402        }
403    }
404}
405
406impl TryFrom<CelResult<'_>> for serde_json::Value {
407    type Error = ResultCoercionError;
408
409    fn try_from(CelResult { expr, val }: CelResult) -> Result<Self, Self::Error> {
410        use serde_json::*;
411        Ok(match val {
412            CelValue::Int(n) => Value::from(n),
413            CelValue::UInt(n) => Value::from(n),
414            CelValue::Double(n) => Value::from(n.to_string()),
415            CelValue::Bool(b) => Value::from(b),
416            CelValue::String(n) => Value::from(n.as_str()),
417            CelValue::Null => Value::Null,
418            CelValue::Date(d) => Value::from(d.to_string()),
419            CelValue::Uuid(u) => Value::from(u.to_string()),
420            CelValue::Map(m) => {
421                let mut res = serde_json::Map::new();
422                for (k, v) in m.inner.iter() {
423                    let key: String = k.try_into()?;
424                    let value = Self::try_from(CelResult {
425                        expr,
426                        val: v.clone(),
427                    })?;
428                    res.insert(key, value);
429                }
430                Value::from(res)
431            }
432            CelValue::List(a) => {
433                let mut res = Vec::new();
434                for v in a.inner.iter() {
435                    res.push(Self::try_from(CelResult {
436                        expr,
437                        val: v.clone(),
438                    })?);
439                }
440                Value::from(res)
441            }
442            _ => unimplemented!(),
443        })
444    }
445}