bytes_parser/
parser.rs

1use crate::endianness::ParsingEndian;
2use crate::errors::BytesParserError;
3
4use std::convert::TryInto;
5use std::mem;
6use std::str;
7
8/// A zero-copy bytes parser, useful when parsing bespoke binary protocols.
9///
10/// It wraps a reference to a byte-array, and adds a thin parsing layer: calls to the `parse_*`
11/// reads the bytes and updates an internal cursor sequentially.
12/// This makes for a very linear sequence of calls, when in need to consume, for example,
13/// messages for a bespoke binary protocol.
14///
15/// By default, the parsing is done using the [`ParsingEndian::BE`] endian system, but that
16/// can be configured.
17///
18/// The internal cursor progresses sequentially from position `0`
19/// (i.e. no bytes has been parsed yet) to maximum position of [`BytesParser::length`]
20/// (i.e. all bytes have been parsed).
21///
22/// If necessary, methods are provided to move the cursor around, with error checking in case the
23/// cursor is moved outside the boundaries of the underlying array.
24#[derive(Debug, Copy, Clone)]
25pub struct BytesParser<'a> {
26    buffer: &'a [u8],
27    length: usize,
28    cursor: usize,
29    endian: ParsingEndian,
30}
31
32impl<'a> From<&'a [u8]> for BytesParser<'a> {
33    fn from(bytes: &'a [u8]) -> Self {
34        BytesParser {
35            buffer: bytes,
36            length: bytes.len(),
37            cursor: 0,
38            endian: ParsingEndian::default(),
39        }
40    }
41}
42
43macro_rules! build_parse_type_fn {
44    ($fn_name:ident, $parsed_type:ty) => {
45        #[doc = "Parse a`"]
46        #[doc=stringify!($parsed_type)]
47        #[doc = "` and update the internal cursor accordingly.\n\n"]
48        #[doc = "It produces an error if [`BytesParser::parseable`] returns an amount inferior to"]
49        #[doc = "the amount of bytes occupied by a `"]
50        #[doc=stringify!($parsed_type)]
51        #[doc = "`."]
52        pub fn $fn_name(&mut self) -> Result<$parsed_type, BytesParserError> {
53            let size = mem::size_of::<$parsed_type>();
54            if self.parseable() < size {
55                return Err(BytesParserError::NotEnoughBytesForTypeError(stringify!($parsed_type).to_string()));
56            }
57
58            let start = self.cursor;
59            let end = self.cursor + size;
60            let slice = self.buffer[start..end].try_into().unwrap();
61
62            let value = match self.endian {
63                ParsingEndian::BE => <$parsed_type>::from_be_bytes(slice),
64                ParsingEndian::LE => <$parsed_type>::from_le_bytes(slice),
65            };
66
67            self.cursor += size;
68
69            Ok(value)
70        }
71    };
72}
73
74impl<'a> BytesParser<'a> {
75    build_parse_type_fn!(parse_i8, i8);
76    build_parse_type_fn!(parse_u8, u8);
77
78    build_parse_type_fn!(parse_i16, i16);
79    build_parse_type_fn!(parse_u16, u16);
80
81    build_parse_type_fn!(parse_i32, i32);
82    build_parse_type_fn!(parse_u32, u32);
83
84    build_parse_type_fn!(parse_i64, i64);
85    build_parse_type_fn!(parse_u64, u64);
86
87    build_parse_type_fn!(parse_i128, i128);
88    build_parse_type_fn!(parse_u128, u128);
89
90    build_parse_type_fn!(parse_f32, f32);
91    build_parse_type_fn!(parse_f64, f64);
92
93    build_parse_type_fn!(parse_isize, isize);
94    build_parse_type_fn!(parse_usize, usize);
95
96    /// Parse a [`&str`] and update the internal cursor accordingly.
97    ///
98    /// It produces an error if `BytesParser::parseable()` returns an amount
99    /// inferior to the given `size`.
100    ///
101    /// Typically for binary protocols, the string is preceded by an integer representation of
102    /// the size of the string in bytes. Unfortunately there is no single standard for how that
103    /// integer is encoded (16 bits? 32 bits?), hence the required argument `size`.
104    ///
105    /// The data returned is a "view" of the original bytes array, so that should be considered
106    /// when handling the returned reference and its lifetime. If the returned reference has to
107    /// outlast the inner bytes array, it should probably be cloned or turned into a [`String`].
108    ///
109    /// # Arguments
110    ///
111    /// * `size` - Size of the UTF-8 [`&str`] to parse, in bytes. For Arabic characters, this will
112    ///   be equivalent to the string length, as UTF-8 uses 1 byte per scalar value.
113    ///   But for non-Arabic characters, UTF-8 might requires multiple bytes per scalar value.
114    ///   More details can be found in the
115    ///   [Rust Programming Language book](https://doc.rust-lang.org/book/ch08-02-strings.html#internal-representation).
116    ///   Because of this, determining how many bytes to consume to parse the [`String`] is left
117    ///   to the user.
118    pub fn parse_str_utf8(&mut self, size: usize) -> Result<&str, BytesParserError> {
119        if self.parseable() < size {
120            return Err(BytesParserError::NotEnoughBytesForStringError(size));
121        }
122
123        let start = self.cursor;
124        let end = self.cursor + size;
125        let slice = self.buffer[start..end].try_into().unwrap();
126
127        match str::from_utf8(slice) {
128            Ok(result) => {
129                self.cursor += size;
130                Ok(result)
131            },
132            Err(err) => Err(BytesParserError::StringParseError(err)),
133        }
134    }
135
136    /// Parse a single [`char`] from a [`u32`] (i.e. 4 bytes).s
137    ///
138    /// As per [`char` representation](https://doc.rust-lang.org/1.66.0/std/primitive.char.html#representation),
139    /// Rust uses the fixed amount of 4 bytes to encode a single character.
140    pub fn parse_char_u32(&mut self) -> Result<char, BytesParserError> {
141        let u32value = self.parse_u32()?;
142        let result = char::from_u32(u32value).ok_or(BytesParserError::InvalidU32ForCharError)?;
143        Ok(result)
144    }
145
146    /// "Parse" a slice of bytes `&[u8]` of given `size`, starting from [`Self::position`].
147    ///
148    /// This doesn't actually create anything: it cuts a slice from the inner bytes array,
149    /// that the user can then manipulate in other ways.
150    ///
151    /// The data returned is a "view" of the original bytes array, so that should be considered
152    /// when handling the returned reference and its lifetime. If the returned slice has to
153    /// outlast the inner bytes array, it should probably be cloned.
154    ///
155    /// # Arguments
156    ///
157    /// * `size` - The size of the new slice to cut. The slice will be cut starting from the
158    ///   current position of the internal cursor (i.e. [`Self::position`]).
159    pub fn parse_slice(&mut self, size: usize) -> Result<&[u8], BytesParserError> {
160        if self.parseable() < size {
161            return Err(BytesParserError::NotEnoughBytesForSlice(size));
162        }
163
164        let start = self.cursor;
165        let end = self.cursor + size;
166
167        self.cursor += size;
168
169        Ok(self.buffer[start..end].try_into().unwrap())
170    }
171
172    /// Creates a new [`BytesParser`] that is set to use a slice of bytes as its inner byte array.
173    ///
174    /// This uses [`Self::parse_slice`] to cut a `&[u8]`, and then initializes
175    /// a new [`BytesParser`] using [`Self::from`].
176    ///
177    /// # Arguments
178    ///
179    /// * `size` - The size of the new slice to cut and wrap inside a [`BytesParser`].
180    pub fn from_slice(&mut self, size: usize) -> Result<BytesParser, BytesParserError> {
181        let slice = self.parse_slice(size)?;
182
183        Ok(BytesParser::from(slice))
184    }
185
186    /// Length of the internal bytes array.
187    pub const fn length(&self) -> usize {
188        self.length
189    }
190
191    /// Returns [true] if the internal bytes array is empty.
192    pub const fn is_empty(&self) -> bool {
193        self.length == 0
194    }
195
196    /// Returns the 0-based position of the cursor.
197    ///
198    /// The index returned corresponds to the next bytes that would be parsed.
199    pub const fn position(&self) -> usize {
200        self.cursor
201    }
202
203    /// Returns [`true`] if the internal cursor points at the very start of the bytes array.
204    ///
205    /// When first created, this will return [`true`].
206    pub const fn is_at_start(&self) -> bool {
207        self.cursor == 0
208    }
209
210    /// Returns [`true`] if the internal cursor points at the very end of the bytes array.
211    ///
212    /// When all bytes have been parsed, this will return [`true`].
213    pub const fn is_at_end(&self) -> bool {
214        self.cursor == self.length
215    }
216
217    /// Returns the amount of bytes that can still be parsed.
218    ///
219    /// If [`BytesParser::is_at_start`] returns [`true`],
220    /// then this will return the same as [`BytesParser::length`].
221    /// If [`BytesParser::is_at_end`] returns [`true`],
222    /// then this will return `0`.
223    pub const fn parseable(&self) -> usize {
224        self.length - self.cursor
225    }
226
227    /// Reset cursor to the very start of the bytes array.
228    ///
229    /// This can be used to re-parse bytes.
230    ///
231    /// After this is called, [`BytesParser::is_at_start`] will return [`true`]
232    pub fn reset(&mut self) {
233        self.cursor = 0
234    }
235
236    /// Move internal cursor forward by `amount`.
237    ///
238    /// The new cursor position corresponds to the next byte that would be parsed.
239    /// It produces an error if the new cursor position would fall out-of-bound of the
240    /// internal bytes array.
241    ///
242    /// # Arguments
243    ///
244    /// * `amount` - Amount of bytes to move forward the cursor.
245    pub fn move_forward(&mut self, amount: usize) -> Result<(), BytesParserError> {
246        let mut new_cursor = self.cursor;
247        new_cursor += amount;
248
249        if new_cursor >= self.length {
250            Err(BytesParserError::CursorOutOfBoundError(new_cursor as isize, self.length, self.cursor))
251        } else {
252            self.cursor = new_cursor;
253            Ok(())
254        }
255    }
256
257    /// Move internal cursor backward by `amount`.
258    ///
259    /// The new cursor position corresponds to the next byte that would be parsed.
260    /// It produces an error if the new cursor position would fall out-of-bound of the
261    /// internal bytes array.
262    ///
263    /// # Arguments
264    ///
265    /// * `amount` - Amount of bytes to move backward the cursor.
266    pub fn move_backward(&mut self, amount: usize) -> Result<(), BytesParserError> {
267        let mut new_cursor = self.cursor as isize;
268        new_cursor -= amount as isize;
269
270        if new_cursor < 0 {
271            Err(BytesParserError::CursorOutOfBoundError(new_cursor, self.length, self.cursor))
272        } else {
273            self.cursor = new_cursor as usize;
274            Ok(())
275        }
276    }
277
278    /// Move internal cursor at `position`.
279    ///
280    /// The new cursor position corresponds to the next byte that would be parsed.
281    /// It produces an error if the new cursor position would fall out-of-bound of the
282    /// internal bytes array.
283    ///
284    /// # Arguments
285    ///
286    /// * `position` - Where to move the cursor at.
287    pub fn move_at(&mut self, position: usize) -> Result<(), BytesParserError> {
288        if position >= self.length {
289            Err(BytesParserError::CursorOutOfBoundError(position as isize, self.length, self.cursor))
290        } else {
291            self.cursor = position;
292            Ok(())
293        }
294    }
295
296    /// Sets the [ParsingEndian] to be used when parsing scalar types from the internal bytes array.
297    ///
298    /// # Arguments
299    ///
300    /// * `endian` - The [ParsingEndian] to use when calling `BytesParser::parse_<scalar_type>`.
301    pub fn set_endian(&mut self, endian: ParsingEndian) {
302        self.endian = endian;
303    }
304
305    /// Return the [ParsingEndian] currently used.
306    pub const fn endian(&self) -> ParsingEndian {
307        self.endian
308    }
309}
310
311#[cfg(test)]
312mod tests {
313    use super::BytesParser;
314    use crate::{BytesParserError, ParsingEndian};
315    use std::error::Error;
316
317    #[test]
318    fn parse_unsigned_scalars_using_big_endian() {
319        let input: &[u8] = &[
320            0x12, //< u8
321            0x12, 0x34, //< u16
322            0x12, 0x34, 0x56, 0x78, //< u32
323            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, //< u64
324            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE,
325            0xF0, //< u128
326        ];
327
328        let mut p = BytesParser::from(input);
329
330        assert_eq!(p.endian(), ParsingEndian::BE);
331        assert_eq!(p.length(), 31);
332        assert_eq!(p.parseable(), 31);
333        assert_eq!(p.is_empty(), false);
334        assert_eq!(p.is_at_start(), true);
335
336        assert_eq!(p.parse_u8().unwrap(), 0x12);
337        assert_eq!(p.parseable(), 30);
338        assert_eq!(p.parse_u16().unwrap(), 0x1234);
339        assert_eq!(p.parseable(), 28);
340        assert_eq!(p.parse_u32().unwrap(), 0x12345678);
341        assert_eq!(p.parseable(), 24);
342        assert_eq!(p.parse_u64().unwrap(), 0x123456789ABCDEF0);
343        assert_eq!(p.parseable(), 16);
344        assert_eq!(p.parse_u128().unwrap(), 0x123456789ABCDEF0123456789ABCDEF0);
345        assert_eq!(p.parseable(), 0);
346
347        assert_eq!(p.is_at_end(), true);
348    }
349
350    #[test]
351    fn parse_unsigned_scalars_using_little_endian() {
352        let input: &[u8] = &[
353            0x12, //< u8
354            0x34, 0x12, //< u16
355            0x78, 0x56, 0x34, 0x12, //< u32
356            0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, //< u64
357            0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, 0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34,
358            0x12, //< u128
359        ];
360
361        let mut p = BytesParser::from(input);
362        p.set_endian(ParsingEndian::LE);
363
364        assert_eq!(p.endian(), ParsingEndian::LE);
365        assert_eq!(p.length(), 31);
366        assert_eq!(p.parseable(), 31);
367        assert_eq!(p.is_empty(), false);
368        assert_eq!(p.is_at_start(), true);
369
370        assert_eq!(p.parse_u8().unwrap(), 0x12);
371        assert_eq!(p.parseable(), 30);
372        assert_eq!(p.parse_u16().unwrap(), 0x1234);
373        assert_eq!(p.parseable(), 28);
374        assert_eq!(p.parse_u32().unwrap(), 0x12345678);
375        assert_eq!(p.parseable(), 24);
376        assert_eq!(p.parse_u64().unwrap(), 0x123456789ABCDEF0);
377        assert_eq!(p.parseable(), 16);
378        assert_eq!(p.parse_u128().unwrap(), 0x123456789ABCDEF0123456789ABCDEF0);
379        assert_eq!(p.parseable(), 0);
380
381        assert_eq!(p.is_at_end(), true);
382    }
383
384    #[test]
385    fn parse_signed_scalars_using_big_endian() {
386        let input: &[u8] = &[
387            0x12, //< i8
388            0x12, 0x34, //< i16
389            0x12, 0x34, 0x56, 0x78, //< i32
390            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, //< i64
391            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE,
392            0xF0, //< i128
393            0xFF, 0x7F, 0xFF, 0xFF, //< f32
394            0x7F, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //< f64
395        ];
396
397        let mut p = BytesParser::from(input);
398
399        assert_eq!(p.endian(), ParsingEndian::BE);
400        assert_eq!(p.length(), 43);
401        assert_eq!(p.is_empty(), false);
402        assert_eq!(p.is_at_start(), true);
403
404        assert_eq!(p.parse_i8().unwrap(), 0x12);
405        assert_eq!(p.parse_i16().unwrap(), 0x1234);
406        assert_eq!(p.parse_i32().unwrap(), 0x12345678);
407        assert_eq!(p.parse_i64().unwrap(), 0x123456789ABCDEF0);
408        assert_eq!(p.parse_i128().unwrap(), 0x123456789ABCDEF0123456789ABCDEF0);
409        assert_eq!(p.parse_f32().unwrap(), f32::MIN);
410        assert_eq!(p.parse_f64().unwrap(), f64::MAX);
411
412        assert_eq!(p.is_at_end(), true);
413    }
414
415    #[test]
416    fn parse_signed_scalars_using_little_endian() {
417        let input: &[u8] = &[
418            0x12, //< i8
419            0x34, 0x12, //< i16
420            0x78, 0x56, 0x34, 0x12, //< i32
421            0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, //< i64
422            0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34, 0x12, 0xF0, 0xDE, 0xBC, 0x9A, 0x78, 0x56, 0x34,
423            0x12, //< i128
424            0xFF, 0xFF, 0x7F, 0xFF, //< f32
425            0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x7F, //< f64
426        ];
427
428        let mut p = BytesParser::from(input);
429        p.set_endian(ParsingEndian::LE);
430        assert_eq!(p.length(), 43);
431        assert_eq!(p.is_empty(), false);
432        assert_eq!(p.is_at_start(), true);
433
434        assert_eq!(p.endian(), ParsingEndian::LE);
435
436        assert_eq!(p.parse_i8().unwrap(), 0x12);
437        assert_eq!(p.parse_i16().unwrap(), 0x1234);
438        assert_eq!(p.parse_i32().unwrap(), 0x12345678);
439        assert_eq!(p.parse_i64().unwrap(), 0x123456789ABCDEF0);
440        assert_eq!(p.parse_i128().unwrap(), 0x123456789ABCDEF0123456789ABCDEF0);
441        assert_eq!(p.parse_f32().unwrap(), f32::MIN);
442        assert_eq!(p.parse_f64().unwrap(), f64::MAX);
443
444        assert_eq!(p.is_at_end(), true);
445    }
446
447    #[test]
448    fn parse_moving_the_cursor_around() {
449        let input: &[u8] = &[
450            0x12, //< u8
451            0x12, 0x34, //< u16
452            0x12, 0x34, 0x56, 0x78, //< u32
453            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, //< u64
454            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE,
455            0xF0, //< u128
456        ];
457
458        let mut p = BytesParser::from(input);
459
460        // Parse the first
461        assert_eq!(p.position(), 0);
462        assert_eq!(p.parse_u8().unwrap(), 0x12);
463
464        // Move forward to the last (u128)
465        assert_eq!(p.move_forward(14), Ok(()));
466        assert_eq!(p.parse_u128().unwrap(), 0x123456789ABCDEF0123456789ABCDEF0);
467        assert_eq!(p.position(), 31);
468
469        // Move backward to the third scalar value (u32)
470        assert_eq!(p.move_backward(28), Ok(()));
471        assert_eq!(p.parse_u32().unwrap(), 0x12345678);
472
473        // Move to where the last scalar begin (u128)
474        assert_eq!(p.move_at(15), Ok(()));
475        assert_eq!(p.parse_u128().unwrap(), 0x123456789ABCDEF0123456789ABCDEF0);
476
477        // Move to where the second scalar begins (u16)
478        assert_eq!(p.move_at(1), Ok(()));
479        assert_eq!(p.parse_u16().unwrap(), 0x1234);
480
481        // Move back at the beginning
482        p.reset();
483        assert_eq!(p.position(), 0);
484        assert_eq!(p.parse_u8().unwrap(), 0x12);
485    }
486
487    #[test]
488    fn parse_string() {
489        let input: &[u8] = &[
490            0x00, 0x13, //< u16
491            0x46, 0x6F, 0x72, 0x7A, 0x61, 0x20, //< "Forza "
492            0x4E, 0x61, 0x70, 0x6F, 0x6C, 0x69, 0x20, //< "Napoli "
493            0x53, 0x65, 0x6D, 0x70, 0x72, 0x65, //< "Sempre"
494        ];
495
496        let mut p = BytesParser::from(input);
497
498        let str_len = p.parse_u16().unwrap();
499        assert_eq!(str_len, 19);
500
501        let str = p.parse_str_utf8(str_len as usize).unwrap();
502        assert_eq!(str, "Forza Napoli Sempre");
503    }
504
505    #[test]
506    fn parse_char() {
507        let input: &[u8] = &[
508            0x00, 0x01, 0xF9, 0x80, //< crab, encoded using the big-endian system
509            0x80, 0xF9, 0x01, 0x00, //< crab, encoded using the little-endian system
510        ];
511
512        let mut p = BytesParser::from(input);
513
514        assert_eq!(p.parse_char_u32().unwrap(), '🦀');
515
516        p.set_endian(ParsingEndian::LE);
517
518        assert_eq!(p.parse_char_u32().unwrap(), '🦀');
519    }
520
521    #[test]
522    fn parse_slice() {
523        let input: &[u8] = &[
524            0x12, //< u8
525            0x12, 0x34, //< u16
526            0x12, 0x34, 0x56, 0x78, //< u32
527            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, //< u64
528        ];
529
530        let mut p = BytesParser::from(input);
531
532        assert!(p.move_forward(3).is_ok());
533
534        let input_slice = p.parse_slice(4).unwrap();
535        let mut ps = BytesParser::from(input_slice);
536
537        assert!(ps.is_at_start());
538        assert_eq!(ps.parseable(), 4);
539        assert_eq!(ps.parse_u32().unwrap(), 0x12345678);
540        assert!(ps.is_at_end());
541
542        assert_eq!(p.parse_u32().unwrap(), 0x12345678);
543    }
544
545    #[test]
546    fn from_slice() {
547        let input: &[u8] = &[
548            0x12, //< u8
549            0x12, 0x34, //< u16
550            0x12, 0x34, 0x56, 0x78, //< u32
551            0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, //< u64
552        ];
553
554        let mut p = BytesParser::from(input);
555
556        assert!(p.move_forward(3).is_ok());
557
558        let mut ps = p.from_slice(4).unwrap();
559
560        assert!(ps.is_at_start());
561        assert_eq!(ps.parseable(), 4);
562        assert_eq!(ps.parse_u32().unwrap(), 0x12345678);
563        assert!(ps.is_at_end());
564
565        assert_eq!(p.parse_u32().unwrap(), 0x12345678);
566    }
567
568    #[test]
569    fn try_parse_empty() {
570        let input: &[u8] = &[];
571
572        let mut p = BytesParser::from(input);
573
574        assert_eq!(p.parseable(), 0);
575        assert_eq!(p.is_empty(), true);
576        assert_eq!(p.is_at_start(), p.is_at_end());
577
578        assert_eq!(p.parse_u16().unwrap_err(), BytesParserError::NotEnoughBytesForTypeError("u16".to_string()));
579        assert_eq!(p.parse_char_u32().unwrap_err(), BytesParserError::NotEnoughBytesForTypeError("u32".to_string()));
580        assert_eq!(p.parse_str_utf8(10).unwrap_err(), BytesParserError::NotEnoughBytesForStringError(10));
581    }
582
583    #[test]
584    fn try_moving_cursor_out_of_bound() {
585        let input: &[u8] = &[0x00, 0x11, 0x22];
586
587        let mut p = BytesParser::from(input);
588
589        assert_eq!(p.position(), 0);
590        assert_eq!(p.move_at(3).unwrap_err(), BytesParserError::CursorOutOfBoundError(3, 3, 0));
591        assert_eq!(p.move_at(33).unwrap_err(), BytesParserError::CursorOutOfBoundError(33, 3, 0));
592
593        assert_eq!(p.move_forward(1).unwrap(), ());
594        assert_eq!(p.move_forward(4).unwrap_err(), BytesParserError::CursorOutOfBoundError(5, 3, 1));
595
596        assert_eq!(p.move_backward(2).unwrap_err(), BytesParserError::CursorOutOfBoundError(-1, 3, 1));
597    }
598
599    #[test]
600    fn try_parsing_char_from_invalid_u32_scalar() {
601        let input: &[u8] = &[0x00, 0x11, 0x22, 0x33];
602
603        let mut p = BytesParser::from(input);
604
605        assert_eq!(p.parse_char_u32().unwrap_err(), BytesParserError::InvalidU32ForCharError);
606    }
607
608    #[test]
609    fn try_parsing_invalid_str() {
610        let input: &[u8] = &[0, 159, 146, 150];
611
612        let mut p = BytesParser::from(input);
613
614        let err = p.parse_str_utf8(4).unwrap_err();
615        assert_eq!(err.to_string(), "Failed to parse UTF-8 string: invalid utf-8 sequence of 1 bytes from index 1");
616        assert_eq!(err.source().unwrap().to_string(), "invalid utf-8 sequence of 1 bytes from index 1");
617    }
618}