cu29_value/
lib.rs

1#![doc(html_root_url = "https://docs.rs/serde-value/0.7.0/")]
2
3use cu29_clock::{CuDuration, CuTime};
4use ordered_float::OrderedFloat;
5use serde::Deserialize;
6use std::cmp::Ordering;
7use std::collections::BTreeMap;
8use std::fmt::{Display, Formatter};
9use std::hash::{Hash, Hasher};
10
11mod bdec;
12mod benc;
13mod de;
14mod ser;
15
16pub use de::*;
17pub use ser::*;
18
19#[derive(Clone, Debug)]
20pub enum Value {
21    Bool(bool),
22
23    U8(u8),
24    U16(u16),
25    U32(u32),
26    U64(u64),
27
28    I8(i8),
29    I16(i16),
30    I32(i32),
31    I64(i64),
32
33    F32(f32),
34    F64(f64),
35
36    Char(char),
37    String(String),
38    Unit,
39    Option(Option<Box<Value>>),
40    Newtype(Box<Value>),
41    Seq(Vec<Value>),
42    Map(BTreeMap<Value, Value>),
43    Bytes(Vec<u8>),
44
45    CuTime(CuTime),
46}
47
48impl Display for Value {
49    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
50        match self {
51            Value::Bool(v) => write!(f, "{}", v),
52            Value::U8(v) => write!(f, "{}", v),
53            Value::U16(v) => write!(f, "{}", v),
54            Value::U32(v) => write!(f, "{}", v),
55            Value::U64(v) => write!(f, "{}", v),
56            Value::I8(v) => write!(f, "{}", v),
57            Value::I16(v) => write!(f, "{}", v),
58            Value::I32(v) => write!(f, "{}", v),
59            Value::I64(v) => write!(f, "{}", v),
60            Value::F32(v) => write!(f, "{}", v),
61            Value::F64(v) => write!(f, "{}", v),
62            Value::Char(v) => write!(f, "{}", v),
63            Value::String(v) => write!(f, "{}", v),
64            Value::Unit => write!(f, "()"),
65            Value::Option(v) => match v {
66                Some(v) => write!(f, "Some({})", v),
67                None => write!(f, "None"),
68            },
69            Value::Newtype(v) => write!(f, "{}", v),
70            Value::Seq(v) => {
71                write!(f, "[")?;
72                for (i, v) in v.iter().enumerate() {
73                    if i > 0 {
74                        write!(f, ", ")?;
75                    }
76                    write!(f, "{}", v)?;
77                }
78                write!(f, "]")
79            }
80            Value::Map(v) => {
81                write!(f, "{{")?;
82                for (i, (k, v)) in v.iter().enumerate() {
83                    if i > 0 {
84                        write!(f, ", ")?;
85                    }
86                    write!(f, "{}: {}", k, v)?;
87                }
88                write!(f, "}}")
89            }
90            Value::Bytes(v) => {
91                write!(f, "[")?;
92                for (i, b) in v.iter().enumerate() {
93                    if i > 0 {
94                        write!(f, " ")?;
95                    }
96                    write!(f, "{:02x}", b)?;
97                }
98                write!(f, "]")
99            }
100            Value::CuTime(v) => write!(f, "{}", v),
101        }
102    }
103}
104
105impl Hash for Value {
106    fn hash<H>(&self, hasher: &mut H)
107    where
108        H: Hasher,
109    {
110        self.discriminant().hash(hasher);
111        match *self {
112            Value::Bool(v) => v.hash(hasher),
113            Value::U8(v) => v.hash(hasher),
114            Value::U16(v) => v.hash(hasher),
115            Value::U32(v) => v.hash(hasher),
116            Value::U64(v) => v.hash(hasher),
117            Value::I8(v) => v.hash(hasher),
118            Value::I16(v) => v.hash(hasher),
119            Value::I32(v) => v.hash(hasher),
120            Value::I64(v) => v.hash(hasher),
121            Value::F32(v) => OrderedFloat(v).hash(hasher),
122            Value::F64(v) => OrderedFloat(v).hash(hasher),
123            Value::Char(v) => v.hash(hasher),
124            Value::String(ref v) => v.hash(hasher),
125            Value::Unit => 0_u8.hash(hasher),
126            Value::Option(ref v) => v.hash(hasher),
127            Value::Newtype(ref v) => v.hash(hasher),
128            Value::Seq(ref v) => v.hash(hasher),
129            Value::Map(ref v) => v.hash(hasher),
130            Value::Bytes(ref v) => v.hash(hasher),
131            Value::CuTime(v) => {
132                let CuDuration(nanos) = v;
133                nanos.hash(hasher)
134            }
135        }
136    }
137}
138
139impl PartialEq for Value {
140    fn eq(&self, rhs: &Self) -> bool {
141        match (self, rhs) {
142            (&Value::Bool(v0), &Value::Bool(v1)) if v0 == v1 => true,
143            (&Value::U8(v0), &Value::U8(v1)) if v0 == v1 => true,
144            (&Value::U16(v0), &Value::U16(v1)) if v0 == v1 => true,
145            (&Value::U32(v0), &Value::U32(v1)) if v0 == v1 => true,
146            (&Value::U64(v0), &Value::U64(v1)) if v0 == v1 => true,
147            (&Value::I8(v0), &Value::I8(v1)) if v0 == v1 => true,
148            (&Value::I16(v0), &Value::I16(v1)) if v0 == v1 => true,
149            (&Value::I32(v0), &Value::I32(v1)) if v0 == v1 => true,
150            (&Value::I64(v0), &Value::I64(v1)) if v0 == v1 => true,
151            (&Value::F32(v0), &Value::F32(v1)) if OrderedFloat(v0) == OrderedFloat(v1) => true,
152            (&Value::F64(v0), &Value::F64(v1)) if OrderedFloat(v0) == OrderedFloat(v1) => true,
153            (&Value::Char(v0), &Value::Char(v1)) if v0 == v1 => true,
154            (Value::String(v0), Value::String(v1)) if v0 == v1 => true,
155            (&Value::Unit, &Value::Unit) => true,
156            (Value::Option(v0), Value::Option(v1)) if v0 == v1 => true,
157            (Value::Newtype(v0), Value::Newtype(v1)) if v0 == v1 => true,
158            (Value::Seq(v0), Value::Seq(v1)) if v0 == v1 => true,
159            (Value::Map(v0), Value::Map(v1)) if v0 == v1 => true,
160            (Value::Bytes(v0), Value::Bytes(v1)) if v0 == v1 => true,
161            (&Value::CuTime(v0), &Value::CuTime(v1)) if v0 == v1 => true,
162            _ => false,
163        }
164    }
165}
166
167impl Ord for Value {
168    fn cmp(&self, rhs: &Self) -> Ordering {
169        match (self, rhs) {
170            (&Value::Bool(v0), Value::Bool(v1)) => v0.cmp(v1),
171            (&Value::U8(v0), Value::U8(v1)) => v0.cmp(v1),
172            (&Value::U16(v0), Value::U16(v1)) => v0.cmp(v1),
173            (&Value::U32(v0), Value::U32(v1)) => v0.cmp(v1),
174            (&Value::U64(v0), Value::U64(v1)) => v0.cmp(v1),
175            (&Value::I8(v0), Value::I8(v1)) => v0.cmp(v1),
176            (&Value::I16(v0), Value::I16(v1)) => v0.cmp(v1),
177            (&Value::I32(v0), Value::I32(v1)) => v0.cmp(v1),
178            (&Value::I64(v0), Value::I64(v1)) => v0.cmp(v1),
179            (&Value::F32(v0), &Value::F32(v1)) => OrderedFloat(v0).cmp(&OrderedFloat(v1)),
180            (&Value::F64(v0), &Value::F64(v1)) => OrderedFloat(v0).cmp(&OrderedFloat(v1)),
181            (&Value::Char(v0), Value::Char(v1)) => v0.cmp(v1),
182            (Value::String(v0), Value::String(v1)) => v0.cmp(v1),
183            (&Value::Unit, &Value::Unit) => Ordering::Equal,
184            (Value::Option(v0), Value::Option(v1)) => v0.cmp(v1),
185            (Value::Newtype(v0), Value::Newtype(v1)) => v0.cmp(v1),
186            (Value::Seq(v0), Value::Seq(v1)) => v0.cmp(v1),
187            (Value::Map(v0), Value::Map(v1)) => v0.cmp(v1),
188            (Value::Bytes(v0), Value::Bytes(v1)) => v0.cmp(v1),
189            (&Value::CuTime(v0), &Value::CuTime(v1)) => v0.cmp(&v1),
190            (v0, v1) => v0.discriminant().cmp(&v1.discriminant()),
191        }
192    }
193}
194
195impl Value {
196    fn discriminant(&self) -> usize {
197        match *self {
198            Value::Bool(..) => 0,
199            Value::U8(..) => 1,
200            Value::U16(..) => 2,
201            Value::U32(..) => 3,
202            Value::U64(..) => 4,
203            Value::I8(..) => 5,
204            Value::I16(..) => 6,
205            Value::I32(..) => 7,
206            Value::I64(..) => 8,
207            Value::F32(..) => 9,
208            Value::F64(..) => 10,
209            Value::Char(..) => 11,
210            Value::String(..) => 12,
211            Value::Unit => 13,
212            Value::Option(..) => 14,
213            Value::Newtype(..) => 15,
214            Value::Seq(..) => 16,
215            Value::Map(..) => 17,
216            Value::Bytes(..) => 18,
217            Value::CuTime(..) => 32,
218        }
219    }
220
221    fn unexpected(&self) -> serde::de::Unexpected {
222        match *self {
223            Value::Bool(b) => serde::de::Unexpected::Bool(b),
224            Value::U8(n) => serde::de::Unexpected::Unsigned(n as u64),
225            Value::U16(n) => serde::de::Unexpected::Unsigned(n as u64),
226            Value::U32(n) => serde::de::Unexpected::Unsigned(n as u64),
227            Value::U64(n) => serde::de::Unexpected::Unsigned(n),
228            Value::I8(n) => serde::de::Unexpected::Signed(n as i64),
229            Value::I16(n) => serde::de::Unexpected::Signed(n as i64),
230            Value::I32(n) => serde::de::Unexpected::Signed(n as i64),
231            Value::I64(n) => serde::de::Unexpected::Signed(n),
232            Value::F32(n) => serde::de::Unexpected::Float(n as f64),
233            Value::F64(n) => serde::de::Unexpected::Float(n),
234            Value::Char(c) => serde::de::Unexpected::Char(c),
235            Value::String(ref s) => serde::de::Unexpected::Str(s),
236            Value::Unit => serde::de::Unexpected::Unit,
237            Value::Option(_) => serde::de::Unexpected::Option,
238            Value::Newtype(_) => serde::de::Unexpected::NewtypeStruct,
239            Value::Seq(_) => serde::de::Unexpected::Seq,
240            Value::Map(_) => serde::de::Unexpected::Map,
241            Value::Bytes(ref b) => serde::de::Unexpected::Bytes(b),
242            Value::CuTime(n) => {
243                let CuDuration(nanos) = n;
244                serde::de::Unexpected::Unsigned(nanos)
245            }
246        }
247    }
248
249    pub fn deserialize_into<'de, T: Deserialize<'de>>(self) -> Result<T, DeserializerError> {
250        T::deserialize(self)
251    }
252}
253
254impl Eq for Value {}
255impl PartialOrd for Value {
256    fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
257        Some(self.cmp(rhs))
258    }
259}
260
261#[cfg(test)]
262mod tests {
263    use super::*;
264    use bincode::config::standard;
265    use cu29_clock::RobotClock;
266    use serde_derive::{Deserialize, Serialize};
267    use std::time::Duration;
268
269    #[test]
270    fn de_smoke_test() {
271        // some convoluted Value
272        let value = Value::Option(Some(Box::new(Value::Seq(vec![
273            Value::U16(8),
274            Value::Char('a'),
275            Value::F32(1.0),
276            Value::String("hello".into()),
277            Value::Map(
278                vec![
279                    (Value::Bool(false), Value::Unit),
280                    (
281                        Value::Bool(true),
282                        Value::Newtype(Box::new(Value::Bytes(b"hi".as_ref().into()))),
283                    ),
284                ]
285                .into_iter()
286                .collect(),
287            ),
288        ]))));
289
290        // assert that the value remains unchanged through deserialization
291        let value_de = Value::deserialize(value.clone()).unwrap();
292        assert_eq!(value_de, value);
293    }
294
295    #[test]
296    fn ser_smoke_test() {
297        #[derive(Serialize)]
298        struct Foo {
299            a: u32,
300            b: String,
301            c: Vec<bool>,
302        }
303
304        let foo = Foo {
305            a: 15,
306            b: "hello".into(),
307            c: vec![true, false],
308        };
309
310        let expected = Value::Map(
311            vec![
312                (Value::String("a".into()), Value::U32(15)),
313                (Value::String("b".into()), Value::String("hello".into())),
314                (
315                    Value::String("c".into()),
316                    Value::Seq(vec![Value::Bool(true), Value::Bool(false)]),
317                ),
318            ]
319            .into_iter()
320            .collect(),
321        );
322
323        let value = to_value(&foo).unwrap();
324        assert_eq!(expected, value);
325    }
326
327    #[test]
328    fn deserialize_into_enum() {
329        #[derive(Deserialize, Debug, PartialEq, Eq)]
330        enum Foo {
331            Bar,
332            Baz(u8),
333        }
334
335        let value = Value::String("Bar".into());
336        assert_eq!(Foo::deserialize(value).unwrap(), Foo::Bar);
337
338        let value = Value::Map(
339            vec![(Value::String("Baz".into()), Value::U8(1))]
340                .into_iter()
341                .collect(),
342        );
343        assert_eq!(Foo::deserialize(value).unwrap(), Foo::Baz(1));
344    }
345
346    #[test]
347    fn serialize_from_enum() {
348        #[derive(Serialize)]
349        enum Foo {
350            Bar,
351            Baz(u8),
352            Qux { quux: u8 },
353            Corge(u8, u8),
354        }
355
356        let bar = Foo::Bar;
357        assert_eq!(to_value(&bar).unwrap(), Value::String("Bar".into()));
358
359        let baz = Foo::Baz(1);
360        assert_eq!(
361            to_value(&baz).unwrap(),
362            Value::Map(
363                vec![(Value::String("Baz".into()), Value::U8(1))]
364                    .into_iter()
365                    .collect(),
366            )
367        );
368
369        let qux = Foo::Qux { quux: 2 };
370        assert_eq!(
371            to_value(&qux).unwrap(),
372            Value::Map(
373                vec![(
374                    Value::String("Qux".into()),
375                    Value::Map(
376                        vec![(Value::String("quux".into()), Value::U8(2))]
377                            .into_iter()
378                            .collect()
379                    )
380                )]
381                .into_iter()
382                .collect()
383            )
384        );
385
386        let corge = Foo::Corge(3, 4);
387        assert_eq!(
388            to_value(&corge).unwrap(),
389            Value::Map(
390                vec![(
391                    Value::String("Corge".into()),
392                    Value::Seq(vec![Value::U8(3), Value::U8(4)])
393                )]
394                .into_iter()
395                .collect()
396            )
397        );
398    }
399
400    #[test]
401    fn deserialize_inside_deserialize_impl() {
402        #[derive(Debug, PartialEq, Eq)]
403        enum Event {
404            Added(u32),
405            Error(u8),
406        }
407
408        impl<'de> serde::Deserialize<'de> for Event {
409            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
410            where
411                D: serde::Deserializer<'de>,
412            {
413                #[derive(Deserialize)]
414                struct RawEvent {
415                    kind: String,
416                    object: Value,
417                }
418
419                let raw_event = RawEvent::deserialize(deserializer)?;
420
421                // Cannot directly use Value as Deserializer, since error type needs to be
422                // generic D::Error rather than specific serde_value::DeserializerError
423                let object_deserializer = ValueDeserializer::new(raw_event.object);
424
425                Ok(match &*raw_event.kind {
426                    "ADDED" => Event::Added(<_>::deserialize(object_deserializer)?),
427                    "ERROR" => Event::Error(<_>::deserialize(object_deserializer)?),
428                    kind => {
429                        return Err(serde::de::Error::unknown_variant(kind, &["ADDED", "ERROR"]))
430                    }
431                })
432            }
433        }
434
435        let input = Value::Map(
436            vec![
437                (
438                    Value::String("kind".to_owned()),
439                    Value::String("ADDED".to_owned()),
440                ),
441                (Value::String("object".to_owned()), Value::U32(5)),
442            ]
443            .into_iter()
444            .collect(),
445        );
446        let event = Event::deserialize(input).expect("could not deserialize ADDED event");
447        assert_eq!(event, Event::Added(5));
448
449        let input = Value::Map(
450            vec![
451                (
452                    Value::String("kind".to_owned()),
453                    Value::String("ERROR".to_owned()),
454                ),
455                (Value::String("object".to_owned()), Value::U8(5)),
456            ]
457            .into_iter()
458            .collect(),
459        );
460        let event = Event::deserialize(input).expect("could not deserialize ERROR event");
461        assert_eq!(event, Event::Error(5));
462
463        let input = Value::Map(
464            vec![
465                (
466                    Value::String("kind".to_owned()),
467                    Value::String("ADDED".to_owned()),
468                ),
469                (Value::String("object".to_owned()), Value::Unit),
470            ]
471            .into_iter()
472            .collect(),
473        );
474        let _ =
475            Event::deserialize(input).expect_err("expected deserializing bad ADDED event to fail");
476    }
477
478    #[test]
479    fn deserialize_newtype() {
480        #[derive(Debug, Deserialize, PartialEq)]
481        struct Foo(i32);
482
483        let input = Value::I32(5);
484        let foo = Foo::deserialize(input).unwrap();
485        assert_eq!(foo, Foo(5));
486    }
487
488    #[test]
489    fn deserialize_newtype2() {
490        #[derive(Debug, Deserialize, PartialEq)]
491        struct Foo(i32);
492
493        #[derive(Debug, Deserialize, PartialEq)]
494        struct Bar {
495            foo: Foo,
496        }
497
498        let input = Value::Map(
499            vec![(Value::String("foo".to_owned()), Value::I32(5))]
500                .into_iter()
501                .collect(),
502        );
503        let bar = Bar::deserialize(input).unwrap();
504        assert_eq!(bar, Bar { foo: Foo(5) });
505    }
506
507    #[test]
508    fn clock_ser_deser() {
509        let (clock, mock) = RobotClock::mock();
510        mock.increment(Duration::from_nanos(42));
511        let c = clock.now();
512
513        let input = Value::CuTime(c);
514        let foo = CuTime::deserialize(input).unwrap();
515        assert_eq!(foo, CuTime::from(Duration::from_nanos(42)));
516    }
517    #[test]
518    fn value_encode_decode() {
519        fn check_value(value: Value) {
520            let v = bincode::encode_to_vec(&value, standard()).expect("encode failed");
521            let (v2, s) = bincode::decode_from_slice::<Value, _>(v.as_slice(), standard())
522                .expect("decode failed");
523            assert_eq!(s, v.len());
524            assert_eq!(&v2, &value);
525        }
526
527        check_value(Value::Bool(true));
528        check_value(Value::U8(42));
529        check_value(Value::U16(42));
530        check_value(Value::U32(42));
531        check_value(Value::U64(42));
532        check_value(Value::I8(42));
533        check_value(Value::I16(42));
534        check_value(Value::I32(42));
535        check_value(Value::I64(42));
536        check_value(Value::F32(42.42));
537        check_value(Value::F64(42.42));
538        check_value(Value::Char('4'));
539        check_value(Value::String("42".into()));
540        check_value(Value::Unit);
541        check_value(Value::Option(Some(Box::new(Value::U32(42)))));
542        check_value(Value::Newtype(Box::new(Value::U32(42))));
543        check_value(Value::Seq(vec![Value::Bool(true), Value::U32(42)]));
544        check_value(Value::Map(BTreeMap::from([
545            (Value::Bool(true), Value::U32(42)),
546            (Value::String("42".into()), Value::I32(42)),
547        ])));
548        check_value(Value::Bytes(vec![0x4, 0x2]));
549        check_value(Value::CuTime(CuTime::from(Duration::from_nanos(42))));
550    }
551
552    #[test]
553    fn test_cutime_tovalue() {
554        let c = CuTime::from(Duration::from_nanos(42));
555        let v = to_value(c).expect("to_value failed");
556        assert_eq!(v, Value::CuTime(c));
557    }
558}