Skip to main content

deser_cbor/
simple.rs

1use alloc::borrow::Cow;
2
3use deser_core::State;
4use deser_core::de::{Deserialize, Slot, default_atom};
5use deser_core::ext::{ExtValue, Extension};
6use deser_core::ser::{Emit, Serialize};
7use deser_core::{Atom, Error, ErrorKind};
8
9/// A CBOR simple value.
10///
11/// The simple values `false`, `true`, `null` and `undefined` (20 to 23) map
12/// onto the deser data model (`undefined` is deserialized as `null`).  All
13/// other simple values are unassigned and passed through deser as extension
14/// atoms of this type.  Their fallback is an unsigned integer.
15///
16/// ```
17/// use deser_cbor::Simple;
18///
19/// let bytes = deser_cbor::to_vec(&Simple::new(16).unwrap()).unwrap();
20/// assert_eq!(bytes, [0xf0]);
21/// let value: Simple = deser_cbor::from_slice(&bytes).unwrap();
22/// assert_eq!(value.value(), 16);
23/// ```
24#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
25pub struct Simple(u8);
26
27impl Simple {
28    /// Creates a simple value.
29    ///
30    /// Returns `None` for the reserved values 24 to 31 which have no valid
31    /// encoding.
32    pub fn new(value: u8) -> Option<Simple> {
33        if (24..32).contains(&value) {
34            None
35        } else {
36            Some(Simple(value))
37        }
38    }
39
40    /// Returns the numeric value.
41    pub fn value(self) -> u8 {
42        self.0
43    }
44}
45
46impl Extension for Simple {
47    fn name(&self) -> &str {
48        "simple value"
49    }
50
51    fn fallback(&self) -> Atom<'_> {
52        Atom::U64(u64::from(self.0))
53    }
54}
55
56impl Serialize for Simple {
57    fn serialize<'a>(value: &'a Self, _state: &mut State) -> Result<Emit<'a>, Error> {
58        Ok(Emit::Atom(Atom::Ext(ExtValue::borrowed(value))))
59    }
60}
61
62impl<'de> Deserialize<'de> for Simple {
63    fn deserialize_atom(slot: &mut Slot<Self>, atom: Atom, state: &mut State) -> Result<(), Error> {
64        let simple = match atom {
65            Atom::Ext(ref ext) if ext.is::<Simple>() => *ext.downcast_ref::<Simple>().unwrap(),
66            Atom::Bool(false) => Simple(20),
67            Atom::Bool(true) => Simple(21),
68            Atom::Null => Simple(22),
69            Atom::U64(value) => match u8::try_from(value).ok().and_then(Simple::new) {
70                Some(simple) => simple,
71                None => {
72                    return Err(Error::new(
73                        ErrorKind::OutOfRange,
74                        "value out of range for simple value",
75                    ));
76                }
77            },
78            other => return default_atom(slot, other, state),
79        };
80        slot.set(simple);
81        Ok(())
82    }
83
84    fn expecting() -> Cow<'static, str> {
85        Cow::Borrowed("simple")
86    }
87}