Skip to main content

cel_core/eval/
value.rs

1//! Runtime values for CEL evaluation.
2//!
3//! `Value` represents all CEL values at runtime, including primitive types,
4//! collections, timestamps, durations, and special values like errors and optionals.
5//!
6//! # Creating Values
7//!
8//! Use Rust's standard `Into` trait to create values from native types:
9//!
10//! ```rust
11//! use cel_core::Value;
12//!
13//! // Primitives - integer types automatically widen to i64/u64
14//! let v: Value = 42.into();      // i32 -> Value::Int(i64)
15//! let v: Value = 42i64.into();   // i64 -> Value::Int(i64)
16//! let v: Value = 42u32.into();   // u32 -> Value::UInt(u64)
17//! let v: Value = true.into();
18//! let v: Value = "hello".into();
19//!
20//! // Collections
21//! let list: Value = vec![Value::Int(1), Value::Int(2)].into();
22//!
23//! // From compile-time constants
24//! use cel_core::CelValue;
25//! let cv = CelValue::Int(42);
26//! let v: Value = cv.into();
27//! ```
28//!
29//! # Extracting Values
30//!
31//! Use `TryFrom` to extract native types from values:
32//!
33//! ```rust
34//! use cel_core::{Value, Timestamp, Duration, ValueMap, OptionalValue, MapKey};
35//! use std::convert::TryFrom;
36//!
37//! // Primitive types
38//! let v = Value::Int(42);
39//! let i: i64 = i64::try_from(&v).unwrap();
40//!
41//! // Timestamp and Duration (Copy types - both owned and borrowed work)
42//! let v = Value::Timestamp(Timestamp::new(1234567890, 0));
43//! let t: Timestamp = Timestamp::try_from(&v).unwrap();
44//!
45//! let v = Value::Duration(Duration::new(60, 0));
46//! let d: Duration = Duration::try_from(&v).unwrap();
47//!
48//! // Collections (borrowed references)
49//! let v: Value = vec![Value::Int(1), Value::Int(2)].into();
50//! let list: &[Value] = <&[Value]>::try_from(&v).unwrap();
51//!
52//! // Maps
53//! let v = Value::map([(MapKey::String("key".into()), Value::Int(42))]);
54//! let map: &ValueMap = <&ValueMap>::try_from(&v).unwrap();
55//!
56//! // Optionals
57//! let v = Value::optional_some(Value::Int(42));
58//! let opt: &OptionalValue = <&OptionalValue>::try_from(&v).unwrap();
59//! ```
60
61use std::cmp::Ordering;
62use std::collections::BTreeMap;
63use std::fmt;
64use std::sync::Arc;
65
66use super::message::MessageValue;
67use super::EvalError;
68use crate::types::{CelType, CelValue};
69
70/// Error returned when converting from Value to a specific type fails.
71#[derive(Debug, Clone, PartialEq, Eq)]
72pub struct ValueError {
73    /// The expected type name.
74    pub expected: &'static str,
75    /// The actual type name found.
76    pub found: String,
77}
78
79impl std::fmt::Display for ValueError {
80    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
81        write!(f, "expected {}, found {}", self.expected, self.found)
82    }
83}
84
85impl std::error::Error for ValueError {}
86
87/// A CEL runtime value.
88///
89/// This enum represents all possible values that can exist during CEL evaluation.
90/// Unlike `CelValue` (which represents compile-time constants), `Value` supports
91/// the full range of CEL types including collections, timestamps, and errors.
92#[derive(Debug, Clone)]
93pub enum Value {
94    /// Null value.
95    Null,
96    /// Boolean value.
97    Bool(bool),
98    /// Signed 64-bit integer.
99    Int(i64),
100    /// Unsigned 64-bit integer.
101    UInt(u64),
102    /// 64-bit floating point.
103    Double(f64),
104    /// Unicode string (Arc for cheap cloning).
105    String(Arc<str>),
106    /// Byte sequence (Arc for cheap cloning).
107    Bytes(Arc<[u8]>),
108    /// Homogeneous list.
109    List(Arc<[Value]>),
110    /// Key-value map (uses BTreeMap for deterministic iteration).
111    Map(Arc<ValueMap>),
112    /// Timestamp (seconds and nanos since Unix epoch).
113    Timestamp(Timestamp),
114    /// Duration (seconds and nanos).
115    Duration(Duration),
116    /// Type value (represents a CEL type at runtime).
117    Type(TypeValue),
118    /// Optional value (present or absent).
119    Optional(OptionalValue),
120    /// Protobuf message value.
121    Message(Box<dyn MessageValue>),
122    /// Enum value with type information (strong enum typing).
123    Enum(EnumValue),
124    /// Error value (evaluation errors propagate as values).
125    Error(Arc<EvalError>),
126}
127
128/// A CEL enum value with type information.
129///
130/// Used for strong enum typing where enum values carry their
131/// fully qualified type name alongside the numeric value.
132#[derive(Debug, Clone)]
133pub struct EnumValue {
134    /// The fully qualified enum type name (e.g., "cel.expr.conformance.proto3.GlobalEnum").
135    pub type_name: Arc<str>,
136    /// The numeric enum value.
137    pub value: i32,
138}
139
140impl EnumValue {
141    /// Create a new enum value.
142    pub fn new(type_name: impl Into<Arc<str>>, value: i32) -> Self {
143        Self {
144            type_name: type_name.into(),
145            value,
146        }
147    }
148}
149
150impl PartialEq for EnumValue {
151    fn eq(&self, other: &Self) -> bool {
152        self.type_name == other.type_name && self.value == other.value
153    }
154}
155
156/// A CEL timestamp value.
157#[derive(Debug, Clone, Copy, PartialEq, Eq)]
158pub struct Timestamp {
159    /// Seconds since Unix epoch.
160    pub seconds: i64,
161    /// Nanoseconds (0..999_999_999).
162    pub nanos: i32,
163}
164
165impl Timestamp {
166    /// Minimum valid timestamp: Year 0001-01-01 00:00:00 UTC
167    /// This is approximately -62135596800 seconds from Unix epoch.
168    pub const MIN_SECONDS: i64 = -62135596800;
169
170    /// Maximum valid timestamp: Year 9999-12-31 23:59:59 UTC
171    /// This is approximately 253402300799 seconds from Unix epoch.
172    pub const MAX_SECONDS: i64 = 253402300799;
173
174    /// Create a new timestamp.
175    pub fn new(seconds: i64, nanos: i32) -> Self {
176        Self { seconds, nanos }
177    }
178
179    /// Create a timestamp from seconds since Unix epoch.
180    pub fn from_seconds(seconds: i64) -> Self {
181        Self { seconds, nanos: 0 }
182    }
183
184    /// Returns true if this timestamp is before another.
185    pub fn is_before(&self, other: &Timestamp) -> bool {
186        (self.seconds, self.nanos) < (other.seconds, other.nanos)
187    }
188
189    /// Returns true if this timestamp is after another.
190    pub fn is_after(&self, other: &Timestamp) -> bool {
191        (self.seconds, self.nanos) > (other.seconds, other.nanos)
192    }
193
194    /// Check if this timestamp is within the valid CEL range (Year 0001 to 9999).
195    pub fn is_valid(&self) -> bool {
196        self.seconds >= Self::MIN_SECONDS && self.seconds <= Self::MAX_SECONDS
197    }
198
199    /// Convert to a chrono DateTime<Utc>.
200    pub fn to_datetime_utc(&self) -> Option<chrono::DateTime<chrono::Utc>> {
201        chrono::DateTime::from_timestamp(self.seconds, self.nanos as u32)
202    }
203
204    /// Create from a chrono DateTime<Utc>.
205    pub fn from_datetime<Tz: chrono::TimeZone>(dt: &chrono::DateTime<Tz>) -> Self {
206        Self {
207            seconds: dt.timestamp(),
208            nanos: dt.timestamp_subsec_nanos() as i32,
209        }
210    }
211
212    /// Convert to total nanoseconds since Unix epoch.
213    pub fn to_nanos(&self) -> Option<i128> {
214        let secs = self.seconds as i128;
215        let nanos = self.nanos as i128;
216        secs.checked_mul(1_000_000_000).map(|s| s + nanos)
217    }
218}
219
220/// A CEL duration value.
221#[derive(Debug, Clone, Copy, PartialEq, Eq)]
222pub struct Duration {
223    /// Seconds component.
224    pub seconds: i64,
225    /// Nanoseconds component (0..999_999_999 for positive durations,
226    /// -999_999_999..0 for negative durations).
227    pub nanos: i32,
228}
229
230impl Duration {
231    /// Maximum valid duration in seconds.
232    /// This is set to one less than the span of the valid timestamp range,
233    /// ensuring that subtracting the min timestamp from the max timestamp
234    /// (or vice versa) produces a range error.
235    pub const MAX_SECONDS: i64 = 315_537_897_598;
236
237    /// Minimum valid duration in seconds (negative max).
238    pub const MIN_SECONDS: i64 = -315_537_897_598;
239
240    /// Create a new duration.
241    pub fn new(seconds: i64, nanos: i32) -> Self {
242        Self { seconds, nanos }
243    }
244
245    /// Create a duration from seconds.
246    pub fn from_seconds(seconds: i64) -> Self {
247        Self { seconds, nanos: 0 }
248    }
249
250    /// Create a duration from nanoseconds.
251    pub fn from_nanos(nanos: i64) -> Self {
252        let seconds = nanos / 1_000_000_000;
253        let nanos = (nanos % 1_000_000_000) as i32;
254        Self { seconds, nanos }
255    }
256
257    /// Convert to total nanoseconds.
258    pub fn to_nanos(&self) -> i64 {
259        self.seconds
260            .saturating_mul(1_000_000_000)
261            .saturating_add(self.nanos as i64)
262    }
263
264    /// Returns true if this duration is negative.
265    pub fn is_negative(&self) -> bool {
266        self.seconds < 0 || (self.seconds == 0 && self.nanos < 0)
267    }
268
269    /// Check if this duration is within the valid CEL range (~10000 years).
270    pub fn is_valid(&self) -> bool {
271        self.seconds >= Self::MIN_SECONDS && self.seconds <= Self::MAX_SECONDS
272    }
273
274    /// Convert to a chrono Duration.
275    pub fn to_chrono(&self) -> chrono::Duration {
276        chrono::Duration::seconds(self.seconds) + chrono::Duration::nanoseconds(self.nanos as i64)
277    }
278
279    /// Create from a chrono Duration.
280    pub fn from_chrono(d: chrono::Duration) -> Self {
281        let total_nanos = d.num_nanoseconds().unwrap_or(0);
282        Self::from_nanos(total_nanos)
283    }
284
285    /// Get total hours (truncated).
286    pub fn get_hours(&self) -> i64 {
287        self.total_seconds() / 3600
288    }
289
290    /// Get total minutes (truncated).
291    pub fn get_minutes(&self) -> i64 {
292        self.total_seconds() / 60
293    }
294
295    /// Get total seconds.
296    pub fn total_seconds(&self) -> i64 {
297        self.seconds
298    }
299
300    /// Get milliseconds component (0-999).
301    pub fn get_milliseconds(&self) -> i64 {
302        // For negative durations, nanos is also negative
303        let ms = if self.nanos >= 0 {
304            self.nanos / 1_000_000
305        } else {
306            -(-self.nanos / 1_000_000)
307        };
308        ms as i64
309    }
310}
311
312/// A CEL type value (runtime representation of types).
313#[derive(Debug, Clone, PartialEq, Eq)]
314pub struct TypeValue {
315    /// The type name as it appears in CEL.
316    pub name: Arc<str>,
317}
318
319impl TypeValue {
320    /// Create a new type value.
321    pub fn new(name: impl Into<Arc<str>>) -> Self {
322        Self { name: name.into() }
323    }
324
325    /// Common type values.
326    pub fn null_type() -> Self {
327        Self::new("null_type")
328    }
329    pub fn bool_type() -> Self {
330        Self::new("bool")
331    }
332    pub fn int_type() -> Self {
333        Self::new("int")
334    }
335    pub fn uint_type() -> Self {
336        Self::new("uint")
337    }
338    pub fn double_type() -> Self {
339        Self::new("double")
340    }
341    pub fn string_type() -> Self {
342        Self::new("string")
343    }
344    pub fn bytes_type() -> Self {
345        Self::new("bytes")
346    }
347    pub fn list_type() -> Self {
348        Self::new("list")
349    }
350    pub fn map_type() -> Self {
351        Self::new("map")
352    }
353    pub fn timestamp_type() -> Self {
354        Self::new("google.protobuf.Timestamp")
355    }
356    pub fn duration_type() -> Self {
357        Self::new("google.protobuf.Duration")
358    }
359    pub fn type_type() -> Self {
360        Self::new("type")
361    }
362    pub fn optional_type() -> Self {
363        Self::new("optional")
364    }
365}
366
367/// A CEL optional value.
368#[derive(Debug, Clone)]
369pub enum OptionalValue {
370    /// An absent optional value.
371    None,
372    /// A present optional value.
373    Some(Box<Value>),
374}
375
376impl OptionalValue {
377    /// Create an absent optional.
378    pub fn none() -> Self {
379        OptionalValue::None
380    }
381
382    /// Create a present optional.
383    pub fn some(value: Value) -> Self {
384        OptionalValue::Some(Box::new(value))
385    }
386
387    /// Returns true if the optional is present.
388    pub fn is_present(&self) -> bool {
389        matches!(self, OptionalValue::Some(_))
390    }
391
392    /// Get the inner value, or None if absent.
393    pub fn as_value(&self) -> Option<&Value> {
394        match self {
395            OptionalValue::None => None,
396            OptionalValue::Some(v) => Some(v),
397        }
398    }
399
400    /// Unwrap the value or return a default.
401    pub fn unwrap_or(self, default: Value) -> Value {
402        match self {
403            OptionalValue::None => default,
404            OptionalValue::Some(v) => *v,
405        }
406    }
407}
408
409/// A CEL map with heterogeneous keys.
410///
411/// Uses a BTreeMap with a custom key type for deterministic iteration order.
412#[derive(Debug, Clone, Default)]
413pub struct ValueMap {
414    entries: BTreeMap<MapKey, Value>,
415}
416
417/// A map key that supports CEL's key types.
418///
419/// CEL allows bool, int, uint, and string as map keys.
420#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
421pub enum MapKey {
422    Bool(bool),
423    Int(i64),
424    UInt(u64),
425    String(Arc<str>),
426}
427
428impl MapKey {
429    /// Create a map key from a Value.
430    pub fn from_value(value: &Value) -> Option<Self> {
431        match value {
432            Value::Bool(b) => Some(MapKey::Bool(*b)),
433            Value::Int(i) => Some(MapKey::Int(*i)),
434            Value::UInt(u) => Some(MapKey::UInt(*u)),
435            Value::String(s) => Some(MapKey::String(s.clone())),
436            _ => None,
437        }
438    }
439
440    /// Convert back to a Value.
441    pub fn to_value(&self) -> Value {
442        match self {
443            MapKey::Bool(b) => Value::Bool(*b),
444            MapKey::Int(i) => Value::Int(*i),
445            MapKey::UInt(u) => Value::UInt(*u),
446            MapKey::String(s) => Value::String(s.clone()),
447        }
448    }
449}
450
451impl From<&str> for MapKey {
452    fn from(s: &str) -> Self {
453        MapKey::String(Arc::from(s))
454    }
455}
456
457impl From<String> for MapKey {
458    fn from(s: String) -> Self {
459        MapKey::String(Arc::from(s))
460    }
461}
462
463impl From<Arc<str>> for MapKey {
464    fn from(s: Arc<str>) -> Self {
465        MapKey::String(s)
466    }
467}
468
469impl From<bool> for MapKey {
470    fn from(b: bool) -> Self {
471        MapKey::Bool(b)
472    }
473}
474
475impl From<i64> for MapKey {
476    fn from(i: i64) -> Self {
477        MapKey::Int(i)
478    }
479}
480
481impl From<u64> for MapKey {
482    fn from(u: u64) -> Self {
483        MapKey::UInt(u)
484    }
485}
486
487impl From<i32> for MapKey {
488    fn from(i: i32) -> Self {
489        MapKey::Int(i as i64)
490    }
491}
492
493impl From<u32> for MapKey {
494    fn from(u: u32) -> Self {
495        MapKey::UInt(u as u64)
496    }
497}
498
499impl ValueMap {
500    /// Create a new empty map.
501    pub fn new() -> Self {
502        Self {
503            entries: BTreeMap::new(),
504        }
505    }
506
507    /// Create a map from an iterator of key-value pairs.
508    pub fn from_entries(entries: impl IntoIterator<Item = (MapKey, Value)>) -> Self {
509        Self {
510            entries: entries.into_iter().collect(),
511        }
512    }
513
514    /// Get a value by key.
515    pub fn get(&self, key: &MapKey) -> Option<&Value> {
516        self.entries.get(key)
517    }
518
519    /// Insert a key-value pair.
520    pub fn insert(&mut self, key: MapKey, value: Value) {
521        self.entries.insert(key, value);
522    }
523
524    /// Check if a key exists.
525    pub fn contains_key(&self, key: &MapKey) -> bool {
526        self.entries.contains_key(key)
527    }
528
529    /// Get a value by key with cross-type numeric coercion.
530    /// Tries exact match first, then Int↔UInt coercion for in-range values.
531    pub fn get_with_numeric_coercion(&self, key: &MapKey) -> Option<&Value> {
532        if let Some(v) = self.entries.get(key) {
533            return Some(v);
534        }
535        match key {
536            MapKey::Int(i) => {
537                if *i >= 0 {
538                    self.entries.get(&MapKey::UInt(*i as u64))
539                } else {
540                    None
541                }
542            }
543            MapKey::UInt(u) => {
544                if *u <= i64::MAX as u64 {
545                    self.entries.get(&MapKey::Int(*u as i64))
546                } else {
547                    None
548                }
549            }
550            _ => None,
551        }
552    }
553
554    /// Check if a key exists with cross-type numeric coercion.
555    pub fn contains_key_with_numeric_coercion(&self, key: &MapKey) -> bool {
556        self.get_with_numeric_coercion(key).is_some()
557    }
558
559    /// Get the number of entries.
560    pub fn len(&self) -> usize {
561        self.entries.len()
562    }
563
564    /// Check if the map is empty.
565    pub fn is_empty(&self) -> bool {
566        self.entries.is_empty()
567    }
568
569    /// Iterate over entries.
570    pub fn iter(&self) -> impl Iterator<Item = (&MapKey, &Value)> {
571        self.entries.iter()
572    }
573
574    /// Iterate over keys.
575    pub fn keys(&self) -> impl Iterator<Item = &MapKey> {
576        self.entries.keys()
577    }
578
579    /// Iterate over values.
580    pub fn values(&self) -> impl Iterator<Item = &Value> {
581        self.entries.values()
582    }
583}
584
585// ==================== Value Constructors ====================
586
587impl Value {
588    /// Create a map value from key-value pairs.
589    ///
590    /// Keys and values are automatically converted using `Into<MapKey>` and `Into<Value>`.
591    ///
592    /// ```
593    /// use cel_core::Value;
594    ///
595    /// // String keys and values
596    /// let map = Value::map([("host", "localhost"), ("port", "8080")]);
597    ///
598    /// // Integer keys
599    /// let map = Value::map([(1i64, "one"), (2i64, "two")]);
600    ///
601    /// // Mixed value types require explicit Value construction
602    /// let map = Value::map([
603    ///     ("name", Value::from("Alice")),
604    ///     ("age", Value::from(30i64)),
605    /// ]);
606    /// ```
607    pub fn map<K, V>(entries: impl IntoIterator<Item = (K, V)>) -> Self
608    where
609        K: Into<MapKey>,
610        V: Into<Value>,
611    {
612        Value::Map(Arc::new(ValueMap::from_entries(
613            entries.into_iter().map(|(k, v)| (k.into(), v.into())),
614        )))
615    }
616
617    /// Create a list value from items.
618    ///
619    /// Items are automatically converted using `Into<Value>`.
620    ///
621    /// ```
622    /// use cel_core::Value;
623    ///
624    /// // Integer list (no i64 suffix needed)
625    /// let list = Value::list([1, 2, 3]);
626    ///
627    /// // String list
628    /// let list = Value::list(["a", "b", "c"]);
629    ///
630    /// // Mixed types require explicit Value construction
631    /// let list = Value::list([Value::from(1), Value::from("two")]);
632    /// ```
633    pub fn list<T>(items: impl IntoIterator<Item = T>) -> Self
634    where
635        T: Into<Value>,
636    {
637        Value::List(Arc::from(
638            items.into_iter().map(Into::into).collect::<Vec<_>>(),
639        ))
640    }
641
642    /// Create a timestamp value.
643    pub fn timestamp(seconds: i64, nanos: i32) -> Self {
644        Value::Timestamp(Timestamp::new(seconds, nanos))
645    }
646
647    /// Create a duration value.
648    pub fn duration(seconds: i64, nanos: i32) -> Self {
649        Value::Duration(Duration::new(seconds, nanos))
650    }
651
652    /// Create a type value.
653    pub fn new_type(name: impl Into<Arc<str>>) -> Self {
654        Value::Type(TypeValue::new(name))
655    }
656
657    /// Create an optional none value.
658    pub fn optional_none() -> Self {
659        Value::Optional(OptionalValue::None)
660    }
661
662    /// Create an optional some value.
663    pub fn optional_some(value: Value) -> Self {
664        Value::Optional(OptionalValue::some(value))
665    }
666
667    /// Convert an Option<T> to a CEL optional value.
668    ///
669    /// Unlike `From<Option<T>>` which maps `None` to `Value::Null`,
670    /// this preserves CEL optional semantics.
671    ///
672    /// ```
673    /// use cel_core::Value;
674    ///
675    /// let some_val = Value::from_option(Some(42));  // optional.of(42)
676    /// let none_val = Value::from_option(None::<i32>);  // optional.none()
677    /// ```
678    pub fn from_option<T: Into<Value>>(opt: Option<T>) -> Self {
679        match opt {
680            Some(v) => Value::optional_some(v.into()),
681            None => Value::optional_none(),
682        }
683    }
684
685    /// Create an error value.
686    pub fn error(err: impl Into<EvalError>) -> Self {
687        Value::Error(Arc::new(err.into()))
688    }
689}
690
691// ==================== From Implementations ====================
692
693impl From<bool> for Value {
694    fn from(b: bool) -> Self {
695        Value::Bool(b)
696    }
697}
698
699impl From<i64> for Value {
700    fn from(i: i64) -> Self {
701        Value::Int(i)
702    }
703}
704
705impl From<u64> for Value {
706    fn from(u: u64) -> Self {
707        Value::UInt(u)
708    }
709}
710
711// Signed integer widening conversions
712impl From<i8> for Value {
713    fn from(i: i8) -> Self {
714        Value::Int(i as i64)
715    }
716}
717
718impl From<i16> for Value {
719    fn from(i: i16) -> Self {
720        Value::Int(i as i64)
721    }
722}
723
724impl From<i32> for Value {
725    fn from(i: i32) -> Self {
726        Value::Int(i as i64)
727    }
728}
729
730impl From<isize> for Value {
731    fn from(i: isize) -> Self {
732        Value::Int(i as i64)
733    }
734}
735
736// Unsigned integer widening conversions
737impl From<u8> for Value {
738    fn from(u: u8) -> Self {
739        Value::UInt(u as u64)
740    }
741}
742
743impl From<u16> for Value {
744    fn from(u: u16) -> Self {
745        Value::UInt(u as u64)
746    }
747}
748
749impl From<u32> for Value {
750    fn from(u: u32) -> Self {
751        Value::UInt(u as u64)
752    }
753}
754
755impl From<usize> for Value {
756    fn from(u: usize) -> Self {
757        Value::UInt(u as u64)
758    }
759}
760
761impl From<f64> for Value {
762    fn from(d: f64) -> Self {
763        Value::Double(d)
764    }
765}
766
767impl From<&str> for Value {
768    fn from(s: &str) -> Self {
769        Value::String(Arc::from(s))
770    }
771}
772
773impl From<String> for Value {
774    fn from(s: String) -> Self {
775        Value::String(Arc::from(s))
776    }
777}
778
779impl From<Arc<str>> for Value {
780    fn from(s: Arc<str>) -> Self {
781        Value::String(s)
782    }
783}
784
785impl From<&[u8]> for Value {
786    fn from(b: &[u8]) -> Self {
787        Value::Bytes(Arc::from(b))
788    }
789}
790
791impl From<Vec<u8>> for Value {
792    fn from(b: Vec<u8>) -> Self {
793        Value::Bytes(Arc::from(b))
794    }
795}
796
797impl From<Arc<[u8]>> for Value {
798    fn from(b: Arc<[u8]>) -> Self {
799        Value::Bytes(b)
800    }
801}
802
803impl From<Vec<Value>> for Value {
804    fn from(v: Vec<Value>) -> Self {
805        Value::List(Arc::from(v))
806    }
807}
808
809impl From<Timestamp> for Value {
810    fn from(t: Timestamp) -> Self {
811        Value::Timestamp(t)
812    }
813}
814
815impl From<Duration> for Value {
816    fn from(d: Duration) -> Self {
817        Value::Duration(d)
818    }
819}
820
821impl From<EvalError> for Value {
822    fn from(e: EvalError) -> Self {
823        Value::Error(Arc::new(e))
824    }
825}
826
827impl From<CelValue> for Value {
828    fn from(cv: CelValue) -> Self {
829        match cv {
830            CelValue::Null => Value::Null,
831            CelValue::Bool(b) => Value::Bool(b),
832            CelValue::Int(i) => Value::Int(i),
833            CelValue::UInt(u) => Value::UInt(u),
834            CelValue::Double(d) => Value::Double(d),
835            CelValue::String(s) => Value::String(Arc::from(s)),
836            CelValue::Bytes(b) => Value::Bytes(Arc::from(b)),
837        }
838    }
839}
840
841impl<T: Into<Value>> From<Option<T>> for Value {
842    fn from(opt: Option<T>) -> Self {
843        match opt {
844            Some(v) => v.into(),
845            None => Value::Null,
846        }
847    }
848}
849
850// ==================== TryFrom Implementations ====================
851
852impl TryFrom<Value> for bool {
853    type Error = ValueError;
854    fn try_from(v: Value) -> Result<Self, Self::Error> {
855        match v {
856            Value::Bool(b) => Ok(b),
857            other => Err(ValueError {
858                expected: "bool",
859                found: other.type_value().name.to_string(),
860            }),
861        }
862    }
863}
864
865impl TryFrom<&Value> for bool {
866    type Error = ValueError;
867    fn try_from(v: &Value) -> Result<Self, Self::Error> {
868        match v {
869            Value::Bool(b) => Ok(*b),
870            other => Err(ValueError {
871                expected: "bool",
872                found: other.type_value().name.to_string(),
873            }),
874        }
875    }
876}
877
878impl TryFrom<Value> for i64 {
879    type Error = ValueError;
880    fn try_from(v: Value) -> Result<Self, Self::Error> {
881        match v {
882            Value::Int(i) => Ok(i),
883            other => Err(ValueError {
884                expected: "int",
885                found: other.type_value().name.to_string(),
886            }),
887        }
888    }
889}
890
891impl TryFrom<&Value> for i64 {
892    type Error = ValueError;
893    fn try_from(v: &Value) -> Result<Self, Self::Error> {
894        match v {
895            Value::Int(i) => Ok(*i),
896            other => Err(ValueError {
897                expected: "int",
898                found: other.type_value().name.to_string(),
899            }),
900        }
901    }
902}
903
904impl TryFrom<Value> for u64 {
905    type Error = ValueError;
906    fn try_from(v: Value) -> Result<Self, Self::Error> {
907        match v {
908            Value::UInt(u) => Ok(u),
909            other => Err(ValueError {
910                expected: "uint",
911                found: other.type_value().name.to_string(),
912            }),
913        }
914    }
915}
916
917impl TryFrom<&Value> for u64 {
918    type Error = ValueError;
919    fn try_from(v: &Value) -> Result<Self, Self::Error> {
920        match v {
921            Value::UInt(u) => Ok(*u),
922            other => Err(ValueError {
923                expected: "uint",
924                found: other.type_value().name.to_string(),
925            }),
926        }
927    }
928}
929
930impl TryFrom<Value> for f64 {
931    type Error = ValueError;
932    fn try_from(v: Value) -> Result<Self, Self::Error> {
933        match v {
934            Value::Double(d) => Ok(d),
935            other => Err(ValueError {
936                expected: "double",
937                found: other.type_value().name.to_string(),
938            }),
939        }
940    }
941}
942
943impl TryFrom<&Value> for f64 {
944    type Error = ValueError;
945    fn try_from(v: &Value) -> Result<Self, Self::Error> {
946        match v {
947            Value::Double(d) => Ok(*d),
948            other => Err(ValueError {
949                expected: "double",
950                found: other.type_value().name.to_string(),
951            }),
952        }
953    }
954}
955
956impl TryFrom<Value> for String {
957    type Error = ValueError;
958    fn try_from(v: Value) -> Result<Self, Self::Error> {
959        match v {
960            Value::String(s) => Ok(s.to_string()),
961            other => Err(ValueError {
962                expected: "string",
963                found: other.type_value().name.to_string(),
964            }),
965        }
966    }
967}
968
969impl<'a> TryFrom<&'a Value> for &'a str {
970    type Error = ValueError;
971    fn try_from(v: &'a Value) -> Result<Self, Self::Error> {
972        match v {
973            Value::String(s) => Ok(s),
974            other => Err(ValueError {
975                expected: "string",
976                found: other.type_value().name.to_string(),
977            }),
978        }
979    }
980}
981
982impl<'a> TryFrom<&'a Value> for &'a [u8] {
983    type Error = ValueError;
984    fn try_from(v: &'a Value) -> Result<Self, Self::Error> {
985        match v {
986            Value::Bytes(b) => Ok(b),
987            other => Err(ValueError {
988                expected: "bytes",
989                found: other.type_value().name.to_string(),
990            }),
991        }
992    }
993}
994
995impl TryFrom<Value> for Timestamp {
996    type Error = ValueError;
997    fn try_from(v: Value) -> Result<Self, Self::Error> {
998        match v {
999            Value::Timestamp(t) => Ok(t),
1000            other => Err(ValueError {
1001                expected: "timestamp",
1002                found: other.type_value().name.to_string(),
1003            }),
1004        }
1005    }
1006}
1007
1008impl TryFrom<&Value> for Timestamp {
1009    type Error = ValueError;
1010    fn try_from(v: &Value) -> Result<Self, Self::Error> {
1011        match v {
1012            Value::Timestamp(t) => Ok(*t),
1013            other => Err(ValueError {
1014                expected: "timestamp",
1015                found: other.type_value().name.to_string(),
1016            }),
1017        }
1018    }
1019}
1020
1021impl TryFrom<Value> for Duration {
1022    type Error = ValueError;
1023    fn try_from(v: Value) -> Result<Self, Self::Error> {
1024        match v {
1025            Value::Duration(d) => Ok(d),
1026            other => Err(ValueError {
1027                expected: "duration",
1028                found: other.type_value().name.to_string(),
1029            }),
1030        }
1031    }
1032}
1033
1034impl TryFrom<&Value> for Duration {
1035    type Error = ValueError;
1036    fn try_from(v: &Value) -> Result<Self, Self::Error> {
1037        match v {
1038            Value::Duration(d) => Ok(*d),
1039            other => Err(ValueError {
1040                expected: "duration",
1041                found: other.type_value().name.to_string(),
1042            }),
1043        }
1044    }
1045}
1046
1047impl<'a> TryFrom<&'a Value> for &'a [Value] {
1048    type Error = ValueError;
1049    fn try_from(v: &'a Value) -> Result<Self, Self::Error> {
1050        match v {
1051            Value::List(l) => Ok(l),
1052            other => Err(ValueError {
1053                expected: "list",
1054                found: other.type_value().name.to_string(),
1055            }),
1056        }
1057    }
1058}
1059
1060impl<'a> TryFrom<&'a Value> for &'a ValueMap {
1061    type Error = ValueError;
1062    fn try_from(v: &'a Value) -> Result<Self, Self::Error> {
1063        match v {
1064            Value::Map(m) => Ok(m.as_ref()),
1065            other => Err(ValueError {
1066                expected: "map",
1067                found: other.type_value().name.to_string(),
1068            }),
1069        }
1070    }
1071}
1072
1073impl<'a> TryFrom<&'a Value> for &'a OptionalValue {
1074    type Error = ValueError;
1075    fn try_from(v: &'a Value) -> Result<Self, Self::Error> {
1076        match v {
1077            Value::Optional(o) => Ok(o),
1078            other => Err(ValueError {
1079                expected: "optional",
1080                found: other.type_value().name.to_string(),
1081            }),
1082        }
1083    }
1084}
1085
1086impl<'a> TryFrom<&'a Value> for &'a EvalError {
1087    type Error = ValueError;
1088    fn try_from(v: &'a Value) -> Result<Self, Self::Error> {
1089        match v {
1090            Value::Error(e) => Ok(e.as_ref()),
1091            other => Err(ValueError {
1092                expected: "error",
1093                found: other.type_value().name.to_string(),
1094            }),
1095        }
1096    }
1097}
1098
1099// ==================== Type Information ====================
1100
1101impl Value {
1102    /// Get the CEL type of this value.
1103    pub fn cel_type(&self) -> CelType {
1104        match self {
1105            Value::Null => CelType::Null,
1106            Value::Bool(_) => CelType::Bool,
1107            Value::Int(_) => CelType::Int,
1108            Value::UInt(_) => CelType::UInt,
1109            Value::Double(_) => CelType::Double,
1110            Value::String(_) => CelType::String,
1111            Value::Bytes(_) => CelType::Bytes,
1112            Value::List(_) => CelType::list(CelType::Dyn),
1113            Value::Map(_) => CelType::map(CelType::Dyn, CelType::Dyn),
1114            Value::Timestamp(_) => CelType::Timestamp,
1115            Value::Duration(_) => CelType::Duration,
1116            Value::Type(_) => CelType::type_of(CelType::Dyn),
1117            Value::Optional(opt) => match opt {
1118                OptionalValue::None => CelType::optional(CelType::Dyn),
1119                OptionalValue::Some(v) => CelType::optional(v.cel_type()),
1120            },
1121            Value::Message(msg) => CelType::message(msg.type_name()),
1122            Value::Enum(ev) => CelType::enum_type(&ev.type_name),
1123            Value::Error(_) => CelType::Error,
1124        }
1125    }
1126
1127    /// Get the CEL type value for this value (for the `type()` function).
1128    pub fn type_value(&self) -> TypeValue {
1129        match self {
1130            Value::Null => TypeValue::null_type(),
1131            Value::Bool(_) => TypeValue::bool_type(),
1132            Value::Int(_) => TypeValue::int_type(),
1133            Value::UInt(_) => TypeValue::uint_type(),
1134            Value::Double(_) => TypeValue::double_type(),
1135            Value::String(_) => TypeValue::string_type(),
1136            Value::Bytes(_) => TypeValue::bytes_type(),
1137            Value::List(_) => TypeValue::list_type(),
1138            Value::Map(_) => TypeValue::map_type(),
1139            Value::Timestamp(_) => TypeValue::timestamp_type(),
1140            Value::Duration(_) => TypeValue::duration_type(),
1141            Value::Type(_) => TypeValue::type_type(),
1142            Value::Optional(_) => TypeValue::new("optional"),
1143            Value::Message(msg) => TypeValue::new(msg.type_name()),
1144            Value::Enum(ev) => TypeValue::new(ev.type_name.as_ref()),
1145            Value::Error(_) => TypeValue::new("error"),
1146        }
1147    }
1148
1149    /// Check if this value is an error.
1150    pub fn is_error(&self) -> bool {
1151        matches!(self, Value::Error(_))
1152    }
1153
1154    /// Check if this value is null.
1155    pub fn is_null(&self) -> bool {
1156        matches!(self, Value::Null)
1157    }
1158
1159    /// Check if this value is truthy (for bool values).
1160    ///
1161    /// Returns Some(true) for proto messages since they are always truthy.
1162    pub fn is_truthy(&self) -> Option<bool> {
1163        match self {
1164            Value::Bool(b) => Some(*b),
1165            Value::Message(_) => Some(true), // Proto messages are always truthy
1166            _ => None,
1167        }
1168    }
1169}
1170
1171// ==================== Equality ====================
1172
1173impl PartialEq for Value {
1174    fn eq(&self, other: &Self) -> bool {
1175        match (self, other) {
1176            (Value::Null, Value::Null) => true,
1177            (Value::Bool(a), Value::Bool(b)) => a == b,
1178            (Value::Int(a), Value::Int(b)) => a == b,
1179            (Value::UInt(a), Value::UInt(b)) => a == b,
1180            (Value::Double(a), Value::Double(b)) => {
1181                // CEL follows IEEE 754 semantics: NaN != NaN
1182                a == b
1183            }
1184            (Value::String(a), Value::String(b)) => a == b,
1185            (Value::Bytes(a), Value::Bytes(b)) => a == b,
1186            (Value::List(a), Value::List(b)) => a == b,
1187            (Value::Map(a), Value::Map(b)) => {
1188                if a.len() != b.len() {
1189                    return false;
1190                }
1191                for (key, val_a) in a.iter() {
1192                    match b.get_with_numeric_coercion(key) {
1193                        Some(val_b) if val_a == val_b => continue,
1194                        _ => return false,
1195                    }
1196                }
1197                true
1198            }
1199            (Value::Timestamp(a), Value::Timestamp(b)) => a == b,
1200            (Value::Duration(a), Value::Duration(b)) => a == b,
1201            (Value::Type(a), Value::Type(b)) => a == b,
1202            (Value::Optional(a), Value::Optional(b)) => match (a, b) {
1203                (OptionalValue::None, OptionalValue::None) => true,
1204                (OptionalValue::Some(va), OptionalValue::Some(vb)) => va == vb,
1205                _ => false,
1206            },
1207            (Value::Message(a), Value::Message(b)) => a.eq_message(b.as_ref()),
1208            (Value::Enum(a), Value::Enum(b)) => a == b,
1209            // Cross-type numeric equality (CEL spec: 42 == 42u == 42.0)
1210            (Value::Int(a), Value::UInt(b)) => {
1211                if *a < 0 {
1212                    false
1213                } else {
1214                    *a as u64 == *b
1215                }
1216            }
1217            (Value::UInt(a), Value::Int(b)) => {
1218                if *b < 0 {
1219                    false
1220                } else {
1221                    *a == *b as u64
1222                }
1223            }
1224            (Value::Int(a), Value::Double(b)) => {
1225                if b.is_nan() {
1226                    return false;
1227                }
1228                let a_f64 = *a as f64;
1229                a_f64 == *b && a_f64 as i64 == *a
1230            }
1231            (Value::Double(a), Value::Int(b)) => {
1232                if a.is_nan() {
1233                    return false;
1234                }
1235                let b_f64 = *b as f64;
1236                *a == b_f64 && b_f64 as i64 == *b
1237            }
1238            (Value::UInt(a), Value::Double(b)) => {
1239                if b.is_nan() {
1240                    return false;
1241                }
1242                let a_f64 = *a as f64;
1243                a_f64 == *b && a_f64 as u64 == *a
1244            }
1245            (Value::Double(a), Value::UInt(b)) => {
1246                if a.is_nan() {
1247                    return false;
1248                }
1249                let b_f64 = *b as f64;
1250                *a == b_f64 && b_f64 as u64 == *b
1251            }
1252            // Enum-numeric cross-type equality (CEL spec: enums compare as their int value)
1253            (Value::Enum(e), Value::Int(i)) | (Value::Int(i), Value::Enum(e)) => {
1254                e.value as i64 == *i
1255            }
1256            (Value::Enum(e), Value::UInt(u)) | (Value::UInt(u), Value::Enum(e)) => {
1257                if e.value < 0 {
1258                    false
1259                } else {
1260                    e.value as u64 == *u
1261                }
1262            }
1263            (Value::Enum(e), Value::Double(d)) | (Value::Double(d), Value::Enum(e)) => {
1264                if d.is_nan() {
1265                    return false;
1266                }
1267                let e_f64 = e.value as f64;
1268                e_f64 == *d && e_f64 as i32 == e.value
1269            }
1270            _ => false,
1271        }
1272    }
1273}
1274
1275// ==================== Comparison ====================
1276
1277impl Value {
1278    /// Compare two values, returning an ordering if comparable.
1279    ///
1280    /// CEL supports comparison between values of the same type,
1281    /// and between numeric types (int, uint, double).
1282    pub fn compare(&self, other: &Value) -> Option<Ordering> {
1283        match (self, other) {
1284            (Value::Bool(a), Value::Bool(b)) => Some(a.cmp(b)),
1285            (Value::Int(a), Value::Int(b)) => Some(a.cmp(b)),
1286            (Value::UInt(a), Value::UInt(b)) => Some(a.cmp(b)),
1287            (Value::Double(a), Value::Double(b)) => a.partial_cmp(b),
1288            (Value::String(a), Value::String(b)) => Some(a.cmp(b)),
1289            (Value::Bytes(a), Value::Bytes(b)) => Some(a.cmp(b)),
1290            (Value::Timestamp(a), Value::Timestamp(b)) => {
1291                Some((a.seconds, a.nanos).cmp(&(b.seconds, b.nanos)))
1292            }
1293            (Value::Duration(a), Value::Duration(b)) => {
1294                Some((a.seconds, a.nanos).cmp(&(b.seconds, b.nanos)))
1295            }
1296            // Cross-numeric comparisons
1297            (Value::Int(a), Value::UInt(b)) => {
1298                if *a < 0 {
1299                    Some(Ordering::Less)
1300                } else {
1301                    (*a as u64).partial_cmp(b)
1302                }
1303            }
1304            (Value::UInt(a), Value::Int(b)) => {
1305                if *b < 0 {
1306                    Some(Ordering::Greater)
1307                } else {
1308                    a.partial_cmp(&(*b as u64))
1309                }
1310            }
1311            (Value::Int(a), Value::Double(b)) => (*a as f64).partial_cmp(b),
1312            (Value::Double(a), Value::Int(b)) => a.partial_cmp(&(*b as f64)),
1313            (Value::UInt(a), Value::Double(b)) => (*a as f64).partial_cmp(b),
1314            (Value::Double(a), Value::UInt(b)) => a.partial_cmp(&(*b as f64)),
1315            // Enum-numeric cross-type ordering
1316            (Value::Enum(e), Value::Int(i)) => (e.value as i64).partial_cmp(i),
1317            (Value::Int(i), Value::Enum(e)) => i.partial_cmp(&(e.value as i64)),
1318            (Value::Enum(e), Value::UInt(u)) => {
1319                if e.value < 0 {
1320                    Some(Ordering::Less)
1321                } else {
1322                    (e.value as u64).partial_cmp(u)
1323                }
1324            }
1325            (Value::UInt(u), Value::Enum(e)) => {
1326                if e.value < 0 {
1327                    Some(Ordering::Greater)
1328                } else {
1329                    u.partial_cmp(&(e.value as u64))
1330                }
1331            }
1332            (Value::Enum(e), Value::Double(d)) => (e.value as f64).partial_cmp(d),
1333            (Value::Double(d), Value::Enum(e)) => d.partial_cmp(&(e.value as f64)),
1334            _ => None,
1335        }
1336    }
1337}
1338
1339// ==================== Display ====================
1340
1341impl fmt::Display for Value {
1342    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1343        match self {
1344            Value::Null => write!(f, "null"),
1345            Value::Bool(v) => write!(f, "{}", v),
1346            Value::Int(v) => write!(f, "{}", v),
1347            Value::UInt(v) => write!(f, "{}u", v),
1348            Value::Double(v) => {
1349                if v.is_nan() {
1350                    write!(f, "NaN")
1351                } else if v.is_infinite() {
1352                    if v.is_sign_positive() {
1353                        write!(f, "+infinity")
1354                    } else {
1355                        write!(f, "-infinity")
1356                    }
1357                } else if v.fract() == 0.0 {
1358                    write!(f, "{}.0", v)
1359                } else {
1360                    write!(f, "{}", v)
1361                }
1362            }
1363            Value::String(v) => write!(f, "\"{}\"", v),
1364            Value::Bytes(v) => write!(f, "b\"{}\"", String::from_utf8_lossy(v)),
1365            Value::List(v) => {
1366                write!(f, "[")?;
1367                for (i, elem) in v.iter().enumerate() {
1368                    if i > 0 {
1369                        write!(f, ", ")?;
1370                    }
1371                    write!(f, "{}", elem)?;
1372                }
1373                write!(f, "]")
1374            }
1375            Value::Map(m) => {
1376                write!(f, "{{")?;
1377                for (i, (key, value)) in m.iter().enumerate() {
1378                    if i > 0 {
1379                        write!(f, ", ")?;
1380                    }
1381                    write!(f, "{}: {}", key.to_value(), value)?;
1382                }
1383                write!(f, "}}")
1384            }
1385            Value::Timestamp(t) => write!(f, "timestamp({})", t.seconds),
1386            Value::Duration(d) => write!(f, "duration({}s)", d.seconds),
1387            Value::Type(t) => write!(f, "type({})", t.name),
1388            Value::Optional(o) => match o {
1389                OptionalValue::None => write!(f, "optional.none()"),
1390                OptionalValue::Some(v) => write!(f, "optional.of({})", v),
1391            },
1392            Value::Message(m) => write!(f, "{}{{...}}", m.type_name()),
1393            Value::Enum(e) => write!(f, "{}({})", e.type_name, e.value),
1394            Value::Error(e) => write!(f, "error({})", e),
1395        }
1396    }
1397}
1398
1399#[cfg(test)]
1400mod tests {
1401    use super::*;
1402
1403    #[test]
1404    fn test_value_equality() {
1405        assert_eq!(Value::Int(42), Value::Int(42));
1406        assert_ne!(Value::Int(42), Value::Int(43));
1407        // Cross-type numeric equality: 42 == 42u
1408        assert_eq!(Value::Int(42), Value::UInt(42));
1409        assert_ne!(Value::Int(-1), Value::UInt(1));
1410        let hello: Value = "hello".into();
1411        assert_eq!(hello, "hello".into());
1412    }
1413
1414    #[test]
1415    fn test_value_comparison() {
1416        assert_eq!(Value::Int(1).compare(&Value::Int(2)), Some(Ordering::Less));
1417        assert_eq!(
1418            Value::Int(2).compare(&Value::Int(1)),
1419            Some(Ordering::Greater)
1420        );
1421        assert_eq!(Value::Int(1).compare(&Value::Int(1)), Some(Ordering::Equal));
1422
1423        // Cross-numeric comparison
1424        assert_eq!(
1425            Value::Int(-1).compare(&Value::UInt(1)),
1426            Some(Ordering::Less)
1427        );
1428        assert_eq!(
1429            Value::Int(1).compare(&Value::Double(1.5)),
1430            Some(Ordering::Less)
1431        );
1432    }
1433
1434    #[test]
1435    fn test_map_operations() {
1436        let mut map = ValueMap::new();
1437        map.insert(MapKey::String(Arc::from("key")), Value::Int(42));
1438
1439        assert_eq!(map.len(), 1);
1440        assert_eq!(
1441            map.get(&MapKey::String(Arc::from("key"))),
1442            Some(&Value::Int(42))
1443        );
1444        assert!(map.contains_key(&MapKey::String(Arc::from("key"))));
1445        assert!(!map.contains_key(&MapKey::String(Arc::from("other"))));
1446    }
1447
1448    #[test]
1449    fn test_map_key_from() {
1450        // From &str
1451        let key: MapKey = "hello".into();
1452        assert_eq!(key, MapKey::String(Arc::from("hello")));
1453
1454        // From String
1455        let key: MapKey = String::from("world").into();
1456        assert_eq!(key, MapKey::String(Arc::from("world")));
1457
1458        // From i64
1459        let key: MapKey = 42i64.into();
1460        assert_eq!(key, MapKey::Int(42));
1461
1462        // From u64
1463        let key: MapKey = 42u64.into();
1464        assert_eq!(key, MapKey::UInt(42));
1465
1466        // From bool
1467        let key: MapKey = true.into();
1468        assert_eq!(key, MapKey::Bool(true));
1469    }
1470
1471    #[test]
1472    fn test_value_map_ergonomic() {
1473        // Homogeneous string keys and values
1474        let map = Value::map([("a", "1"), ("b", "2")]);
1475        if let Value::Map(m) = &map {
1476            assert_eq!(m.len(), 2);
1477            assert_eq!(
1478                m.get(&MapKey::String(Arc::from("a"))),
1479                Some(&Value::String(Arc::from("1")))
1480            );
1481        } else {
1482            panic!("expected map");
1483        }
1484
1485        // Integer keys
1486        let map = Value::map([(1i64, "one"), (2i64, "two")]);
1487        if let Value::Map(m) = &map {
1488            assert_eq!(
1489                m.get(&MapKey::Int(1)),
1490                Some(&Value::String(Arc::from("one")))
1491            );
1492        } else {
1493            panic!("expected map");
1494        }
1495
1496        // Mixed value types with explicit Value::from
1497        let map = Value::map([("name", Value::from("Alice")), ("age", Value::from(30i64))]);
1498        if let Value::Map(m) = &map {
1499            assert_eq!(m.len(), 2);
1500        } else {
1501            panic!("expected map");
1502        }
1503    }
1504
1505    #[test]
1506    fn test_optional_value() {
1507        let none = OptionalValue::none();
1508        assert!(!none.is_present());
1509        assert!(none.as_value().is_none());
1510
1511        let some = OptionalValue::some(Value::Int(42));
1512        assert!(some.is_present());
1513        assert_eq!(some.as_value(), Some(&Value::Int(42)));
1514    }
1515
1516    #[test]
1517    fn test_timestamp_comparison() {
1518        let t1 = Timestamp::new(100, 0);
1519        let t2 = Timestamp::new(200, 0);
1520        let t3 = Timestamp::new(100, 500);
1521
1522        assert!(t1.is_before(&t2));
1523        assert!(t2.is_after(&t1));
1524        assert!(t1.is_before(&t3));
1525    }
1526
1527    #[test]
1528    fn test_duration_nanos() {
1529        let d = Duration::from_nanos(1_500_000_000);
1530        assert_eq!(d.seconds, 1);
1531        assert_eq!(d.nanos, 500_000_000);
1532        assert_eq!(d.to_nanos(), 1_500_000_000);
1533    }
1534
1535    #[test]
1536    fn test_cel_type() {
1537        assert_eq!(Value::Int(42).cel_type(), CelType::Int);
1538        let hello: Value = "hello".into();
1539        assert_eq!(hello.cel_type(), CelType::String);
1540        let list: Value = vec![Value::Int(1)].into();
1541        assert_eq!(list.cel_type(), CelType::list(CelType::Dyn));
1542    }
1543
1544    #[test]
1545    fn test_display() {
1546        assert_eq!(format!("{}", Value::Null), "null");
1547        assert_eq!(format!("{}", Value::Int(42)), "42");
1548        assert_eq!(format!("{}", Value::UInt(42)), "42u");
1549        let hello: Value = "hello".into();
1550        assert_eq!(format!("{}", hello), "\"hello\"");
1551        assert_eq!(format!("{}", Value::Bool(true)), "true");
1552    }
1553
1554    #[test]
1555    #[allow(clippy::approx_constant)]
1556    fn test_from_primitives() {
1557        let v: Value = true.into();
1558        assert_eq!(v, Value::Bool(true));
1559
1560        let v: Value = 42i64.into();
1561        assert_eq!(v, Value::Int(42));
1562
1563        let v: Value = 42u64.into();
1564        assert_eq!(v, Value::UInt(42));
1565
1566        let v: Value = 3.14f64.into();
1567        assert_eq!(v, Value::Double(3.14));
1568
1569        let v: Value = "hello".into();
1570        assert_eq!(v, Value::String(Arc::from("hello")));
1571
1572        let v: Value = String::from("world").into();
1573        assert_eq!(v, Value::String(Arc::from("world")));
1574    }
1575
1576    #[test]
1577    fn test_from_collections() {
1578        let v: Value = vec![Value::Int(1), Value::Int(2)].into();
1579        assert!(matches!(v, Value::List(_)));
1580
1581        let v: Value = vec![1u8, 2, 3].into();
1582        assert!(matches!(v, Value::Bytes(_)));
1583    }
1584
1585    #[test]
1586    #[allow(clippy::approx_constant)]
1587    fn test_try_from_success() {
1588        let v = Value::Int(42);
1589        let i: i64 = (&v).try_into().unwrap();
1590        assert_eq!(i, 42);
1591
1592        let v: Value = "hello".into();
1593        let s: &str = (&v).try_into().unwrap();
1594        assert_eq!(s, "hello");
1595
1596        let v = Value::Bool(true);
1597        let b: bool = (&v).try_into().unwrap();
1598        assert!(b);
1599
1600        let v = Value::UInt(100);
1601        let u: u64 = (&v).try_into().unwrap();
1602        assert_eq!(u, 100);
1603
1604        let v = Value::Double(3.14);
1605        let d: f64 = (&v).try_into().unwrap();
1606        assert_eq!(d, 3.14);
1607    }
1608
1609    #[test]
1610    fn test_try_from_error() {
1611        let v: Value = "hello".into();
1612        let result: Result<i64, ValueError> = (&v).try_into();
1613        assert!(result.is_err());
1614        let err = result.unwrap_err();
1615        assert_eq!(err.expected, "int");
1616        assert_eq!(err.found, "string");
1617    }
1618
1619    #[test]
1620    fn test_cel_value_to_value() {
1621        use crate::types::CelValue;
1622
1623        let cv = CelValue::String("test".to_string());
1624        let v: Value = cv.into();
1625        let s: &str = (&v).try_into().unwrap();
1626        assert_eq!(s, "test");
1627
1628        let cv = CelValue::Int(42);
1629        let v: Value = cv.into();
1630        assert_eq!(v, Value::Int(42));
1631
1632        let cv = CelValue::Null;
1633        let v: Value = cv.into();
1634        assert_eq!(v, Value::Null);
1635    }
1636
1637    #[test]
1638    fn test_try_from_timestamp() {
1639        let v = Value::Timestamp(Timestamp::new(1234567890, 0));
1640        let t: Timestamp = (&v).try_into().unwrap();
1641        assert_eq!(t.seconds, 1234567890);
1642
1643        // Owned conversion
1644        let v = Value::Timestamp(Timestamp::new(1234567890, 500));
1645        let t: Timestamp = v.try_into().unwrap();
1646        assert_eq!(t.nanos, 500);
1647
1648        let v: Value = "not a timestamp".into();
1649        let result: Result<Timestamp, ValueError> = (&v).try_into();
1650        assert!(result.is_err());
1651        let err = result.unwrap_err();
1652        assert_eq!(err.expected, "timestamp");
1653        assert_eq!(err.found, "string");
1654    }
1655
1656    #[test]
1657    fn test_try_from_duration() {
1658        let v = Value::Duration(Duration::new(60, 0));
1659        let d: Duration = (&v).try_into().unwrap();
1660        assert_eq!(d.seconds, 60);
1661
1662        // Owned conversion
1663        let v = Value::Duration(Duration::new(120, 500));
1664        let d: Duration = v.try_into().unwrap();
1665        assert_eq!(d.seconds, 120);
1666        assert_eq!(d.nanos, 500);
1667
1668        let v = Value::Int(42);
1669        let result: Result<Duration, ValueError> = (&v).try_into();
1670        assert!(result.is_err());
1671        let err = result.unwrap_err();
1672        assert_eq!(err.expected, "duration");
1673        assert_eq!(err.found, "int");
1674    }
1675
1676    #[test]
1677    fn test_try_from_list() {
1678        let v: Value = vec![Value::Int(1), Value::Int(2)].into();
1679        let list: &[Value] = (&v).try_into().unwrap();
1680        assert_eq!(list.len(), 2);
1681        assert_eq!(list[0], Value::Int(1));
1682        assert_eq!(list[1], Value::Int(2));
1683
1684        let v: Value = "not a list".into();
1685        let result: Result<&[Value], ValueError> = (&v).try_into();
1686        assert!(result.is_err());
1687        let err = result.unwrap_err();
1688        assert_eq!(err.expected, "list");
1689        assert_eq!(err.found, "string");
1690    }
1691
1692    #[test]
1693    fn test_try_from_map() {
1694        let v = Value::map([(MapKey::String("key".into()), Value::Int(42))]);
1695        let map: &ValueMap = (&v).try_into().unwrap();
1696        assert_eq!(map.len(), 1);
1697        assert_eq!(
1698            map.get(&MapKey::String("key".into())),
1699            Some(&Value::Int(42))
1700        );
1701
1702        let v: Value = "not a map".into();
1703        let result: Result<&ValueMap, ValueError> = (&v).try_into();
1704        assert!(result.is_err());
1705        let err = result.unwrap_err();
1706        assert_eq!(err.expected, "map");
1707        assert_eq!(err.found, "string");
1708    }
1709
1710    #[test]
1711    fn test_try_from_optional() {
1712        let v = Value::optional_some(Value::Int(42));
1713        let opt: &OptionalValue = (&v).try_into().unwrap();
1714        assert!(opt.is_present());
1715        assert_eq!(opt.as_value(), Some(&Value::Int(42)));
1716
1717        let v = Value::optional_none();
1718        let opt: &OptionalValue = (&v).try_into().unwrap();
1719        assert!(!opt.is_present());
1720
1721        let v = Value::Int(42);
1722        let result: Result<&OptionalValue, ValueError> = (&v).try_into();
1723        assert!(result.is_err());
1724        let err = result.unwrap_err();
1725        assert_eq!(err.expected, "optional");
1726        assert_eq!(err.found, "int");
1727    }
1728
1729    #[test]
1730    fn test_try_from_eval_error() {
1731        let v = Value::error(EvalError::division_by_zero());
1732        let err: &EvalError = (&v).try_into().unwrap();
1733        assert_eq!(err.message, "division by zero");
1734
1735        let v = Value::Int(42);
1736        let result: Result<&EvalError, ValueError> = (&v).try_into();
1737        assert!(result.is_err());
1738        let err = result.unwrap_err();
1739        assert_eq!(err.expected, "error");
1740        assert_eq!(err.found, "int");
1741    }
1742
1743    #[test]
1744    fn test_from_integer_widening() {
1745        // Signed integers widen to Value::Int
1746        let v: Value = 42i8.into();
1747        assert_eq!(v, Value::Int(42));
1748
1749        let v: Value = 42i16.into();
1750        assert_eq!(v, Value::Int(42));
1751
1752        let v: Value = 42i32.into();
1753        assert_eq!(v, Value::Int(42));
1754
1755        let v: Value = (42isize).into();
1756        assert_eq!(v, Value::Int(42));
1757
1758        // Unsigned integers widen to Value::UInt
1759        let v: Value = 42u8.into();
1760        assert_eq!(v, Value::UInt(42));
1761
1762        let v: Value = 42u16.into();
1763        assert_eq!(v, Value::UInt(42));
1764
1765        let v: Value = 42u32.into();
1766        assert_eq!(v, Value::UInt(42));
1767
1768        let v: Value = (42usize).into();
1769        assert_eq!(v, Value::UInt(42));
1770    }
1771
1772    #[test]
1773    fn test_map_key_from_i32_u32() {
1774        // From i32
1775        let key: MapKey = 42i32.into();
1776        assert_eq!(key, MapKey::Int(42));
1777
1778        // From u32
1779        let key: MapKey = 42u32.into();
1780        assert_eq!(key, MapKey::UInt(42));
1781    }
1782
1783    #[test]
1784    fn test_from_option() {
1785        // Some values convert to inner value
1786        let v: Value = Some(42).into();
1787        assert_eq!(v, Value::Int(42));
1788
1789        let v: Value = Some("hello").into();
1790        assert_eq!(v, Value::String(Arc::from("hello")));
1791
1792        // None converts to Null
1793        let v: Value = None::<i32>.into();
1794        assert_eq!(v, Value::Null);
1795
1796        let v: Value = None::<String>.into();
1797        assert_eq!(v, Value::Null);
1798
1799        // Nested options
1800        let v: Value = Some(Some(42)).into();
1801        assert_eq!(v, Value::Int(42));
1802    }
1803
1804    #[test]
1805    fn test_from_option_in_map() {
1806        let email: Option<String> = None;
1807        let name: Option<&str> = Some("Alice");
1808
1809        let user = Value::map([("email", Value::from(email)), ("name", Value::from(name))]);
1810
1811        if let Value::Map(m) = user {
1812            assert_eq!(m.get(&MapKey::from("email")), Some(&Value::Null));
1813            assert_eq!(
1814                m.get(&MapKey::from("name")),
1815                Some(&Value::String(Arc::from("Alice")))
1816            );
1817        } else {
1818            panic!("expected map");
1819        }
1820    }
1821
1822    #[test]
1823    fn test_enum_numeric_equality() {
1824        let enum_val = Value::Enum(EnumValue::new("test.MyEnum", 1));
1825
1826        // Enum == Int
1827        assert_eq!(enum_val, Value::Int(1));
1828        assert_eq!(Value::Int(1), enum_val);
1829        assert_ne!(enum_val, Value::Int(2));
1830
1831        // Enum == UInt
1832        assert_eq!(enum_val, Value::UInt(1));
1833        assert_eq!(Value::UInt(1), enum_val);
1834
1835        // Negative enum value != UInt
1836        let neg_enum = Value::Enum(EnumValue::new("test.MyEnum", -1));
1837        assert_ne!(neg_enum, Value::UInt(1));
1838
1839        // Enum == Double
1840        assert_eq!(enum_val, Value::Double(1.0));
1841        assert_eq!(Value::Double(1.0), enum_val);
1842        assert_ne!(enum_val, Value::Double(1.5));
1843
1844        // NaN != Enum
1845        assert_ne!(Value::Double(f64::NAN), enum_val);
1846
1847        // List membership: Int in [Enum] uses PartialEq
1848        let list = Value::List(Arc::from(vec![Value::Enum(EnumValue::new(
1849            "test.MyEnum",
1850            1,
1851        ))]));
1852        if let Value::List(items) = &list {
1853            assert!(items.contains(&Value::Int(1)));
1854        }
1855    }
1856
1857    #[test]
1858    fn test_enum_numeric_comparison() {
1859        let enum_val = Value::Enum(EnumValue::new("test.MyEnum", 5));
1860
1861        assert_eq!(enum_val.compare(&Value::Int(3)), Some(Ordering::Greater));
1862        assert_eq!(enum_val.compare(&Value::Int(5)), Some(Ordering::Equal));
1863        assert_eq!(enum_val.compare(&Value::Int(10)), Some(Ordering::Less));
1864
1865        assert_eq!(enum_val.compare(&Value::UInt(3)), Some(Ordering::Greater));
1866        assert_eq!(enum_val.compare(&Value::Double(5.0)), Some(Ordering::Equal));
1867
1868        // Negative enum vs UInt
1869        let neg_enum = Value::Enum(EnumValue::new("test.MyEnum", -1));
1870        assert_eq!(neg_enum.compare(&Value::UInt(0)), Some(Ordering::Less));
1871    }
1872
1873    #[test]
1874    fn test_value_from_option_cel_optional() {
1875        // from_option preserves CEL optional semantics
1876        let v = Value::from_option(Some(42));
1877        assert!(matches!(v, Value::Optional(OptionalValue::Some(_))));
1878
1879        let v = Value::from_option(None::<i32>);
1880        assert!(matches!(v, Value::Optional(OptionalValue::None)));
1881    }
1882}