cbor_data/validated/
mod.rs

1//! Everything in this module and below assumes that we’re dealing with valid CBOR bytes!
2use self::iterators::{ArrayIter, BytesIter, DictIter, StringIter};
3use crate::{
4    constants::*,
5    reader::{float, indefinite, integer, major, tags},
6    Cbor, ItemKind, Tags,
7};
8
9pub mod indexing;
10pub mod item;
11pub mod iterators;
12pub mod tags;
13
14fn skip_bytes(bytes: &[u8]) -> (Option<&[u8]>, &[u8]) {
15    let (len, _, mut rest) = integer(bytes).or_else(|| indefinite(bytes)).unwrap();
16    if len == u64::MAX {
17        // since an item takes at least 1 byte, u64::MAX is an impossible size
18        while rest[0] != STOP_BYTE {
19            let (len, _, r) = integer(rest).unwrap();
20            rest = &r[len as usize..];
21        }
22        rest = &rest[1..];
23        (None, rest)
24    } else {
25        let len = len as usize;
26        (Some(&rest[..len]), &rest[len..])
27    }
28}
29
30fn skip(bytes: &[u8]) -> (Option<&[u8]>, &[u8]) {
31    match major(bytes).unwrap() {
32        MAJOR_POS | MAJOR_NEG | MAJOR_LIT => (None, integer(bytes).unwrap().2),
33        MAJOR_STR | MAJOR_BYTES => skip_bytes(bytes),
34        MAJOR_TAG => skip(integer(bytes).unwrap().2),
35        MAJOR_ARRAY => {
36            let (len, _, mut rest) = integer(bytes).or_else(|| indefinite(bytes)).unwrap();
37            if len == u64::MAX {
38                // since an item takes at least 1 byte, u64::MAX is an impossible size
39                while rest[0] != STOP_BYTE {
40                    rest = skip(rest).1;
41                }
42                rest = &rest[1..];
43            } else {
44                for _ in 0..len {
45                    rest = skip(rest).1;
46                }
47            }
48            (None, rest)
49        }
50        MAJOR_DICT => {
51            let (len, _, mut rest) = integer(bytes).or_else(|| indefinite(bytes)).unwrap();
52            if len == u64::MAX {
53                // since an item takes at least 1 byte, u64::MAX is an impossible size
54                while rest[0] != STOP_BYTE {
55                    rest = skip(rest).1;
56                    rest = skip(rest).1;
57                }
58                rest = &rest[1..];
59            } else {
60                for _ in 0..len {
61                    rest = skip(rest).1;
62                    rest = skip(rest).1;
63                }
64            }
65            (None, rest)
66        }
67        _ => unreachable!(),
68    }
69}
70
71fn string_iter(bytes: &[u8]) -> StringIter<'_> {
72    if bytes[0] & 31 == INDEFINITE_SIZE {
73        StringIter::new(&bytes[1..], None)
74    } else {
75        StringIter::new(bytes, Some(1))
76    }
77}
78
79fn bytes_iter(bytes: &[u8]) -> BytesIter<'_> {
80    if bytes[0] & 31 == INDEFINITE_SIZE {
81        BytesIter::new(&bytes[1..], None)
82    } else {
83        BytesIter::new(bytes, Some(1))
84    }
85}
86
87fn item(bytes: &[u8]) -> ItemKind {
88    use ItemKind::*;
89
90    match major(bytes).unwrap() {
91        MAJOR_POS => Pos(integer(bytes).unwrap().0),
92        MAJOR_NEG => Neg(integer(bytes).unwrap().0),
93        MAJOR_BYTES => Bytes(bytes_iter(bytes)),
94        MAJOR_STR => Str(string_iter(bytes)),
95        MAJOR_LIT => match bytes[0] & 31 {
96            LIT_FALSE => Bool(false),
97            LIT_TRUE => Bool(true),
98            LIT_NULL => Null,
99            LIT_UNDEFINED => Undefined,
100            LIT_SIMPLE => Simple(bytes[1]),
101            LIT_FLOAT16 | LIT_FLOAT32 | LIT_FLOAT64 => Float(float(bytes).unwrap().0),
102            x if x < 24 => Simple(x),
103            _ => unreachable!(),
104        },
105        MAJOR_TAG => item(integer(bytes).unwrap().2),
106        MAJOR_ARRAY => {
107            let (len, _, arr) = integer(bytes).or_else(|| indefinite(bytes)).unwrap();
108            let len = if len == u64::MAX { None } else { Some(len) };
109            Array(ArrayIter::new(arr, len))
110        }
111        MAJOR_DICT => {
112            let (len, _, dict) = integer(bytes).or_else(|| indefinite(bytes)).unwrap();
113            let len = if len == u64::MAX { None } else { Some(len) };
114            Dict(DictIter::new(dict, len))
115        }
116        _ => unreachable!(),
117    }
118}
119
120pub fn tagged_item(bytes: &[u8]) -> (Tags, ItemKind) {
121    let (tags, rest) = tags(bytes).unwrap();
122    let kind = item(rest);
123    (tags, kind)
124}
125
126/// Iterator over CBOR items provided within a byte slice
127///
128/// The iterator yields either a known number of elements or until encountering a STOP_BYTE.
129#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
130struct CborIter<'a>(&'a [u8], Option<u64>);
131
132impl<'a> CborIter<'a> {
133    pub fn new(bytes: &'a [u8], len: Option<u64>) -> Self {
134        Self(bytes, len)
135    }
136    pub fn size(&self) -> Option<u64> {
137        self.1
138    }
139}
140
141impl<'a> Iterator for CborIter<'a> {
142    type Item = (Option<&'a [u8]>, &'a Cbor);
143
144    fn next(&mut self) -> Option<Self::Item> {
145        let CborIter(b, elems) = self;
146        if *elems == Some(0) || *elems == None && b[0] == STOP_BYTE {
147            None
148        } else {
149            let (value, rest) = skip(b);
150            let bytes = &b[..b.len() - rest.len()];
151            if let Some(x) = elems.as_mut() {
152                *x -= 1;
153            }
154            *b = rest;
155            Some((value, Cbor::unchecked(bytes)))
156        }
157    }
158}