1 //! CBOR values, keys and serialization routines.
2 
3 mod de;
4 mod ser;
5 
6 use std::cmp::{Ord, Ordering, PartialOrd};
7 use std::collections::BTreeMap;
8 
9 #[doc(inline)]
10 pub use self::de::from_value;
11 #[doc(inline)]
12 pub 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)]
23 pub 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 
62 impl PartialEq for Value {
eq(&self, other: &Value) -> bool63     fn eq(&self, other: &Value) -> bool {
64         self.cmp(other) == Ordering::Equal
65     }
66 }
67 
68 impl Eq for Value {}
69 
70 impl PartialOrd for Value {
partial_cmp(&self, other: &Value) -> Option<Ordering>71     fn partial_cmp(&self, other: &Value) -> Option<Ordering> {
72         Some(self.cmp(other))
73     }
74 }
75 
76 impl Ord for Value {
cmp(&self, other: &Value) -> Ordering77     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 
105 macro_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 
115 impl_from!(Value::Bool, bool);
116 impl_from!(Value::Integer, i8);
117 impl_from!(Value::Integer, i16);
118 impl_from!(Value::Integer, i32);
119 impl_from!(Value::Integer, i64);
120 // i128 omitted because not all numbers fit in CBOR serialization
121 impl_from!(Value::Integer, u8);
122 impl_from!(Value::Integer, u16);
123 impl_from!(Value::Integer, u32);
124 impl_from!(Value::Integer, u64);
125 // u128 omitted because not all numbers fit in CBOR serialization
126 impl_from!(Value::Float, f32);
127 impl_from!(Value::Float, f64);
128 impl_from!(Value::Bytes, Vec<u8>);
129 impl_from!(Value::Text, String);
130 // TODO: figure out if these impls should be more generic or removed.
131 impl_from!(Value::Array, Vec<Value>);
132 impl_from!(Value::Map, BTreeMap<Value, Value>);
133 
134 impl Value {
major_type(&self) -> u8135     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 }
157