1#![doc(html_root_url = "https://docs.rs/serde-value/0.7.0/")]
2#![cfg_attr(not(feature = "std"), no_std)]
3extern 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 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 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 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]
646 fn test_value_creation_and_types() {
647 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 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 assert_eq!(bool_val.discriminant(), 0);
663 assert_eq!(i32_val.discriminant(), 7);
664 assert_eq!(str_val.discriminant(), 12);
665 }
666
667 #[test]
669 fn test_numeric_boundaries_and_special_values() {
670 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 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 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 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 assert!(pos_inf > zero);
712 assert!(neg_inf < zero);
713
714 let nan2 = Value::F64(f64::NAN);
716 assert_eq!(nan, nan2); assert_eq!(zero, neg_zero);
720 }
721
722 #[test]
724 fn test_container_types() {
725 let empty_seq = Value::Seq(vec![]);
727 let empty_map = Value::Map(BTreeMap::new());
728
729 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 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 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]
760 fn test_large_values() {
761 let large_seq = Value::Seq((0..10000).map(Value::I32).collect());
763
764 let large_string = Value::String("x".repeat(100000));
766
767 let large_bytes = Value::Bytes((0..10000).map(|i| (i % 256) as u8).collect());
769
770 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 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]
790 fn test_value_comparison() {
791 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 assert!(Value::Bool(true) < Value::I32(0)); assert!(Value::I32(100) < Value::String("a".to_string())); 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 let nan1 = Value::F64(f64::NAN);
816 let nan2 = Value::F64(f64::NAN);
817 assert_eq!(nan1, nan2); }
819
820 #[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 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 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 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]
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 let value = to_value(&person).unwrap();
899
900 assert!(matches!(value, Value::Map(_)));
902
903 let person2 = value.deserialize_into::<Person>().unwrap();
905 assert_eq!(person, person2);
906 }
907
908 #[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 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]
936 fn test_cutime_handling() {
937 let times = vec![
939 CuTime::from(CuDuration(0)),
940 CuTime::from(CuDuration(1)),
941 CuTime::from(CuDuration(u64::MAX / 2)),
942 ];
944
945 for time in times {
946 let time_value = Value::CuTime(time);
948
949 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 let via_to_value = to_value(time).unwrap();
956 assert_eq!(via_to_value, time_value);
957
958 let time_roundtrip = via_to_value.deserialize_into::<CuTime>().unwrap();
960 assert_eq!(time, time_roundtrip);
961 }
962 }
963
964 #[test]
966 fn test_error_handling() {
967 let bool_val = Value::Bool(true);
969 let result = bool_val.clone().deserialize_into::<i32>();
970 assert!(result.is_err());
971
972 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 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 match bool_val.deserialize_into::<String>() {
998 Err(DeserializerError::InvalidType(..)) => (), other => panic!("Expected InvalidType error, got: {other:?}"),
1000 }
1001 }
1002
1003 #[test]
1005 fn test_unicode_handling() {
1006 let strings = vec![
1007 "".to_string(), "ASCII only".to_string(), "Café 🍰".to_string(), "日本語".to_string(), "👨👩👧👦 Family".to_string(), "ᛁᚲ ᚲᚨᚾ ᚱᚢᚾᛖᛋ".to_string(), ];
1014
1015 for s in strings {
1016 let string_val = Value::String(s.clone());
1017
1018 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 let chars = vec!['a', 'é', '日', '🦀'];
1031
1032 for c in chars {
1033 let char_val = Value::Char(c);
1034
1035 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]
1049 fn test_value_deserializer() {
1050 let original = vec![1, 2, 3];
1051 let value = to_value(&original).unwrap();
1052
1053 let deserializer: de::ValueDeserializer<DeserializerError> = ValueDeserializer::new(value);
1055
1056 let result: Vec<i32> = serde::Deserialize::deserialize(deserializer).unwrap();
1058
1059 assert_eq!(original, result);
1060 }
1061
1062 #[test]
1064 fn test_option_handling() {
1065 let some_i32 = Some(42);
1067 let some_string = Some("test".to_string());
1068
1069 let none_i32: Option<i32> = None;
1071 let none_string: Option<String> = None;
1072
1073 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 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 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]
1099 fn test_nested_options() {
1100 let nested_option: Option<Option<Option<i32>>> = Some(Some(Some(42)));
1102
1103 let value = to_value(nested_option).unwrap();
1105
1106 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 let result: Option<Option<Option<i32>>> = value.deserialize_into().unwrap();
1120 assert_eq!(nested_option, result);
1121 }
1122
1123 #[test]
1125 fn test_numeric_conversions() {
1126 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 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 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]
1169 fn test_display_implementation() {
1170 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 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 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 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 let max_i32 = Value::I64(i32::MAX as i64);
1213 assert!(max_i32.deserialize_into::<i32>().is_ok());
1214
1215 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 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 assert!(round_trip.is_err());
1247
1248 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 let nan = Value::F64(f64::NAN);
1258 assert!(nan.deserialize_into::<i32>().is_err());
1259
1260 let infinity = Value::F64(f64::INFINITY);
1262 assert!(infinity.deserialize_into::<i64>().is_err());
1263
1264 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;