Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add NoSeek wrapper type for io::Read -> io::Read + io::Seek #78

Closed
jam1garner opened this issue Oct 23, 2021 · 3 comments
Closed

Add NoSeek wrapper type for io::Read -> io::Read + io::Seek #78

jam1garner opened this issue Oct 23, 2021 · 3 comments
Assignees
Labels
enhancement New feature or request good first issue Good for newcomers

Comments

@jam1garner
Copy link
Owner

jam1garner commented Oct 23, 2021

The idea would be that for format that don't involve any reverse seeking, io::Seek can be implemented in terms of just a position tracker an io::Read. This would better enable BinRead to be used for streaming use-cases (networking, serial connection, etc)

This issue is replacing #6 as I feel it didn't adequately reflect the state of the project

@jam1garner jam1garner added enhancement New feature or request good first issue Good for newcomers labels Oct 23, 2021
@m4tx
Copy link

m4tx commented Jun 20, 2022

+1 for this, requiring io::Seek is very annoying

@m4tx
Copy link

m4tx commented Jun 20, 2022

I've actually written a simple NoSeek wrapper in my project. It seems that at least for my use case, the only seeks the library is doing are no-ops, so it works perfectly fine. I've needed it to support stdin/stdout for reading and writing.

use std::io::{Read, Seek, Write};

pub struct NoSeek<T> {
    inner: T,
    position: u64,
}

impl<T> NoSeek<T> {
    pub fn new(inner: T) -> Self {
        Self { inner, position: 0 }
    }
}

impl<T> Seek for NoSeek<T> {
    fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
        match pos {
            std::io::SeekFrom::Start(i) => {
                if i == self.position {
                    Ok(self.position)
                } else {
                    unimplemented!()
                }
            }
            std::io::SeekFrom::End(_) => unimplemented!(),
            std::io::SeekFrom::Current(i) => {
                if i == 0 {
                    Ok(self.position)
                } else {
                    unimplemented!()
                }
            }
        }
    }
}

impl<R: Read> Read for NoSeek<R> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        let size = self.inner.read(buf)?;
        self.position += size as u64;
        Ok(size)
    }

    fn read_vectored(&mut self, bufs: &mut [std::io::IoSliceMut<'_>]) -> std::io::Result<usize> {
        let size = self.inner.read_vectored(bufs)?;
        self.position += size as u64;
        Ok(size)
    }
}

impl<W: Write> Write for NoSeek<W> {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        let size = self.inner.write(buf)?;
        self.position += size as u64;
        Ok(size)
    }

    fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
        let size = self.inner.write_vectored(bufs)?;
        self.position += size as u64;
        Ok(size)
    }

    fn flush(&mut self) -> std::io::Result<()> {
        self.inner.flush()
    }
}

@jam1garner
Copy link
Owner Author

@m4tx I'd accept a PR with this* as an initial implementation if you'd like :)

*albeit replace unimplemented!() with an io::Error

@csnover csnover self-assigned this Aug 23, 2022
csnover added a commit to csnover/binrw that referenced this issue Aug 23, 2022
csnover added a commit to csnover/binrw that referenced this issue Aug 24, 2022
csnover added a commit to csnover/binrw that referenced this issue Aug 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers
Projects
Status: No status
Development

No branches or pull requests

3 participants