1use std::io;
2use std::io::Seek as _;
3
4use crate::Error;
5
6pub 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}