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 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 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}