/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ciborium-ll-0.2.2/src/dec.rs
Line | Count | Source |
1 | | use super::*; |
2 | | |
3 | | use ciborium_io::Read; |
4 | | |
5 | | /// An error that occurred while decoding |
6 | | #[derive(Debug)] |
7 | | pub enum Error<T> { |
8 | | /// An error occurred while reading bytes |
9 | | /// |
10 | | /// Contains the underlying error returned while reading. |
11 | | Io(T), |
12 | | |
13 | | /// An error occurred while parsing bytes |
14 | | /// |
15 | | /// Contains the offset into the stream where the syntax error occurred. |
16 | | Syntax(usize), |
17 | | } |
18 | | |
19 | | impl<T> From<T> for Error<T> { |
20 | | #[inline] |
21 | 0 | fn from(value: T) -> Self { |
22 | 0 | Self::Io(value) |
23 | 0 | } Unexecuted instantiation: <ciborium_ll::dec::Error<std::io::error::Error> as core::convert::From<std::io::error::Error>>::from Unexecuted instantiation: <ciborium_ll::dec::Error<_> as core::convert::From<_>>::from |
24 | | } |
25 | | |
26 | | /// A decoder for deserializing CBOR items |
27 | | /// |
28 | | /// This decoder manages the low-level decoding of CBOR items into `Header` |
29 | | /// objects. It also contains utility functions for parsing segmented bytes |
30 | | /// and text inputs. |
31 | | pub struct Decoder<R: Read> { |
32 | | reader: R, |
33 | | offset: usize, |
34 | | buffer: Option<Title>, |
35 | | } |
36 | | |
37 | | impl<R: Read> From<R> for Decoder<R> { |
38 | | #[inline] |
39 | 0 | fn from(value: R) -> Self { |
40 | 0 | Self { |
41 | 0 | reader: value, |
42 | 0 | offset: 0, |
43 | 0 | buffer: None, |
44 | 0 | } |
45 | 0 | } Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]> as core::convert::From<&[u8]>>::from Unexecuted instantiation: <ciborium_ll::dec::Decoder<_> as core::convert::From<_>>::from |
46 | | } |
47 | | |
48 | | impl<R: Read> Read for Decoder<R> { |
49 | | type Error = R::Error; |
50 | | |
51 | | #[inline] |
52 | 0 | fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { |
53 | 0 | assert!(self.buffer.is_none()); |
54 | 0 | self.reader.read_exact(data)?; |
55 | 0 | self.offset += data.len(); |
56 | 0 | Ok(()) |
57 | 0 | } Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]> as ciborium_io::Read>::read_exact Unexecuted instantiation: <ciborium_ll::dec::Decoder<_> as ciborium_io::Read>::read_exact |
58 | | } |
59 | | |
60 | | impl<R: Read> Decoder<R> { |
61 | | #[inline] |
62 | 0 | fn pull_title(&mut self) -> Result<Title, Error<R::Error>> { |
63 | 0 | if let Some(title) = self.buffer.take() { |
64 | 0 | self.offset += title.1.as_ref().len() + 1; |
65 | 0 | return Ok(title); |
66 | 0 | } |
67 | | |
68 | 0 | let mut prefix = [0u8; 1]; |
69 | 0 | self.read_exact(&mut prefix[..])?; |
70 | | |
71 | 0 | let major = match prefix[0] >> 5 { |
72 | 0 | 0 => Major::Positive, |
73 | 0 | 1 => Major::Negative, |
74 | 0 | 2 => Major::Bytes, |
75 | 0 | 3 => Major::Text, |
76 | 0 | 4 => Major::Array, |
77 | 0 | 5 => Major::Map, |
78 | 0 | 6 => Major::Tag, |
79 | 0 | 7 => Major::Other, |
80 | 0 | _ => unreachable!(), |
81 | | }; |
82 | | |
83 | 0 | let mut minor = match prefix[0] & 0b00011111 { |
84 | 0 | x if x < 24 => Minor::This(x), |
85 | 0 | 24 => Minor::Next1([0; 1]), |
86 | 0 | 25 => Minor::Next2([0; 2]), |
87 | 0 | 26 => Minor::Next4([0; 4]), |
88 | 0 | 27 => Minor::Next8([0; 8]), |
89 | 0 | 31 => Minor::More, |
90 | 0 | _ => return Err(Error::Syntax(self.offset - 1)), |
91 | | }; |
92 | | |
93 | 0 | self.read_exact(minor.as_mut())?; |
94 | 0 | Ok(Title(major, minor)) |
95 | 0 | } Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::pull_title Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::pull_title |
96 | | |
97 | | #[inline] |
98 | 0 | fn push_title(&mut self, item: Title) { |
99 | 0 | assert!(self.buffer.is_none()); |
100 | 0 | self.buffer = Some(item); |
101 | 0 | self.offset -= item.1.as_ref().len() + 1; |
102 | 0 | } Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::push_title Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::push_title |
103 | | |
104 | | /// Pulls the next header from the input |
105 | | #[inline] |
106 | 0 | pub fn pull(&mut self) -> Result<Header, Error<R::Error>> { |
107 | 0 | let offset = self.offset; |
108 | 0 | self.pull_title()? |
109 | 0 | .try_into() |
110 | 0 | .map_err(|_| Error::Syntax(offset)) Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::pull::{closure#0}Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::pull::{closure#0} |
111 | 0 | } Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::pull Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::pull |
112 | | |
113 | | /// Push a single header into the input buffer |
114 | | /// |
115 | | /// # Panics |
116 | | /// |
117 | | /// This function panics if called while there is already a header in the |
118 | | /// input buffer. You should take care to call this function only after |
119 | | /// pulling a header to ensure there is nothing in the input buffer. |
120 | | #[inline] |
121 | 0 | pub fn push(&mut self, item: Header) { |
122 | 0 | self.push_title(Title::from(item)) |
123 | 0 | } Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::push Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::push |
124 | | |
125 | | /// Gets the current byte offset into the stream |
126 | | /// |
127 | | /// The offset starts at zero when the decoder is created. Therefore, if |
128 | | /// bytes were already read from the reader before the decoder was created, |
129 | | /// you must account for this. |
130 | | #[inline] |
131 | 0 | pub fn offset(&mut self) -> usize { |
132 | 0 | self.offset |
133 | 0 | } Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::offset Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::offset |
134 | | |
135 | | /// Process an incoming bytes item |
136 | | /// |
137 | | /// In CBOR, bytes can be segmented. The logic for this can be a bit tricky, |
138 | | /// so we encapsulate that logic using this function. This function **MUST** |
139 | | /// be called immediately after first pulling a `Header::Bytes(len)` from |
140 | | /// the wire and `len` must be provided to this function from that value. |
141 | | /// |
142 | | /// The `buf` parameter provides a buffer used when reading in the segmented |
143 | | /// bytes. A large buffer will result in fewer calls to read incoming bytes |
144 | | /// at the cost of memory usage. You should consider this trade off when |
145 | | /// deciding the size of your buffer. |
146 | | #[inline] |
147 | 0 | pub fn bytes(&mut self, len: Option<usize>) -> Segments<R, crate::seg::Bytes> { |
148 | 0 | self.push(Header::Bytes(len)); |
149 | 0 | Segments::new(self, |header| match header { |
150 | 0 | Header::Bytes(len) => Ok(len), |
151 | 0 | _ => Err(()), |
152 | 0 | }) Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::bytes::{closure#0}Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::bytes::{closure#0} |
153 | 0 | } Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::bytes Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::bytes |
154 | | |
155 | | /// Process an incoming text item |
156 | | /// |
157 | | /// In CBOR, text can be segmented. The logic for this can be a bit tricky, |
158 | | /// so we encapsulate that logic using this function. This function **MUST** |
159 | | /// be called immediately after first pulling a `Header::Text(len)` from |
160 | | /// the wire and `len` must be provided to this function from that value. |
161 | | /// |
162 | | /// The `buf` parameter provides a buffer used when reading in the segmented |
163 | | /// text. A large buffer will result in fewer calls to read incoming bytes |
164 | | /// at the cost of memory usage. You should consider this trade off when |
165 | | /// deciding the size of your buffer. |
166 | | #[inline] |
167 | 0 | pub fn text(&mut self, len: Option<usize>) -> Segments<R, crate::seg::Text> { |
168 | 0 | self.push(Header::Text(len)); |
169 | 0 | Segments::new(self, |header| match header { |
170 | 0 | Header::Text(len) => Ok(len), |
171 | 0 | _ => Err(()), |
172 | 0 | }) Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::text::{closure#0}Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::text::{closure#0} |
173 | 0 | } Unexecuted instantiation: <ciborium_ll::dec::Decoder<&[u8]>>::text Unexecuted instantiation: <ciborium_ll::dec::Decoder<_>>::text |
174 | | } |