Skip to main content

zune_core/bytestream/reader/
std_readers.rs

1#![cfg(feature = "std")]
2
3use std::io;
4use std::io::SeekFrom;
5
6use crate::bytestream::reader::{ZByteIoError, ZSeekFrom};
7use crate::bytestream::{ZByteReaderTrait, ZCursor};
8// note (cae): If Rust ever stabilizes trait specialization, specialize this for Cursor
9impl<T: io::BufRead + io::Seek> ZByteReaderTrait for T {
10    #[inline(always)]
11    fn read_byte_no_error(&mut self) -> u8 {
12        let mut buf = [0];
13        let _ = self.read(&mut buf);
14        buf[0]
15    }
16    #[inline(always)]
17    fn read_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError> {
18        let mut bytes_read = 0;
19
20        while bytes_read < buf.len() {
21            match self.read(&mut buf[bytes_read..]) {
22                Ok(0) => {
23                    // if a read returns zero bytes read, it means it encountered an EOF so we seek
24                    // back to where we started because some paths may aggressively read forward and
25                    // ZCursor maintains the position.
26
27                    // NB: (cae) [tag=perf] This adds a branch on every read, and will slow down every function
28                    // resting on it. Sorry
29                    self.seek(SeekFrom::Current(-(bytes_read as i64)))
30                        .map_err(ZByteIoError::from)?;
31                    return Err(ZByteIoError::NotEnoughBytes(bytes_read, buf.len()));
32                }
33                Ok(bytes) => {
34                    bytes_read += bytes;
35                }
36                Err(e) => return Err(ZByteIoError::from(e))
37            }
38        }
39
40        Ok(())
41    }
42
43    #[inline]
44    fn read_const_bytes<const N: usize>(&mut self, buf: &mut [u8; N]) -> Result<(), ZByteIoError> {
45        self.read_exact_bytes(buf)
46    }
47
48    fn read_const_bytes_no_error<const N: usize>(&mut self, buf: &mut [u8; N]) {
49        let _ = self.read_const_bytes(buf);
50    }
51
52    #[inline(always)]
53    fn read_bytes(&mut self, buf: &mut [u8]) -> Result<usize, ZByteIoError> {
54        self.read(buf).map_err(ZByteIoError::from)
55    }
56
57    #[inline(always)]
58    fn peek_bytes(&mut self, buf: &mut [u8]) -> Result<usize, ZByteIoError> {
59        // first read bytes to the buffer
60        let bytes_read = self.read_bytes(buf)?;
61        let converted = -i64::try_from(bytes_read).map_err(ZByteIoError::from)?;
62        self.seek(std::io::SeekFrom::Current(converted))
63            .map_err(ZByteIoError::from)?;
64
65        Ok(bytes_read)
66    }
67
68    #[inline(always)]
69    fn peek_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError> {
70        // first read bytes to the buffer
71        self.read_exact_bytes(buf)?;
72        let converted = -i64::try_from(buf.len()).map_err(ZByteIoError::from)?;
73        self.seek(std::io::SeekFrom::Current(converted))
74            .map_err(ZByteIoError::from)?;
75
76        Ok(())
77    }
78
79    #[inline(always)]
80    fn z_seek(&mut self, from: ZSeekFrom) -> Result<u64, ZByteIoError> {
81        self.seek(from.to_std_seek()).map_err(ZByteIoError::from)
82    }
83
84    #[inline(always)]
85    fn is_eof(&mut self) -> Result<bool, ZByteIoError> {
86        self.fill_buf()
87            .map(|b| b.is_empty())
88            .map_err(ZByteIoError::from)
89    }
90
91    #[inline(always)]
92    fn z_position(&mut self) -> Result<u64, ZByteIoError> {
93        self.stream_position().map_err(ZByteIoError::from)
94    }
95
96    #[inline(always)]
97    fn read_remaining(&mut self, sink: &mut Vec<u8>) -> Result<usize, ZByteIoError> {
98        self.read_to_end(sink).map_err(ZByteIoError::from)
99    }
100}
101
102impl<T: AsRef<[u8]>> std::io::Read for ZCursor<T> {
103    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
104        self.read_bytes_impl(buf)
105            .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("{:?}", e)))
106    }
107}
108
109impl<T: AsRef<[u8]>> std::io::BufRead for ZCursor<T> {
110    fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
111        Ok(ZCursor::split(self).1)
112    }
113
114    fn consume(&mut self, amount: usize) {
115        self.position += amount;
116    }
117}
118
119impl<T: AsRef<[u8]>> std::io::Seek for ZCursor<T> {
120    fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
121        let (base_pos, offset) = match pos {
122            std::io::SeekFrom::Start(n) => {
123                self.position = n as usize;
124                return Ok(n);
125            }
126            std::io::SeekFrom::End(n) => (self.stream.as_ref().len(), n as isize),
127            std::io::SeekFrom::Current(n) => (self.position, n as isize)
128        };
129        match base_pos.checked_add_signed(offset) {
130            Some(n) => {
131                self.position = n;
132                Ok(self.position as u64)
133            }
134            None => Err(std::io::Error::new(
135                std::io::ErrorKind::Other,
136                "Negative seek"
137            ))
138        }
139    }
140}