zune_core/bytestream/reader/
no_std_readers.rs

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