io::Read higher stack error handling

Hello Rustaceans,

It's a common pattern to consume a reader instead of passing it as a reference. The problem is; if something goes wrong with the I/O, I lose the reader and cannot write a notification to it (in case it is io::Write also).

Question: How to recover the reader if fetch_data fails?

Of course I can do some tricks, but I'd like to go the idiomatic way.

Example:

use std::io;

fn fetch_data<R>(reader: R, buf: &mut [u8]) -> Result<R, io::Error>
where
    R: io::Read,
{
    let mut reader = reader;
    reader.read(buf)?;

    // Ok(reader)
    Err(io::Error::new(io::ErrorKind::Other, "Something is wrong!"))
}

fn execute() -> Result<(), io::Error> {
    let data = [0xffu8; 128];
    let mut buf = [0x00u8; 32];
    let data = fetch_data(&data[..], &mut buf);

    // There is no way I can recapture the reader
    // Sometimes, it is a stream and I need to write
    // the error cause into it

    Ok(())
}

fn main() {
    execute().unwrap();
}

You can pass a mutable reference to the Read

    fn execute() -> Result<(), io::Error> {
        let data = [0xffu8; 128];
        let mut buf = [0x00u8; 32];
        //A &[u8] is Read
        let mut cur = &data[..];
        let data = fetch_data(&mut cur, &mut buf);

        // The Read is still available
        println!("{:?}", &cur[..10]);

        Ok(())
    }

This works due to the builtin
impl<'_, R: Read + ?Sized> Read for &'_ mut R

2 Likes

Oh, cool, any mutable reference to an implementation of io::Read will implement the reader itself.

Therefore:

use std::io;

struct Some {}

impl io::Read for Some {
    fn read(&mut self, _buf: &mut [u8]) -> Result<usize, io::Error> {
        unimplemented!()
    }
}

fn fetch_data<R>(reader: R, buf: &mut [u8]) -> Result<R, io::Error>
where
    R: io::Read,
{
    let mut reader = reader;
    reader.read(buf)?;

    Ok(reader)
}

fn execute() -> Result<(), io::Error> {
    let mut data = Some {};
    let mut buf = [0x00u8; 32];
    fetch_data(&mut data, &mut buf)?;

    Ok(())
}

Thanks!