symphonia_core/io/
buf_reader.rs1use std::cmp;
9use std::io;
10
11use super::{FiniteStream, ReadBytes};
12
13#[inline(always)]
14fn underrun_error<T>() -> io::Result<T> {
15 Err(io::Error::new(io::ErrorKind::UnexpectedEof, "buffer underrun"))
16}
17
18pub struct BufReader<'a> {
20 buf: &'a [u8],
21 pos: usize,
22}
23
24impl<'a> BufReader<'a> {
25 pub fn new(buf: &'a [u8]) -> Self {
27 BufReader { buf, pos: 0 }
28 }
29
30 #[inline(always)]
36 pub fn scan_bytes_ref(&mut self, pattern: &[u8], scan_len: usize) -> io::Result<&'a [u8]> {
37 self.scan_bytes_aligned_ref(pattern, 1, scan_len)
38 }
39
40 pub fn scan_bytes_aligned_ref(
43 &mut self,
44 pattern: &[u8],
45 align: usize,
46 scan_len: usize,
47 ) -> io::Result<&'a [u8]> {
48 debug_assert!(!pattern.is_empty());
50
51 let start = self.pos;
52 let remaining = self.buf.len() - start;
53 let end = start + cmp::min(remaining, scan_len);
54
55 if remaining < pattern.len() || scan_len < pattern.len() {
60 self.pos = end;
61 return Ok(&self.buf[start..end]);
62 }
63
64 let mut i = start;
65 let mut j = start + pattern.len();
66
67 while j < end {
68 if &self.buf[i..j] == pattern {
69 break;
70 }
71 j += align;
72 i += align;
73 }
74
75 self.pos = cmp::min(j, self.buf.len());
76 Ok(&self.buf[start..self.pos])
77 }
78
79 pub fn read_buf_bytes_ref(&mut self, len: usize) -> io::Result<&'a [u8]> {
81 if self.pos + len > self.buf.len() {
82 return underrun_error();
83 }
84 self.pos += len;
85 Ok(&self.buf[self.pos - len..self.pos])
86 }
87
88 pub fn read_buf_bytes_available_ref(&mut self) -> &'a [u8] {
90 let pos = self.pos;
91 self.pos = self.buf.len();
92 &self.buf[pos..]
93 }
94}
95
96impl ReadBytes for BufReader<'_> {
97 #[inline(always)]
98 fn read_byte(&mut self) -> io::Result<u8> {
99 if self.buf.len() - self.pos < 1 {
100 return underrun_error();
101 }
102
103 self.pos += 1;
104 Ok(self.buf[self.pos - 1])
105 }
106
107 #[inline(always)]
108 fn read_double_bytes(&mut self) -> io::Result<[u8; 2]> {
109 if self.buf.len() - self.pos < 2 {
110 return underrun_error();
111 }
112
113 let mut bytes: [u8; 2] = [0u8; 2];
114 bytes.copy_from_slice(&self.buf[self.pos..self.pos + 2]);
115 self.pos += 2;
116
117 Ok(bytes)
118 }
119
120 #[inline(always)]
121 fn read_triple_bytes(&mut self) -> io::Result<[u8; 3]> {
122 if self.buf.len() - self.pos < 3 {
123 return underrun_error();
124 }
125
126 let mut bytes: [u8; 3] = [0u8; 3];
127 bytes.copy_from_slice(&self.buf[self.pos..self.pos + 3]);
128 self.pos += 3;
129
130 Ok(bytes)
131 }
132
133 #[inline(always)]
134 fn read_quad_bytes(&mut self) -> io::Result<[u8; 4]> {
135 if self.buf.len() - self.pos < 4 {
136 return underrun_error();
137 }
138
139 let mut bytes: [u8; 4] = [0u8; 4];
140 bytes.copy_from_slice(&self.buf[self.pos..self.pos + 4]);
141 self.pos += 4;
142
143 Ok(bytes)
144 }
145
146 fn read_buf(&mut self, buf: &mut [u8]) -> io::Result<usize> {
147 let len = cmp::min(self.buf.len() - self.pos, buf.len());
148 buf[..len].copy_from_slice(&self.buf[self.pos..self.pos + len]);
149 self.pos += len;
150
151 Ok(len)
152 }
153
154 fn read_buf_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
155 let len = buf.len();
156
157 if self.buf.len() - self.pos < len {
158 return underrun_error();
159 }
160
161 buf.copy_from_slice(&self.buf[self.pos..self.pos + len]);
162 self.pos += len;
163
164 Ok(())
165 }
166
167 fn scan_bytes_aligned<'b>(
168 &mut self,
169 pattern: &[u8],
170 align: usize,
171 buf: &'b mut [u8],
172 ) -> io::Result<&'b mut [u8]> {
173 let scanned = self.scan_bytes_aligned_ref(pattern, align, buf.len())?;
174 buf[..scanned.len()].copy_from_slice(scanned);
175
176 Ok(&mut buf[..scanned.len()])
177 }
178
179 fn ignore_bytes(&mut self, count: u64) -> io::Result<()> {
180 if self.buf.len() - self.pos < count as usize {
181 return underrun_error();
182 }
183
184 self.pos += count as usize;
185 Ok(())
186 }
187
188 #[inline(always)]
189 fn pos(&self) -> u64 {
190 self.pos as u64
191 }
192}
193
194impl FiniteStream for BufReader<'_> {
195 #[inline(always)]
196 fn byte_len(&self) -> u64 {
197 self.buf.len() as u64
198 }
199
200 #[inline(always)]
201 fn bytes_read(&self) -> u64 {
202 self.pos as u64
203 }
204
205 #[inline(always)]
206 fn bytes_available(&self) -> u64 {
207 (self.buf.len() - self.pos) as u64
208 }
209}