Skip to main content

cu29_value/
lib.rs

1#![doc(html_root_url = "https://docs.rs/serde-value/0.7.0/")]
2#![cfg_attr(not(feature = "std"), no_std)]
3//! A Copper-oriented value tree used for serialization, logging, and reflection bridges.
4//!
5//! The type is a forked/adapted serde-value-style representation with Copper-specific
6//! additions such as [`Value::CuTime`].
7//!
8//! When the `python` feature is enabled, this crate also exposes helpers for converting
9//! between [`Value`] and Python objects through PyO3. Those helpers are used by:
10//!
11//! - `cu-python-task` for runtime prototyping across the Rust/Python boundary
12//! - `cu29-export` for offline Python log analysis
13//!
14//! The Python bridge is intentionally conservative:
15//!
16//! - `None` becomes [`Value::Unit`]
17//! - Python lists and tuples become [`Value::Seq`]
18//! - Python dicts become [`Value::Map`]
19//! - Python integers are accepted up to the 128-bit range
20//! - Python bytes become [`Value::Bytes`]
21
22extern crate alloc;
23
24use alloc::boxed::Box;
25use alloc::collections::BTreeMap;
26use alloc::string::String;
27use alloc::vec::Vec;
28
29use core::cmp::Ordering;
30use core::fmt::{Display, Formatter};
31use core::hash::{Hash, Hasher};
32use cu29_clock::CuTime;
33pub use cu29_value_types::{
34    Quantity, QuantityMetadata, RecordShape, Scalar, StorageUnit, TimeStorageUnit, ValueMetadata,
35};
36use ordered_float::OrderedFloat;
37use serde::Deserialize;
38
39#[cfg(feature = "decode-catalog")]
40pub mod catalog;
41#[cfg(any(feature = "self-describing-logs", feature = "decode-catalog"))]
42pub mod catalog_format;
43#[cfg(any(feature = "self-describing-logs", feature = "decode-catalog"))]
44#[doc(hidden)]
45pub mod catalog_stream;
46#[cfg(feature = "decode-catalog")]
47pub mod decode;
48#[cfg(feature = "decode-catalog")]
49mod metadata;
50
51mod bdec;
52mod benc;
53mod de;
54#[cfg(feature = "python")]
55mod python;
56mod ser;
57
58pub use de::*;
59#[cfg(feature = "python")]
60pub use python::{py_to_value, value_to_py};
61pub use ser::*;
62
63#[derive(Clone, Debug)]
64pub enum Value {
65    Bool(bool),
66
67    U8(u8),
68    U16(u16),
69    U32(u32),
70    U64(u64),
71    U128(u128),
72
73    I8(i8),
74    I16(i16),
75    I32(i32),
76    I64(i64),
77    I128(i128),
78
79    F32(f32),
80    F64(f64),
81
82    Char(char),
83    String(String),
84    Unit,
85    Option(Option<Box<Value>>),
86    Newtype(Box<Value>),
87    Seq(Vec<Value>),
88    Map(BTreeMap<Value, Value>),
89    Bytes(Vec<u8>),
90
91    CuTime(CuTime),
92}
93
94impl Display for Value {
95    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
96        match self {
97            Value::Bool(v) => write!(f, "{v}"),
98            Value::U8(v) => write!(f, "{v}"),
99            Value::U16(v) => write!(f, "{v}"),
100            Value::U32(v) => write!(f, "{v}"),
101            Value::U64(v) => write!(f, "{v}"),
102            Value::U128(v) => write!(f, "{v}"),
103            Value::I8(v) => write!(f, "{v}"),
104            Value::I16(v) => write!(f, "{v}"),
105            Value::I32(v) => write!(f, "{v}"),
106            Value::I64(v) => write!(f, "{v}"),
107            Value::I128(v) => write!(f, "{v}"),
108            Value::F32(v) => write!(f, "{v}"),
109            Value::F64(v) => write!(f, "{v}"),
110            Value::Char(v) => write!(f, "{v}"),
111            Value::String(v) => write!(f, "{v}"),
112            Value::Unit => write!(f, "()"),
113            Value::Option(v) => match v {
114                Some(v) => write!(f, "Some({v})"),
115                None => write!(f, "None"),
116            },
117            Value::Newtype(v) => write!(f, "{v}"),
118            Value::Seq(v) => {
119                write!(f, "[")?;
120                for (i, v) in v.iter().enumerate() {
121                    if i > 0 {
122                        write!(f, ", ")?;
123                    }
124                    write!(f, "{v}")?;
125                }
126                write!(f, "]")
127            }
128            Value::Map(v) => {
129                write!(f, "{{")?;
130                for (i, (k, v)) in v.iter().enumerate() {
131                    if i > 0 {
132                        write!(f, ", ")?;
133                    }
134                    write!(f, "{k}: {v}")?;
135                }
136                write!(f, "}}")
137            }
138            Value::Bytes(v) => {
139                write!(f, "[")?;
140                for (i, b) in v.iter().enumerate() {
141                    if i > 0 {
142                        write!(f, " ")?;
143                    }
144                    write!(f, "{b:02x}")?;
145                }
146                write!(f, "]")
147            }
148            Value::CuTime(v) => write!(f, "{v}"),
149        }
150    }
151}
152
153impl Hash for Value {
154    fn hash<H>(&self, hasher: &mut H)
155    where
156        H: Hasher,
157    {
158        self.discriminant().hash(hasher);
159        match *self {
160            Value::Bool(v) => v.hash(hasher),
161            Value::U8(v) => v.hash(hasher),
162            Value::U16(v) => v.hash(hasher),
163            Value::U32(v) => v.hash(hasher),
164            Value::U64(v) => v.hash(hasher),
165            Value::U128(v) => v.hash(hasher),
166            Value::I8(v) => v.hash(hasher),
167            Value::I16(v) => v.hash(hasher),
168            Value::I32(v) => v.hash(hasher),
169            Value::I64(v) => v.hash(hasher),
170            Value::I128(v) => v.hash(hasher),
171            Value::F32(v) => OrderedFloat(v).hash(hasher),
172            Value::F64(v) => OrderedFloat(v).hash(hasher),
173            Value::Char(v) => v.hash(hasher),
174            Value::String(ref v) => v.hash(hasher),
175            Value::Unit => 0_u8.hash(hasher),
176            Value::Option(ref v) => v.hash(hasher),
177            Value::Newtype(ref v) => v.hash(hasher),
178            Value::Seq(ref v) => v.hash(hasher),
179            Value::Map(ref v) => v.hash(hasher),
180            Value::Bytes(ref v) => v.hash(hasher),
181            Value::CuTime(v) => v.as_nanos().hash(hasher),
182        }
183    }
184}
185
186impl PartialEq for Value {
187    fn eq(&self, rhs: &Self) -> bool {
188        match (self, rhs) {
189            (&Value::Bool(v0), &Value::Bool(v1)) if v0 == v1 => true,
190            (&Value::U8(v0), &Value::U8(v1)) if v0 == v1 => true,
191            (&Value::U16(v0), &Value::U16(v1)) if v0 == v1 => true,
192            (&Value::U32(v0), &Value::U32(v1)) if v0 == v1 => true,
193            (&Value::U64(v0), &Value::U64(v1)) if v0 == v1 => true,
194            (&Value::U128(v0), &Value::U128(v1)) if v0 == v1 => true,
195            (&Value::I8(v0), &Value::I8(v1)) if v0 == v1 => true,
196            (&Value::I16(v0), &Value::I16(v1)) if v0 == v1 => true,
197            (&Value::I32(v0), &Value::I32(v1)) if v0 == v1 => true,
198            (&Value::I64(v0), &Value::I64(v1)) if v0 == v1 => true,
199            (&Value::I128(v0), &Value::I128(v1)) if v0 == v1 => true,
200            (&Value::F32(v0), &Value::F32(v1)) if OrderedFloat(v0) == OrderedFloat(v1) => true,
201            (&Value::F64(v0), &Value::F64(v1)) if OrderedFloat(v0) == OrderedFloat(v1) => true,
202            (&Value::Char(v0), &Value::Char(v1)) if v0 == v1 => true,
203            (Value::String(v0), Value::String(v1)) if v0 == v1 => true,
204            (&Value::Unit, &Value::Unit) => true,
205            (Value::Option(v0), Value::Option(v1)) if v0 == v1 => true,
206            (Value::Newtype(v0), Value::Newtype(v1)) if v0 == v1 => true,
207            (Value::Seq(v0), Value::Seq(v1)) if v0 == v1 => true,
208            (Value::Map(v0), Value::Map(v1)) if v0 == v1 => true,
209            (Value::Bytes(v0), Value::Bytes(v1)) if v0 == v1 => true,
210            (&Value::CuTime(v0), &Value::CuTime(v1)) if v0 == v1 => true,
211            _ => false,
212        }
213    }
214}
215
216impl Ord for Value {
217    fn cmp(&self, rhs: &Self) -> Ordering {
218        match (self, rhs) {
219            (&Value::Bool(v0), Value::Bool(v1)) => v0.cmp(v1),
220            (&Value::U8(v0), Value::U8(v1)) => v0.cmp(v1),
221            (&Value::U16(v0), Value::U16(v1)) => v0.cmp(v1),
222            (&Value::U32(v0), Value::U32(v1)) => v0.cmp(v1),
223            (&Value::U64(v0), Value::U64(v1)) => v0.cmp(v1),
224            (&Value::U128(v0), Value::U128(v1)) => v0.cmp(v1),
225            (&Value::I8(v0), Value::I8(v1)) => v0.cmp(v1),
226            (&Value::I16(v0), Value::I16(v1)) => v0.cmp(v1),
227            (&Value::I32(v0), Value::I32(v1)) => v0.cmp(v1),
228            (&Value::I64(v0), Value::I64(v1)) => v0.cmp(v1),
229            (&Value::I128(v0), Value::I128(v1)) => v0.cmp(v1),
230            (&Value::F32(v0), &Value::F32(v1)) => OrderedFloat(v0).cmp(&OrderedFloat(v1)),
231            (&Value::F64(v0), &Value::F64(v1)) => OrderedFloat(v0).cmp(&OrderedFloat(v1)),
232            (&Value::Char(v0), Value::Char(v1)) => v0.cmp(v1),
233            (Value::String(v0), Value::String(v1)) => v0.cmp(v1),
234            (&Value::Unit, &Value::Unit) => Ordering::Equal,
235            (Value::Option(v0), Value::Option(v1)) => v0.cmp(v1),
236            (Value::Newtype(v0), Value::Newtype(v1)) => v0.cmp(v1),
237            (Value::Seq(v0), Value::Seq(v1)) => v0.cmp(v1),
238            (Value::Map(v0), Value::Map(v1)) => v0.cmp(v1),
239            (Value::Bytes(v0), Value::Bytes(v1)) => v0.cmp(v1),
240            (&Value::CuTime(v0), &Value::CuTime(v1)) => v0.cmp(&v1),
241            (v0, v1) => v0.discriminant().cmp(&v1.discriminant()),
242        }
243    }
244}
245
246impl Value {
247    fn discriminant(&self) -> usize {
248        match *self {
249            Value::Bool(..) => 0,
250            Value::U8(..) => 1,
251            Value::U16(..) => 2,
252            Value::U32(..) => 3,
253            Value::U64(..) => 4,
254            Value::U128(..) => 19,
255            Value::I8(..) => 5,
256            Value::I16(..) => 6,
257            Value::I32(..) => 7,
258            Value::I64(..) => 8,
259            Value::I128(..) => 20,
260            Value::F32(..) => 9,
261            Value::F64(..) => 10,
262            Value::Char(..) => 11,
263            Value::String(..) => 12,
264            Value::Unit => 13,
265            Value::Option(..) => 14,
266            Value::Newtype(..) => 15,
267            Value::Seq(..) => 16,
268            Value::Map(..) => 17,
269            Value::Bytes(..) => 18,
270            Value::CuTime(..) => 32,
271        }
272    }
273
274    fn unexpected(&self) -> serde::de::Unexpected<'_> {
275        match *self {
276            Value::Bool(b) => serde::de::Unexpected::Bool(b),
277            Value::U8(n) => serde::de::Unexpected::Unsigned(n as u64),
278            Value::U16(n) => serde::de::Unexpected::Unsigned(n as u64),
279            Value::U32(n) => serde::de::Unexpected::Unsigned(n as u64),
280            Value::U64(n) => serde::de::Unexpected::Unsigned(n),
281            Value::U128(n) => match u64::try_from(n) {
282                Ok(n) => serde::de::Unexpected::Unsigned(n),
283                Err(_) => serde::de::Unexpected::Other("128-bit unsigned integer"),
284            },
285            Value::I8(n) => serde::de::Unexpected::Signed(n as i64),
286            Value::I16(n) => serde::de::Unexpected::Signed(n as i64),
287            Value::I32(n) => serde::de::Unexpected::Signed(n as i64),
288            Value::I64(n) => serde::de::Unexpected::Signed(n),
289            Value::I128(n) => match i64::try_from(n) {
290                Ok(n) => serde::de::Unexpected::Signed(n),
291                Err(_) => serde::de::Unexpected::Other("128-bit signed integer"),
292            },
293            Value::F32(n) => serde::de::Unexpected::Float(n as f64),
294            Value::F64(n) => serde::de::Unexpected::Float(n),
295            Value::Char(c) => serde::de::Unexpected::Char(c),
296            Value::String(ref s) => serde::de::Unexpected::Str(s),
297            Value::Unit => serde::de::Unexpected::Unit,
298            Value::Option(_) => serde::de::Unexpected::Option,
299            Value::Newtype(_) => serde::de::Unexpected::NewtypeStruct,
300            Value::Seq(_) => serde::de::Unexpected::Seq,
301            Value::Map(_) => serde::de::Unexpected::Map,
302            Value::Bytes(ref b) => serde::de::Unexpected::Bytes(b),
303            Value::CuTime(n) => serde::de::Unexpected::Unsigned(n.as_nanos()),
304        }
305    }
306
307    pub fn deserialize_into<'de, T: Deserialize<'de>>(self) -> Result<T, DeserializerError> {
308        T::deserialize(self)
309    }
310}
311
312impl Eq for Value {}
313impl PartialOrd for Value {
314    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
315        Some(self.cmp(rhs))
316    }
317}
318
319#[cfg(test)]
320mod tests {
321    use super::*;
322    #[cfg(not(feature = "std"))]
323    use alloc::borrow::ToOwned;
324    #[cfg(not(feature = "std"))]
325    use alloc::string::ToString;
326    #[cfg(not(feature = "std"))]
327    use alloc::vec;
328
329    use bincode::{borrow_decode_from_slice, config::standard, decode_from_slice, encode_to_vec};
330    use core::time::Duration;
331    use cu29_clock::{CuDuration, CuTime, RobotClock};
332    use serde_derive::{Deserialize, Serialize};
333
334    #[test]
335    fn de_smoke_test() {
336        // some convoluted Value
337        let value = Value::Option(Some(Box::new(Value::Seq(vec![
338            Value::U16(8),
339            Value::Char('a'),
340            Value::F32(1.0),
341            Value::String("hello".into()),
342            Value::Map(
343                vec![
344                    (Value::Bool(false), Value::Unit),
345                    (
346                        Value::Bool(true),
347                        Value::Newtype(Box::new(Value::Bytes(b"hi".as_ref().into()))),
348                    ),
349                ]
350                .into_iter()
351                .collect(),
352            ),
353        ]))));
354
355        // assert that the value remains unchanged through deserialization
356        let value_de = Value::deserialize(value.clone()).unwrap();
357        assert_eq!(value_de, value);
358    }
359
360    #[test]
361    fn ser_smoke_test() {
362        #[derive(Serialize, Deserialize)]
363        struct Foo {
364            a: u32,
365            b: String,
366            c: Vec<bool>,
367        }
368
369        let foo = Foo {
370            a: 15,
371            b: "hello".into(),
372            c: vec![true, false],
373        };
374
375        let expected = Value::Map(
376            vec![
377                (Value::String("a".into()), Value::U32(15)),
378                (Value::String("b".into()), Value::String("hello".into())),
379                (
380                    Value::String("c".into()),
381                    Value::Seq(vec![Value::Bool(true), Value::Bool(false)]),
382                ),
383            ]
384            .into_iter()
385            .collect(),
386        );
387
388        let value = to_value(&foo).unwrap();
389        assert_eq!(expected, value);
390    }
391
392    #[test]
393    fn deserialize_into_enum() {
394        #[derive(Deserialize, Debug, PartialEq, Eq)]
395        enum Foo {
396            Bar,
397            Baz(u8),
398        }
399
400        let value = Value::String("Bar".into());
401        assert_eq!(Foo::deserialize(value).unwrap(), Foo::Bar);
402
403        let value = Value::Map(
404            vec![(Value::String("Baz".into()), Value::U8(1))]
405                .into_iter()
406                .collect(),
407        );
408        assert_eq!(Foo::deserialize(value).unwrap(), Foo::Baz(1));
409    }
410
411    #[test]
412    fn serialize_from_enum() {
413        #[derive(Serialize, Deserialize)]
414        enum Foo {
415            Bar,
416            Baz(u8),
417            Qux { quux: u8 },
418            Corge(u8, u8),
419        }
420
421        let bar = Foo::Bar;
422        assert_eq!(to_value(&bar).unwrap(), Value::String("Bar".into()));
423
424        let baz = Foo::Baz(1);
425        assert_eq!(
426            to_value(&baz).unwrap(),
427            Value::Map(
428                vec![(Value::String("Baz".into()), Value::U8(1))]
429                    .into_iter()
430                    .collect(),
431            )
432        );
433
434        let qux = Foo::Qux { quux: 2 };
435        assert_eq!(
436            to_value(&qux).unwrap(),
437            Value::Map(
438                vec![(
439                    Value::String("Qux".into()),
440                    Value::Map(
441                        vec![(Value::String("quux".into()), Value::U8(2))]
442                            .into_iter()
443                            .collect()
444                    )
445                )]
446                .into_iter()
447                .collect()
448            )
449        );
450
451        let corge = Foo::Corge(3, 4);
452        assert_eq!(
453            to_value(&corge).unwrap(),
454            Value::Map(
455                vec![(
456                    Value::String("Corge".into()),
457                    Value::Seq(vec![Value::U8(3), Value::U8(4)])
458                )]
459                .into_iter()
460                .collect()
461            )
462        );
463    }
464
465    #[test]
466    fn deserialize_inside_deserialize_impl() {
467        #[derive(Debug, PartialEq, Eq)]
468        enum Event {
469            Added(u32),
470            Error(u8),
471        }
472
473        impl<'de> serde::Deserialize<'de> for Event {
474            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
475            where
476                D: serde::Deserializer<'de>,
477            {
478                #[derive(Deserialize)]
479                struct RawEvent {
480                    kind: String,
481                    object: Value,
482                }
483
484                let raw_event = RawEvent::deserialize(deserializer)?;
485
486                // Cannot directly use Value as Deserializer, since error type needs to be
487                // generic D::Error rather than specific serde_value::DeserializerError
488                let object_deserializer = ValueDeserializer::new(raw_event.object);
489
490                Ok(match &*raw_event.kind {
491                    "ADDED" => Event::Added(<_>::deserialize(object_deserializer)?),
492                    "ERROR" => Event::Error(<_>::deserialize(object_deserializer)?),
493                    kind => {
494                        return Err(serde::de::Error::unknown_variant(kind, &["ADDED", "ERROR"]));
495                    }
496                })
497            }
498        }
499
500        let input = Value::Map(
501            vec![
502                (
503                    Value::String("kind".to_owned()),
504                    Value::String("ADDED".to_owned()),
505                ),
506                (Value::String("object".to_owned()), Value::U32(5)),
507            ]
508            .into_iter()
509            .collect(),
510        );
511        let event = Event::deserialize(input).expect("could not deserialize ADDED event");
512        assert_eq!(event, Event::Added(5));
513
514        let input = Value::Map(
515            vec![
516                (
517                    Value::String("kind".to_owned()),
518                    Value::String("ERROR".to_owned()),
519                ),
520                (Value::String("object".to_owned()), Value::U8(5)),
521            ]
522            .into_iter()
523            .collect(),
524        );
525        let event = Event::deserialize(input).expect("could not deserialize ERROR event");
526        assert_eq!(event, Event::Error(5));
527
528        let input = Value::Map(
529            vec![
530                (
531                    Value::String("kind".to_owned()),
532                    Value::String("ADDED".to_owned()),
533                ),
534                (Value::String("object".to_owned()), Value::Unit),
535            ]
536            .into_iter()
537            .collect(),
538        );
539        let _ =
540            Event::deserialize(input).expect_err("expected deserializing bad ADDED event to fail");
541    }
542
543    #[test]
544    fn deserialize_newtype() {
545        #[derive(Debug, Deserialize, PartialEq)]
546        struct Foo(i32);
547
548        let input = Value::I32(5);
549        let foo = Foo::deserialize(input).unwrap();
550        assert_eq!(foo, Foo(5));
551    }
552
553    #[test]
554    fn deserialize_newtype2() {
555        #[derive(Debug, Deserialize, PartialEq)]
556        struct Foo(i32);
557
558        #[derive(Debug, Deserialize, PartialEq)]
559        struct Bar {
560            foo: Foo,
561        }
562
563        let input = Value::Map(
564            vec![(Value::String("foo".to_owned()), Value::I32(5))]
565                .into_iter()
566                .collect(),
567        );
568        let bar = Bar::deserialize(input).unwrap();
569        assert_eq!(bar, Bar { foo: Foo(5) });
570    }
571
572    #[test]
573    fn clock_ser_deser() {
574        let (clock, mock) = RobotClock::mock();
575        mock.increment(CuDuration::from_nanos(42));
576        let c = clock.now();
577
578        let input = Value::CuTime(c);
579        let foo = CuTime::deserialize(input).unwrap();
580        assert_eq!(foo, CuTime::from(Duration::from_nanos(42)));
581    }
582    #[test]
583    fn value_encode_decode() {
584        fn check_value(value: Value) {
585            let v = bincode::encode_to_vec(&value, standard()).expect("encode failed");
586            let (v2, s) = bincode::decode_from_slice::<Value, _>(v.as_slice(), standard())
587                .expect("decode failed");
588            assert_eq!(s, v.len());
589            assert_eq!(&v2, &value);
590        }
591
592        check_value(Value::Bool(true));
593        check_value(Value::U8(42));
594        check_value(Value::U16(42));
595        check_value(Value::U32(42));
596        check_value(Value::U64(42));
597        check_value(Value::U128(u128::from(u64::MAX) + 42));
598        check_value(Value::I8(42));
599        check_value(Value::I16(42));
600        check_value(Value::I32(42));
601        check_value(Value::I64(42));
602        check_value(Value::I128(i128::from(i64::MIN) - 42));
603        check_value(Value::F32(42.42));
604        check_value(Value::F64(42.42));
605        check_value(Value::Char('4'));
606        check_value(Value::String("42".into()));
607        check_value(Value::Unit);
608        check_value(Value::Option(Some(Box::new(Value::U32(42)))));
609        check_value(Value::Newtype(Box::new(Value::U32(42))));
610        check_value(Value::Seq(vec![Value::Bool(true), Value::U32(42)]));
611        check_value(Value::Map(BTreeMap::from([
612            (Value::Bool(true), Value::U32(42)),
613            (Value::String("42".into()), Value::I32(42)),
614        ])));
615        check_value(Value::Bytes(vec![0x4, 0x2]));
616        check_value(Value::CuTime(CuTime::from(Duration::from_nanos(42))));
617    }
618
619    #[test]
620    fn value_borrow_decode() {
621        fn check_value(value: Value) {
622            let encoded = encode_to_vec(&value, standard()).expect("encode failed");
623            let (decoded, size) =
624                borrow_decode_from_slice::<Value, _>(encoded.as_slice(), standard())
625                    .expect("borrow decode failed");
626            assert_eq!(size, encoded.len());
627            assert_eq!(decoded, value);
628        }
629
630        check_value(Value::Bool(true));
631        check_value(Value::U128(u128::from(u64::MAX) + 7));
632        check_value(Value::I128(i128::from(i64::MIN) - 7));
633        check_value(Value::String("borrow".into()));
634        check_value(Value::Bytes(vec![1, 2, 3]));
635        check_value(Value::CuTime(CuTime::from(Duration::from_nanos(42))));
636    }
637
638    #[test]
639    fn test_cutime_tovalue() {
640        let c = CuTime::from(Duration::from_nanos(42));
641        let v = to_value(c).expect("to_value failed");
642        assert_eq!(v, Value::CuTime(c));
643    }
644    /// Test basic value creation and type checking
645    #[test]
646    fn test_value_creation_and_types() {
647        // Create various value types
648        let bool_val = Value::Bool(true);
649        let i32_val = Value::I32(42);
650        let str_val = Value::String("test".to_string());
651        let unit_val = Value::Unit;
652        let option_val = Value::Option(Some(Box::new(Value::U8(5))));
653
654        // Verify type discrimination
655        assert!(matches!(bool_val, Value::Bool(true)));
656        assert!(matches!(i32_val, Value::I32(42)));
657        assert!(matches!(str_val, Value::String(ref s) if s == "test"));
658        assert!(matches!(unit_val, Value::Unit));
659        assert!(matches!(option_val, Value::Option(Some(_))));
660
661        // Check discriminant values
662        assert_eq!(bool_val.discriminant(), 0);
663        assert_eq!(i32_val.discriminant(), 7);
664        assert_eq!(str_val.discriminant(), 12);
665    }
666
667    /// Test numeric boundary values and special floating points
668    #[test]
669    fn test_numeric_boundaries_and_special_values() {
670        // Integer boundaries
671        let min_i8 = Value::I8(i8::MIN);
672        let max_i8 = Value::I8(i8::MAX);
673        let min_i64 = Value::I64(i64::MIN);
674        let max_u64 = Value::U64(u64::MAX);
675        let min_i128 = Value::I128(i128::MIN);
676        let max_u128 = Value::U128(u128::MAX);
677
678        // Special floating points
679        let nan = Value::F64(f64::NAN);
680        let pos_inf = Value::F64(f64::INFINITY);
681        let neg_inf = Value::F64(f64::NEG_INFINITY);
682        let zero = Value::F64(0.0);
683        let neg_zero = Value::F64(-0.0);
684
685        // Make sure these encode and decode correctly
686        for val in [
687            min_i8,
688            max_i8,
689            min_i64,
690            max_u64,
691            min_i128,
692            max_u128,
693            nan.clone(),
694            pos_inf.clone(),
695            neg_inf.clone(),
696            zero.clone(),
697            neg_zero.clone(),
698        ] {
699            let encoded = encode_to_vec(&val, standard()).unwrap();
700            let (decoded, _): (Value, _) = decode_from_slice(&encoded, standard()).unwrap();
701
702            // Special case for NaN since NaN != NaN in normal floating point comparisons
703            if matches!(val, Value::F64(f) if f.is_nan()) {
704                assert!(matches!(decoded, Value::F64(f) if f.is_nan()));
705            } else {
706                assert_eq!(val, decoded);
707            }
708        }
709
710        // Test ordering behavior with special values
711        assert!(pos_inf > zero);
712        assert!(neg_inf < zero);
713
714        // NaN should be equal to itself when wrapped in Value (due to OrderedFloat)
715        let nan2 = Value::F64(f64::NAN);
716        assert_eq!(nan, nan2); // This works because Value uses OrderedFloat
717
718        // Verify zero and negative zero are treated as equal
719        assert_eq!(zero, neg_zero);
720    }
721
722    /// Test handling of containers (maps, sequences)
723    #[test]
724    fn test_container_types() {
725        // Empty containers
726        let empty_seq = Value::Seq(vec![]);
727        let empty_map = Value::Map(BTreeMap::new());
728
729        // Simple containers
730        let simple_seq = Value::Seq(vec![Value::I32(1), Value::I32(2), Value::I32(3)]);
731        let mut simple_map = BTreeMap::new();
732        simple_map.insert(Value::String("key".to_string()), Value::Bool(true));
733        let simple_map_val = Value::Map(simple_map);
734
735        // Deeply nested containers
736        let mut nested_map = BTreeMap::new();
737        nested_map.insert(
738            Value::String("outer".to_string()),
739            Value::Seq(vec![
740                Value::Option(Some(Box::new(Value::Map({
741                    let mut m = BTreeMap::new();
742                    m.insert(Value::I32(1), Value::String("nested".to_string()));
743                    m
744                })))),
745                Value::Bool(false),
746            ]),
747        );
748        let nested_val = Value::Map(nested_map);
749
750        // Encode and decode all container types
751        for val in [empty_seq, empty_map, simple_seq, simple_map_val, nested_val] {
752            let encoded = encode_to_vec(&val, standard()).unwrap();
753            let (decoded, _): (Value, _) = decode_from_slice(&encoded, standard()).unwrap();
754            assert_eq!(val, decoded);
755        }
756    }
757
758    /// Test handling of large values
759    #[test]
760    fn test_large_values() {
761        // Large sequence
762        let large_seq = Value::Seq((0..10000).map(Value::I32).collect());
763
764        // Large string
765        let large_string = Value::String("x".repeat(100000));
766
767        // Large bytes
768        let large_bytes = Value::Bytes((0..10000).map(|i| (i % 256) as u8).collect());
769
770        // Large nested structure
771        let mut large_map = BTreeMap::new();
772        for i in 0..1000 {
773            large_map.insert(
774                Value::I32(i),
775                Value::Seq((0..10).map(|j| Value::I32(i * j)).collect()),
776            );
777        }
778        let large_nested = Value::Map(large_map);
779
780        // Test round-trip for large values
781        for val in [large_seq, large_string, large_bytes, large_nested] {
782            let encoded = encode_to_vec(&val, standard()).unwrap();
783            let (decoded, _): (Value, _) = decode_from_slice(&encoded, standard()).unwrap();
784            assert_eq!(val, decoded);
785        }
786    }
787
788    /// Test value comparison across different types
789    #[test]
790    fn test_value_comparison() {
791        // Same type comparisons
792        assert!(Value::I32(1) < Value::I32(2));
793        assert!(Value::String("a".to_string()) < Value::String("b".to_string()));
794        assert!(Value::Bool(false) < Value::Bool(true));
795
796        // Different type comparisons (based on discriminant)
797        assert!(Value::Bool(true) < Value::I32(0)); // Bool(0) < I32(7) by discriminant
798        assert!(Value::I32(100) < Value::String("a".to_string())); // I32(7) < String(12)
799
800        // Container comparisons
801        assert!(
802            Value::Seq(vec![Value::I32(1), Value::I32(2)])
803                < Value::Seq(vec![Value::I32(1), Value::I32(3)])
804        );
805
806        let mut map1 = BTreeMap::new();
807        map1.insert(Value::String("key".to_string()), Value::I32(1));
808
809        let mut map2 = BTreeMap::new();
810        map2.insert(Value::String("key".to_string()), Value::I32(2));
811
812        assert!(Value::Map(map1) < Value::Map(map2));
813
814        // Test equality with NaN handling
815        let nan1 = Value::F64(f64::NAN);
816        let nan2 = Value::F64(f64::NAN);
817        assert_eq!(nan1, nan2); // OrderedFloat makes NaN == NaN
818    }
819
820    /// Test hash consistency for various value types
821    #[test]
822    #[cfg(feature = "std")]
823    fn test_value_hashing() {
824        use core::hash::Hasher;
825        use std::collections::hash_map::DefaultHasher;
826
827        let values = [
828            Value::Bool(true),
829            Value::I32(42),
830            Value::String("hash me".to_string()),
831            Value::F64(3.1),
832            Value::Char('🦀'),
833            Value::Option(Some(Box::new(Value::U8(5)))),
834            Value::Unit,
835        ];
836
837        for val in values {
838            // Hash the same value twice, should be consistent
839            let mut hasher1 = DefaultHasher::new();
840            let mut hasher2 = DefaultHasher::new();
841            val.hash(&mut hasher1);
842            val.hash(&mut hasher2);
843            assert_eq!(hasher1.finish(), hasher2.finish());
844
845            // Clone and hash, should be the same
846            let val_clone = val.clone();
847            let mut hasher3 = DefaultHasher::new();
848            val_clone.hash(&mut hasher3);
849            assert_eq!(hasher1.finish(), hasher3.finish());
850        }
851
852        // Special case: NaN should have consistent hash
853        let nan1 = Value::F64(f64::NAN);
854        let nan2 = Value::F64(f64::NAN);
855
856        let mut hasher1 = DefaultHasher::new();
857        let mut hasher2 = DefaultHasher::new();
858        nan1.hash(&mut hasher1);
859        nan2.hash(&mut hasher2);
860        assert_eq!(hasher1.finish(), hasher2.finish());
861    }
862
863    /// Test serialization/deserialization of custom data structures
864    #[test]
865    fn test_struct_serde() {
866        #[derive(Serialize, Deserialize, Debug, PartialEq)]
867        struct Person {
868            name: String,
869            age: u32,
870            addresses: Vec<Address>,
871        }
872
873        #[derive(Serialize, Deserialize, Debug, PartialEq)]
874        struct Address {
875            street: String,
876            city: String,
877            zip: u32,
878        }
879
880        let person = Person {
881            name: "Alice".to_string(),
882            age: 30,
883            addresses: vec![
884                Address {
885                    street: "123 Main St".to_string(),
886                    city: "Anytown".to_string(),
887                    zip: 12345,
888                },
889                Address {
890                    street: "456 Oak Ave".to_string(),
891                    city: "Somewhere".to_string(),
892                    zip: 67890,
893                },
894            ],
895        };
896
897        // Convert to Value
898        let value = to_value(&person).unwrap();
899
900        // Check structure
901        assert!(matches!(value, Value::Map(_)));
902
903        // Convert back to original type
904        let person2 = value.deserialize_into::<Person>().unwrap();
905        assert_eq!(person, person2);
906    }
907
908    /// Test enum serialization/deserialization
909    #[test]
910    fn test_enum_serde() {
911        #[derive(Serialize, Deserialize, Debug, PartialEq)]
912        enum MyEnum {
913            Unit,
914            NewType(i32),
915            Tuple(String, bool),
916            Struct { x: f64, y: f64 },
917        }
918
919        // Test all variants
920        let variants = vec![
921            MyEnum::Unit,
922            MyEnum::NewType(42),
923            MyEnum::Tuple("hello".to_string(), true),
924            MyEnum::Struct { x: 1.0, y: 2.0 },
925        ];
926
927        for variant in variants {
928            let value = to_value(&variant).unwrap();
929            let roundtrip = value.deserialize_into::<MyEnum>().unwrap();
930            assert_eq!(variant, roundtrip);
931        }
932    }
933
934    /// Test custom CuTime type handling
935    #[test]
936    fn test_cutime_handling() {
937        // Test round-trip for CuTime values
938        let times = vec![
939            CuTime::from(CuDuration(0)),
940            CuTime::from(CuDuration(1)),
941            CuTime::from(CuDuration(u64::MAX / 2)),
942            // Exclude MAX as it might be reserved for special use
943        ];
944
945        for time in times {
946            // Direct Value creation
947            let time_value = Value::CuTime(time);
948
949            // Serialize/deserialize as Value
950            let encoded = encode_to_vec(&time_value, standard()).unwrap();
951            let (decoded, _): (Value, _) = decode_from_slice(&encoded, standard()).unwrap();
952            assert_eq!(time_value, decoded);
953
954            // Convert through to_value
955            let via_to_value = to_value(time).unwrap();
956            assert_eq!(via_to_value, time_value);
957
958            // Deserialize back to CuTime
959            let time_roundtrip = via_to_value.deserialize_into::<CuTime>().unwrap();
960            assert_eq!(time, time_roundtrip);
961        }
962    }
963
964    /// Test error handling in deserialization
965    #[test]
966    fn test_error_handling() {
967        // Type mismatch
968        let bool_val = Value::Bool(true);
969        let result = bool_val.clone().deserialize_into::<i32>();
970        assert!(result.is_err());
971
972        // Missing fields
973        let empty_map = Value::Map(BTreeMap::new());
974
975        #[derive(Deserialize)]
976        struct RequiredFields {
977            _required: String,
978        }
979
980        let result = empty_map.deserialize_into::<RequiredFields>();
981        assert!(result.is_err());
982
983        // Invalid enum variant
984        let invalid_variant = Value::String("NonExistentVariant".to_string());
985
986        #[derive(Deserialize)]
987        enum TestEnum {
988            A,
989            B,
990            C,
991        }
992
993        let result = invalid_variant.deserialize_into::<TestEnum>();
994        assert!(result.is_err());
995
996        // Check we get appropriate error types
997        match bool_val.deserialize_into::<String>() {
998            Err(DeserializerError::InvalidType(..)) => (), // Expected
999            other => panic!("Expected InvalidType error, got: {other:?}"),
1000        }
1001    }
1002
1003    /// Test unicode handling in strings and chars
1004    #[test]
1005    fn test_unicode_handling() {
1006        let strings = vec![
1007            "".to_string(),             // Empty
1008            "ASCII only".to_string(),   // ASCII
1009            "Café 🍰".to_string(),      // Mixed ASCII and Unicode
1010            "日本語".to_string(),       // CJK characters
1011            "👨‍👩‍👧‍👦 Family".to_string(),    // Complex emoji with ZWJ sequences
1012            "ᛁᚲ ᚲᚨᚾ ᚱᚢᚾᛖᛋ".to_string(), // Ancient runes
1013        ];
1014
1015        for s in strings {
1016            let string_val = Value::String(s.clone());
1017
1018            // Test round-trip
1019            let encoded = encode_to_vec(&string_val, standard()).unwrap();
1020            let (decoded, _): (Value, _) = decode_from_slice(&encoded, standard()).unwrap();
1021
1022            if let Value::String(decoded_s) = decoded {
1023                assert_eq!(s, decoded_s);
1024            } else {
1025                panic!("Expected String value");
1026            }
1027        }
1028
1029        // Test various Unicode characters
1030        let chars = vec!['a', 'é', '日', '🦀'];
1031
1032        for c in chars {
1033            let char_val = Value::Char(c);
1034
1035            // Test round-trip
1036            let encoded = encode_to_vec(&char_val, standard()).unwrap();
1037            let (decoded, _): (Value, _) = decode_from_slice(&encoded, standard()).unwrap();
1038
1039            if let Value::Char(decoded_c) = decoded {
1040                assert_eq!(c, decoded_c);
1041            } else {
1042                panic!("Expected Char value");
1043            }
1044        }
1045    }
1046
1047    /// Test ValueDeserializer directly
1048    #[test]
1049    fn test_value_deserializer() {
1050        let original = vec![1, 2, 3];
1051        let value = to_value(&original).unwrap();
1052
1053        // Create a deserializer
1054        let deserializer: de::ValueDeserializer<DeserializerError> = ValueDeserializer::new(value);
1055
1056        // Use it to deserialize
1057        let result: Vec<i32> = serde::Deserialize::deserialize(deserializer).unwrap();
1058
1059        assert_eq!(original, result);
1060    }
1061
1062    /// Test serialization/deserialization with custom types and Option
1063    #[test]
1064    fn test_option_handling() {
1065        // Some values
1066        let some_i32 = Some(42);
1067        let some_string = Some("test".to_string());
1068
1069        // None values of different types
1070        let none_i32: Option<i32> = None;
1071        let none_string: Option<String> = None;
1072
1073        // Convert to Value
1074        let some_i32_value = to_value(some_i32).unwrap();
1075        let some_string_value = to_value(&some_string).unwrap();
1076        let none_i32_value = to_value(none_i32).unwrap();
1077        let none_string_value = to_value(&none_string).unwrap();
1078
1079        // Check structure
1080        assert!(matches!(some_i32_value, Value::Option(Some(_))));
1081        assert!(matches!(some_string_value, Value::Option(Some(_))));
1082        assert!(matches!(none_i32_value, Value::Option(None)));
1083        assert!(matches!(none_string_value, Value::Option(None)));
1084
1085        // Round-trip
1086        let some_i32_rt: Option<i32> = some_i32_value.deserialize_into().unwrap();
1087        let some_string_rt: Option<String> = some_string_value.deserialize_into().unwrap();
1088        let none_i32_rt: Option<i32> = none_i32_value.deserialize_into().unwrap();
1089        let none_string_rt: Option<String> = none_string_value.deserialize_into().unwrap();
1090
1091        assert_eq!(some_i32, some_i32_rt);
1092        assert_eq!(some_string, some_string_rt);
1093        assert_eq!(none_i32, none_i32_rt);
1094        assert_eq!(none_string, none_string_rt);
1095    }
1096
1097    /// Test deeply nested option values
1098    #[test]
1099    fn test_nested_options() {
1100        // Create deeply nested Option structure
1101        let nested_option: Option<Option<Option<i32>>> = Some(Some(Some(42)));
1102
1103        // Convert to Value
1104        let value = to_value(nested_option).unwrap();
1105
1106        // Verify structure
1107        let mut current = &value;
1108        for _ in 0..3 {
1109            assert!(matches!(current, Value::Option(Some(_))));
1110            if let Value::Option(Some(inner)) = current {
1111                current = inner;
1112            } else {
1113                panic!("Expected Some");
1114            }
1115        }
1116        assert!(matches!(current, Value::I32(42)));
1117
1118        // Round-trip test
1119        let result: Option<Option<Option<i32>>> = value.deserialize_into().unwrap();
1120        assert_eq!(nested_option, result);
1121    }
1122
1123    /// Test conversion behaviors between numeric types
1124    #[test]
1125    fn test_numeric_conversions() {
1126        // Create values of different numeric types
1127        let i8_val = Value::I8(42);
1128        let i16_val = Value::I16(42);
1129        let i32_val = Value::I32(42);
1130        let i64_val = Value::I64(42);
1131        let i128_val = Value::I128(42);
1132        let u8_val = Value::U8(42);
1133        let u16_val = Value::U16(42);
1134        let u32_val = Value::U32(42);
1135        let u64_val = Value::U64(42);
1136        let u64_val_large = Value::U64(u64::MAX);
1137        let u128_val = Value::U128(42);
1138        let u128_val_large = Value::U128(u128::from(u64::MAX) + 1);
1139        let f32_val = Value::F32(42.0);
1140        let f64_val = Value::F64(42.0);
1141
1142        // Test valid conversions
1143        // Note: Some of these might depend on implementation details
1144        assert!(i8_val.deserialize_into::<i16>().is_ok());
1145        assert!(i16_val.deserialize_into::<i32>().is_ok());
1146        assert!(i32_val.clone().deserialize_into::<i64>().is_ok());
1147        assert!(u8_val.deserialize_into::<u16>().is_ok());
1148        assert!(u16_val.deserialize_into::<u32>().is_ok());
1149        assert!(u32_val.deserialize_into::<u64>().is_ok());
1150        assert!(u64_val.clone().deserialize_into::<u128>().is_ok());
1151        assert!(u128_val.deserialize_into::<u128>().is_ok());
1152        assert!(u64_val.clone().deserialize_into::<f64>().is_ok());
1153        assert!(i32_val.deserialize_into::<f32>().is_ok());
1154        assert!(f32_val.deserialize_into::<f64>().is_ok());
1155        assert!(i64_val.clone().deserialize_into::<f64>().is_ok());
1156        assert!(i64_val.clone().deserialize_into::<i128>().is_ok());
1157        assert!(i128_val.deserialize_into::<i128>().is_ok());
1158        assert!(u64_val.deserialize_into::<i8>().is_ok());
1159
1160        // Test conversions that shouldn't work
1161        assert!(u64_val_large.deserialize_into::<i8>().is_err());
1162        assert!(u128_val_large.deserialize_into::<u64>().is_err());
1163        assert!(f64_val.deserialize_into::<u32>().is_err());
1164        assert!(i64_val.deserialize_into::<bool>().is_err());
1165    }
1166
1167    /// Test Display implementation
1168    #[test]
1169    fn test_display_implementation() {
1170        // Sample different value types and check their string representation
1171        let values = [
1172            (Value::Bool(true), "true"),
1173            (Value::I32(42), "42"),
1174            (Value::String("test".to_string()), "test"),
1175            (Value::Unit, "()"),
1176            (
1177                Value::CuTime(CuTime::from(CuDuration(1_000_000_000))),
1178                "1.000 s",
1179            ),
1180        ];
1181
1182        for (val, expected) in values {
1183            assert_eq!(val.to_string(), expected);
1184        }
1185
1186        // More complex values
1187        let seq = Value::Seq(vec![Value::I32(1), Value::I32(2), Value::I32(3)]);
1188        assert_eq!(seq.to_string(), "[1, 2, 3]");
1189
1190        let mut map = BTreeMap::new();
1191        map.insert(Value::String("key".to_string()), Value::Bool(true));
1192        let map_val = Value::Map(map);
1193        assert_eq!(map_val.to_string(), "{key: true}");
1194    }
1195    #[test]
1196    fn test_numeric_overflow_detection() {
1197        // Test overflow detection
1198        let large_i64 = Value::I64(i64::MAX);
1199        assert!(large_i64.deserialize_into::<i32>().is_err());
1200
1201        let large_u128 = Value::U128(u128::from(u64::MAX) + 1);
1202        assert!(large_u128.deserialize_into::<u64>().is_err());
1203
1204        // Test underflow detection
1205        let negative = Value::I64(-1);
1206        assert!(negative.deserialize_into::<u64>().is_err());
1207
1208        let negative_i128 = Value::I128(-1);
1209        assert!(negative_i128.deserialize_into::<u64>().is_err());
1210
1211        // Edge case: exactly at boundary
1212        let max_i32 = Value::I64(i32::MAX as i64);
1213        assert!(max_i32.deserialize_into::<i32>().is_ok());
1214
1215        // Edge case: one beyond boundary
1216        let beyond_max_i32 = Value::I64((i32::MAX as i64) + 1);
1217        assert!(beyond_max_i32.deserialize_into::<i32>().is_err());
1218    }
1219
1220    #[test]
1221    fn test_u128_and_i128_round_trip() {
1222        let u128_value = to_value(u128::from(u64::MAX) + 99).expect("to_value failed");
1223        assert_eq!(u128_value, Value::U128(u128::from(u64::MAX) + 99));
1224        let round_trip_u128: u128 = u128_value
1225            .deserialize_into()
1226            .expect("u128 round-trip failed");
1227        assert_eq!(round_trip_u128, u128::from(u64::MAX) + 99);
1228
1229        let i128_value = to_value(i128::from(i64::MIN) - 99).expect("to_value failed");
1230        assert_eq!(i128_value, Value::I128(i128::from(i64::MIN) - 99));
1231        let round_trip_i128: i128 = i128_value
1232            .deserialize_into()
1233            .expect("i128 round-trip failed");
1234        assert_eq!(round_trip_i128, i128::from(i64::MIN) - 99);
1235    }
1236
1237    #[test]
1238    fn test_float_precision_handling() {
1239        // Integer -> float -> integer round trip
1240        let original = i64::MAX;
1241        let as_value = Value::I64(original);
1242        let as_f64: f64 = as_value.deserialize_into().unwrap();
1243        let round_trip = Value::F64(as_f64).deserialize_into::<i64>();
1244
1245        // the round_trip should return Error since f64 cannot represent all i64 values
1246        assert!(round_trip.is_err());
1247
1248        // Fractional values to integers
1249        let half = Value::F64(0.5);
1250        let half_as_i32 = half.deserialize_into::<i32>();
1251        assert!(half_as_i32.is_err());
1252    }
1253
1254    #[test]
1255    fn test_float_special_values() {
1256        // NaN to integer
1257        let nan = Value::F64(f64::NAN);
1258        assert!(nan.deserialize_into::<i32>().is_err());
1259
1260        // Infinity to integer
1261        let infinity = Value::F64(f64::INFINITY);
1262        assert!(infinity.deserialize_into::<i64>().is_err());
1263
1264        // Huge values within float range but beyond integer range
1265        let huge = Value::F64(1e20);
1266        assert!(huge.deserialize_into::<i64>().is_err());
1267    }
1268}
1269
1270#[cfg(all(test, feature = "decode-catalog", feature = "self-describing-logs"))]
1271mod decode_tests;