serde_cbor/value/
mod.rs

1//! CBOR values, keys and serialization routines.
2
3mod de;
4mod ser;
5
6use std::cmp::{Ord, Ordering, PartialOrd};
7use std::collections::BTreeMap;
8
9#[doc(inline)]
10pub use self::de::from_value;
11#[doc(inline)]
12pub use self::ser::to_value;
13
14/// The `Value` enum, a loosely typed way of representing any valid CBOR value.
15///
16/// Maps are sorted according to the canonical ordering
17/// described in [RFC 7049 bis].
18/// Therefore values are unambiguously serialized
19/// to a canonical form of CBOR from the same RFC.
20///
21/// [RFC 7049 bis]: https://tools.ietf.org/html/draft-ietf-cbor-7049bis-04#section-2
22#[derive(Clone, Debug)]
23pub enum Value {
24    /// Represents the absence of a value or the value undefined.
25    Null,
26    /// Represents a boolean value.
27    Bool(bool),
28    /// Integer CBOR numbers.
29    ///
30    /// The biggest value that can be represented is 2^64 - 1.
31    /// While the smallest value is -2^64.
32    /// Values outside this range can't be serialized
33    /// and will cause an error.
34    Integer(i128),
35    /// Represents a floating point value.
36    Float(f64),
37    /// Represents a byte string.
38    Bytes(Vec<u8>),
39    /// Represents an UTF-8 encoded string.
40    Text(String),
41    /// Represents an array of values.
42    Array(Vec<Value>),
43    /// Represents a map.
44    ///
45    /// Maps are also called tables, dictionaries, hashes, or objects (in JSON).
46    /// While any value can be used as a CBOR key
47    /// it is better to use only one type of key in a map
48    /// to avoid ambiguity.
49    /// If floating point values are used as keys they are compared bit-by-bit for equality.
50    /// If arrays or maps are used as keys the comparisons
51    /// to establish canonical order may be slow and therefore insertion
52    /// and retrieval of values will be slow too.
53    Map(BTreeMap<Value, Value>),
54    /// Represents a tagged value
55    Tag(u64, Box<Value>),
56    // The hidden variant allows the enum to be extended
57    // with variants for tags and simple values.
58    #[doc(hidden)]
59    __Hidden,
60}
61
62impl PartialEq for Value {
63    fn eq(&self, other: &Value) -> bool {
64        self.cmp(other) == Ordering::Equal
65    }
66}
67
68impl Eq for Value {}
69
70impl PartialOrd for Value {
71    fn partial_cmp(&self, other: &Value) -> Option<Ordering> {
72        Some(self.cmp(other))
73    }
74}
75
76impl Ord for Value {
77    fn cmp(&self, other: &Value) -> Ordering {
78        // Determine the canonical order of two values:
79        // 1. Smaller major type sorts first.
80        // 2. Shorter sequence sorts first.
81        // 3. Compare integers by magnitude.
82        // 4. Compare byte and text sequences lexically.
83        // 5. Compare the serializations of both types. (expensive)
84        use self::Value::*;
85        if self.major_type() != other.major_type() {
86            return self.major_type().cmp(&other.major_type());
87        }
88        match (self, other) {
89            (Integer(a), Integer(b)) => a.abs().cmp(&b.abs()),
90            (Bytes(a), Bytes(b)) if a.len() != b.len() => a.len().cmp(&b.len()),
91            (Text(a), Text(b)) if a.len() != b.len() => a.len().cmp(&b.len()),
92            (Array(a), Array(b)) if a.len() != b.len() => a.len().cmp(&b.len()),
93            (Map(a), Map(b)) if a.len() != b.len() => a.len().cmp(&b.len()),
94            (Bytes(a), Bytes(b)) => a.cmp(b),
95            (Text(a), Text(b)) => a.cmp(b),
96            (a, b) => {
97                let a = crate::to_vec(a).expect("self is serializable");
98                let b = crate::to_vec(b).expect("other is serializable");
99                a.cmp(&b)
100            }
101        }
102    }
103}
104
105macro_rules! impl_from {
106    ($variant:path, $for_type:ty) => {
107        impl From<$for_type> for Value {
108            fn from(v: $for_type) -> Value {
109                $variant(v.into())
110            }
111        }
112    };
113}
114
115impl_from!(Value::Bool, bool);
116impl_from!(Value::Integer, i8);
117impl_from!(Value::Integer, i16);
118impl_from!(Value::Integer, i32);
119impl_from!(Value::Integer, i64);
120// i128 omitted because not all numbers fit in CBOR serialization
121impl_from!(Value::Integer, u8);
122impl_from!(Value::Integer, u16);
123impl_from!(Value::Integer, u32);
124impl_from!(Value::Integer, u64);
125// u128 omitted because not all numbers fit in CBOR serialization
126impl_from!(Value::Float, f32);
127impl_from!(Value::Float, f64);
128impl_from!(Value::Bytes, Vec<u8>);
129impl_from!(Value::Text, String);
130// TODO: figure out if these impls should be more generic or removed.
131impl_from!(Value::Array, Vec<Value>);
132impl_from!(Value::Map, BTreeMap<Value, Value>);
133
134impl Value {
135    fn major_type(&self) -> u8 {
136        use self::Value::*;
137        match self {
138            Null => 7,
139            Bool(_) => 7,
140            Integer(v) => {
141                if *v >= 0 {
142                    0
143                } else {
144                    1
145                }
146            }
147            Tag(_, _) => 6,
148            Float(_) => 7,
149            Bytes(_) => 2,
150            Text(_) => 3,
151            Array(_) => 4,
152            Map(_) => 5,
153            __Hidden => unreachable!(),
154        }
155    }
156}