Skip to main content

oasis_cbor/
decode.rs

1//! CBOR decoding.
2use std::{
3    cmp::Ordering,
4    collections::{BTreeMap, BTreeSet, HashMap, HashSet},
5    convert::TryInto,
6};
7
8use impl_trait_for_tuples::impl_for_tuples;
9
10use crate::{DecodeError, SimpleValue, Value};
11
12/// Trait for types that can be decoded from CBOR.
13pub trait Decode {
14    /// Try to decode from a missing/null/undefined value.
15    fn try_default() -> Result<Self, DecodeError>
16    where
17        Self: Sized,
18    {
19        Err(DecodeError::MissingField)
20    }
21
22    /// Try to decode from a given CBOR value.
23    fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError>
24    where
25        Self: Sized;
26
27    /// Try to decode from a given CBOR value, calling `try_default` in case the value is null or
28    /// undefined.
29    fn try_from_cbor_value_default(value: Value) -> Result<Self, DecodeError>
30    where
31        Self: Sized,
32    {
33        match value {
34            // In case of explicit null / undefined values, try to use the default value if one is
35            // available (may still fail if one is not available).
36            Value::Simple(SimpleValue::NullValue | SimpleValue::Undefined) => Self::try_default(),
37            _ => Self::try_from_cbor_value(value),
38        }
39    }
40}
41
42#[impl_for_tuples(1, 10)]
43impl Decode for Tuple {
44    fn try_default() -> Result<Self, DecodeError> {
45        Ok((for_tuples!( #( Tuple::try_default()? ),* )))
46    }
47
48    fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
49        match value {
50            Value::Array(mut values) => {
51                Ok((for_tuples!( #( Tuple::try_from_cbor_value(values.remove(0))? ),* )))
52            }
53            _ => Err(DecodeError::UnexpectedType),
54        }
55    }
56}
57
58macro_rules! impl_uint {
59    ($name:ty) => {
60        impl Decode for $name {
61            fn try_default() -> Result<Self, DecodeError> {
62                Ok(Default::default())
63            }
64
65            fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
66                match value {
67                    Value::Unsigned(v) => {
68                        v.try_into().map_err(|_| DecodeError::UnexpectedIntegerSize)
69                    }
70                    _ => Err(DecodeError::UnexpectedType),
71                }
72            }
73        }
74    };
75}
76
77macro_rules! impl_int {
78    ($name:ty) => {
79        impl Decode for $name {
80            fn try_default() -> Result<Self, DecodeError> {
81                Ok(Default::default())
82            }
83
84            fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
85                match value {
86                    Value::Unsigned(v) => {
87                        v.try_into().map_err(|_| DecodeError::UnexpectedIntegerSize)
88                    }
89                    Value::Negative(v) => {
90                        v.try_into().map_err(|_| DecodeError::UnexpectedIntegerSize)
91                    }
92                    _ => Err(DecodeError::UnexpectedType),
93                }
94            }
95        }
96    };
97}
98
99impl_uint!(u8);
100impl_uint!(u16);
101impl_uint!(u32);
102impl_uint!(u64);
103impl_int!(i8);
104impl_int!(i16);
105impl_int!(i32);
106impl_int!(i64);
107
108impl Decode for u128 {
109    fn try_default() -> Result<Self, DecodeError> {
110        Ok(Default::default())
111    }
112
113    fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
114        match value {
115            Value::ByteString(v) => {
116                const SIZE: usize = std::mem::size_of::<u128>();
117
118                match v.len().cmp(&SIZE) {
119                    Ordering::Greater => {
120                        // We only support what can be represented in u128. For all practical cases,
121                        // this should be fine.
122                        Err(DecodeError::UnexpectedIntegerSize)
123                    }
124                    Ordering::Less => {
125                        // Fill any leading bytes with zeros.
126                        let mut data = [0u8; SIZE];
127                        data[SIZE - v.len()..].copy_from_slice(&v);
128                        Ok(u128::from_be_bytes(data))
129                    }
130                    Ordering::Equal => {
131                        // Exactly the right size.
132                        Ok(u128::from_be_bytes(v.try_into().unwrap()))
133                    }
134                }
135            }
136            _ => Err(DecodeError::UnexpectedType),
137        }
138    }
139}
140
141impl Decode for bool {
142    fn try_default() -> Result<Self, DecodeError> {
143        Ok(Default::default())
144    }
145
146    fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
147        match value {
148            Value::Simple(SimpleValue::FalseValue) => Ok(false),
149            Value::Simple(SimpleValue::TrueValue) => Ok(true),
150            _ => Err(DecodeError::UnexpectedType),
151        }
152    }
153}
154
155impl Decode for String {
156    fn try_default() -> Result<Self, DecodeError> {
157        Ok(Default::default())
158    }
159
160    fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
161        match value {
162            Value::TextString(v) => Ok(v),
163            _ => Err(DecodeError::UnexpectedType),
164        }
165    }
166}
167
168impl Decode for char {
169    fn try_default() -> Result<Self, DecodeError> {
170        Ok(Default::default())
171    }
172
173    fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
174        match value {
175            Value::Unsigned(n) if n <= (u32::MAX as u64) => {
176                char::from_u32(n as u32).ok_or(DecodeError::UnexpectedType)
177            }
178            _ => Err(DecodeError::UnexpectedType),
179        }
180    }
181}
182
183impl<T: Decode> Decode for Vec<T> {
184    default fn try_default() -> Result<Self, DecodeError> {
185        Ok(Default::default())
186    }
187
188    default fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
189        match value {
190            Value::Array(v) => v.into_iter().map(T::try_from_cbor_value).collect(),
191            _ => Err(DecodeError::UnexpectedType),
192        }
193    }
194}
195
196impl Decode for Vec<u8> {
197    fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
198        match value {
199            Value::ByteString(v) => Ok(v),
200            _ => Err(DecodeError::UnexpectedType),
201        }
202    }
203}
204
205impl<T: Decode, const N: usize> Decode for [T; N] {
206    default fn try_default() -> Result<Self, DecodeError> {
207        Err(DecodeError::MissingField)
208    }
209
210    default fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
211        match value {
212            Value::Array(v) => v
213                .into_iter()
214                .map(T::try_from_cbor_value)
215                .collect::<Result<Vec<_>, _>>()?
216                .try_into()
217                .map_err(|_| DecodeError::UnexpectedType),
218            _ => Err(DecodeError::UnexpectedType),
219        }
220    }
221}
222
223impl<const N: usize> Decode for [u8; N] {
224    fn try_default() -> Result<Self, DecodeError> {
225        Ok([0u8; N])
226    }
227
228    fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
229        match value {
230            Value::ByteString(v) => v.try_into().map_err(|_| DecodeError::UnexpectedType),
231            _ => Err(DecodeError::UnexpectedType),
232        }
233    }
234}
235
236impl<T: Decode> Decode for Option<T> {
237    fn try_default() -> Result<Self, DecodeError> {
238        Ok(Default::default())
239    }
240
241    fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
242        match value {
243            Value::Simple(SimpleValue::NullValue) => Ok(None),
244            _ => Ok(Some(T::try_from_cbor_value(value)?)),
245        }
246    }
247}
248
249impl Decode for Value {
250    fn try_default() -> Result<Self, DecodeError> {
251        Ok(Value::Simple(SimpleValue::NullValue))
252    }
253
254    fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
255        Ok(value)
256    }
257}
258
259impl<K: Decode + Ord, V: Decode> Decode for BTreeMap<K, V> {
260    fn try_default() -> Result<Self, DecodeError> {
261        Ok(Default::default())
262    }
263
264    fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
265        match value {
266            Value::Map(v) => {
267                let result: Result<Vec<_>, DecodeError> = v
268                    .into_iter()
269                    .map(|(k, v)| Ok((K::try_from_cbor_value(k)?, V::try_from_cbor_value(v)?)))
270                    .collect();
271                Ok(result?.into_iter().collect())
272            }
273            _ => Err(DecodeError::UnexpectedType),
274        }
275    }
276}
277
278impl<T: Decode + Ord> Decode for BTreeSet<T> {
279    fn try_default() -> Result<Self, DecodeError> {
280        Ok(Default::default())
281    }
282
283    fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
284        match value {
285            Value::Array(v) => v.into_iter().map(T::try_from_cbor_value).collect(),
286            _ => Err(DecodeError::UnexpectedType),
287        }
288    }
289}
290
291impl<K: Decode + Eq + std::hash::Hash, V: Decode> Decode for HashMap<K, V> {
292    fn try_default() -> Result<Self, DecodeError> {
293        Ok(Default::default())
294    }
295
296    fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
297        match value {
298            Value::Map(v) => {
299                let result: Result<Vec<_>, DecodeError> = v
300                    .into_iter()
301                    .map(|(k, v)| Ok((K::try_from_cbor_value(k)?, V::try_from_cbor_value(v)?)))
302                    .collect();
303                Ok(result?.into_iter().collect())
304            }
305            _ => Err(DecodeError::UnexpectedType),
306        }
307    }
308}
309
310impl<T: Decode + Eq + std::hash::Hash> Decode for HashSet<T> {
311    fn try_default() -> Result<Self, DecodeError> {
312        Ok(Default::default())
313    }
314
315    fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
316        match value {
317            Value::Array(v) => v.into_iter().map(T::try_from_cbor_value).collect(),
318            _ => Err(DecodeError::UnexpectedType),
319        }
320    }
321}
322
323impl Decode for () {
324    fn try_default() -> Result<Self, DecodeError> {
325        Ok(())
326    }
327
328    fn try_from_cbor_value(value: Value) -> Result<Self, DecodeError> {
329        match value {
330            Value::Simple(SimpleValue::NullValue) => Ok(()),
331            Value::Simple(SimpleValue::Undefined) => Ok(()),
332            _ => Err(DecodeError::UnexpectedType),
333        }
334    }
335}