1use alloc::boxed::Box;
18use core::fmt;
19
20use crate::traits::BoxedError;
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
25#[non_exhaustive]
26pub enum AccessPattern {
27 #[default]
29 Sequential,
30 BoundedBacktrack {
32 window_bytes: u64,
34 },
35 RandomAccess,
38}
39
40impl AccessPattern {
41 pub const fn most_demanding(self, other: Self) -> Self {
45 match (self, other) {
46 (Self::RandomAccess, _) | (_, Self::RandomAccess) => Self::RandomAccess,
47 (
48 Self::BoundedBacktrack { window_bytes: a },
49 Self::BoundedBacktrack { window_bytes: b },
50 ) => Self::BoundedBacktrack {
51 window_bytes: if a > b { a } else { b },
52 },
53 (Self::BoundedBacktrack { window_bytes }, _)
54 | (_, Self::BoundedBacktrack { window_bytes }) => {
55 Self::BoundedBacktrack { window_bytes }
56 }
57 _ => Self::Sequential,
58 }
59 }
60}
61
62#[derive(Debug, Clone, PartialEq, Eq)]
64#[non_exhaustive]
65pub enum SourceError {
66 BeyondWindow {
68 offset: u64,
70 oldest_retained: u64,
72 },
73 BeyondLimit {
75 needed: u64,
77 limit: u64,
79 },
80 UnexpectedEof {
82 offset: u64,
84 len: u64,
86 total: Option<u64>,
88 },
89 Io {
91 message: alloc::string::String,
93 },
94}
95
96impl fmt::Display for SourceError {
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 match self {
99 Self::BeyondWindow {
100 offset,
101 oldest_retained,
102 } => write!(
103 f,
104 "source read at {offset} is behind the buffered window (oldest retained: {oldest_retained})"
105 ),
106 Self::BeyondLimit { needed, limit } => write!(
107 f,
108 "source buffering would retain {needed} bytes, over the {limit}-byte limit"
109 ),
110 Self::UnexpectedEof { offset, len, total } => write!(
111 f,
112 "source read of {len} bytes at {offset} ran past end of source (total: {total:?})"
113 ),
114 Self::Io { message } => write!(f, "source I/O error: {message}"),
115 }
116 }
117}
118
119impl core::error::Error for SourceError {}
120
121pub trait ReadAt {
140 type Error: core::error::Error + Send + Sync + 'static;
142
143 fn len(&mut self) -> Result<u64, Self::Error>;
148
149 fn len_hint(&self) -> Option<u64> {
151 None
152 }
153
154 fn is_empty(&mut self) -> Result<bool, Self::Error> {
156 Ok(self.len()? == 0)
157 }
158
159 fn read_exact_at(&mut self, offset: u64, out: &mut [u8]) -> Result<(), Self::Error>;
162
163 fn read_at(&mut self, offset: u64, out: &mut [u8]) -> Result<usize, Self::Error> {
169 let len = self.len()?;
170 let n = len.saturating_sub(offset).min(out.len() as u64) as usize;
171 self.read_exact_at(offset, &mut out[..n])?;
172 Ok(n)
173 }
174
175 fn read_many_at(&mut self, reqs: &mut [(u64, &mut [u8])]) -> Result<(), Self::Error> {
178 for (offset, out) in reqs.iter_mut() {
179 self.read_exact_at(*offset, out)?;
180 }
181 Ok(())
182 }
183
184 fn as_slice(&self) -> Option<&[u8]> {
187 None
188 }
189}
190
191#[derive(Debug, Clone)]
194pub struct SliceReadAt<'a> {
195 bytes: &'a [u8],
196}
197
198impl<'a> SliceReadAt<'a> {
199 pub const fn new(bytes: &'a [u8]) -> Self {
201 Self { bytes }
202 }
203
204 fn eof(&self, offset: u64, len: usize) -> SourceError {
205 SourceError::UnexpectedEof {
206 offset,
207 len: len as u64,
208 total: Some(self.bytes.len() as u64),
209 }
210 }
211}
212
213impl ReadAt for SliceReadAt<'_> {
214 type Error = SourceError;
215
216 fn len(&mut self) -> Result<u64, Self::Error> {
217 Ok(self.bytes.len() as u64)
218 }
219
220 fn len_hint(&self) -> Option<u64> {
221 Some(self.bytes.len() as u64)
222 }
223
224 fn read_at(&mut self, offset: u64, out: &mut [u8]) -> Result<usize, Self::Error> {
225 let start = usize::try_from(offset)
226 .unwrap_or(usize::MAX)
227 .min(self.bytes.len());
228 let n = (self.bytes.len() - start).min(out.len());
229 out[..n].copy_from_slice(&self.bytes[start..start + n]);
230 Ok(n)
231 }
232
233 fn as_slice(&self) -> Option<&[u8]> {
234 Some(self.bytes)
235 }
236
237 fn read_exact_at(&mut self, offset: u64, out: &mut [u8]) -> Result<(), Self::Error> {
238 let start = usize::try_from(offset).map_err(|_| self.eof(offset, out.len()))?;
239 let end = start
240 .checked_add(out.len())
241 .ok_or_else(|| self.eof(offset, out.len()))?;
242 let data = self
243 .bytes
244 .get(start..end)
245 .ok_or_else(|| self.eof(offset, out.len()))?;
246 out.copy_from_slice(data);
247 Ok(())
248 }
249}
250
251pub trait DynReadAt {
259 fn len(&mut self) -> Result<u64, BoxedError>;
261 fn len_hint(&self) -> Option<u64> {
263 None
264 }
265 fn is_empty(&mut self) -> Result<bool, BoxedError> {
267 Ok(self.len()? == 0)
268 }
269 fn read_exact_at(&mut self, offset: u64, out: &mut [u8]) -> Result<(), BoxedError>;
271 fn read_at(&mut self, offset: u64, out: &mut [u8]) -> Result<usize, BoxedError> {
273 let len = self.len()?;
274 let n = len.saturating_sub(offset).min(out.len() as u64) as usize;
275 self.read_exact_at(offset, &mut out[..n])?;
276 Ok(n)
277 }
278 fn read_many_at(&mut self, reqs: &mut [(u64, &mut [u8])]) -> Result<(), BoxedError> {
280 for (offset, out) in reqs.iter_mut() {
281 self.read_exact_at(*offset, out)?;
282 }
283 Ok(())
284 }
285 fn as_slice(&self) -> Option<&[u8]> {
287 None
288 }
289}
290
291impl<S: DynReadAt + ?Sized> DynReadAt for Box<S> {
292 fn len(&mut self) -> Result<u64, BoxedError> {
293 (**self).len()
294 }
295
296 fn read_exact_at(&mut self, offset: u64, out: &mut [u8]) -> Result<(), BoxedError> {
297 (**self).read_exact_at(offset, out)
298 }
299
300 fn read_many_at(&mut self, reqs: &mut [(u64, &mut [u8])]) -> Result<(), BoxedError> {
301 (**self).read_many_at(reqs)
302 }
303
304 fn len_hint(&self) -> Option<u64> {
305 (**self).len_hint()
306 }
307
308 fn read_at(&mut self, offset: u64, out: &mut [u8]) -> Result<usize, BoxedError> {
309 (**self).read_at(offset, out)
310 }
311
312 fn as_slice(&self) -> Option<&[u8]> {
313 (**self).as_slice()
314 }
315}
316
317impl<S: DynReadAt + ?Sized> DynReadAt for &mut S {
318 fn len(&mut self) -> Result<u64, BoxedError> {
319 (**self).len()
320 }
321
322 fn read_exact_at(&mut self, offset: u64, out: &mut [u8]) -> Result<(), BoxedError> {
323 (**self).read_exact_at(offset, out)
324 }
325
326 fn read_many_at(&mut self, reqs: &mut [(u64, &mut [u8])]) -> Result<(), BoxedError> {
327 (**self).read_many_at(reqs)
328 }
329
330 fn len_hint(&self) -> Option<u64> {
331 (**self).len_hint()
332 }
333
334 fn read_at(&mut self, offset: u64, out: &mut [u8]) -> Result<usize, BoxedError> {
335 (**self).read_at(offset, out)
336 }
337
338 fn as_slice(&self) -> Option<&[u8]> {
339 (**self).as_slice()
340 }
341}
342
343pub struct ReadAtShim<S>(pub S);
345
346impl<S: ReadAt> DynReadAt for ReadAtShim<S> {
347 fn len(&mut self) -> Result<u64, BoxedError> {
348 self.0.len().map_err(|e| Box::new(e) as BoxedError)
349 }
350
351 fn read_exact_at(&mut self, offset: u64, out: &mut [u8]) -> Result<(), BoxedError> {
352 self.0
353 .read_exact_at(offset, out)
354 .map_err(|e| Box::new(e) as BoxedError)
355 }
356
357 fn read_many_at(&mut self, reqs: &mut [(u64, &mut [u8])]) -> Result<(), BoxedError> {
358 self.0
359 .read_many_at(reqs)
360 .map_err(|e| Box::new(e) as BoxedError)
361 }
362
363 fn len_hint(&self) -> Option<u64> {
364 self.0.len_hint()
365 }
366
367 fn read_at(&mut self, offset: u64, out: &mut [u8]) -> Result<usize, BoxedError> {
368 self.0
369 .read_at(offset, out)
370 .map_err(|e| Box::new(e) as BoxedError)
371 }
372
373 fn as_slice(&self) -> Option<&[u8]> {
374 self.0.as_slice()
375 }
376}
377
378impl<'a, S: ReadAt + 'a> From<S> for Box<dyn DynReadAt + 'a> {
379 fn from(source: S) -> Self {
380 Box::new(ReadAtShim(source))
381 }
382}
383
384impl<'a, S: ReadAt + Send + 'a> From<S> for Box<dyn DynReadAt + Send + 'a> {
385 fn from(source: S) -> Self {
386 Box::new(ReadAtShim(source))
387 }
388}
389
390#[cfg(test)]
391mod tests {
392 use super::*;
393
394 #[test]
395 fn slice_reads_and_fails_past_end() {
396 let data = [1u8, 2, 3, 4, 5];
397 let mut src = SliceReadAt::new(&data);
398 assert_eq!(src.len().unwrap(), 5);
399 let mut two = [0u8; 2];
400 src.read_exact_at(3, &mut two).unwrap();
401 assert_eq!(two, [4, 5]);
402 let mut three = [0u8; 3];
403 assert!(matches!(
404 src.read_exact_at(3, &mut three),
405 Err(SourceError::UnexpectedEof {
406 offset: 3,
407 len: 3,
408 total: Some(5)
409 })
410 ));
411 assert!(src.read_exact_at(u64::MAX, &mut two).is_err());
412 }
413
414 #[test]
415 fn shim_and_box_dispatch() {
416 static DATA: [u8; 3] = [9, 8, 7];
417 let mut boxed: Box<dyn DynReadAt> = SliceReadAt::new(&DATA).into();
418 let mut a = [0u8; 1];
419 let mut b = [0u8; 2];
420 boxed
421 .read_many_at(&mut [(2, &mut a[..]), (0, &mut b[..])])
422 .unwrap();
423 assert_eq!((a, b), ([7], [9, 8]));
424 let by_ref: &mut dyn DynReadAt = &mut *boxed;
425 assert_eq!(by_ref.len().unwrap(), 3);
426 }
427}