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}