Skip to main content

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