planus/
slice_helpers.rs

1use crate::errors::ErrorKind;
2
3#[doc(hidden)]
4#[derive(Copy, Clone, Debug)]
5pub struct SliceWithStartOffset<'buf> {
6    pub buffer: &'buf [u8],
7    pub offset_from_start: usize,
8}
9
10impl<'buf> SliceWithStartOffset<'buf> {
11    /// Length of the slize in bytes.
12    pub fn len(&self) -> usize {
13        self.buffer.len()
14    }
15
16    /// Returns true if the slice is empty.
17    pub fn is_empty(&self) -> bool {
18        self.len() == 0
19    }
20
21    /// Returns the inner buffer as a slice.
22    pub fn as_slice(&self) -> &'buf [u8] {
23        self.buffer
24    }
25
26    /// Returns a new slice which is advanced by `amount` bytes.
27    pub fn advance(&self, amount: usize) -> core::result::Result<Self, ErrorKind> {
28        let buffer = self.buffer.get(amount..).ok_or(ErrorKind::InvalidOffset)?;
29        Ok(Self {
30            buffer,
31            offset_from_start: self.offset_from_start + amount,
32        })
33    }
34
35    /// The same as [`SliceWithStartOffset::advance`], but converted to an array reference.
36    pub fn advance_as_array<const N: usize>(
37        &self,
38        amount: usize,
39    ) -> core::result::Result<ArrayWithStartOffset<'buf, N>, ErrorKind> {
40        let buffer = self
41            .buffer
42            .get(amount..amount + N)
43            .ok_or(ErrorKind::InvalidOffset)?;
44        Ok(ArrayWithStartOffset {
45            buffer: buffer.try_into().unwrap(),
46            offset_from_start: self.offset_from_start + amount,
47        })
48    }
49
50    /// # Safety
51    ///
52    /// Calling this function is only safe if you guarantee that `amount + N < self.len()`
53    pub unsafe fn unchecked_advance_as_array<const N: usize>(
54        &self,
55        amount: usize,
56    ) -> ArrayWithStartOffset<'buf, N> {
57        let buffer = self.buffer.get_unchecked(amount..amount + N);
58        ArrayWithStartOffset {
59            buffer: buffer.try_into().unwrap(),
60            offset_from_start: self.offset_from_start + amount,
61        }
62    }
63}
64
65#[doc(hidden)]
66#[derive(Copy, Clone, Debug)]
67pub struct ArrayWithStartOffset<'buf, const N: usize> {
68    pub buffer: &'buf [u8; N],
69    pub offset_from_start: usize,
70}
71
72impl<'buf, const N: usize> ArrayWithStartOffset<'buf, N> {
73    /// Get inner buffer as an array reference
74    pub fn as_array(&self) -> &'buf [u8; N] {
75        self.buffer
76    }
77
78    /// Returns a new array which is advanced by `amount` bytes.
79    pub fn advance_as_array<const K: usize>(
80        &self,
81        amount: usize,
82    ) -> core::result::Result<ArrayWithStartOffset<'buf, K>, ErrorKind> {
83        let buffer = self
84            .buffer
85            .get(amount..amount + K)
86            .ok_or(ErrorKind::InvalidOffset)?;
87        Ok(ArrayWithStartOffset {
88            buffer: buffer.try_into().unwrap(),
89            offset_from_start: self.offset_from_start + amount,
90        })
91    }
92}