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;
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}