binhex-rs 0.1.1

Crate to read BinHex 4 encoded files
Documentation
use std::io;
use std::io::Seek as _;

use crate::Error;

/// Reader for data or resource fork embedded in an archive
pub struct ForkReader<R> {
    inner: R,
    position: u64,
    end: u64,
}

impl<R> ForkReader<R> {
    pub(crate) fn new(inner: R, position: u64, end: u64) -> Self {
        Self {
            inner,
            position,
            end,
        }
    }
}

impl<R: io::Read + io::Seek> io::Read for ForkReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let pos = self.stream_position()?;
        if pos + buf.len() as u64 > self.end {
            if pos >= self.end {
                Ok(0)
            } else {
                let len = self.end - pos;
                self.inner.read(&mut buf[0..(len as usize)])
            }
        } else {
            self.inner.read(buf)
        }
    }
}

impl<R: io::Read + io::Seek> io::Seek for ForkReader<R> {
    fn seek(&mut self, pos: io::SeekFrom) -> io::Result<u64> {
        match pos {
            io::SeekFrom::Start(x) => {
                Ok(self.inner.seek(io::SeekFrom::Start(self.position + x))? - self.position)
            }
            io::SeekFrom::End(mode) => {
                eprintln!("Unsupported seek {mode:?}");
                Err(Error::UnsupportedSeek.into())
            }
            io::SeekFrom::Current(x) => {
                Ok(self.inner.seek(io::SeekFrom::Current(x))? - self.position)
            }
        }
    }
}