sk_cbor/
values.rs

1// Copyright 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Types for expressing CBOR values.
16
17use super::writer::write;
18use alloc::boxed::Box;
19use alloc::string::{String, ToString};
20use alloc::vec::Vec;
21use core::cmp::Ordering;
22
23/// Possible CBOR values.
24#[derive(Clone, Debug)]
25pub enum Value {
26    /// Unsigned integer value (uint).
27    Unsigned(u64),
28    /// Signed integer value (nint). Only 63 bits of information are used here.
29    Negative(i64),
30    /// Byte string (bstr).
31    ByteString(Vec<u8>),
32    /// Text string (tstr).
33    TextString(String),
34    /// Array/tuple of values.
35    Array(Vec<Value>),
36    /// Map of key-value pairs.
37    Map(Vec<(Value, Value)>),
38    /// Tagged value.
39    Tag(u64, Box<Value>),
40    /// Simple value.
41    Simple(SimpleValue),
42}
43
44/// Specific simple CBOR values.
45#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
46pub enum SimpleValue {
47    FalseValue = 20,
48    TrueValue = 21,
49    NullValue = 22,
50    Undefined = 23,
51}
52
53/// Constant values required for CBOR encoding.
54pub struct Constants {}
55
56impl Constants {
57    /// Number of bits used to shift left the major type of a CBOR type byte.
58    pub const MAJOR_TYPE_BIT_SHIFT: u8 = 5;
59    /// Mask to retrieve the additional information held in a CBOR type bytes,
60    /// ignoring the major type.
61    pub const ADDITIONAL_INFORMATION_MASK: u8 = 0x1F;
62    /// Additional information value that indicates the largest inline value.
63    pub const ADDITIONAL_INFORMATION_MAX_INT: u8 = 23;
64    /// Additional information value indicating that a 1-byte length follows.
65    pub const ADDITIONAL_INFORMATION_1_BYTE: u8 = 24;
66    /// Additional information value indicating that a 2-byte length follows.
67    pub const ADDITIONAL_INFORMATION_2_BYTES: u8 = 25;
68    /// Additional information value indicating that a 4-byte length follows.
69    pub const ADDITIONAL_INFORMATION_4_BYTES: u8 = 26;
70    /// Additional information value indicating that an 8-byte length follows.
71    pub const ADDITIONAL_INFORMATION_8_BYTES: u8 = 27;
72}
73
74impl Value {
75    /// Create an appropriate CBOR integer value (uint/nint).
76    /// For simplicity, this only takes i64. Construct directly for the last bit.
77    pub fn integer(int: i64) -> Value {
78        if int >= 0 {
79            Value::Unsigned(int as u64)
80        } else {
81            Value::Negative(int)
82        }
83    }
84
85    /// Create a CBOR boolean simple value.
86    pub fn bool_value(b: bool) -> Value {
87        if b {
88            Value::Simple(SimpleValue::TrueValue)
89        } else {
90            Value::Simple(SimpleValue::FalseValue)
91        }
92    }
93
94    /// Return the major type for the [`Value`].
95    pub fn type_label(&self) -> u8 {
96        // TODO use enum discriminant instead when stable
97        // https://github.com/rust-lang/rust/issues/60553
98        match self {
99            Value::Unsigned(_) => 0,
100            Value::Negative(_) => 1,
101            Value::ByteString(_) => 2,
102            Value::TextString(_) => 3,
103            Value::Array(_) => 4,
104            Value::Map(_) => 5,
105            Value::Tag(_, _) => 6,
106            Value::Simple(_) => 7,
107        }
108    }
109}
110
111impl Ord for Value {
112    fn cmp(&self, other: &Value) -> Ordering {
113        use super::values::Value::{
114            Array, ByteString, Map, Negative, Simple, Tag, TextString, Unsigned,
115        };
116        let self_type_value = self.type_label();
117        let other_type_value = other.type_label();
118        if self_type_value != other_type_value {
119            return self_type_value.cmp(&other_type_value);
120        }
121        match (self, other) {
122            (Unsigned(u1), Unsigned(u2)) => u1.cmp(u2),
123            (Negative(n1), Negative(n2)) => n1.cmp(n2).reverse(),
124            (ByteString(b1), ByteString(b2)) => b1.len().cmp(&b2.len()).then(b1.cmp(b2)),
125            (TextString(t1), TextString(t2)) => t1.len().cmp(&t2.len()).then(t1.cmp(t2)),
126            (Array(a1), Array(a2)) if a1.len() != a2.len() => a1.len().cmp(&a2.len()),
127            (Map(m1), Map(m2)) if m1.len() != m2.len() => m1.len().cmp(&m2.len()),
128            (Tag(t1, v1), Tag(t2, v2)) => t1.cmp(t2).then(v1.cmp(v2)),
129            (Simple(s1), Simple(s2)) => s1.cmp(s2),
130            (v1, v2) => {
131                // This case could handle all of the above as well. Checking individually is faster.
132                let mut encoding1 = Vec::new();
133                let _ = write(v1.clone(), &mut encoding1);
134                let mut encoding2 = Vec::new();
135                let _ = write(v2.clone(), &mut encoding2);
136                encoding1.cmp(&encoding2)
137            }
138        }
139    }
140}
141
142impl PartialOrd for Value {
143    fn partial_cmp(&self, other: &Value) -> Option<Ordering> {
144        Some(self.cmp(other))
145    }
146}
147
148impl Eq for Value {}
149
150impl PartialEq for Value {
151    fn eq(&self, other: &Value) -> bool {
152        self.cmp(other) == Ordering::Equal
153    }
154}
155
156impl SimpleValue {
157    /// Create a simple value from its encoded value.
158    pub fn from_integer(int: u64) -> Option<SimpleValue> {
159        match int {
160            20 => Some(SimpleValue::FalseValue),
161            21 => Some(SimpleValue::TrueValue),
162            22 => Some(SimpleValue::NullValue),
163            23 => Some(SimpleValue::Undefined),
164            _ => None,
165        }
166    }
167}
168
169impl From<u64> for Value {
170    fn from(unsigned: u64) -> Self {
171        Value::Unsigned(unsigned)
172    }
173}
174
175impl From<i64> for Value {
176    fn from(i: i64) -> Self {
177        Value::integer(i)
178    }
179}
180
181impl From<i32> for Value {
182    fn from(i: i32) -> Self {
183        Value::integer(i as i64)
184    }
185}
186
187impl From<Vec<u8>> for Value {
188    fn from(bytes: Vec<u8>) -> Self {
189        Value::ByteString(bytes)
190    }
191}
192
193impl From<&[u8]> for Value {
194    fn from(bytes: &[u8]) -> Self {
195        Value::ByteString(bytes.to_vec())
196    }
197}
198
199impl From<String> for Value {
200    fn from(text: String) -> Self {
201        Value::TextString(text)
202    }
203}
204
205impl From<&str> for Value {
206    fn from(text: &str) -> Self {
207        Value::TextString(text.to_string())
208    }
209}
210
211impl From<Vec<(Value, Value)>> for Value {
212    fn from(map: Vec<(Value, Value)>) -> Self {
213        Value::Map(map)
214    }
215}
216
217impl From<bool> for Value {
218    fn from(b: bool) -> Self {
219        Value::bool_value(b)
220    }
221}
222
223/// Trait that indicates that a type can be converted to a CBOR [`Value`].
224pub trait IntoCborValue {
225    /// Convert `self` into a CBOR [`Value`], consuming it along the way.
226    fn into_cbor_value(self) -> Value;
227}
228
229impl<T> IntoCborValue for T
230where
231    Value: From<T>,
232{
233    fn into_cbor_value(self) -> Value {
234        Value::from(self)
235    }
236}
237
238/// Trait that indicates that a type can be converted to a CBOR [`Option<Value>`].
239pub trait IntoCborValueOption {
240    /// Convert `self` into a CBOR [`Option<Value>`], consuming it along the way.
241    fn into_cbor_value_option(self) -> Option<Value>;
242}
243
244impl<T> IntoCborValueOption for T
245where
246    Value: From<T>,
247{
248    fn into_cbor_value_option(self) -> Option<Value> {
249        Some(Value::from(self))
250    }
251}
252
253impl<T> IntoCborValueOption for Option<T>
254where
255    Value: From<T>,
256{
257    fn into_cbor_value_option(self) -> Option<Value> {
258        self.map(Value::from)
259    }
260}
261
262#[cfg(test)]
263mod test {
264    use super::*;
265    use crate::{cbor_array, cbor_bool, cbor_bytes, cbor_int, cbor_map, cbor_tagged, cbor_text};
266    use alloc::vec;
267
268    #[test]
269    fn test_value_ordering() {
270        assert!(cbor_int!(0) < cbor_int!(23));
271        assert!(cbor_int!(23) < cbor_int!(24));
272        assert!(cbor_int!(24) < cbor_int!(1000));
273        assert!(cbor_int!(1000) < cbor_int!(1000000));
274        assert!(cbor_int!(1000000) < cbor_int!(core::i64::MAX));
275        assert!(cbor_int!(core::i64::MAX) < cbor_int!(-1));
276        assert!(cbor_int!(-1) < cbor_int!(-23));
277        assert!(cbor_int!(-23) < cbor_int!(-24));
278        assert!(cbor_int!(-24) < cbor_int!(-1000));
279        assert!(cbor_int!(-1000) < cbor_int!(-1000000));
280        assert!(cbor_int!(-1000000) < cbor_int!(core::i64::MIN));
281        assert!(cbor_int!(core::i64::MIN) < cbor_bytes!(vec![]));
282        assert!(cbor_bytes!(vec![]) < cbor_bytes!(vec![0x00]));
283        assert!(cbor_bytes!(vec![0x00]) < cbor_bytes!(vec![0x01]));
284        assert!(cbor_bytes!(vec![0x01]) < cbor_bytes!(vec![0xFF]));
285        assert!(cbor_bytes!(vec![0xFF]) < cbor_bytes!(vec![0x00, 0x00]));
286        assert!(cbor_bytes!(vec![0x00, 0x00]) < cbor_text!(""));
287        assert!(cbor_text!("") < cbor_text!("a"));
288        assert!(cbor_text!("a") < cbor_text!("b"));
289        assert!(cbor_text!("b") < cbor_text!("aa"));
290        assert!(cbor_text!("aa") < cbor_array![]);
291        assert!(cbor_array![] < cbor_array![0]);
292        assert!(cbor_array![0] < cbor_array![-1]);
293        assert!(cbor_array![1] < cbor_array![b""]);
294        assert!(cbor_array![b""] < cbor_array![""]);
295        assert!(cbor_array![""] < cbor_array![cbor_array![]]);
296        assert!(cbor_array![cbor_array![]] < cbor_array![cbor_map! {}]);
297        assert!(cbor_array![cbor_map! {}] < cbor_array![false]);
298        assert!(cbor_array![false] < cbor_array![0, 0]);
299        assert!(cbor_array![0, 0] < cbor_map! {});
300        assert!(cbor_map! {} < cbor_map! {0 => 0});
301        assert!(cbor_map! {0 => 0} < cbor_map! {0 => 1});
302        assert!(cbor_map! {0 => 1} < cbor_map! {1 => 0});
303        assert!(cbor_map! {1 => 0} < cbor_map! {-1 => 0});
304        assert!(cbor_map! {-1 => 0} < cbor_map! {b"" => 0});
305        assert!(cbor_map! {b"" => 0} < cbor_map! {"" => 0});
306        assert!(cbor_map! {"" => 0} < cbor_map! {cbor_array![] => 0});
307        assert!(cbor_map! {cbor_array![] => 0} < cbor_map! {cbor_map!{} => 0});
308        assert!(cbor_map! {cbor_map!{} => 0} < cbor_map! {false => 0});
309        assert!(cbor_map! {false => 0} < cbor_map! {0 => 0, 0 => 0});
310        assert!(cbor_map! {0 => 0} < cbor_tagged!(2, cbor_int!(0)));
311        assert!(cbor_map! {0 => 0, 0 => 0} < cbor_bool!(false));
312        assert!(cbor_bool!(false) < cbor_bool!(true));
313        assert!(cbor_bool!(true) < Value::Simple(SimpleValue::NullValue));
314        assert!(Value::Simple(SimpleValue::NullValue) < Value::Simple(SimpleValue::Undefined));
315        assert!(cbor_tagged!(1, cbor_text!("s")) < cbor_tagged!(2, cbor_int!(0)));
316        assert!(cbor_int!(1) < cbor_int!(-1));
317        assert!(cbor_int!(1) < cbor_bytes!(vec![0x00]));
318        assert!(cbor_int!(1) < cbor_text!("s"));
319        assert!(cbor_int!(1) < cbor_array![]);
320        assert!(cbor_int!(1) < cbor_map! {});
321        assert!(cbor_int!(1) < cbor_tagged!(1, cbor_text!("s")));
322        assert!(cbor_int!(1) < cbor_bool!(false));
323        assert!(cbor_int!(-1) < cbor_bytes!(vec![0x00]));
324        assert!(cbor_int!(-1) < cbor_text!("s"));
325        assert!(cbor_int!(-1) < cbor_array![]);
326        assert!(cbor_int!(-1) < cbor_map! {});
327        assert!(cbor_int!(-1) < cbor_tagged!(1, cbor_text!("s")));
328        assert!(cbor_int!(-1) < cbor_bool!(false));
329        assert!(cbor_bytes!(vec![0x00]) < cbor_text!("s"));
330        assert!(cbor_bytes!(vec![0x00]) < cbor_array![]);
331        assert!(cbor_bytes!(vec![0x00]) < cbor_map! {});
332        assert!(cbor_bytes!(vec![0x00]) < cbor_tagged!(1, cbor_text!("s")));
333        assert!(cbor_bytes!(vec![0x00]) < cbor_bool!(false));
334        assert!(cbor_text!("s") < cbor_array![]);
335        assert!(cbor_text!("s") < cbor_map! {});
336        assert!(cbor_text!("s") < cbor_tagged!(1, cbor_text!("s")));
337        assert!(cbor_text!("s") < cbor_bool!(false));
338        assert!(cbor_array![] < cbor_map!(0 => 1));
339        assert!(cbor_array![] < cbor_tagged!(2, cbor_int!(0)));
340        assert!(cbor_array![] < cbor_bool!(false));
341        assert!(cbor_tagged!(1, cbor_text!("s")) < cbor_bool!(false));
342    }
343}