Skip to main content

binhex_rs/
fork_reader.rs

1use std::io;
2use std::io::Seek as _;
3
4use crate::Error;
5
6/// Reader for data or resource fork embedded in an archive
7pub struct ForkReader<R> {
8    inner: R,
9    position: u64,
10    end: u64,
11}
12
13impl<R> ForkReader<R> {
14    pub(crate) fn new(inner: R, position: u64, end: u64) -> Self {
15        Self {
16            inner,
17            position,
18            end,
19        }
20    }
21}
22
23impl<R: io::Read + io::Seek> io::Read for ForkReader<R> {
24    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
25        let pos = self.stream_position()?;
26        if pos + buf.len() as u64 > self.end {
27            if pos >= self.end {
28                Ok(0)
29            } else {
30                let len = self.end - pos;
31                self.inner.read(&mut buf[0..(len as usize)])
32            }
33        } else {
34            self.inner.read(buf)
35        }
36    }
37}
38
39impl<R: io::Read + io::Seek> io::Seek for ForkReader<R> {
40    fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
41        match pos {
42            io::SeekFrom::Start(x) => {
43                Ok(self.inner.seek(io::SeekFrom::Start(self.position + x))? - self.position)
44            }
45            io::SeekFrom::End(mode) => {
46                eprintln!("Unsupported seek {mode:?}");
47                Err(Error::UnsupportedSeek.into())
48            }
49            io::SeekFrom::Current(x) => {
50                Ok(self.inner.seek(io::SeekFrom::Current(x))? - self.position)
51            }
52        }
53    }
54}