Skip to main content

cel/
objects.rs

1use crate::common::ast::{operators, EntryExpr, Expr};
2use crate::common::types::bool::Bool;
3use crate::common::types::*;
4use crate::common::value::Val;
5use crate::context::Context;
6use crate::ExecutionError::NoSuchOverload;
7use crate::{ExecutionError, Expression, FunctionContext};
8#[cfg(feature = "chrono")]
9use chrono::TimeZone;
10use std::any::Any;
11use std::borrow::{Borrow, Cow};
12use std::cmp::Ordering;
13use std::collections::HashMap;
14use std::convert::{Infallible, TryFrom, TryInto};
15use std::fmt::{Debug, Display, Formatter};
16use std::ops;
17use std::ops::Deref;
18use std::sync::Arc;
19#[cfg(feature = "chrono")]
20use std::sync::LazyLock;
21
22/// Timestamp values are limited to the range of values which can be serialized as a string:
23/// `["0001-01-01T00:00:00Z", "9999-12-31T23:59:59.999999999Z"]`. Since the max is a smaller
24/// and the min is a larger timestamp than what is possible to represent with
25/// [`chrono::DateTime`], we need to perform our own spec-compliant overflow checks.
26///
27/// <https://github.com/google/cel-spec/blob/master/doc/langdef.md#overflow>
28#[cfg(feature = "chrono")]
29static MAX_TIMESTAMP: LazyLock<chrono::DateTime<chrono::FixedOffset>> = LazyLock::new(|| {
30    let naive = chrono::NaiveDate::from_ymd_opt(9999, 12, 31)
31        .unwrap()
32        .and_hms_nano_opt(23, 59, 59, 999_999_999)
33        .unwrap();
34    chrono::FixedOffset::east_opt(0)
35        .unwrap()
36        .from_utc_datetime(&naive)
37});
38
39#[cfg(feature = "chrono")]
40static MIN_TIMESTAMP: LazyLock<chrono::DateTime<chrono::FixedOffset>> = LazyLock::new(|| {
41    let naive = chrono::NaiveDate::from_ymd_opt(1, 1, 1)
42        .unwrap()
43        .and_hms_opt(0, 0, 0)
44        .unwrap();
45    chrono::FixedOffset::east_opt(0)
46        .unwrap()
47        .from_utc_datetime(&naive)
48});
49
50#[derive(Debug, PartialEq, Clone)]
51pub struct Map {
52    pub map: Arc<HashMap<Key, Value>>,
53}
54
55impl PartialOrd for Map {
56    fn partial_cmp(&self, _: &Self) -> Option<Ordering> {
57        None
58    }
59}
60
61impl Map {
62    pub(crate) fn contains_key(&self, key: &(dyn AsKeyRef + '_)) -> bool {
63        self.map.contains_key(key)
64    }
65    /// Returns a reference to the value corresponding to the key. Implicitly converts between int
66    /// and uint keys.
67    pub fn get(&self, key: &(dyn AsKeyRef + '_)) -> Option<&Value> {
68        self.map.get(key).or_else(|| {
69            // Also check keys that are cross type comparable.
70            let keyref = key.as_keyref();
71            match keyref {
72                KeyRef::Int(k) => {
73                    let converted = u64::try_from(k).ok()?;
74                    self.map.get(&Key::Uint(converted))
75                }
76                KeyRef::Uint(k) => {
77                    let converted = i64::try_from(k).ok()?;
78                    self.map.get(&Key::Int(converted))
79                }
80                _ => None,
81            }
82        })
83    }
84}
85
86#[derive(Debug, Eq, PartialEq, Hash, Ord, Clone, PartialOrd)]
87pub enum Key {
88    Int(i64),
89    Uint(u64),
90    Bool(bool),
91    String(Arc<String>),
92}
93
94impl From<CelMapKey> for Key {
95    fn from(value: CelMapKey) -> Self {
96        match value {
97            CelMapKey::Bool(b) => b.into_inner().into(),
98            CelMapKey::Int(i) => i.into_inner().into(),
99            CelMapKey::String(s) => s.into_inner().into(),
100            CelMapKey::UInt(u) => u.into_inner().into(),
101        }
102    }
103}
104
105impl From<Key> for CelMapKey {
106    fn from(key: Key) -> Self {
107        match key {
108            Key::Int(i) => CelMapKey::from(i),
109            Key::Uint(u) => CelMapKey::from(u),
110            Key::Bool(b) => CelMapKey::from(b),
111            Key::String(s) => CelMapKey::from(s.as_str()),
112        }
113    }
114}
115
116/// A borrowed version of [`Key`] that avoids allocating for lookups.
117#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
118pub enum KeyRef<'a> {
119    Int(i64),
120    Uint(u64),
121    Bool(bool),
122    String(&'a str),
123}
124
125/// Trait for converting to a borrowed [`KeyRef`] for efficient lookups.
126pub trait AsKeyRef {
127    fn as_keyref(&self) -> KeyRef<'_>;
128}
129
130impl AsKeyRef for Key {
131    fn as_keyref(&self) -> KeyRef<'_> {
132        match self {
133            Key::Int(i) => KeyRef::Int(*i),
134            Key::Uint(u) => KeyRef::Uint(*u),
135            Key::Bool(b) => KeyRef::Bool(*b),
136            Key::String(s) => KeyRef::String(s.as_str()),
137        }
138    }
139}
140
141impl<'a> AsKeyRef for KeyRef<'a> {
142    fn as_keyref(&self) -> KeyRef<'a> {
143        *self
144    }
145}
146
147/// Trait object implementations for `dyn AsKeyRef` to enable hashing and comparison.
148impl<'a> PartialEq for dyn AsKeyRef + 'a {
149    fn eq(&self, other: &Self) -> bool {
150        self.as_keyref().eq(&other.as_keyref())
151    }
152}
153
154impl<'a> Eq for dyn AsKeyRef + 'a {}
155
156impl<'a> std::hash::Hash for dyn AsKeyRef + 'a {
157    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
158        self.as_keyref().hash(state)
159    }
160}
161
162impl<'a> PartialOrd for dyn AsKeyRef + 'a {
163    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
164        Some(self.cmp(other))
165    }
166}
167
168impl<'a> Ord for dyn AsKeyRef + 'a {
169    fn cmp(&self, other: &Self) -> Ordering {
170        self.as_keyref().cmp(&other.as_keyref())
171    }
172}
173
174/// Implement `Borrow<dyn AsKeyRef>` for `Key` to enable efficient lookups.
175impl<'a> Borrow<dyn AsKeyRef + 'a> for Key {
176    fn borrow(&self) -> &(dyn AsKeyRef + 'a) {
177        self
178    }
179}
180
181/// Implement conversions from primitive types to [`Key`]
182impl From<String> for Key {
183    fn from(v: String) -> Self {
184        Key::String(v.into())
185    }
186}
187
188impl From<Arc<String>> for Key {
189    fn from(v: Arc<String>) -> Self {
190        Key::String(v)
191    }
192}
193
194impl<'a> From<&'a str> for Key {
195    fn from(v: &'a str) -> Self {
196        Key::String(Arc::new(v.into()))
197    }
198}
199
200impl From<bool> for Key {
201    fn from(v: bool) -> Self {
202        Key::Bool(v)
203    }
204}
205
206impl From<i64> for Key {
207    fn from(v: i64) -> Self {
208        Key::Int(v)
209    }
210}
211
212impl From<i32> for Key {
213    fn from(v: i32) -> Self {
214        Key::Int(v as i64)
215    }
216}
217
218impl From<u64> for Key {
219    fn from(v: u64) -> Self {
220        Key::Uint(v)
221    }
222}
223
224impl From<u32> for Key {
225    fn from(v: u32) -> Self {
226        Key::Uint(v as u64)
227    }
228}
229
230impl serde::Serialize for Key {
231    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
232    where
233        S: serde::Serializer,
234    {
235        match self {
236            Key::Int(v) => v.serialize(serializer),
237            Key::Uint(v) => v.serialize(serializer),
238            Key::Bool(v) => v.serialize(serializer),
239            Key::String(v) => v.serialize(serializer),
240        }
241    }
242}
243
244impl Display for Key {
245    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
246        match self {
247            Key::Int(v) => write!(f, "{v}"),
248            Key::Uint(v) => write!(f, "{v}"),
249            Key::Bool(v) => write!(f, "{v}"),
250            Key::String(v) => write!(f, "{v}"),
251        }
252    }
253}
254
255/// Implement conversions from [`Key`] into [`Value`]
256impl TryInto<Key> for Value {
257    type Error = Value;
258
259    #[inline(always)]
260    fn try_into(self) -> Result<Key, Self::Error> {
261        match self {
262            Value::Int(v) => Ok(Key::Int(v)),
263            Value::UInt(v) => Ok(Key::Uint(v)),
264            Value::String(v) => Ok(Key::String(v)),
265            Value::Bool(v) => Ok(Key::Bool(v)),
266            _ => Err(self),
267        }
268    }
269}
270
271/// Implement conversions from [`KeyRef`] into [`Value`]
272impl<'a> TryFrom<&'a Value> for KeyRef<'a> {
273    type Error = Value;
274
275    fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
276        match value {
277            Value::Int(v) => Ok(KeyRef::Int(*v)),
278            Value::UInt(v) => Ok(KeyRef::Uint(*v)),
279            Value::String(v) => Ok(KeyRef::String(v.as_str())),
280            Value::Bool(v) => Ok(KeyRef::Bool(*v)),
281            _ => Err(value.clone()),
282        }
283    }
284}
285
286// Implement conversion from HashMap<K, V> into CelMap
287impl<K: Into<Key>, V: Into<Value>> From<HashMap<K, V>> for Map {
288    fn from(map: HashMap<K, V>) -> Self {
289        let mut new_map = HashMap::with_capacity(map.len());
290        for (k, v) in map {
291            new_map.insert(k.into(), v.into());
292        }
293        Map {
294            map: Arc::new(new_map),
295        }
296    }
297}
298
299/// Equality helper for [`Opaque`] values.
300///
301/// Implementors define how two values of the same runtime type compare for
302/// equality when stored as [`Value::Opaque`].
303///
304/// You normally don't implement this trait manually. It is automatically
305/// provided for any `T: Eq + PartialEq + Any + Opaque` (see the blanket impl
306/// below). The runtime will first ensure the two values have the same
307/// [`Opaque::runtime_type_name`], and only then attempt a downcast and call
308/// `Eq::eq`.
309pub trait OpaqueEq {
310    /// Compare with another [`Opaque`] erased value.
311    ///
312    /// Implementations should return `false` if `other` does not have the same
313    /// runtime type, or if it cannot be downcast to the concrete type of `self`.
314    fn opaque_eq(&self, other: &dyn Opaque) -> bool;
315}
316
317impl<T> OpaqueEq for T
318where
319    T: Eq + PartialEq + Any + Opaque,
320{
321    fn opaque_eq(&self, other: &dyn Opaque) -> bool {
322        if self.runtime_type_name() != other.runtime_type_name() {
323            return false;
324        }
325        if let Some(other) = other.downcast_ref::<T>() {
326            self.eq(other)
327        } else {
328            false
329        }
330    }
331}
332
333/// Helper trait to obtain a `&dyn Debug` view.
334///
335/// This is auto-implemented for any `T: Debug` and is used by the runtime to
336/// format [`Opaque`] values without knowing their concrete type.
337pub trait AsDebug {
338    /// Returns `self` as a `&dyn Debug` trait object.
339    fn as_debug(&self) -> &dyn Debug;
340}
341
342impl<T> AsDebug for T
343where
344    T: Debug,
345{
346    fn as_debug(&self) -> &dyn Debug {
347        self
348    }
349}
350
351/// Trait for user-defined opaque values stored inside [`Value::Opaque`].
352///
353/// Implement this trait for types that should participate in CEL evaluation as
354/// opaque/user-defined values. An opaque value:
355/// - must report a stable runtime type name via [`Opaque::runtime_type_name`];
356/// - participates in equality via the blanket [`OpaqueEq`] implementation;
357/// - can be formatted via [`AsDebug`];
358/// - must be thread-safe (`Send + Sync`).
359///
360/// When the `json` feature is enabled you may optionally provide a JSON
361/// representation for diagnostics, logging or interop. Returning `None` keeps the
362/// value non-serializable for JSON.
363///
364/// Example
365/// ```rust
366/// use std::fmt::{Debug, Formatter, Result as FmtResult};
367/// use std::sync::Arc;
368/// use cel::objects::{Opaque, Value};
369///
370/// #[derive(Eq, PartialEq)]
371/// struct MyId(u64);
372///
373/// impl Debug for MyId {
374///     fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { write!(f, "MyId({})", self.0) }
375/// }
376///
377/// impl Opaque for MyId {
378///     fn runtime_type_name(&self) -> &str { "example.MyId" }
379/// }
380///
381/// // Values of `MyId` can now be wrapped in `Value::Opaque` and compared.
382/// let a = Value::Opaque(Arc::new(MyId(7)));
383/// let b = Value::Opaque(Arc::new(MyId(7)));
384/// assert_eq!(a, b);
385/// ```
386pub trait Opaque: Any + OpaqueEq + AsDebug + Send + Sync {
387    /// Returns a stable, fully-qualified type name for this value's runtime type.
388    ///
389    /// This name is used to check type compatibility before attempting downcasts
390    /// during equality checks and other operations. It should be stable across
391    /// versions and unique within your application or library (e.g., a package
392    /// qualified name like `my.pkg.Type`).
393    fn runtime_type_name(&self) -> &str;
394
395    /// Optional JSON representation (requires the `json` feature).
396    ///
397    /// The default implementation returns `None`, indicating that the value
398    /// cannot be represented as JSON.
399    #[cfg(feature = "json")]
400    fn json(&self) -> Option<serde_json::Value> {
401        None
402    }
403}
404
405impl dyn Opaque {
406    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
407        let any: &dyn Any = self;
408        any.downcast_ref()
409    }
410}
411
412struct OpaqueVal {
413    r#type: Type,
414    val: Arc<dyn Opaque>,
415}
416
417impl Debug for OpaqueVal {
418    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
419        write!(f, "OpaqueVal<{}>", self.val.runtime_type_name())
420    }
421}
422
423impl Val for OpaqueVal {
424    fn get_type(&self) -> &Type {
425        &self.r#type
426    }
427
428    fn equals(&self, other: &dyn Val) -> bool {
429        if other.get_type() != self.get_type() {
430            false
431        } else {
432            match other.downcast_ref::<OpaqueVal>() {
433                None => false,
434                Some(other) => self.val.opaque_eq(other.val.deref()),
435            }
436        }
437    }
438
439    fn clone_as_boxed(&self) -> Box<dyn Val> {
440        Box::new(Self {
441            r#type: Type::new_opaque_type(self.val.runtime_type_name().to_owned()),
442            val: self.val.clone(),
443        })
444    }
445}
446
447impl OpaqueVal {
448    fn new(val: Arc<dyn Opaque>) -> Self {
449        Self {
450            r#type: Type::new_opaque_type(val.runtime_type_name().to_owned()),
451            val,
452        }
453    }
454
455    fn clone_inner(&self) -> Arc<dyn Opaque> {
456        self.val.clone()
457    }
458}
459
460#[derive(Debug, Eq, PartialEq)]
461pub struct OptionalValue {
462    value: Option<Value>,
463}
464
465impl OptionalValue {
466    pub fn of(value: Value) -> Self {
467        OptionalValue { value: Some(value) }
468    }
469    pub fn none() -> Self {
470        OptionalValue { value: None }
471    }
472    pub fn value(&self) -> Option<&Value> {
473        self.value.as_ref()
474    }
475
476    pub(crate) fn inner(&self) -> Option<&Value> {
477        self.value.as_ref()
478    }
479}
480
481impl Opaque for OptionalValue {
482    fn runtime_type_name(&self) -> &str {
483        "optional_type"
484    }
485}
486
487impl From<OptionalValue> for Option<Value> {
488    fn from(value: OptionalValue) -> Self {
489        value.value
490    }
491}
492
493impl<'a> TryFrom<&'a Value> for &'a OptionalValue {
494    type Error = ExecutionError;
495
496    fn try_from(value: &'a Value) -> Result<Self, Self::Error> {
497        match value {
498            Value::Opaque(opaque) if opaque.runtime_type_name() == "optional_type" => opaque
499                .downcast_ref::<OptionalValue>()
500                .ok_or_else(|| ExecutionError::function_error("optional", "failed to downcast")),
501            Value::Opaque(opaque) => Err(ExecutionError::UnexpectedType {
502                got: opaque.runtime_type_name().to_string(),
503                want: "optional_type".to_string(),
504            }),
505            v => Err(ExecutionError::UnexpectedType {
506                got: v.type_of().to_string(),
507                want: "optional_type".to_string(),
508            }),
509        }
510    }
511}
512
513pub trait TryIntoValue {
514    type Error: std::error::Error + 'static + Send + Sync;
515    fn try_into_value(self) -> Result<Value, Self::Error>;
516}
517
518impl<T: serde::Serialize> TryIntoValue for T {
519    type Error = crate::ser::SerializationError;
520    fn try_into_value(self) -> Result<Value, Self::Error> {
521        crate::ser::to_value(self)
522    }
523}
524impl TryIntoValue for Value {
525    type Error = Infallible;
526    fn try_into_value(self) -> Result<Value, Self::Error> {
527        Ok(self)
528    }
529}
530
531#[derive(Clone)]
532pub enum Value {
533    List(Arc<Vec<Value>>),
534    Map(Map),
535
536    Function(Arc<String>, Option<Box<Value>>),
537
538    // Atoms
539    Int(i64),
540    UInt(u64),
541    Float(f64),
542    String(Arc<String>),
543    Bytes(Arc<Vec<u8>>),
544    Bool(bool),
545    #[cfg(feature = "chrono")]
546    Duration(chrono::Duration),
547    #[cfg(feature = "chrono")]
548    Timestamp(chrono::DateTime<chrono::FixedOffset>),
549    Opaque(Arc<dyn Opaque>),
550    #[cfg(feature = "structs")]
551    Struct(Arc<CelStruct>),
552    Null,
553}
554
555impl Debug for Value {
556    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
557        match self {
558            Value::List(l) => write!(f, "List({:?})", l),
559            Value::Map(m) => write!(f, "Map({:?})", m),
560            Value::Function(name, func) => write!(f, "Function({:?}, {:?})", name, func),
561            Value::Int(i) => write!(f, "Int({:?})", i),
562            Value::UInt(u) => write!(f, "UInt({:?})", u),
563            Value::Float(d) => write!(f, "Float({:?})", d),
564            Value::String(s) => write!(f, "String({:?})", s),
565            Value::Bytes(b) => write!(f, "Bytes({:?})", b),
566            Value::Bool(b) => write!(f, "Bool({:?})", b),
567            #[cfg(feature = "chrono")]
568            Value::Duration(d) => write!(f, "Duration({:?})", d),
569            #[cfg(feature = "chrono")]
570            Value::Timestamp(t) => write!(f, "Timestamp({:?})", t),
571            Value::Opaque(o) => write!(f, "Opaque<{}>({:?})", o.runtime_type_name(), o.as_debug()),
572            Value::Null => write!(f, "Null"),
573            #[cfg(feature = "structs")]
574            Value::Struct(s) => write!(f, "{} {{}}", s.name()),
575        }
576    }
577}
578
579#[derive(Clone, Copy, Debug)]
580pub enum ValueType {
581    List,
582    Map,
583    Function,
584    Int,
585    UInt,
586    Float,
587    String,
588    Bytes,
589    Bool,
590    Duration,
591    Timestamp,
592    Opaque,
593    Null,
594    #[cfg(feature = "structs")]
595    Struct,
596}
597
598impl Display for ValueType {
599    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
600        match self {
601            ValueType::List => write!(f, "list"),
602            ValueType::Map => write!(f, "map"),
603            ValueType::Function => write!(f, "function"),
604            ValueType::Int => write!(f, "int"),
605            ValueType::UInt => write!(f, "uint"),
606            ValueType::Float => write!(f, "float"),
607            ValueType::String => write!(f, "string"),
608            ValueType::Bytes => write!(f, "bytes"),
609            ValueType::Bool => write!(f, "bool"),
610            ValueType::Opaque => write!(f, "opaque"),
611            ValueType::Duration => write!(f, "duration"),
612            ValueType::Timestamp => write!(f, "timestamp"),
613            ValueType::Null => write!(f, "null"),
614            #[cfg(feature = "structs")]
615            ValueType::Struct => write!(f, "struct"),
616        }
617    }
618}
619
620impl Value {
621    pub fn type_of(&self) -> ValueType {
622        match self {
623            Value::List(_) => ValueType::List,
624            Value::Map(_) => ValueType::Map,
625            Value::Function(_, _) => ValueType::Function,
626            Value::Int(_) => ValueType::Int,
627            Value::UInt(_) => ValueType::UInt,
628            Value::Float(_) => ValueType::Float,
629            Value::String(_) => ValueType::String,
630            Value::Bytes(_) => ValueType::Bytes,
631            Value::Bool(_) => ValueType::Bool,
632            Value::Opaque(_) => ValueType::Opaque,
633            #[cfg(feature = "chrono")]
634            Value::Duration(_) => ValueType::Duration,
635            #[cfg(feature = "chrono")]
636            Value::Timestamp(_) => ValueType::Timestamp,
637            Value::Null => ValueType::Null,
638            #[cfg(feature = "structs")]
639            Value::Struct(_) => ValueType::Struct,
640        }
641    }
642
643    pub fn is_zero(&self) -> bool {
644        match self {
645            Value::List(v) => v.is_empty(),
646            Value::Map(v) => v.map.is_empty(),
647            Value::Int(0) => true,
648            Value::UInt(0) => true,
649            Value::Float(f) => *f == 0.0,
650            Value::String(v) => v.is_empty(),
651            Value::Bytes(v) => v.is_empty(),
652            Value::Bool(false) => true,
653            #[cfg(feature = "chrono")]
654            Value::Duration(v) => v.is_zero(),
655            Value::Null => true,
656            _ => false,
657        }
658    }
659
660    pub fn error_expected_type(&self, expected: ValueType) -> ExecutionError {
661        ExecutionError::UnexpectedType {
662            got: self.type_of().to_string(),
663            want: expected.to_string(),
664        }
665    }
666}
667
668impl From<&Value> for Value {
669    fn from(value: &Value) -> Self {
670        value.clone()
671    }
672}
673
674impl PartialEq for Value {
675    fn eq(&self, other: &Self) -> bool {
676        match (self, other) {
677            (Value::Map(a), Value::Map(b)) => a == b,
678            (Value::List(a), Value::List(b)) => a == b,
679            (Value::Function(a1, a2), Value::Function(b1, b2)) => a1 == b1 && a2 == b2,
680            (Value::Int(a), Value::Int(b)) => a == b,
681            (Value::UInt(a), Value::UInt(b)) => a == b,
682            (Value::Float(a), Value::Float(b)) => a == b,
683            (Value::String(a), Value::String(b)) => a == b,
684            (Value::Bytes(a), Value::Bytes(b)) => a == b,
685            (Value::Bool(a), Value::Bool(b)) => a == b,
686            (Value::Null, Value::Null) => true,
687            #[cfg(feature = "chrono")]
688            (Value::Duration(a), Value::Duration(b)) => a == b,
689            #[cfg(feature = "chrono")]
690            (Value::Timestamp(a), Value::Timestamp(b)) => a == b,
691            // Allow different numeric types to be compared without explicit casting.
692            (Value::Int(a), Value::UInt(b)) => a
693                .to_owned()
694                .try_into()
695                .map(|a: u64| a == *b)
696                .unwrap_or(false),
697            (Value::Int(a), Value::Float(b)) => (*a as f64) == *b,
698            (Value::UInt(a), Value::Int(b)) => a
699                .to_owned()
700                .try_into()
701                .map(|a: i64| a == *b)
702                .unwrap_or(false),
703            (Value::UInt(a), Value::Float(b)) => (*a as f64) == *b,
704            (Value::Float(a), Value::Int(b)) => *a == (*b as f64),
705            (Value::Float(a), Value::UInt(b)) => *a == (*b as f64),
706            (Value::Opaque(a), Value::Opaque(b)) => a.opaque_eq(b.deref()),
707            (_, _) => false,
708        }
709    }
710}
711
712impl Eq for Value {}
713
714impl PartialOrd for Value {
715    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
716        match (self, other) {
717            (Value::Int(a), Value::Int(b)) => Some(a.cmp(b)),
718            (Value::UInt(a), Value::UInt(b)) => Some(a.cmp(b)),
719            (Value::Float(a), Value::Float(b)) => a.partial_cmp(b),
720            (Value::String(a), Value::String(b)) => Some(a.cmp(b)),
721            (Value::Bool(a), Value::Bool(b)) => Some(a.cmp(b)),
722            (Value::Null, Value::Null) => Some(Ordering::Equal),
723            #[cfg(feature = "chrono")]
724            (Value::Duration(a), Value::Duration(b)) => Some(a.cmp(b)),
725            #[cfg(feature = "chrono")]
726            (Value::Timestamp(a), Value::Timestamp(b)) => Some(a.cmp(b)),
727            // Allow different numeric types to be compared without explicit casting.
728            (Value::Int(a), Value::UInt(b)) => Some(
729                a.to_owned()
730                    .try_into()
731                    .map(|a: u64| a.cmp(b))
732                    // If the i64 doesn't fit into a u64 it must be less than 0.
733                    .unwrap_or(Ordering::Less),
734            ),
735            (Value::Int(a), Value::Float(b)) => (*a as f64).partial_cmp(b),
736            (Value::UInt(a), Value::Int(b)) => Some(
737                a.to_owned()
738                    .try_into()
739                    .map(|a: i64| a.cmp(b))
740                    // If the u64 doesn't fit into a i64 it must be greater than i64::MAX.
741                    .unwrap_or(Ordering::Greater),
742            ),
743            (Value::UInt(a), Value::Float(b)) => (*a as f64).partial_cmp(b),
744            (Value::Float(a), Value::Int(b)) => a.partial_cmp(&(*b as f64)),
745            (Value::Float(a), Value::UInt(b)) => a.partial_cmp(&(*b as f64)),
746            _ => None,
747        }
748    }
749}
750
751impl From<&Key> for Value {
752    fn from(value: &Key) -> Self {
753        match value {
754            Key::Int(v) => Value::Int(*v),
755            Key::Uint(v) => Value::UInt(*v),
756            Key::Bool(v) => Value::Bool(*v),
757            Key::String(v) => Value::String(v.clone()),
758        }
759    }
760}
761
762impl From<Key> for Value {
763    fn from(value: Key) -> Self {
764        match value {
765            Key::Int(v) => Value::Int(v),
766            Key::Uint(v) => Value::UInt(v),
767            Key::Bool(v) => Value::Bool(v),
768            Key::String(v) => Value::String(v),
769        }
770    }
771}
772
773impl From<&Key> for Key {
774    fn from(key: &Key) -> Self {
775        key.clone()
776    }
777}
778
779// Convert Vec<T> to Value
780impl<T: Into<Value>> From<Vec<T>> for Value {
781    fn from(v: Vec<T>) -> Self {
782        Value::List(v.into_iter().map(|v| v.into()).collect::<Vec<_>>().into())
783    }
784}
785
786// Convert Vec<u8> to Value
787impl From<Vec<u8>> for Value {
788    fn from(v: Vec<u8>) -> Self {
789        Value::Bytes(v.into())
790    }
791}
792
793#[cfg(feature = "bytes")]
794// Convert Bytes to Value
795impl From<::bytes::Bytes> for Value {
796    fn from(v: ::bytes::Bytes) -> Self {
797        Value::Bytes(v.to_vec().into())
798    }
799}
800
801#[cfg(feature = "bytes")]
802// Convert &Bytes to Value
803impl From<&::bytes::Bytes> for Value {
804    fn from(v: &::bytes::Bytes) -> Self {
805        Value::Bytes(v.to_vec().into())
806    }
807}
808
809// Convert String to Value
810impl From<String> for Value {
811    fn from(v: String) -> Self {
812        Value::String(v.into())
813    }
814}
815
816impl From<&str> for Value {
817    fn from(v: &str) -> Self {
818        Value::String(v.to_string().into())
819    }
820}
821
822// Convert Option<T> to Value
823impl<T: Into<Value>> From<Option<T>> for Value {
824    fn from(v: Option<T>) -> Self {
825        match v {
826            Some(v) => v.into(),
827            None => Value::Null,
828        }
829    }
830}
831
832// Convert HashMap<K, V> to Value
833impl<K: Into<Key>, V: Into<Value>> From<HashMap<K, V>> for Value {
834    fn from(v: HashMap<K, V>) -> Self {
835        Value::Map(v.into())
836    }
837}
838
839impl From<ExecutionError> for ResolveResult {
840    fn from(value: ExecutionError) -> Self {
841        Err(value)
842    }
843}
844
845pub type ResolveResult = Result<Value, ExecutionError>;
846
847impl From<Value> for ResolveResult {
848    fn from(value: Value) -> Self {
849        Ok(value)
850    }
851}
852
853impl TryFrom<&dyn Val> for Value {
854    type Error = ExecutionError;
855    fn try_from(v: &dyn Val) -> Result<Self, Self::Error> {
856        match v.get_type().kind() {
857            Kind::Boolean => Ok(Value::Bool(*v.downcast_ref::<CelBool>().unwrap().inner())),
858            Kind::Int => Ok(Value::Int(*v.downcast_ref::<CelInt>().unwrap().inner())),
859            Kind::UInt => Ok(Value::UInt(*v.downcast_ref::<CelUInt>().unwrap().inner())),
860            Kind::Double => Ok(Value::Float(
861                *v.downcast_ref::<CelDouble>().unwrap().inner(),
862            )),
863            Kind::String => Ok(Value::String(Arc::new(
864                v.downcast_ref::<CelString>().unwrap().inner().to_string(),
865            ))),
866            Kind::NullType => Ok(Value::Null),
867            Kind::Bytes => Ok(Value::Bytes(Arc::new(
868                v.downcast_ref::<CelBytes>().unwrap().inner().to_vec(),
869            ))),
870            #[cfg(feature = "chrono")]
871            Kind::Duration => Ok(Value::Duration(
872                *v.downcast_ref::<CelDuration>().unwrap().inner(),
873            )),
874            #[cfg(feature = "chrono")]
875            Kind::Timestamp => {
876                let ts = v.downcast_ref::<CelTimestamp>().unwrap().inner();
877                Ok(Value::Timestamp(*ts))
878            }
879            Kind::List => {
880                let list = v.downcast_ref::<CelList>().unwrap().inner();
881                Ok(Value::List(Arc::new(
882                    list.iter()
883                        .map(|i| i.as_ref().try_into().expect("Not a Value list item"))
884                        .collect(),
885                )))
886            }
887            Kind::Map => {
888                let map = v.downcast_ref::<CelMap>().unwrap().inner();
889                Ok(Value::Map(Map {
890                    map: Arc::new(
891                        map.iter()
892                            .map(|(k, v)| {
893                                (
894                                    Key::from(k.clone()),
895                                    Value::try_from(v.as_ref()).expect("Not a Value map value"),
896                                )
897                            })
898                            .collect(),
899                    ),
900                }))
901            }
902            Kind::Opaque => Ok(Value::Opaque(match v.downcast_ref::<CelOptional>() {
903                None => v.downcast_ref::<OpaqueVal>().unwrap().clone_inner(),
904                Some(opt) => {
905                    let opt: Option<Result<Value, _>> = opt.option().map(|v| v.try_into());
906                    match opt {
907                        None => Arc::new(OptionalValue::none()),
908                        Some(t) => match t {
909                            Ok(v) => Arc::new(OptionalValue::of(v)),
910                            Err(_) => Arc::new(OptionalValue::none()),
911                        },
912                    }
913                }
914            })),
915            _ => {
916                #[cfg(feature = "structs")]
917                {
918                    if let Some(v) = v.downcast_ref::<CelStruct>() {
919                        use crate::common::value::Downcast;
920
921                        return match v.clone_as_boxed().downcast::<CelStruct>() {
922                            Ok(v) => Ok(Value::Struct(Arc::new(*v))),
923                            Err(v) => Err(ExecutionError::InternalError(format!(
924                                "Not a Struct: `{v:?}`"
925                            ))),
926                        };
927                    }
928                }
929                if let Some(opaque) = v.downcast_ref::<OpaqueVal>() {
930                    Ok(Value::Opaque(opaque.val.clone()))
931                } else {
932                    Err(ExecutionError::UnexpectedType {
933                        got: v.get_type().name().to_string(),
934                        want:
935                            "(BOOL|INT|UINT|DOUBLE|STRING|NULL|BYTES|TIMESTAMP|DURATION|LIST|MAP)"
936                                .to_string(),
937                    })
938                }
939            }
940        }
941    }
942}
943
944impl TryFrom<Value> for Box<dyn Val> {
945    type Error = ExecutionError;
946    fn try_from(value: Value) -> Result<Self, Self::Error> {
947        match value {
948            Value::Bool(b) => Ok(Box::new(CelBool::from(b))),
949            Value::Int(i) => Ok(Box::new(CelInt::from(i))),
950            Value::UInt(u) => Ok(Box::new(CelUInt::from(u))),
951            Value::Float(f) => Ok(Box::new(CelDouble::from(f))),
952            Value::String(s) => Ok(Box::new(CelString::from(s.as_str()))),
953            Value::Null => Ok(Box::new(CelNull)),
954            Value::Bytes(b) => Ok(Box::new(CelBytes::from(b.as_slice().to_vec()))),
955            #[cfg(feature = "chrono")]
956            Value::Duration(d) => Ok(Box::new(CelDuration::from(d))),
957            #[cfg(feature = "chrono")]
958            Value::Timestamp(ts) => Ok(Box::new(CelTimestamp::from(ts))),
959            Value::List(l) => {
960                let result: Result<Vec<Box<dyn Val>>, ExecutionError> =
961                    (*l).clone().into_iter().map(|i| i.try_into()).collect();
962                Ok(Box::new(CelList::from(result?)))
963            }
964            Value::Map(map) => {
965                let result: Result<HashMap<CelMapKey, Box<dyn Val>>, ExecutionError> = (*map.map)
966                    .clone()
967                    .into_iter()
968                    .map(|(k, v)| v.clone().try_into().map(|v| (k.clone().into(), v)))
969                    .collect();
970                Ok(Box::new(CelMap::from(result?)))
971            }
972            Value::Opaque(o) => {
973                let v: Box<dyn Val> = if let Some(value) = o.downcast_ref::<OptionalValue>() {
974                    match value.inner() {
975                        None => Box::new(CelOptional::none()),
976                        Some(v) => Box::new(CelOptional::of(v.clone().try_into()?)),
977                    }
978                } else {
979                    Box::new(OpaqueVal::new(o))
980                };
981                Ok(v)
982            }
983            #[cfg(feature = "structs")]
984            Value::Struct(s) => Ok(Arc::try_unwrap(s)
985                .map(|s| Box::new(s) as Box<dyn Val>)
986                .unwrap_or_else(|arc| arc.clone_as_boxed())),
987            _ => Err(ExecutionError::UnsupportedTargetType { target: value }),
988        }
989    }
990}
991
992impl Value {
993    pub fn resolve_all(expr: &[Expression], ctx: &Context) -> ResolveResult {
994        let mut res = Vec::with_capacity(expr.len());
995        for expr in expr {
996            res.push(Value::resolve(expr, ctx)?);
997        }
998        Ok(Value::List(res.into()))
999    }
1000
1001    pub fn resolve(expr: &Expression, ctx: &Context) -> ResolveResult {
1002        Self::resolve_val(expr, ctx)?.as_ref().try_into()
1003    }
1004
1005    #[inline(always)]
1006    pub fn resolve_val<'a>(
1007        expr: &'a Expression,
1008        ctx: &'a Context<'a>,
1009    ) -> Result<Cow<'a, dyn Val>, ExecutionError> {
1010        match &expr.expr {
1011            Expr::Literal(literal) => Ok(literal.to_val()),
1012            Expr::Call(call) => {
1013                // START OF SPECIAL CASES FOR operators::...
1014                if call.args.len() == 3 && call.func_name == operators::CONDITIONAL {
1015                    let cond = Value::resolve_val(&call.args[0], ctx);
1016                    return if try_bool(cond)? {
1017                        Value::resolve_val(&call.args[1], ctx)
1018                    } else {
1019                        Value::resolve_val(&call.args[2], ctx)
1020                    };
1021                }
1022                if call.args.len() == 2 {
1023                    match call.func_name.as_str() {
1024                        operators::LOGICAL_OR => {
1025                            let left = try_bool(Value::resolve_val(&call.args[0], ctx));
1026                            return if Ok(true) == left {
1027                                Ok(Cow::<dyn Val>::Owned(Box::new(CelBool::from(true))))
1028                            } else {
1029                                let right = Value::resolve_val(&call.args[1], ctx)?
1030                                    .downcast_ref::<CelBool>()
1031                                    .map(|b| *b.inner());
1032                                match (left, right) {
1033                                    (Ok(false), Some(right)) => {
1034                                        Ok(Cow::<dyn Val>::Owned(Box::new(CelBool::from(right))))
1035                                    }
1036                                    (Err(_), Some(true)) => {
1037                                        Ok(Cow::<dyn Val>::Owned(Box::new(CelBool::from(true))))
1038                                    }
1039                                    (left, _) => Err(left.err().unwrap_or(NoSuchOverload)),
1040                                }
1041                            };
1042                        }
1043                        operators::LOGICAL_AND => {
1044                            let left = try_bool(Value::resolve_val(&call.args[0], ctx));
1045                            return if Ok(false) == left {
1046                                Ok(Cow::<dyn Val>::Owned(Box::new(CelBool::from(false))))
1047                            } else {
1048                                let right = Value::resolve_val(&call.args[1], ctx)?
1049                                    .downcast_ref::<CelBool>()
1050                                    .map(|b| *b.inner());
1051                                match (left, right) {
1052                                    (Ok(true), Some(right)) => {
1053                                        Ok(Cow::<dyn Val>::Owned(Box::new(CelBool::from(right))))
1054                                    }
1055                                    (Err(_), Some(false)) => {
1056                                        Ok(Cow::<dyn Val>::Owned(Box::new(CelBool::from(false))))
1057                                    }
1058                                    (left, _) => Err(left.err().unwrap_or(NoSuchOverload)),
1059                                }
1060                            };
1061                        }
1062                        operators::EQUALS => {
1063                            return Ok(bool(
1064                                Value::resolve_val(&call.args[0], ctx)?
1065                                    .eq(&Value::resolve_val(&call.args[1], ctx)?),
1066                            ))
1067                        }
1068                        operators::NOT_EQUALS => {
1069                            return Ok(bool(
1070                                Value::resolve_val(&call.args[0], ctx)?
1071                                    .ne(&Value::resolve_val(&call.args[1], ctx)?),
1072                            ))
1073                        }
1074                        operators::INDEX | operators::OPT_INDEX => {
1075                            let mut is_optional = call.func_name == operators::OPT_INDEX;
1076                            let value = Value::resolve_val(&call.args[0], ctx)?;
1077
1078                            let value = if let Some(opt) = value.downcast_ref::<CelOptional>() {
1079                                is_optional = true;
1080                                match opt.inner() {
1081                                    // todo try to keep this borrowed
1082                                    Some(v) => Cow::Owned(v.clone_as_boxed()),
1083                                    None => {
1084                                        return Ok(Cow::<dyn Val>::Owned(Box::new(
1085                                            CelOptional::none(),
1086                                        )))
1087                                    }
1088                                }
1089                            } else {
1090                                value
1091                            };
1092
1093                            let result = match value {
1094                                Cow::Borrowed(val) => val
1095                                    .as_indexer()
1096                                    .ok_or(ExecutionError::NoSuchOverload)?
1097                                    .get(Self::resolve_val(&call.args[1], ctx)?.as_ref()),
1098                                Cow::Owned(val) => val
1099                                    .into_indexer()
1100                                    .ok_or(ExecutionError::NoSuchOverload)?
1101                                    .steal(Self::resolve_val(&call.args[1], ctx)?.as_ref())
1102                                    .map(Cow::Owned),
1103                            };
1104                            return if is_optional {
1105                                Ok(match result {
1106                                    Ok(val) => Cow::<dyn Val>::Owned(Box::new(CelOptional::from(
1107                                        val.clone_as_boxed(),
1108                                    ))),
1109                                    Err(_) => Cow::<dyn Val>::Owned(Box::new(CelOptional::none())),
1110                                })
1111                            } else {
1112                                result
1113                            };
1114                        }
1115                        operators::OPT_SELECT => {
1116                            let operand = Value::resolve_val(&call.args[0], ctx)?;
1117                            let field_literal = Value::resolve_val(&call.args[1], ctx)?;
1118                            let field = match field_literal.get_type().kind() {
1119                                Kind::String => field_literal
1120                                    .downcast_ref::<CelString>()
1121                                    .expect("field must be string"),
1122                                _ => {
1123                                    return Err(ExecutionError::function_error(
1124                                        "_?._",
1125                                        "field must be string",
1126                                    ))
1127                                }
1128                            };
1129                            return Ok(Cow::<dyn Val>::Owned(Box::new(
1130                                if let Some(opt) = operand.as_ref().downcast_ref::<CelOptional>() {
1131                                    opt.map(|operand| {
1132                                        operand
1133                                            .as_indexer()
1134                                            .map(|i| {
1135                                                i.get(field)
1136                                                    .map(|v| v.clone_as_boxed())
1137                                                    .unwrap_or(CelOptional::none().clone_as_boxed())
1138                                            })
1139                                            .unwrap_or(CelOptional::none().clone_as_boxed())
1140                                    })
1141                                } else {
1142                                    CelOptional::of(
1143                                        operand
1144                                            .as_indexer()
1145                                            .ok_or(NoSuchOverload)?
1146                                            .get(field)?
1147                                            .clone_as_boxed(),
1148                                    )
1149                                },
1150                            )));
1151                        }
1152                        // END OF SPECIAL CASES
1153
1154                        // all below is NOT special in the interpreter
1155                        operators::ADD => {
1156                            let lhs = Value::resolve_val(&call.args[0], ctx)?;
1157                            let rhs = Value::resolve_val(&call.args[1], ctx)?;
1158                            return Ok(Cow::Owned(
1159                                lhs.as_ref()
1160                                    .as_adder()
1161                                    .ok_or_else(|| {
1162                                        ExecutionError::UnsupportedBinaryOperator(
1163                                            "add",
1164                                            lhs.as_ref().try_into().unwrap_or(Value::Null),
1165                                            rhs.as_ref().try_into().unwrap_or(Value::Null),
1166                                        )
1167                                    })?
1168                                    .add(rhs.as_ref())?
1169                                    .into_owned(),
1170                            ));
1171                        }
1172                        operators::SUBSTRACT => {
1173                            let lhs = Value::resolve_val(&call.args[0], ctx)?;
1174                            let rhs = Value::resolve_val(&call.args[1], ctx)?;
1175                            return Ok(Cow::Owned(
1176                                lhs.as_subtractor()
1177                                    .ok_or_else(|| {
1178                                        ExecutionError::UnsupportedBinaryOperator(
1179                                            "sub",
1180                                            lhs.as_ref().try_into().unwrap_or(Value::Null),
1181                                            rhs.as_ref().try_into().unwrap_or(Value::Null),
1182                                        )
1183                                    })?
1184                                    .sub(rhs.as_ref())?
1185                                    .into_owned(),
1186                            ));
1187                        }
1188                        operators::DIVIDE => {
1189                            let lhs = Value::resolve_val(&call.args[0], ctx)?;
1190                            let rhs = Value::resolve_val(&call.args[1], ctx)?;
1191                            return Ok(Cow::Owned(
1192                                lhs.as_divider()
1193                                    .ok_or_else(|| {
1194                                        ExecutionError::UnsupportedBinaryOperator(
1195                                            "div",
1196                                            lhs.as_ref().try_into().unwrap_or(Value::Null),
1197                                            rhs.as_ref().try_into().unwrap_or(Value::Null),
1198                                        )
1199                                    })?
1200                                    .div(rhs.as_ref())?
1201                                    .into_owned(),
1202                            ));
1203                        }
1204                        operators::MULTIPLY => {
1205                            let lhs = Value::resolve_val(&call.args[0], ctx)?;
1206                            let rhs = Value::resolve_val(&call.args[1], ctx)?;
1207                            return Ok(Cow::Owned(
1208                                lhs.as_multiplier()
1209                                    .ok_or_else(|| {
1210                                        ExecutionError::UnsupportedBinaryOperator(
1211                                            "mul",
1212                                            lhs.as_ref().try_into().unwrap_or(Value::Null),
1213                                            rhs.as_ref().try_into().unwrap_or(Value::Null),
1214                                        )
1215                                    })?
1216                                    .mul(rhs.as_ref())?
1217                                    .into_owned(),
1218                            ));
1219                        }
1220                        operators::MODULO => {
1221                            let lhs = Value::resolve_val(&call.args[0], ctx)?;
1222                            let rhs = Value::resolve_val(&call.args[1], ctx)?;
1223                            return Ok(Cow::Owned(
1224                                lhs.as_modder()
1225                                    .ok_or_else(|| {
1226                                        ExecutionError::UnsupportedBinaryOperator(
1227                                            "rem",
1228                                            lhs.as_ref().try_into().unwrap_or(Value::Null),
1229                                            rhs.as_ref().try_into().unwrap_or(Value::Null),
1230                                        )
1231                                    })?
1232                                    .modulo(rhs.as_ref())?
1233                                    .into_owned(),
1234                            ));
1235                        }
1236                        operators::LESS => {
1237                            let lhs = Value::resolve_val(&call.args[0], ctx)?;
1238                            let rhs = Value::resolve_val(&call.args[1], ctx)?;
1239                            return Ok(bool(
1240                                lhs.as_comparer()
1241                                    .ok_or(ExecutionError::NoSuchOverload)?
1242                                    .compare(rhs.as_ref())?
1243                                    == Ordering::Less,
1244                            ));
1245                        }
1246                        operators::LESS_EQUALS => {
1247                            let lhs = Value::resolve_val(&call.args[0], ctx)?;
1248                            let rhs = Value::resolve_val(&call.args[1], ctx)?;
1249                            return if lhs
1250                                .as_comparer()
1251                                .ok_or(ExecutionError::NoSuchOverload)?
1252                                .compare(rhs.as_ref())?
1253                                == Ordering::Greater
1254                            {
1255                                Ok(bool(false))
1256                            } else {
1257                                Ok(bool(true))
1258                            };
1259                        }
1260                        operators::GREATER => {
1261                            let lhs = Value::resolve_val(&call.args[0], ctx)?;
1262                            let rhs = Value::resolve_val(&call.args[1], ctx)?;
1263                            return Ok(bool(
1264                                lhs.as_comparer()
1265                                    .ok_or(ExecutionError::NoSuchOverload)?
1266                                    .compare(rhs.as_ref())?
1267                                    == Ordering::Greater,
1268                            ));
1269                        }
1270                        operators::GREATER_EQUALS => {
1271                            let lhs = Value::resolve_val(&call.args[0], ctx)?;
1272                            let rhs = Value::resolve_val(&call.args[1], ctx)?;
1273                            return if lhs
1274                                .as_comparer()
1275                                .ok_or(ExecutionError::NoSuchOverload)?
1276                                .compare(rhs.as_ref())?
1277                                == Ordering::Less
1278                            {
1279                                Ok(bool(false))
1280                            } else {
1281                                Ok(bool(true))
1282                            };
1283                        }
1284                        operators::IN => {
1285                            let lhs = Value::resolve_val(&call.args[0], ctx)?;
1286                            let rhs = Value::resolve_val(&call.args[1], ctx)?;
1287                            return if let Some(container) = rhs.as_container() {
1288                                Ok(bool(container.contains(lhs.as_ref())?))
1289                            } else {
1290                                Err(ExecutionError::NoSuchOverload)
1291                            };
1292                        }
1293                        _ => (),
1294                    }
1295                }
1296                if call.args.len() == 1 {
1297                    match call.func_name.as_str() {
1298                        operators::LOGICAL_NOT => {
1299                            let expr = Value::resolve_val(&call.args[0], ctx)?;
1300                            return expr
1301                                .downcast_ref::<CelBool>()
1302                                .map(Bool::negate)
1303                                .ok_or(ExecutionError::NoSuchOverload)
1304                                .map(|b| bool(b.into_inner()));
1305                        }
1306                        operators::NEGATE => {
1307                            let val = Value::resolve_val(&call.args[0], ctx)?;
1308                            return Ok(Cow::<dyn Val>::Owned(
1309                                val.as_negator()
1310                                    .ok_or(ExecutionError::NoSuchOverload)?
1311                                    .negate()?,
1312                            ));
1313                        }
1314                        operators::NOT_STRICTLY_FALSE => {
1315                            return Ok(bool(
1316                                try_bool(Value::resolve_val(&call.args[0], ctx)).unwrap_or(true),
1317                            ));
1318                        }
1319                        _ => (),
1320                    }
1321                }
1322                match &call.target {
1323                    None => {
1324                        // TODO: Optimize for the 1 and 2 arg cases and avoid the Vec altogether
1325                        let args: Result<Vec<Cow<dyn Val>>, ExecutionError> = call
1326                            .args
1327                            .iter()
1328                            .map(|a| Value::resolve_val(a, ctx))
1329                            .collect();
1330                        let args = args?;
1331                        if let Some(op) = ctx.env().find_overload(&call.func_name, &args) {
1332                            return op(args);
1333                        }
1334                        let func = ctx.get_function(call.func_name.as_str()).ok_or_else(|| {
1335                            ExecutionError::UndeclaredReference(call.func_name.clone().into())
1336                        })?;
1337                        let mut ctx = FunctionContext::new(&call.func_name, None, ctx, args);
1338                        let v = (func)(&mut ctx)?;
1339                        Ok(Cow::<dyn Val>::Owned(TryInto::<Box<dyn Val>>::try_into(v)?))
1340                    }
1341                    Some(target) => {
1342                        let args: Result<Vec<Cow<dyn Val>>, ExecutionError> = call
1343                            .args
1344                            .iter()
1345                            .map(|a| Value::resolve_val(a, ctx))
1346                            .collect();
1347                        let args = args?;
1348                        let qualified_func = match &target.expr {
1349                            Expr::Ident(prefix) => {
1350                                let qualified_name = format!("{prefix}.{}", &call.func_name);
1351                                if let Some(op) = ctx.env().find_overload(&qualified_name, &args) {
1352                                    return op(args);
1353                                }
1354                                ctx.get_function(&qualified_name)
1355                            }
1356                            _ => None,
1357                        };
1358                        let (target, func, args) = match qualified_func {
1359                            None => {
1360                                let target = Value::resolve_val(target, ctx)?;
1361                                let mut args = args;
1362                                args.insert(0, target);
1363                                if let Some(op) =
1364                                    ctx.env().find_member_overload(&call.func_name, &args)
1365                                {
1366                                    return op(args);
1367                                }
1368                                let target = args.remove(0);
1369                                let func =
1370                                    ctx.get_function(call.func_name.as_str()).ok_or_else(|| {
1371                                        ExecutionError::UndeclaredReference(
1372                                            call.func_name.clone().into(),
1373                                        )
1374                                    })?;
1375                                (Some(target), func, args)
1376                            }
1377                            Some(func) => (None, func, args),
1378                        };
1379                        let mut ctx = FunctionContext::new(&call.func_name, target, ctx, args);
1380                        // todo fix this to _not_ use `Value`
1381                        let v = (func)(&mut ctx)?;
1382                        Ok(Cow::<dyn Val>::Owned(TryInto::<Box<dyn Val>>::try_into(v)?))
1383                    }
1384                }
1385            }
1386            Expr::Ident(name) => Ok(ctx
1387                .get_variable(name)
1388                .ok_or_else(|| ExecutionError::UndeclaredReference(Arc::new(name.to_string())))?),
1389            Expr::Select(select) => {
1390                let left = Value::resolve_val(select.operand.deref(), ctx)?;
1391                let key: CelString = select.field.as_str().into();
1392
1393                if select.test {
1394                    match left.get_type().kind() {
1395                        Kind::Map => Ok(bool(
1396                            left.as_container()
1397                                .ok_or_else(|| {
1398                                    ExecutionError::NoSuchKey(Arc::new(key.inner().to_string()))
1399                                })?
1400                                .contains(&key)?,
1401                        )),
1402                        #[cfg(feature = "structs")]
1403                        Kind::Struct => {
1404                            if let Some(indexer) = left.as_indexer() {
1405                                Ok(bool(indexer.get(&key).is_ok()))
1406                            } else {
1407                                Ok(bool(false))
1408                            }
1409                        }
1410                        _ => Ok(Cow::<dyn Val>::Owned(
1411                            left.as_indexer()
1412                                .ok_or_else(|| ExecutionError::NoSuchOverload)?
1413                                .get(&key)?
1414                                .into_owned(),
1415                        )),
1416                    }
1417                } else {
1418                    match left.get_type().kind() {
1419                        Kind::Map => {
1420                            // todo avoid cloning when not needed
1421                            Ok(Cow::<dyn Val>::Owned(
1422                                left.as_indexer()
1423                                    .ok_or_else(|| {
1424                                        ExecutionError::NoSuchKey(Arc::new(key.inner().to_string()))
1425                                    })?
1426                                    .get(&key)?
1427                                    .into_owned(),
1428                            ))
1429                        }
1430                        _ => Ok(Cow::<dyn Val>::Owned(
1431                            left.as_indexer()
1432                                .ok_or_else(|| ExecutionError::NoSuchOverload)?
1433                                .get(&key)?
1434                                .into_owned(),
1435                        )),
1436                    }
1437                }
1438            }
1439            Expr::List(list_expr) => {
1440                let list = list_expr
1441                    .elements
1442                    .iter()
1443                    .enumerate()
1444                    .map(|(idx, element)| {
1445                        Value::resolve_val(element, ctx).map(|value| {
1446                            if list_expr.optional_indices.contains(&idx) {
1447                                if let Some(opt_val) = value.downcast_ref::<CelOptional>() {
1448                                    opt_val.inner().map(|v| v.clone_as_boxed())
1449                                } else {
1450                                    Some(value.into_owned())
1451                                }
1452                            } else {
1453                                Some(value.into_owned())
1454                            }
1455                        })
1456                    })
1457                    .collect::<Result<Vec<_>, _>>()?
1458                    .into_iter()
1459                    .flatten()
1460                    .collect::<Vec<_>>();
1461                Ok(Cow::<dyn Val>::Owned(Box::new(CelList::from(list))))
1462            }
1463            Expr::Map(map_expr) => {
1464                let mut map = HashMap::with_capacity(map_expr.entries.len());
1465                for entry in map_expr.entries.iter() {
1466                    let (k, v, is_optional) = match &entry.expr {
1467                        EntryExpr::StructField(_) => panic!("WAT?"),
1468                        EntryExpr::MapEntry(e) => (&e.key, &e.value, e.optional),
1469                    };
1470                    let key: CelMapKey = Value::resolve_val(k, ctx)?.into_owned().try_into()?;
1471                    // todo do not clone if not needed!
1472                    let value = Value::resolve_val(v, ctx)?.into_owned();
1473
1474                    if is_optional {
1475                        if let Some(opt_val) = value.downcast_ref::<CelOptional>() {
1476                            if let Some(inner) = opt_val.inner() {
1477                                map.insert(key, inner.clone_as_boxed());
1478                            }
1479                        } else {
1480                            map.insert(key, value);
1481                        }
1482                    } else {
1483                        map.insert(key, value);
1484                    }
1485                }
1486                let map: Box<CelMap> = CelMap::from(map).into();
1487                Ok(Cow::<dyn Val>::Owned(map))
1488            }
1489            Expr::Comprehension(comprehension) => {
1490                let accu_init = Value::resolve_val(&comprehension.accu_init, ctx)?;
1491                let iter = Value::resolve_val(&comprehension.iter_range, ctx)?;
1492                let mut ctx = ctx.new_inner_scope();
1493                ctx.add_variable_as_val(&comprehension.accu_var, accu_init.clone_as_boxed());
1494
1495                let mut items = iter
1496                    .as_iterable()
1497                    .ok_or(ExecutionError::NoSuchOverload)?
1498                    .iter();
1499                while let Some(item) = items.next() {
1500                    if !try_bool(Value::resolve_val(&comprehension.loop_cond, &ctx))? {
1501                        break;
1502                    }
1503                    ctx.add_variable_as_val(&comprehension.iter_var, item.clone_as_boxed());
1504                    let accu = Value::resolve_val(&comprehension.loop_step, &ctx)?;
1505                    ctx.add_variable_as_val(&comprehension.accu_var, accu.clone_as_boxed());
1506                }
1507                Ok(Cow::<dyn Val>::Owned(
1508                    Value::resolve_val(&comprehension.result, &ctx)?.into_owned(),
1509                ))
1510            }
1511            Expr::Struct(strct) => {
1512                let name = strct.type_name.clone();
1513                #[cfg(not(feature = "structs"))]
1514                {
1515                    Err(ExecutionError::InternalError(format!(
1516                        "Found struct {name}, feature not enabled!"
1517                    )))
1518                }
1519                #[cfg(feature = "structs")]
1520                {
1521                    let struct_def =
1522                        ctx.env()
1523                            .find_struct(&name)
1524                            .ok_or(ExecutionError::UnexpectedType {
1525                                got: name.to_owned(),
1526                                want: "known struct".to_owned(),
1527                            })?;
1528                    let mut fields = std::collections::BTreeMap::new();
1529                    for entry in &strct.entries {
1530                        match &entry.expr {
1531                            EntryExpr::StructField(expr) => {
1532                                let f = expr.field.clone();
1533                                fields.insert(f, Value::resolve_val(&expr.value, ctx)?);
1534                            }
1535                            EntryExpr::MapEntry(entry) => {
1536                                return Err(ExecutionError::InternalError(format!(
1537                                    "Expected struct_field_expr, got {entry:?}"
1538                                )))
1539                            }
1540                        }
1541                    }
1542                    let s = struct_def.new_struct(fields)?;
1543                    Ok(Cow::<dyn Val>::Owned(Box::new(s)))
1544                }
1545            }
1546            Expr::Unspecified => panic!("Can't evaluate Unspecified Expr"),
1547        }
1548    }
1549}
1550
1551fn bool<'a>(boolean: bool) -> Cow<'a, dyn Val> {
1552    Cow::<dyn Val>::Owned(Box::new(CelBool::from(boolean)))
1553}
1554
1555fn try_bool(val: Result<Cow<dyn Val>, ExecutionError>) -> Result<bool, ExecutionError> {
1556    match val {
1557        Ok(val) => val
1558            .downcast_ref::<CelBool>()
1559            .map(|b| *b.inner())
1560            .ok_or(ExecutionError::NoSuchOverload),
1561        Err(err) => Result::Err(err),
1562    }
1563}
1564
1565impl ops::Add<Value> for Value {
1566    type Output = ResolveResult;
1567
1568    #[inline(always)]
1569    fn add(self, rhs: Value) -> Self::Output {
1570        match (self, rhs) {
1571            (Value::Int(l), Value::Int(r)) => l
1572                .checked_add(r)
1573                .ok_or_else(|| ExecutionError::Overflow("add", l.into(), r.into()))
1574                .map(Value::Int),
1575
1576            (Value::UInt(l), Value::UInt(r)) => l
1577                .checked_add(r)
1578                .ok_or_else(|| ExecutionError::Overflow("add", l.into(), r.into()))
1579                .map(Value::UInt),
1580
1581            (Value::Float(l), Value::Float(r)) => Value::Float(l + r).into(),
1582
1583            (Value::List(mut l), Value::List(mut r)) => {
1584                {
1585                    // If this is the only reference to `l`, we can append to it in place.
1586                    // `l` is replaced with a clone otherwise.
1587                    let l = Arc::make_mut(&mut l);
1588
1589                    // Likewise, if this is the only reference to `r`, we can move its values
1590                    // instead of cloning them.
1591                    match Arc::get_mut(&mut r) {
1592                        Some(r) => l.append(r),
1593                        None => l.extend(r.iter().cloned()),
1594                    }
1595                }
1596
1597                Ok(Value::List(l))
1598            }
1599            (Value::String(mut l), Value::String(r)) => {
1600                // If this is the only reference to `l`, we can append to it in place.
1601                // `l` is replaced with a clone otherwise.
1602                Arc::make_mut(&mut l).push_str(&r);
1603                Ok(Value::String(l))
1604            }
1605            #[cfg(feature = "chrono")]
1606            (Value::Duration(l), Value::Duration(r)) => l
1607                .checked_add(&r)
1608                .ok_or_else(|| ExecutionError::Overflow("add", l.into(), r.into()))
1609                .map(Value::Duration),
1610            #[cfg(feature = "chrono")]
1611            (Value::Timestamp(l), Value::Duration(r)) => checked_op(TsOp::Add, &l, &r),
1612            #[cfg(feature = "chrono")]
1613            (Value::Duration(l), Value::Timestamp(r)) => r
1614                .checked_add_signed(l)
1615                .ok_or_else(|| ExecutionError::Overflow("add", l.into(), r.into()))
1616                .map(Value::Timestamp),
1617            (left, right) => Err(ExecutionError::UnsupportedBinaryOperator(
1618                "add", left, right,
1619            )),
1620        }
1621    }
1622}
1623
1624impl ops::Sub<Value> for Value {
1625    type Output = ResolveResult;
1626
1627    #[inline(always)]
1628    fn sub(self, rhs: Value) -> Self::Output {
1629        match (self, rhs) {
1630            (Value::Int(l), Value::Int(r)) => l
1631                .checked_sub(r)
1632                .ok_or_else(|| ExecutionError::Overflow("sub", l.into(), r.into()))
1633                .map(Value::Int),
1634
1635            (Value::UInt(l), Value::UInt(r)) => l
1636                .checked_sub(r)
1637                .ok_or_else(|| ExecutionError::Overflow("sub", l.into(), r.into()))
1638                .map(Value::UInt),
1639
1640            (Value::Float(l), Value::Float(r)) => Value::Float(l - r).into(),
1641
1642            #[cfg(feature = "chrono")]
1643            (Value::Duration(l), Value::Duration(r)) => l
1644                .checked_sub(&r)
1645                .ok_or_else(|| ExecutionError::Overflow("sub", l.into(), r.into()))
1646                .map(Value::Duration),
1647            #[cfg(feature = "chrono")]
1648            (Value::Timestamp(l), Value::Duration(r)) => checked_op(TsOp::Sub, &l, &r),
1649            #[cfg(feature = "chrono")]
1650            (Value::Timestamp(l), Value::Timestamp(r)) => {
1651                Value::Duration(l.signed_duration_since(r)).into()
1652            }
1653            (left, right) => Err(ExecutionError::UnsupportedBinaryOperator(
1654                "sub", left, right,
1655            )),
1656        }
1657    }
1658}
1659
1660impl ops::Div<Value> for Value {
1661    type Output = ResolveResult;
1662
1663    #[inline(always)]
1664    fn div(self, rhs: Value) -> Self::Output {
1665        match (self, rhs) {
1666            (Value::Int(l), Value::Int(r)) => {
1667                if r == 0 {
1668                    Err(ExecutionError::DivisionByZero(l.into()))
1669                } else {
1670                    l.checked_div(r)
1671                        .ok_or_else(|| ExecutionError::Overflow("div", l.into(), r.into()))
1672                        .map(Value::Int)
1673                }
1674            }
1675
1676            (Value::UInt(l), Value::UInt(r)) => l
1677                .checked_div(r)
1678                .ok_or_else(|| ExecutionError::DivisionByZero(l.into()))
1679                .map(Value::UInt),
1680
1681            (Value::Float(l), Value::Float(r)) => Value::Float(l / r).into(),
1682
1683            (left, right) => Err(ExecutionError::UnsupportedBinaryOperator(
1684                "div", left, right,
1685            )),
1686        }
1687    }
1688}
1689
1690impl ops::Mul<Value> for Value {
1691    type Output = ResolveResult;
1692
1693    #[inline(always)]
1694    fn mul(self, rhs: Value) -> Self::Output {
1695        match (self, rhs) {
1696            (Value::Int(l), Value::Int(r)) => l
1697                .checked_mul(r)
1698                .ok_or_else(|| ExecutionError::Overflow("mul", l.into(), r.into()))
1699                .map(Value::Int),
1700
1701            (Value::UInt(l), Value::UInt(r)) => l
1702                .checked_mul(r)
1703                .ok_or_else(|| ExecutionError::Overflow("mul", l.into(), r.into()))
1704                .map(Value::UInt),
1705
1706            (Value::Float(l), Value::Float(r)) => Value::Float(l * r).into(),
1707
1708            (left, right) => Err(ExecutionError::UnsupportedBinaryOperator(
1709                "mul", left, right,
1710            )),
1711        }
1712    }
1713}
1714
1715impl ops::Rem<Value> for Value {
1716    type Output = ResolveResult;
1717
1718    #[inline(always)]
1719    fn rem(self, rhs: Value) -> Self::Output {
1720        match (self, rhs) {
1721            (Value::Int(l), Value::Int(r)) => {
1722                if r == 0 {
1723                    Err(ExecutionError::RemainderByZero(l.into()))
1724                } else {
1725                    l.checked_rem(r)
1726                        .ok_or_else(|| ExecutionError::Overflow("rem", l.into(), r.into()))
1727                        .map(Value::Int)
1728                }
1729            }
1730
1731            (Value::UInt(l), Value::UInt(r)) => l
1732                .checked_rem(r)
1733                .ok_or_else(|| ExecutionError::RemainderByZero(l.into()))
1734                .map(Value::UInt),
1735
1736            (left, right) => Err(ExecutionError::UnsupportedBinaryOperator(
1737                "rem", left, right,
1738            )),
1739        }
1740    }
1741}
1742
1743/// Op represents a binary arithmetic operation supported on a timestamp
1744///
1745#[cfg(feature = "chrono")]
1746enum TsOp {
1747    Add,
1748    Sub,
1749}
1750
1751#[cfg(feature = "chrono")]
1752impl TsOp {
1753    fn str(&self) -> &'static str {
1754        match self {
1755            TsOp::Add => "add",
1756            TsOp::Sub => "sub",
1757        }
1758    }
1759}
1760
1761/// Performs a checked arithmetic operation [`TsOp`] on a timestamp and a duration and ensures that
1762/// the resulting timestamp does not overflow the data type internal limits, as well as the timestamp
1763/// limits defined in the cel-spec. See [`MAX_TIMESTAMP`] and [`MIN_TIMESTAMP`] for more details.
1764#[cfg(feature = "chrono")]
1765fn checked_op(
1766    op: TsOp,
1767    lhs: &chrono::DateTime<chrono::FixedOffset>,
1768    rhs: &chrono::Duration,
1769) -> ResolveResult {
1770    // Add lhs and rhs together, checking for data type overflow
1771    let result = match op {
1772        TsOp::Add => lhs.checked_add_signed(*rhs),
1773        TsOp::Sub => lhs.checked_sub_signed(*rhs),
1774    }
1775    .ok_or_else(|| ExecutionError::Overflow(op.str(), (*lhs).into(), (*rhs).into()))?;
1776
1777    // Check for cel-spec limits
1778    if result > *MAX_TIMESTAMP || result < *MIN_TIMESTAMP {
1779        Err(ExecutionError::Overflow(
1780            op.str(),
1781            (*lhs).into(),
1782            (*rhs).into(),
1783        ))
1784    } else {
1785        Value::Timestamp(result).into()
1786    }
1787}
1788
1789#[cfg(test)]
1790mod tests {
1791    use crate::{objects::Key, Context, ExecutionError, Program, Value};
1792    use std::collections::HashMap;
1793    use std::sync::Arc;
1794
1795    #[test]
1796    fn test_indexed_map_access() {
1797        let mut context = Context::default();
1798        let mut headers = HashMap::new();
1799        headers.insert("Content-Type", "application/json".to_string());
1800        context.add_variable_from_value("headers", headers);
1801
1802        let program = Program::compile("headers[\"Content-Type\"]").unwrap();
1803        let value = program.execute(&context).unwrap();
1804        assert_eq!(value, "application/json".into());
1805    }
1806
1807    #[test]
1808    fn test_numeric_map_access() {
1809        let mut context = Context::default();
1810        let mut numbers = HashMap::new();
1811        numbers.insert(Key::Uint(1), "one".to_string());
1812        context.add_variable_from_value("numbers", numbers);
1813
1814        let program = Program::compile("numbers[1u]").unwrap();
1815        let value = program.execute(&context).unwrap();
1816        assert_eq!(value, "one".into());
1817    }
1818
1819    #[test]
1820    fn test_heterogeneous_compare() {
1821        let context = Context::default();
1822
1823        let program = Program::compile("1 < uint(2)").unwrap();
1824        let value = program.execute(&context).unwrap();
1825        assert_eq!(value, true.into());
1826
1827        let program = Program::compile("1 < 1.1").unwrap();
1828        let value = program.execute(&context).unwrap();
1829        assert_eq!(value, true.into());
1830
1831        let program = Program::compile("uint(0) > -10").unwrap();
1832        let value = program.execute(&context).unwrap();
1833        assert_eq!(
1834            value,
1835            true.into(),
1836            "negative signed ints should be less than uints"
1837        );
1838    }
1839
1840    #[test]
1841    fn test_float_compare() {
1842        let context = Context::default();
1843
1844        let program = Program::compile("1.0 > 0.0").unwrap();
1845        let value = program.execute(&context).unwrap();
1846        assert_eq!(value, true.into());
1847
1848        let program = Program::compile("double('NaN') == double('NaN')").unwrap();
1849        let value = program.execute(&context).unwrap();
1850        assert_eq!(value, false.into(), "NaN should not equal itself");
1851
1852        let program = Program::compile("1.0 > double('NaN')").unwrap();
1853        let result = program.execute(&context);
1854        assert!(
1855            result.is_err(),
1856            "NaN should not be comparable with inequality operators"
1857        );
1858    }
1859
1860    #[test]
1861    fn test_invalid_compare() {
1862        let context = Context::default();
1863
1864        let program = Program::compile("{} == []").unwrap();
1865        let value = program.execute(&context).unwrap();
1866        assert_eq!(value, false.into());
1867    }
1868
1869    #[test]
1870    fn test_size_fn_var() {
1871        let program = Program::compile("size(requests) + size == 5").unwrap();
1872        let mut context = Context::default();
1873        let requests = vec![Value::Int(42), Value::Int(42)];
1874        context
1875            .add_variable("requests", Value::List(Arc::new(requests)))
1876            .unwrap();
1877        context.add_variable("size", Value::Int(3)).unwrap();
1878        assert_eq!(program.execute(&context).unwrap(), Value::Bool(true));
1879    }
1880
1881    fn test_execution_error(program: &str, expected: ExecutionError) {
1882        let program = Program::compile(program).unwrap();
1883        let result = program.execute(&Context::default());
1884        assert_eq!(result.unwrap_err(), expected);
1885    }
1886
1887    #[test]
1888    fn test_invalid_sub() {
1889        test_execution_error(
1890            "'foo' - 10",
1891            ExecutionError::UnsupportedBinaryOperator("sub", "foo".into(), Value::Int(10)),
1892        );
1893    }
1894
1895    #[test]
1896    fn test_invalid_add() {
1897        test_execution_error(
1898            "'foo' + 10",
1899            ExecutionError::UnsupportedBinaryOperator("add", "foo".into(), Value::Int(10)),
1900        );
1901    }
1902
1903    #[test]
1904    fn test_invalid_div() {
1905        test_execution_error(
1906            "'foo' / 10",
1907            ExecutionError::UnsupportedBinaryOperator("div", "foo".into(), Value::Int(10)),
1908        );
1909    }
1910
1911    #[test]
1912    fn test_invalid_rem() {
1913        test_execution_error(
1914            "'foo' % 10",
1915            ExecutionError::UnsupportedBinaryOperator("rem", "foo".into(), Value::Int(10)),
1916        );
1917    }
1918
1919    #[test]
1920    fn out_of_bound_list_access() {
1921        let program = Program::compile("list[10]").unwrap();
1922        let mut context = Context::default();
1923        context
1924            .add_variable("list", Value::List(Arc::new(vec![])))
1925            .unwrap();
1926        let result = program.execute(&context);
1927        assert_eq!(
1928            result,
1929            Err(ExecutionError::IndexOutOfBounds(Value::Int(10)))
1930        );
1931    }
1932
1933    #[test]
1934    fn out_of_bound_list_access_negative() {
1935        let program = Program::compile("list[-1]").unwrap();
1936        let mut context = Context::default();
1937        context
1938            .add_variable("list", Value::List(Arc::new(vec![])))
1939            .unwrap();
1940        let result = program.execute(&context);
1941        assert_eq!(
1942            result,
1943            Err(ExecutionError::IndexOutOfBounds(Value::Int(-1)))
1944        );
1945    }
1946
1947    #[test]
1948    fn list_access_uint() {
1949        let program = Program::compile("list[1u]").unwrap();
1950        let mut context = Context::default();
1951        context
1952            .add_variable("list", Value::List(Arc::new(vec![1.into(), 2.into()])))
1953            .unwrap();
1954        let result = program.execute(&context);
1955        assert_eq!(result, Ok(Value::Int(2.into())));
1956    }
1957
1958    #[test]
1959    fn reference_to_value() {
1960        let test = "example".to_string();
1961        let direct: Value = test.as_str().into();
1962        assert_eq!(direct, Value::String(Arc::new(String::from("example"))));
1963
1964        let vec = vec![test.as_str()];
1965        let indirect: Value = vec.into();
1966        assert_eq!(
1967            indirect,
1968            Value::List(Arc::new(vec![Value::String(Arc::new(String::from(
1969                "example"
1970            )))]))
1971        );
1972    }
1973
1974    #[test]
1975    fn test_short_circuit_and() {
1976        let mut context = Context::default();
1977        let data: HashMap<String, String> = HashMap::new();
1978        context.add_variable_from_value("data", data);
1979
1980        let program = Program::compile("has(data.x) && data.x.startsWith(\"foo\")").unwrap();
1981        let value = program.execute(&context);
1982        println!("{value:?}");
1983        assert!(
1984            value.is_ok(),
1985            "The AND expression should support short-circuit evaluation."
1986        );
1987    }
1988
1989    #[test]
1990    fn test_or_ignores_err_when_short_circuiting() {
1991        let mut context = Context::default();
1992        context.add_variable_from_value("foo", 42);
1993        context.add_variable_from_value("bar", 42);
1994        let program = Program::compile("foo || bar > 0").unwrap();
1995        let value = program.execute(&context);
1996        assert_eq!(value, Ok(true.into()));
1997
1998        let program = Program::compile("foo || bar < 0").unwrap();
1999        let value = program.execute(&context);
2000        assert!(value.is_err());
2001    }
2002
2003    #[test]
2004    fn test_and_ignores_err_when_short_circuiting() {
2005        let mut context = Context::default();
2006        context.add_variable_from_value("foo", 42);
2007        context.add_variable_from_value("bar", 42);
2008        let program = Program::compile("foo && bar < 0").unwrap();
2009        let value = program.execute(&context);
2010        assert_eq!(value, Ok(false.into()));
2011
2012        let program = Program::compile("foo && bar > 0").unwrap();
2013        let value = program.execute(&context);
2014        assert!(value.is_err());
2015    }
2016
2017    #[test]
2018    fn invalid_int_math() {
2019        use ExecutionError::*;
2020
2021        let cases = [
2022            ("1 / 0", DivisionByZero(1.into())),
2023            ("1 % 0", RemainderByZero(1.into())),
2024            (
2025                &format!("{} + 1", i64::MAX),
2026                Overflow("add", i64::MAX.into(), 1.into()),
2027            ),
2028            (
2029                &format!("{} - 1", i64::MIN),
2030                Overflow("sub", i64::MIN.into(), 1.into()),
2031            ),
2032            (
2033                &format!("{} * 2", i64::MAX),
2034                Overflow("mul", i64::MAX.into(), 2.into()),
2035            ),
2036            (
2037                &format!("{} / -1", i64::MIN),
2038                Overflow("div", i64::MIN.into(), (-1).into()),
2039            ),
2040            (
2041                &format!("{} % -1", i64::MIN),
2042                Overflow("rem", i64::MIN.into(), (-1).into()),
2043            ),
2044        ];
2045
2046        for (expr, err) in cases {
2047            test_execution_error(expr, err);
2048        }
2049    }
2050
2051    #[test]
2052    fn invalid_uint_math() {
2053        use ExecutionError::*;
2054
2055        let cases = [
2056            ("1u / 0u", DivisionByZero(1u64.into())),
2057            ("1u % 0u", RemainderByZero(1u64.into())),
2058            (
2059                &format!("{}u + 1u", u64::MAX),
2060                Overflow("add", u64::MAX.into(), 1u64.into()),
2061            ),
2062            ("0u - 1u", Overflow("sub", 0u64.into(), 1u64.into())),
2063            (
2064                &format!("{}u * 2u", u64::MAX),
2065                Overflow("mul", u64::MAX.into(), 2u64.into()),
2066            ),
2067        ];
2068
2069        for (expr, err) in cases {
2070            test_execution_error(expr, err);
2071        }
2072    }
2073
2074    #[test]
2075    fn test_index_missing_map_key() {
2076        let mut ctx = Context::default();
2077        let mut map = HashMap::new();
2078        map.insert("a".to_string(), Value::Int(1));
2079        ctx.add_variable_from_value("mymap", map);
2080
2081        let p = Program::compile(r#"mymap["missing"]"#).expect("Must compile");
2082        let result = p.execute(&ctx);
2083
2084        assert!(result.is_err(), "Should error on missing map key");
2085    }
2086
2087    mod opaque {
2088        use crate::objects::{Map, Opaque, OpaqueVal, OptionalValue};
2089        use crate::parser::Parser;
2090        use crate::{Context, ExecutionError, FunctionContext, Program, Value};
2091        use serde::Serialize;
2092        use std::collections::HashMap;
2093        use std::fmt::Debug;
2094        use std::ops::Deref;
2095        use std::sync::Arc;
2096
2097        #[derive(Debug, Eq, PartialEq, Serialize)]
2098        struct MyStruct {
2099            field: String,
2100        }
2101
2102        impl Opaque for MyStruct {
2103            fn runtime_type_name(&self) -> &str {
2104                "my_struct"
2105            }
2106
2107            #[cfg(feature = "json")]
2108            fn json(&self) -> Option<serde_json::Value> {
2109                Some(serde_json::to_value(self).unwrap())
2110            }
2111        }
2112
2113        #[test]
2114        fn test_opaque_fn() {
2115            pub fn my_fn(ftx: &FunctionContext) -> Result<Value, ExecutionError> {
2116                if let Some(Some(opaque)) = ftx.this.as_ref().map(|v| v.downcast_ref::<OpaqueVal>())
2117                {
2118                    if opaque.val.runtime_type_name() == "my_struct" {
2119                        Ok(opaque
2120                            .val
2121                            .deref()
2122                            .downcast_ref::<MyStruct>()
2123                            .unwrap()
2124                            .field
2125                            .clone()
2126                            .into())
2127                    } else {
2128                        Err(ExecutionError::UnexpectedType {
2129                            got: opaque.val.runtime_type_name().to_string(),
2130                            want: "my_struct".to_string(),
2131                        })
2132                    }
2133                } else {
2134                    Err(ExecutionError::UnexpectedType {
2135                        got: format!("{:?}", ftx.this),
2136                        want: "Value::Opaque".to_string(),
2137                    })
2138                }
2139            }
2140
2141            let value = Arc::new(MyStruct {
2142                field: String::from("value"),
2143            });
2144
2145            let mut ctx = Context::default();
2146            ctx.add_variable_from_value("mine", Value::Opaque(value.clone()));
2147            ctx.add_function("myFn", my_fn);
2148            let prog = Program::compile("mine.myFn()").unwrap();
2149            assert_eq!(
2150                Ok(Value::String(Arc::new("value".into()))),
2151                prog.execute(&ctx)
2152            );
2153        }
2154
2155        #[test]
2156        fn opaque_eq() {
2157            let value_1 = Arc::new(MyStruct {
2158                field: String::from("1"),
2159            });
2160            let value_2 = Arc::new(MyStruct {
2161                field: String::from("2"),
2162            });
2163
2164            let mut ctx = Context::default();
2165            ctx.add_variable_from_value("v1", Value::Opaque(value_1.clone()));
2166            ctx.add_variable_from_value("v1b", Value::Opaque(value_1));
2167            ctx.add_variable_from_value("v2", Value::Opaque(value_2));
2168            assert_eq!(
2169                Program::compile("v2 == v1").unwrap().execute(&ctx),
2170                Ok(false.into())
2171            );
2172            assert_eq!(
2173                Program::compile("v1 == v1b").unwrap().execute(&ctx),
2174                Ok(true.into())
2175            );
2176            assert_eq!(
2177                Program::compile("v2 == v2").unwrap().execute(&ctx),
2178                Ok(true.into())
2179            );
2180        }
2181
2182        #[test]
2183        fn test_value_holder_dbg() {
2184            let opaque = Arc::new(MyStruct {
2185                field: "not so opaque".to_string(),
2186            });
2187            let opaque = Value::Opaque(opaque);
2188            assert_eq!(
2189                "Opaque<my_struct>(MyStruct { field: \"not so opaque\" })",
2190                format!("{:?}", opaque)
2191            );
2192        }
2193
2194        #[test]
2195        #[cfg(feature = "json")]
2196        fn test_json() {
2197            let value = Arc::new(MyStruct {
2198                field: String::from("value"),
2199            });
2200            let cel_value = Value::Opaque(value);
2201            let mut map = serde_json::Map::new();
2202            map.insert(
2203                "field".to_string(),
2204                serde_json::Value::String("value".to_string()),
2205            );
2206            assert_eq!(
2207                cel_value.json().expect("Must convert"),
2208                serde_json::Value::Object(map)
2209            );
2210        }
2211
2212        #[test]
2213        fn test_optional() {
2214            let expr = Parser::default()
2215                .enable_optional_syntax(true)
2216                .parse("optional.none()")
2217                .expect("Must parse");
2218            assert_eq!(
2219                Value::resolve(&expr, &Context::default()),
2220                Ok(Value::Opaque(Arc::new(OptionalValue::none())))
2221            );
2222
2223            let expr = Parser::default()
2224                .enable_optional_syntax(true)
2225                .parse("optional.of(1)")
2226                .expect("Must parse");
2227            assert_eq!(
2228                Value::resolve(&expr, &Context::default()),
2229                Ok(Value::Opaque(Arc::new(OptionalValue::of(Value::Int(1)))))
2230            );
2231
2232            let expr = Parser::default()
2233                .enable_optional_syntax(true)
2234                .parse("optional.ofNonZeroValue(0)")
2235                .expect("Must parse");
2236            assert_eq!(
2237                Value::resolve(&expr, &Context::default()),
2238                Ok(Value::Opaque(Arc::new(OptionalValue::none())))
2239            );
2240
2241            let expr = Parser::default()
2242                .enable_optional_syntax(true)
2243                .parse("optional.ofNonZeroValue(1)")
2244                .expect("Must parse");
2245            assert_eq!(
2246                Value::resolve(&expr, &Context::default()),
2247                Ok(Value::Opaque(Arc::new(OptionalValue::of(Value::Int(1)))))
2248            );
2249
2250            let expr = Parser::default()
2251                .enable_optional_syntax(true)
2252                .parse("optional.of(1).value()")
2253                .expect("Must parse");
2254            assert_eq!(
2255                Value::resolve(&expr, &Context::default()),
2256                Ok(Value::Int(1))
2257            );
2258            let expr = Parser::default()
2259                .enable_optional_syntax(true)
2260                .parse("optional.none().value()")
2261                .expect("Must parse");
2262            assert_eq!(
2263                Value::resolve(&expr, &Context::default()),
2264                Err(ExecutionError::FunctionError {
2265                    function: "value".to_string(),
2266                    message: "optional.none() dereference".to_string()
2267                })
2268            );
2269
2270            let expr = Parser::default()
2271                .enable_optional_syntax(true)
2272                .parse("optional.of(1).hasValue()")
2273                .expect("Must parse");
2274            assert_eq!(
2275                Value::resolve(&expr, &Context::default()),
2276                Ok(Value::Bool(true))
2277            );
2278            let expr = Parser::default()
2279                .enable_optional_syntax(true)
2280                .parse("optional.none().hasValue()")
2281                .expect("Must parse");
2282            assert_eq!(
2283                Value::resolve(&expr, &Context::default()),
2284                Ok(Value::Bool(false))
2285            );
2286
2287            let expr = Parser::default()
2288                .enable_optional_syntax(true)
2289                .parse("optional.of(1).or(optional.of(2))")
2290                .expect("Must parse");
2291            assert_eq!(
2292                Value::resolve(&expr, &Context::default()),
2293                Ok(Value::Opaque(Arc::new(OptionalValue::of(Value::Int(1)))))
2294            );
2295            let expr = Parser::default()
2296                .enable_optional_syntax(true)
2297                .parse("optional.none().or(optional.of(2))")
2298                .expect("Must parse");
2299            assert_eq!(
2300                Value::resolve(&expr, &Context::default()),
2301                Ok(Value::Opaque(Arc::new(OptionalValue::of(Value::Int(2)))))
2302            );
2303            let expr = Parser::default()
2304                .enable_optional_syntax(true)
2305                .parse("optional.none().or(optional.none())")
2306                .expect("Must parse");
2307            assert_eq!(
2308                Value::resolve(&expr, &Context::default()),
2309                Ok(Value::Opaque(Arc::new(OptionalValue::none())))
2310            );
2311
2312            let expr = Parser::default()
2313                .enable_optional_syntax(true)
2314                .parse("optional.of(1).orValue(5)")
2315                .expect("Must parse");
2316            assert_eq!(
2317                Value::resolve(&expr, &Context::default()),
2318                Ok(Value::Int(1))
2319            );
2320            let expr = Parser::default()
2321                .enable_optional_syntax(true)
2322                .parse("optional.none().orValue(5)")
2323                .expect("Must parse");
2324            assert_eq!(
2325                Value::resolve(&expr, &Context::default()),
2326                Ok(Value::Int(5))
2327            );
2328
2329            let mut ctx = Context::default();
2330            ctx.add_variable_from_value("msg", HashMap::from([("field", "value")]));
2331
2332            let expr = Parser::default()
2333                .enable_optional_syntax(true)
2334                .parse("msg.?field")
2335                .expect("Must parse");
2336            assert_eq!(
2337                Value::resolve(&expr, &ctx),
2338                Ok(Value::Opaque(Arc::new(OptionalValue::of(Value::String(
2339                    Arc::new("value".to_string())
2340                )))))
2341            );
2342
2343            let expr = Parser::default()
2344                .enable_optional_syntax(true)
2345                .parse("optional.of(msg).?field")
2346                .expect("Must parse");
2347            assert_eq!(
2348                Value::resolve(&expr, &ctx),
2349                Ok(Value::Opaque(Arc::new(OptionalValue::of(Value::String(
2350                    Arc::new("value".to_string())
2351                )))))
2352            );
2353
2354            let expr = Parser::default()
2355                .enable_optional_syntax(true)
2356                .parse("optional.none().?field")
2357                .expect("Must parse");
2358            assert_eq!(
2359                Value::resolve(&expr, &ctx),
2360                Ok(Value::Opaque(Arc::new(OptionalValue::none())))
2361            );
2362
2363            let expr = Parser::default()
2364                .enable_optional_syntax(true)
2365                .parse("optional.of(msg).?field.orValue('default')")
2366                .expect("Must parse");
2367            assert_eq!(
2368                Value::resolve(&expr, &ctx),
2369                Ok(Value::String(Arc::new("value".to_string())))
2370            );
2371
2372            let expr = Parser::default()
2373                .enable_optional_syntax(true)
2374                .parse("optional.none().?field.orValue('default')")
2375                .expect("Must parse");
2376            assert_eq!(
2377                Value::resolve(&expr, &ctx),
2378                Ok(Value::String(Arc::new("default".to_string())))
2379            );
2380
2381            let mut map_ctx = Context::default();
2382            let mut map = HashMap::new();
2383            map.insert("a".to_string(), Value::Int(1));
2384            map_ctx.add_variable_from_value("mymap", map);
2385
2386            let expr = Parser::default()
2387                .enable_optional_syntax(true)
2388                .parse(r#"mymap[?"missing"].orValue(99)"#)
2389                .expect("Must parse");
2390            assert_eq!(Value::resolve(&expr, &map_ctx), Ok(Value::Int(99)));
2391
2392            let expr = Parser::default()
2393                .enable_optional_syntax(true)
2394                .parse(r#"mymap[?"missing"].hasValue()"#)
2395                .expect("Must parse");
2396            assert_eq!(Value::resolve(&expr, &map_ctx), Ok(Value::Bool(false)));
2397
2398            let expr = Parser::default()
2399                .enable_optional_syntax(true)
2400                .parse(r#"mymap[?"a"].orValue(99)"#)
2401                .expect("Must parse");
2402            assert_eq!(Value::resolve(&expr, &map_ctx), Ok(Value::Int(1)));
2403
2404            let expr = Parser::default()
2405                .enable_optional_syntax(true)
2406                .parse(r#"mymap[?"a"].hasValue()"#)
2407                .expect("Must parse");
2408            assert_eq!(Value::resolve(&expr, &map_ctx), Ok(Value::Bool(true)));
2409
2410            let mut list_ctx = Context::default();
2411            list_ctx.add_variable_from_value(
2412                "mylist",
2413                vec![Value::Int(1), Value::Int(2), Value::Int(3)],
2414            );
2415
2416            let expr = Parser::default()
2417                .enable_optional_syntax(true)
2418                .parse("mylist[?10].orValue(99)")
2419                .expect("Must parse");
2420            assert_eq!(Value::resolve(&expr, &list_ctx), Ok(Value::Int(99)));
2421
2422            let expr = Parser::default()
2423                .enable_optional_syntax(true)
2424                .parse("mylist[?1].orValue(99)")
2425                .expect("Must parse");
2426            assert_eq!(Value::resolve(&expr, &list_ctx), Ok(Value::Int(2)));
2427
2428            let expr = Parser::default()
2429                .enable_optional_syntax(true)
2430                .parse("optional.of([1, 2, 3])[1].orValue(99)")
2431                .expect("Must parse");
2432            assert_eq!(
2433                Value::resolve(&expr, &Context::default()),
2434                Ok(Value::Int(2))
2435            );
2436
2437            let expr = Parser::default()
2438                .enable_optional_syntax(true)
2439                .parse("optional.of([1, 2, 3])[4].orValue(99)")
2440                .expect("Must parse");
2441            assert_eq!(
2442                Value::resolve(&expr, &Context::default()),
2443                Ok(Value::Int(99))
2444            );
2445
2446            let expr = Parser::default()
2447                .enable_optional_syntax(true)
2448                .parse("optional.none()[1].orValue(99)")
2449                .expect("Must parse");
2450            assert_eq!(
2451                Value::resolve(&expr, &Context::default()),
2452                Ok(Value::Int(99))
2453            );
2454
2455            let expr = Parser::default()
2456                .enable_optional_syntax(true)
2457                .parse("optional.of([1, 2, 3])[?1].orValue(99)")
2458                .expect("Must parse");
2459            assert_eq!(
2460                Value::resolve(&expr, &Context::default()),
2461                Ok(Value::Int(2))
2462            );
2463
2464            let expr = Parser::default()
2465                .enable_optional_syntax(true)
2466                .parse("[1, 2, ?optional.of(3), 4]")
2467                .expect("Must parse");
2468            assert_eq!(
2469                Value::resolve(&expr, &Context::default()),
2470                Ok(Value::List(Arc::new(vec![
2471                    Value::Int(1),
2472                    Value::Int(2),
2473                    Value::Int(3),
2474                    Value::Int(4)
2475                ])))
2476            );
2477
2478            let expr = Parser::default()
2479                .enable_optional_syntax(true)
2480                .parse("[1, 2, ?optional.none(), 4]")
2481                .expect("Must parse");
2482            assert_eq!(
2483                Value::resolve(&expr, &Context::default()),
2484                Ok(Value::List(Arc::new(vec![
2485                    Value::Int(1),
2486                    Value::Int(2),
2487                    Value::Int(4)
2488                ])))
2489            );
2490
2491            let expr = Parser::default()
2492                .enable_optional_syntax(true)
2493                .parse("[?optional.of(1), ?optional.none(), ?optional.of(3)]")
2494                .expect("Must parse");
2495            assert_eq!(
2496                Value::resolve(&expr, &Context::default()),
2497                Ok(Value::List(Arc::new(vec![Value::Int(1), Value::Int(3)])))
2498            );
2499
2500            let expr = Parser::default()
2501                .enable_optional_syntax(true)
2502                .parse(r#"[1, ?mymap[?"missing"], 3]"#)
2503                .expect("Must parse");
2504            assert_eq!(
2505                Value::resolve(&expr, &map_ctx),
2506                Ok(Value::List(Arc::new(vec![Value::Int(1), Value::Int(3)])))
2507            );
2508
2509            let expr = Parser::default()
2510                .enable_optional_syntax(true)
2511                .parse(r#"[1, ?mymap[?"a"], 3]"#)
2512                .expect("Must parse");
2513            assert_eq!(
2514                Value::resolve(&expr, &map_ctx),
2515                Ok(Value::List(Arc::new(vec![
2516                    Value::Int(1),
2517                    Value::Int(1),
2518                    Value::Int(3)
2519                ])))
2520            );
2521
2522            let expr = Parser::default()
2523                .enable_optional_syntax(true)
2524                .parse("[?optional.none(), ?optional.none()]")
2525                .expect("Must parse");
2526            assert_eq!(
2527                Value::resolve(&expr, &Context::default()),
2528                Ok(Value::List(Arc::new(vec![])))
2529            );
2530
2531            let expr = Parser::default()
2532                .enable_optional_syntax(true)
2533                .parse(r#"{"a": 1, "b": 2, ?"c": optional.of(3)}"#)
2534                .expect("Must parse");
2535            let mut expected_map = HashMap::new();
2536            expected_map.insert("a".into(), Value::Int(1));
2537            expected_map.insert("b".into(), Value::Int(2));
2538            expected_map.insert("c".into(), Value::Int(3));
2539            assert_eq!(
2540                Value::resolve(&expr, &Context::default()),
2541                Ok(Value::Map(Map {
2542                    map: Arc::from(expected_map)
2543                }))
2544            );
2545
2546            let expr = Parser::default()
2547                .enable_optional_syntax(true)
2548                .parse(r#"{"a": 1, "b": 2, ?"c": optional.none()}"#)
2549                .expect("Must parse");
2550            let mut expected_map = HashMap::new();
2551            expected_map.insert("a".into(), Value::Int(1));
2552            expected_map.insert("b".into(), Value::Int(2));
2553            assert_eq!(
2554                Value::resolve(&expr, &Context::default()),
2555                Ok(Value::Map(Map {
2556                    map: Arc::from(expected_map)
2557                }))
2558            );
2559
2560            let expr = Parser::default()
2561                .enable_optional_syntax(true)
2562                .parse(r#"{"a": 1, ?"b": optional.none(), ?"c": optional.of(3)}"#)
2563                .expect("Must parse");
2564            let mut expected_map = HashMap::new();
2565            expected_map.insert("a".into(), Value::Int(1));
2566            expected_map.insert("c".into(), Value::Int(3));
2567            assert_eq!(
2568                Value::resolve(&expr, &Context::default()),
2569                Ok(Value::Map(Map {
2570                    map: Arc::from(expected_map)
2571                }))
2572            );
2573
2574            let expr = Parser::default()
2575                .enable_optional_syntax(true)
2576                .parse(r#"{"a": 1, ?"b": mymap[?"missing"]}"#)
2577                .expect("Must parse");
2578            let mut expected_map = HashMap::new();
2579            expected_map.insert("a".into(), Value::Int(1));
2580            assert_eq!(
2581                Value::resolve(&expr, &map_ctx),
2582                Ok(Value::Map(Map {
2583                    map: Arc::from(expected_map)
2584                }))
2585            );
2586
2587            let expr = Parser::default()
2588                .enable_optional_syntax(true)
2589                .parse(r#"{"x": 10, ?"y": mymap[?"a"]}"#)
2590                .expect("Must parse");
2591            let mut expected_map = HashMap::new();
2592            expected_map.insert("x".into(), Value::Int(10));
2593            expected_map.insert("y".into(), Value::Int(1));
2594            assert_eq!(
2595                Value::resolve(&expr, &map_ctx),
2596                Ok(Value::Map(Map {
2597                    map: Arc::from(expected_map)
2598                }))
2599            );
2600
2601            let expr = Parser::default()
2602                .enable_optional_syntax(true)
2603                .parse(r#"{?"a": optional.none(), ?"b": optional.none()}"#)
2604                .expect("Must parse");
2605            assert_eq!(
2606                Value::resolve(&expr, &Context::default()),
2607                Ok(Value::Map(Map {
2608                    map: Arc::from(HashMap::new())
2609                }))
2610            );
2611        }
2612    }
2613
2614    #[cfg(feature = "structs")]
2615    mod structs {
2616        use std::borrow::Cow;
2617        use std::sync::Arc;
2618
2619        use crate::{
2620            common::{
2621                types::{self, CelBool, CelInt, CelString, CelStruct},
2622                value::Val,
2623            },
2624            env::StructDef,
2625            Context, Env, ExecutionError, Program, Value,
2626        };
2627
2628        #[test]
2629        fn test_empty_struct() {
2630            let mut env = Env::stdlib();
2631            env.add_struct(StructDef::new(String::from("cel.MyStruct")));
2632            let program = Program::compile("cel.MyStruct {}").unwrap();
2633            let value = program.execute(&Context::with_env(Arc::new(env))).unwrap();
2634            match value {
2635                Value::Struct(s) => assert_eq!(s.name(), "cel.MyStruct"),
2636                _ => panic!("This can't be!"),
2637            }
2638        }
2639
2640        #[test]
2641        fn test_struct() {
2642            let mut env = Env::stdlib();
2643            env.add_struct(
2644                StructDef::new(String::from("cel.Problem"))
2645                    .add_field(String::from("solved"), types::BOOL_TYPE)
2646                    .add_field(String::from("answer"), types::INT_TYPE),
2647            );
2648            let program =
2649                Program::compile("cel.Problem { solved: 0 != null, answer: 21 * 2 }").unwrap();
2650            let value = program.execute(&Context::with_env(Arc::new(env))).unwrap();
2651            match value {
2652                Value::Struct(s) => {
2653                    assert_eq!(s.name(), "cel.Problem");
2654                    assert_eq!(
2655                        s.field_value("solved"),
2656                        Some(&CelBool::from(true) as &dyn Val)
2657                    );
2658                    assert_eq!(s.field_value("answer"), Some(&CelInt::from(42) as &dyn Val));
2659                    assert_eq!(s.field_values().len(), 2);
2660                    assert_eq!(
2661                        s.field_values().get("solved").cloned(),
2662                        Some(Arc::new(CelBool::from(true)) as Arc<dyn Val>)
2663                    );
2664                    assert_eq!(
2665                        s.field_values().get("answer").cloned(),
2666                        Some(Arc::new(CelInt::from(42)) as Arc<dyn Val>)
2667                    );
2668                }
2669                _ => panic!("This can't be!"),
2670            }
2671        }
2672
2673        #[test]
2674        fn test_struct_field_access() {
2675            let mut env = Env::stdlib();
2676            env.add_struct(
2677                StructDef::new(String::from("cel.MyStruct"))
2678                    .add_field("some".into(), types::STRING_TYPE),
2679            );
2680            let program = Program::compile("cel.MyStruct { some: 'value' }.some").unwrap();
2681            let value = program.execute(&Context::with_env(env.into())).unwrap();
2682            assert_eq!(value, Value::String(Arc::new("value".to_owned())));
2683        }
2684
2685        #[test]
2686        fn test_struct_no_such_field() {
2687            let mut env = Env::stdlib();
2688            env.add_struct(
2689                StructDef::new(String::from("cel.MyStruct"))
2690                    .add_field("some".into(), types::STRING_TYPE),
2691            );
2692            let program = Program::compile("cel.MyStruct { not_here: 'value' }").unwrap();
2693            let result = program.execute(&Context::with_env(env.into()));
2694            assert_eq!(
2695                result,
2696                Err(ExecutionError::NoSuchKey(
2697                    String::from("field `not_here` on struct `cel.MyStruct`").into()
2698                ))
2699            );
2700        }
2701
2702        #[test]
2703        fn test_struct_with_default() {
2704            let mut env = Env::stdlib();
2705            env.add_struct(
2706                StructDef::new(String::from("cel.MyStruct"))
2707                    .add_field("some".into(), types::STRING_TYPE)
2708                    .add_field_with_default("here".into(), Box::new(CelString::from("yes"))),
2709            );
2710            let program = Program::compile("cel.MyStruct { some: 'value' }.here").unwrap();
2711            let result = program.execute(&Context::with_env(env.into()));
2712            assert_eq!(result, Ok(Value::String(Arc::new(String::from("yes")))));
2713        }
2714
2715        #[test]
2716        fn test_struct_with_default_overwritten() {
2717            let mut env = Env::stdlib();
2718            env.add_struct(
2719                StructDef::new(String::from("cel.MyStruct"))
2720                    .add_field("some".into(), types::STRING_TYPE)
2721                    .add_field_with_default("here".into(), Box::new(CelString::from("yes"))),
2722            );
2723            let program =
2724                Program::compile("cel.MyStruct { some: 'value', here: 'totally' }.here").unwrap();
2725            let result = program.execute(&Context::with_env(env.into()));
2726            assert_eq!(result, Ok(Value::String(Arc::new(String::from("totally")))));
2727        }
2728
2729        #[test]
2730        fn test_struct_has_macro() {
2731            let mut env = Env::stdlib();
2732            env.add_struct(
2733                StructDef::new(String::from("cel.MyStruct"))
2734                    .add_field("name".into(), types::STRING_TYPE)
2735                    .add_field("value".into(), types::INT_TYPE),
2736            );
2737
2738            let mut my_struct = CelStruct::new("cel.MyStruct".to_owned());
2739            my_struct.add_field_value(
2740                "name".to_owned(),
2741                Cow::<dyn Val>::Owned(Box::new(CelString::from("test"))),
2742            );
2743            my_struct.add_field_value(
2744                "value".to_owned(),
2745                Cow::<dyn Val>::Owned(Box::new(CelInt::from(42))),
2746            );
2747
2748            let mut context = Context::with_env(Arc::new(env));
2749            context
2750                .add_variable("my_var", Value::Struct(Arc::new(my_struct)))
2751                .unwrap();
2752
2753            let program = Program::compile("has(my_var.name)").unwrap();
2754            let result = program.execute(&context).unwrap();
2755            assert_eq!(result, Value::Bool(true));
2756
2757            let program = Program::compile("has(my_var.missing)").unwrap();
2758            let result = program.execute(&context).unwrap();
2759            assert_eq!(result, Value::Bool(false));
2760
2761            let program =
2762                Program::compile("has(cel.MyStruct{name: 'foo', value: 1}.name)").unwrap();
2763            let result = program.execute(&context).unwrap();
2764            assert_eq!(result, Value::Bool(true));
2765
2766            let program = Program::compile("has(cel.MyStruct{}.name)").unwrap();
2767            let result = program.execute(&context).unwrap();
2768            assert_eq!(result, Value::Bool(false));
2769        }
2770
2771        #[test]
2772        fn test_struct_no_such_field_access() {
2773            let mut env = Env::stdlib();
2774            env.add_struct(
2775                StructDef::new(String::from("cel.MyStruct"))
2776                    .add_field("some".into(), types::STRING_TYPE),
2777            );
2778            let program = Program::compile("cel.MyStruct { some: 'value' }.not_here").unwrap();
2779            let result = program.execute(&Context::with_env(env.into()));
2780            assert_eq!(
2781                result,
2782                Err(ExecutionError::NoSuchKey(String::from("not_here").into()))
2783            );
2784        }
2785
2786        #[test]
2787        fn unknown_struct() {
2788            let program = Program::compile("cel.MyStruct { some: 'value' }.not_here").unwrap();
2789            let result = program.execute(&Context::default());
2790            assert_eq!(
2791                result,
2792                Err(ExecutionError::UnexpectedType {
2793                    got: String::from("cel.MyStruct"),
2794                    want: String::from("known struct")
2795                })
2796            );
2797        }
2798
2799        #[test]
2800        fn add_struct_variable_to_context() {
2801            let mut env = Env::stdlib();
2802            env.add_struct(
2803                StructDef::new(String::from("cel.MyStruct"))
2804                    .add_field("name".into(), types::STRING_TYPE)
2805                    .add_field("value".into(), types::INT_TYPE),
2806            );
2807
2808            let mut my_struct = CelStruct::new("cel.MyStruct".to_owned());
2809            my_struct.add_field_value(
2810                "name".to_owned(),
2811                Cow::<dyn Val>::Owned(Box::new(CelString::from("test"))),
2812            );
2813            my_struct.add_field_value(
2814                "value".to_owned(),
2815                Cow::<dyn Val>::Owned(Box::new(CelInt::from(42))),
2816            );
2817
2818            let mut context = Context::with_env(Arc::new(env));
2819            context
2820                .add_variable("my_var", Value::Struct(Arc::new(my_struct)))
2821                .unwrap();
2822
2823            let program = Program::compile("my_var.name + ' ' + string(my_var.value)").unwrap();
2824            let result = program.execute(&context).unwrap();
2825            assert_eq!(result, Value::String(Arc::new("test 42".to_owned())));
2826        }
2827    }
2828}