symphonia_core/io/
scoped_stream.rs
1use std::cmp;
9use std::io;
10
11use super::{FiniteStream, ReadBytes, SeekBuffered};
12
13#[inline(always)]
14fn out_of_bounds_error<T>() -> io::Result<T> {
15 Err(io::Error::new(io::ErrorKind::UnexpectedEof, "out of bounds"))
16}
17
18pub struct ScopedStream<B: ReadBytes> {
20 inner: B,
21 start: u64,
22 len: u64,
23 read: u64,
24}
25
26impl<B: ReadBytes> ScopedStream<B> {
27 pub fn new(inner: B, len: u64) -> Self {
30 ScopedStream { start: inner.pos(), inner, len, read: 0 }
31 }
32
33 pub fn inner(&self) -> &B {
35 &self.inner
36 }
37
38 pub fn inner_mut(&mut self) -> &mut B {
40 &mut self.inner
41 }
42
43 pub fn ignore(&mut self) -> io::Result<()> {
45 self.inner.ignore_bytes(self.len - self.read)
46 }
47
48 pub fn into_inner(self) -> B {
50 self.inner
51 }
52}
53
54impl<B: ReadBytes> FiniteStream for ScopedStream<B> {
55 fn byte_len(&self) -> u64 {
57 self.len
58 }
59
60 fn bytes_read(&self) -> u64 {
62 self.read
63 }
64
65 fn bytes_available(&self) -> u64 {
67 self.len - self.read
68 }
69}
70
71impl<B: ReadBytes> ReadBytes for ScopedStream<B> {
72 #[inline(always)]
73 fn read_byte(&mut self) -> io::Result<u8> {
74 if self.len - self.read < 1 {
75 return out_of_bounds_error();
76 }
77
78 self.read += 1;
79 self.inner.read_byte()
80 }
81
82 #[inline(always)]
83 fn read_double_bytes(&mut self) -> io::Result<[u8; 2]> {
84 if self.len - self.read < 2 {
85 return out_of_bounds_error();
86 }
87
88 self.read += 2;
89 self.inner.read_double_bytes()
90 }
91
92 #[inline(always)]
93 fn read_triple_bytes(&mut self) -> io::Result<[u8; 3]> {
94 if self.len - self.read < 3 {
95 return out_of_bounds_error();
96 }
97
98 self.read += 3;
99 self.inner.read_triple_bytes()
100 }
101
102 #[inline(always)]
103 fn read_quad_bytes(&mut self) -> io::Result<[u8; 4]> {
104 if self.len - self.read < 4 {
105 return out_of_bounds_error();
106 }
107
108 self.read += 4;
109 self.inner.read_quad_bytes()
110 }
111
112 fn read_buf(&mut self, buf: &mut [u8]) -> io::Result<usize> {
113 let scoped_len = cmp::min(self.len - self.read, buf.len() as u64) as usize;
115 let result = self.inner.read_buf(&mut buf[0..scoped_len])?;
116 self.read += result as u64;
117 Ok(result)
118 }
119
120 fn read_buf_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
121 if self.len - self.read < buf.len() as u64 {
122 return out_of_bounds_error();
123 }
124
125 self.read += buf.len() as u64;
126 self.inner.read_buf_exact(buf)
127 }
128
129 #[inline(always)]
130 fn scan_bytes_aligned<'a>(
131 &mut self,
132 pattern: &[u8],
133 align: usize,
134 buf: &'a mut [u8],
135 ) -> io::Result<&'a mut [u8]> {
136 if self.len - self.read < buf.len() as u64 {
137 return out_of_bounds_error();
138 }
139
140 let result = self.inner.scan_bytes_aligned(pattern, align, buf)?;
141 self.read += result.len() as u64;
142 Ok(result)
143 }
144
145 #[inline(always)]
146 fn ignore_bytes(&mut self, count: u64) -> io::Result<()> {
147 if self.len - self.read < count {
148 return out_of_bounds_error();
149 }
150
151 self.read += count;
152 self.inner.ignore_bytes(count)
153 }
154
155 #[inline(always)]
156 fn pos(&self) -> u64 {
157 self.inner.pos()
158 }
159}
160
161impl<B: ReadBytes + SeekBuffered> SeekBuffered for ScopedStream<B> {
162 #[inline(always)]
163 fn ensure_seekback_buffer(&mut self, len: usize) {
164 self.inner.ensure_seekback_buffer(len)
165 }
166
167 #[inline(always)]
168 fn unread_buffer_len(&self) -> usize {
169 self.inner.unread_buffer_len().min((self.len - self.read) as usize)
170 }
171
172 #[inline(always)]
173 fn read_buffer_len(&self) -> usize {
174 self.inner.read_buffer_len().min(self.read as usize)
175 }
176
177 #[inline(always)]
178 fn seek_buffered(&mut self, pos: u64) -> u64 {
179 self.inner.seek_buffered(pos.clamp(self.start, self.start + self.len))
181 }
182
183 #[inline(always)]
184 fn seek_buffered_rel(&mut self, delta: isize) -> u64 {
185 let max_back = self.read.min(std::isize::MAX as u64) as isize;
188 let max_forward = (self.len - self.read).min(std::isize::MAX as u64) as isize;
189 self.inner.seek_buffered_rel(delta.clamp(-max_back, max_forward))
190 }
191}