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 return Ok(&self.buf[start..end]);
61 }
62
63 let mut j = start;
64 let mut i = start + pattern.len();
65
66 while i < end {
67 if &self.buf[j..i] == pattern {
68 break;
69 }
70 i += align;
71 j += align;
72 }
73
74 self.pos = cmp::min(i, self.buf.len());
75 Ok(&self.buf[start..self.pos])
76 }
77
78 pub fn read_buf_bytes_ref(&mut self, len: usize) -> io::Result<&'a [u8]> {
80 if self.pos + len > self.buf.len() {
81 return underrun_error();
82 }
83 self.pos += len;
84 Ok(&self.buf[self.pos - len..self.pos])
85 }
86
87 pub fn read_buf_bytes_available_ref(&mut self) -> &'a [u8] {
89 let pos = self.pos;
90 self.pos = self.buf.len();
91 &self.buf[pos..]
92 }
93}
94
95impl<'a> ReadBytes for BufReader<'a> {
96 #[inline(always)]
97 fn read_byte(&mut self) -> io::Result<u8> {
98 if self.buf.len() - self.pos < 1 {
99 return underrun_error();
100 }
101
102 self.pos += 1;
103 Ok(self.buf[self.pos - 1])
104 }
105
106 #[inline(always)]
107 fn read_double_bytes(&mut self) -> io::Result<[u8; 2]> {
108 if self.buf.len() - self.pos < 2 {
109 return underrun_error();
110 }
111
112 let mut bytes: [u8; 2] = [0u8; 2];
113 bytes.copy_from_slice(&self.buf[self.pos..self.pos + 2]);
114 self.pos += 2;
115
116 Ok(bytes)
117 }
118
119 #[inline(always)]
120 fn read_triple_bytes(&mut self) -> io::Result<[u8; 3]> {
121 if self.buf.len() - self.pos < 3 {
122 return underrun_error();
123 }
124
125 let mut bytes: [u8; 3] = [0u8; 3];
126 bytes.copy_from_slice(&self.buf[self.pos..self.pos + 3]);
127 self.pos += 3;
128
129 Ok(bytes)
130 }
131
132 #[inline(always)]
133 fn read_quad_bytes(&mut self) -> io::Result<[u8; 4]> {
134 if self.buf.len() - self.pos < 4 {
135 return underrun_error();
136 }
137
138 let mut bytes: [u8; 4] = [0u8; 4];
139 bytes.copy_from_slice(&self.buf[self.pos..self.pos + 4]);
140 self.pos += 4;
141
142 Ok(bytes)
143 }
144
145 fn read_buf(&mut self, buf: &mut [u8]) -> io::Result<usize> {
146 let len = cmp::min(self.buf.len() - self.pos, buf.len());
147 buf[..len].copy_from_slice(&self.buf[self.pos..self.pos + len]);
148 self.pos += len;
149
150 Ok(len)
151 }
152
153 fn read_buf_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
154 let len = buf.len();
155
156 if self.buf.len() - self.pos < len {
157 return underrun_error();
158 }
159
160 buf.copy_from_slice(&self.buf[self.pos..self.pos + len]);
161 self.pos += len;
162
163 Ok(())
164 }
165
166 fn scan_bytes_aligned<'b>(
167 &mut self,
168 pattern: &[u8],
169 align: usize,
170 buf: &'b mut [u8],
171 ) -> io::Result<&'b mut [u8]> {
172 let scanned = self.scan_bytes_aligned_ref(pattern, align, buf.len())?;
173 buf[..scanned.len()].copy_from_slice(scanned);
174
175 Ok(&mut buf[..scanned.len()])
176 }
177
178 fn ignore_bytes(&mut self, count: u64) -> io::Result<()> {
179 if self.buf.len() - self.pos < count as usize {
180 return underrun_error();
181 }
182
183 self.pos += count as usize;
184 Ok(())
185 }
186
187 #[inline(always)]
188 fn pos(&self) -> u64 {
189 self.pos as u64
190 }
191}
192
193impl<'a> FiniteStream for BufReader<'a> {
194 #[inline(always)]
195 fn byte_len(&self) -> u64 {
196 self.buf.len() as u64
197 }
198
199 #[inline(always)]
200 fn bytes_read(&self) -> u64 {
201 self.pos as u64
202 }
203
204 #[inline(always)]
205 fn bytes_available(&self) -> u64 {
206 (self.buf.len() - self.pos) as u64
207 }
208}