Skip to main content

zune_core/bytestream/reader/
no_std_readers.rs

1#![allow(dead_code)]
2#![allow(clippy::wrong_self_convention)]
3#![allow(clippy::wrong_self_convention)]
4
5use crate::bytestream::{ZByteIoError, ZByteReaderTrait, ZSeekFrom};
6/// Wraps an in memory buffer providing it with a `Seek` method
7/// but works in `no_std` environments
8///
9/// `std::io::Cursor` is available in std environments, but we also need support
10/// for `no_std` environments so this serves as a drop in replacement
11pub struct ZCursor<T> {
12    pub(crate) stream:   T,
13    pub(crate) position: usize
14}
15
16impl<T: AsRef<[u8]>> ZCursor<T> {
17    pub fn new(buffer: T) -> ZCursor<T> {
18        ZCursor {
19            stream:   buffer,
20            position: 0
21        }
22    }
23}
24
25impl<T: AsRef<[u8]>> ZCursor<T> {
26    /// Move forward `num` bytes  from
27    /// the current position.
28    ///
29    /// It doesn't check that position overflowed, new position
30    /// may point past the internal buffer, all subsequent reads will
31    /// either return an error or zero depending on the method called
32    #[inline]
33    pub fn skip(&mut self, num: usize) {
34        // Can this overflow ??
35        self.position = self.position.wrapping_add(num);
36    }
37    /// Move back `num` bytes from the current position
38    ///
39    ///
40    /// This saturates at zero, it can never be negative or wraparound
41    /// when the value becomes too small
42    #[inline]
43    pub fn rewind(&mut self, num: usize) {
44        self.position = self.position.saturating_sub(num);
45    }
46
47    pub fn split(&self) -> (&[u8], &[u8]) {
48        let slice = self.stream.as_ref();
49        let pos = self.position.min(slice.len());
50        slice.split_at(pos)
51    }
52}
53
54impl<T: AsRef<[u8]>>  ZCursor<T> {
55    #[inline(always)]
56    pub (crate) fn read_byte_no_error_impl(&mut self) -> u8 {
57        let byte = self.stream.as_ref().get(self.position).unwrap_or(&0);
58        self.position += 1;
59        *byte
60    }
61    #[inline(always)]
62    pub (crate) fn read_exact_bytes_impl(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError> {
63        let bytes_read = self.read_bytes(buf)?;
64        if bytes_read != buf.len() {
65            // restore read to initial position it was in.
66            self.rewind(bytes_read);
67            // not all bytes were read.
68            return Err(ZByteIoError::NotEnoughBytes(bytes_read, buf.len()));
69        }
70        Ok(())
71    }
72
73    pub (crate) fn read_const_bytes_impl<const N: usize>(&mut self, buf: &mut [u8; N]) -> Result<(), ZByteIoError> {
74        if self.position + N <= self.stream.as_ref().len() {
75            // we are in bounds
76            let reference = self.stream.as_ref();
77            let position = self.position;
78            if let Some(buf_ref) = reference.get(position..position + N) {
79                self.position += N;
80                buf.copy_from_slice(buf_ref);
81                return Ok(());
82            }
83        }
84        Err(ZByteIoError::Generic("Cannot satisfy read"))
85    }
86
87    pub (crate) fn read_const_bytes_no_error_impl<const N: usize>(&mut self, buf: &mut [u8; N]) {
88        if self.position + N <= self.stream.as_ref().len() {
89            // we are in bounds
90            let reference = self.stream.as_ref();
91            let position = self.position;
92            if let Some(buf_ref) = reference.get(position..position + N) {
93                self.position += N;
94                buf.copy_from_slice(buf_ref);
95            }
96        }
97    }
98
99    #[inline(always)]
100  pub (crate) fn read_bytes_impl(&mut self, buf: &mut [u8]) -> Result<usize, ZByteIoError> {
101        let len = self.peek_bytes_impl(buf)?;
102        self.skip(len);
103        Ok(len)
104    }
105
106    #[inline(always)]
107    pub (crate) fn peek_bytes_impl(&mut self, buf: &mut [u8]) -> Result<usize, ZByteIoError> {
108        let stream_end = self.stream.as_ref().len();
109
110        let start = core::cmp::min(self.position, stream_end);
111        let end = core::cmp::min(self.position + buf.len(), stream_end);
112
113        let slice = self.stream.as_ref().get(start..end).unwrap();
114        buf[..slice.len()].copy_from_slice(slice);
115        let len = slice.len();
116
117        Ok(len)
118    }
119
120    #[inline(always)]
121    pub (crate) fn peek_exact_bytes_impl(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError> {
122        self.read_exact_bytes_impl(buf)?;
123        self.rewind(buf.len());
124        Ok(())
125    }
126
127    #[inline(always)]
128    pub (crate) fn z_seek_impl(&mut self, from: ZSeekFrom) -> Result<u64, ZByteIoError> {
129        let (base_pos, offset) = match from {
130            ZSeekFrom::Start(n) => {
131                self.position = n as usize;
132                return Ok(n);
133            }
134            ZSeekFrom::End(n) => (self.stream.as_ref().len(), n as isize),
135            ZSeekFrom::Current(n) => (self.position, n as isize)
136        };
137        match base_pos.checked_add_signed(offset) {
138            Some(n) => {
139                self.position = n;
140                Ok(self.position as u64)
141            }
142            None => Err(ZByteIoError::SeekError("Negative seek"))
143        }
144    }
145
146    #[inline(always)]
147    pub (crate) fn is_eof_impl(&mut self) -> Result<bool, ZByteIoError> {
148        Ok(self.position >= self.stream.as_ref().len())
149    }
150    #[inline(always)]
151    pub (crate) fn z_position_impl(&mut self) -> Result<u64, ZByteIoError> {
152        Ok(self.position as u64)
153    }
154
155    pub (crate) fn read_remaining_impl(&mut self, sink: &mut alloc::vec::Vec<u8>) -> Result<usize, ZByteIoError> {
156        let start = self.position;
157        let end = self.stream.as_ref().len();
158        match self.stream.as_ref().get(start..end) {
159            None => {
160                return Err(ZByteIoError::Generic(
161                    "Somehow read remaining couldn't satisfy it's invariants"
162                ))
163            }
164            Some(e) => {
165                sink.extend_from_slice(e);
166            }
167        }
168        self.skip(end - start);
169        Ok(end - start)
170    }
171}
172
173impl<T: AsRef<[u8]>> From<T> for ZCursor<T> {
174    fn from(value: T) -> Self {
175        ZCursor::new(value)
176    }
177}