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();
}
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