zencodec_io/
read_at_reader.rs1use alloc::boxed::Box;
4use std::io::{self, Read, Seek, SeekFrom};
5use zencodec::source::ReadAt;
6
7use crate::StdSourceError;
8
9#[derive(Debug)]
28pub struct ReadAtReader<S> {
29 source: S,
30 position: u64,
31}
32
33impl<S> ReadAtReader<S> {
34 pub const fn new(source: S) -> Self {
36 Self {
37 source,
38 position: 0,
39 }
40 }
41
42 pub fn into_inner(self) -> S {
44 self.source
45 }
46}
47
48fn into_io(error: impl core::error::Error + Send + Sync + 'static) -> io::Error {
49 let error: Box<dyn core::error::Error + Send + Sync> = Box::new(error);
50 let error = match error.downcast::<io::Error>() {
51 Ok(native) => return *native,
52 Err(other) => other,
53 };
54 let error = match error.downcast::<StdSourceError>() {
55 Ok(source) => match *source {
56 StdSourceError::Io(native) => return native,
57 other => return io::Error::other(other),
58 },
59 Err(other) => other,
60 };
61 let kind = zencodec::find_cause::<io::Error>(error.as_ref())
62 .map_or(io::ErrorKind::Other, io::Error::kind);
63 io::Error::new(kind, error)
64}
65
66impl<S: ReadAt> Read for ReadAtReader<S> {
67 fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
68 if out.is_empty() {
69 return Ok(0);
70 }
71 let n = self.source.read_at(self.position, out).map_err(into_io)?;
72 if n > out.len() {
73 return Err(io::Error::new(
74 io::ErrorKind::InvalidData,
75 "positional source returned a count larger than its buffer",
76 ));
77 }
78 self.position = self.position.checked_add(n as u64).ok_or_else(|| {
79 io::Error::new(io::ErrorKind::InvalidData, "source position overflow")
80 })?;
81 Ok(n)
82 }
83}
84
85impl<S: ReadAt> Seek for ReadAtReader<S> {
86 fn seek(&mut self, to: SeekFrom) -> io::Result<u64> {
87 let position = match to {
88 SeekFrom::Start(n) => Some(n),
89 SeekFrom::Current(n) => self.position.checked_add_signed(n),
90 SeekFrom::End(n) => self.source.len().map_err(into_io)?.checked_add_signed(n),
91 }
92 .ok_or_else(|| {
93 io::Error::new(io::ErrorKind::InvalidInput, "seek outside u64 offset space")
94 })?;
95 self.position = position;
96 Ok(position)
97 }
98
99 fn stream_position(&mut self) -> io::Result<u64> {
100 Ok(self.position)
101 }
102}