toe_beans/v4/message/
slicer.rs

1use log::trace;
2
3/// Takes a slice as input and divides it into smaller slices.
4/// This processes the slice from start to end by user-provided _len_ sized chunks.
5///
6/// For example `&[1, 2, 3, 4] --> &[1, 2] and &[3, 4]`.
7///
8/// Uses:
9/// - When you know the length to slice at runtime but not compile time.
10/// - When parsing formats within formats. For example,
11///   the DHCP format has an options field that contains TLV
12///   formatted options. See `options/options.rs`.
13pub struct Slicer<'de> {
14    input: &'de [u8],
15    input_index: usize,
16}
17
18impl<'de> Slicer<'de> {
19    /// Creates an instance of Slicer.
20    pub fn new(input: &'de [u8]) -> Self {
21        Slicer {
22            input,
23            input_index: 0,
24        }
25    }
26
27    /// Returns the next len number of bytes and changes the current position the same amount.
28    ///
29    /// Returns an Option instead of panicking. Use `slice_unchecked` if it is okay to panic.
30    #[inline]
31    pub fn slice(&mut self, len: usize) -> Option<&'de [u8]> {
32        trace!("slice");
33        let slice = self.input.get(self.input_index..self.input_index + len);
34
35        if slice.is_some() {
36            self.input_index += len;
37        }
38
39        slice
40    }
41
42    /// Returns the next len number of bytes and changes the current position the same amount.
43    ///
44    /// Can panic if slicing past array length. Use `slice` for no panic.
45    #[inline]
46    pub fn slice_unchecked(&mut self, len: usize) -> &'de [u8] {
47        trace!("slice_unchecked");
48        let slice = &self.input[self.input_index..self.input_index + len];
49        self.input_index += len;
50        slice
51    }
52
53    /// Returns the remaining bytes in the input and resets the current position to the start.
54    #[inline]
55    pub fn slice_remainder(&mut self) -> &'de [u8] {
56        trace!("slice_remainder");
57        let slice = &self.input[self.input_index..];
58        self.reset();
59        slice
60    }
61
62    /// Slicer keeps track of how many bytes have been sliced (the position from start).
63    /// This resets that internal state.
64    #[inline]
65    pub fn reset(&mut self) {
66        self.input_index = 0;
67    }
68}