lilliput_core/
decoder.rs

1//! Decoders for decoding lilliput-encoded values.
2
3use crate::{
4    error::{Error, Result},
5    header::Header,
6    io::{Read, Reference},
7    marker::Marker,
8    value::Value,
9};
10
11mod bool;
12mod bytes;
13mod float;
14mod int;
15mod map;
16mod null;
17mod seq;
18mod string;
19mod unit;
20
21/// A decoder for decoding lilliput-encoded values.
22#[derive(Debug)]
23pub struct Decoder<R> {
24    reader: R,
25    pos: usize,
26}
27
28impl<R> Decoder<R> {
29    /// Creates a decoder from a `reader`.
30    pub fn from_reader(reader: R) -> Self {
31        Decoder { reader, pos: 0 }
32    }
33
34    /// Returns the decoder's internal `reader`, consuming `self`.
35    pub fn into_reader(self) -> R {
36        self.reader
37    }
38
39    /// Returns the decoder's current read position.
40    pub fn pos(&self) -> usize {
41        self.pos
42    }
43}
44
45impl<'de, R> Decoder<R>
46where
47    R: Read<'de>,
48{
49    // MARK: - Value
50
51    /// Decodes a `Value`.
52    pub fn decode_value(&mut self) -> Result<Value> {
53        let header = self.decode_header()?;
54        self.decode_value_of(header)
55    }
56
57    // MARK: - Marker
58
59    /// Decodes a value's type `Marker`.
60    pub fn peek_marker(&mut self) -> Result<Marker> {
61        self.peek_byte().map(Marker::detect)
62    }
63
64    // MARK: - Header
65
66    /// Decodes a value's `Header`.
67    pub fn decode_header(&mut self) -> Result<Header> {
68        match self.peek_marker()? {
69            Marker::Int => self.decode_int_header().map(From::from),
70            Marker::String => self.decode_string_header().map(From::from),
71            Marker::Seq => self.decode_seq_header().map(From::from),
72            Marker::Map => self.decode_map_header().map(From::from),
73            Marker::Float => self.decode_float_header().map(From::from),
74            Marker::Bytes => self.decode_bytes_header().map(From::from),
75            Marker::Bool => self.decode_bool_header().map(From::from),
76            Marker::Unit => self.decode_unit_header().map(From::from),
77            Marker::Null => self.decode_null_header().map(From::from),
78        }
79    }
80
81    // MARK: - Skip
82
83    /// Skips the next to-be-decoded value.
84    #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
85    pub fn skip_value(&mut self) -> Result<()> {
86        let header = self.decode_header()?;
87        self.skip_value_of(header)
88    }
89
90    /// Skips the value for a given `header`.
91    #[cfg_attr(feature = "tracing", tracing::instrument(skip_all))]
92    pub fn skip_value_of(&mut self, header: Header) -> Result<()> {
93        match header {
94            Header::Int(header) => self.skip_int_value_of(header),
95            Header::String(header) => self.skip_string_value_of(header),
96            Header::Seq(header) => self.skip_seq_value_of(header),
97            Header::Map(header) => self.skip_map_value_of(header),
98            Header::Float(header) => self.skip_float_value_of(header),
99            Header::Bytes(header) => self.skip_bytes_value_of(header),
100            Header::Bool(header) => self.skip_bool_value_of(header),
101            Header::Unit(header) => self.skip_unit_value_of(header),
102            Header::Null(header) => self.skip_null_value_of(header),
103        }
104    }
105
106    // MARK: - Body
107
108    /// Decodes value for a given `header`.
109    pub fn decode_value_of(&mut self, header: Header) -> Result<Value> {
110        match header {
111            Header::Int(header) => self.decode_int_value_of(header).map(From::from),
112            Header::String(header) => self.decode_string_value_of(header).map(From::from),
113            Header::Seq(header) => self.decode_seq_value_of(header).map(From::from),
114            Header::Map(header) => self.decode_map_value_of(header).map(From::from),
115            Header::Float(header) => self.decode_float_value_of(header).map(From::from),
116            Header::Bytes(header) => self.decode_bytes_value_of(header).map(From::from),
117            Header::Bool(header) => self.decode_bool_value_of(header).map(From::from),
118            Header::Unit(header) => self.decode_unit_value_of(header).map(From::from),
119            Header::Null(header) => self.decode_null_value_of(header).map(From::from),
120        }
121    }
122}
123
124// MARK: - Auxiliary Methods
125
126impl<'de, R> Decoder<R>
127where
128    R: Read<'de>,
129{
130    #[inline]
131    fn peek_byte(&mut self) -> Result<u8> {
132        self.reader.peek_one()
133    }
134
135    #[inline]
136    fn pull_byte_expecting(&mut self, marker: Marker) -> Result<u8> {
137        let pos = self.pos;
138
139        let byte = self.pull_byte()?;
140
141        marker.validate(byte).map_err(|exp| {
142            Error::invalid_type(
143                exp.unexpected.to_string(),
144                exp.expected.to_string(),
145                Some(pos),
146            )
147        })?;
148
149        Ok(byte)
150    }
151
152    #[inline]
153    fn pull_byte(&mut self) -> Result<u8> {
154        let byte = self.reader.read_one()?;
155
156        self.pos += 1;
157
158        Ok(byte)
159    }
160
161    #[inline]
162    fn pull_bytes_into<'s>(&'s mut self, buf: &'s mut [u8]) -> Result<()> {
163        let len = buf.len();
164
165        if len == 0 {
166            return Ok(());
167        }
168
169        self.reader.read_into(buf)?;
170
171        self.pos += len;
172
173        Ok(())
174    }
175
176    #[inline]
177    fn pull_bytes<'s>(
178        &'s mut self,
179        len: usize,
180        scratch: &'s mut Vec<u8>,
181    ) -> Result<Reference<'de, 's, [u8]>> {
182        let bytes = self.reader.read(len, scratch)?;
183
184        debug_assert_eq!(bytes.len(), len);
185
186        self.pos += len;
187
188        Ok(bytes)
189    }
190
191    #[inline]
192    fn pull_len_bytes(&mut self, width: u8) -> Result<usize> {
193        let pos = self.pos;
194
195        const MAX_WIDTH: usize = 8;
196        let mut padded_be_bytes: [u8; MAX_WIDTH] = [0b0; MAX_WIDTH];
197        self.pull_bytes_into(&mut padded_be_bytes[(MAX_WIDTH - (width as usize))..])?;
198
199        u64::from_be_bytes(padded_be_bytes)
200            .try_into()
201            .map_err(|_| Error::number_out_of_range(Some(pos)))
202    }
203}
204
205// MARK: - Tests
206
207#[cfg(test)]
208mod test {
209    use crate::{error::ErrorCode, io::SliceReader};
210
211    use super::*;
212
213    #[test]
214    fn new() {
215        let bytes = SliceReader::new(&[1, 2, 3]);
216        let decoder = Decoder::from_reader(&bytes);
217        assert_eq!(decoder.pos, 0);
218    }
219
220    #[test]
221    fn pull_byte() {
222        let bytes = SliceReader::new(&[1, 2, 3]);
223        let mut decoder = Decoder::from_reader(bytes);
224        assert_eq!(decoder.pos, 0);
225
226        let byte = decoder.pull_byte().unwrap();
227        assert_eq!(byte, 1);
228        assert_eq!(decoder.pos, 1);
229
230        let byte = decoder.pull_byte().unwrap();
231        assert_eq!(byte, 2);
232        assert_eq!(decoder.pos, 2);
233
234        let byte = decoder.pull_byte().unwrap();
235        assert_eq!(byte, 3);
236        assert_eq!(decoder.pos, 3);
237
238        let error_code = decoder.pull_byte().unwrap_err().code();
239        assert_eq!(error_code, ErrorCode::UnexpectedEndOfFile);
240    }
241
242    #[test]
243    fn pull_bytes_into() {
244        let bytes = SliceReader::new(&[1, 2, 3]);
245        let mut decoder = Decoder::from_reader(bytes);
246        assert_eq!(decoder.pos, 0);
247
248        let mut buf = vec![];
249        decoder.pull_bytes_into(&mut buf).unwrap();
250        assert_eq!(buf, &[]);
251        assert_eq!(decoder.pos, 0);
252
253        let mut buf = vec![0];
254        decoder.pull_bytes_into(&mut buf).unwrap();
255        assert_eq!(buf, &[1]);
256        assert_eq!(decoder.pos, 1);
257
258        let mut buf = vec![0, 0];
259        decoder.pull_bytes_into(&mut buf).unwrap();
260        assert_eq!(buf, &[2, 3]);
261        assert_eq!(decoder.pos, 3);
262
263        let mut buf = vec![0, 0, 0];
264        let error_code = decoder.pull_bytes_into(&mut buf).unwrap_err().code();
265        assert_eq!(error_code, ErrorCode::UnexpectedEndOfFile);
266        assert_eq!(decoder.pos, 3);
267    }
268
269    #[test]
270    fn pull_bytes() {
271        let bytes = SliceReader::new(&[1, 2, 3]);
272        let mut decoder = Decoder::from_reader(bytes);
273        let mut scratch = vec![];
274        assert_eq!(decoder.pos, 0);
275
276        let reference = decoder.pull_bytes(0, &mut scratch).unwrap();
277        assert_eq!(reference.as_ref(), &[]);
278        assert_eq!(decoder.pos, 0);
279
280        scratch.clear();
281
282        let reference = decoder.pull_bytes(1, &mut scratch).unwrap();
283        assert_eq!(reference.as_ref(), &[1]);
284        assert_eq!(decoder.pos, 1);
285
286        scratch.clear();
287
288        let reference = decoder.pull_bytes(2, &mut scratch).unwrap();
289        assert_eq!(reference.as_ref(), &[2, 3]);
290        assert_eq!(decoder.pos, 3);
291
292        scratch.clear();
293
294        let error_code = decoder.pull_bytes(1, &mut scratch).unwrap_err().code();
295        assert_eq!(error_code, ErrorCode::UnexpectedEndOfFile);
296        assert_eq!(decoder.pos, 3);
297    }
298}