pub struct ChainReader<'a, R, F, I = Empty<R>>{ /* private fields */ }Expand description
A sequential chaining reader that combines multiple Read instances with configurable error handling.
§Behavior
- Readers are consumed in FIFO (first-in, first-out) order.
- Automatically switches to the next reader when the current one reaches EOF (returns
Ok(0)). - Allows custom error handling to decide whether to retry or skip on I/O errors.
- Supports both single readers and iterators that produce readers.
§Comparison with io::Chain
- Supports a dynamic queue of readers instead of a fixed pair.
- Configurable error handling strategies (see
ErrorActionfor details) - Automatically advances to the next reader on EOF.
- Handles both single readers and iterators of readers.
§Examples
use chain_reader::{ChainReader, ErrorAction};
use std::io::{self, Read};
// Define a custom reader type that can handle both stdin and files
enum Readers {
Stdin,
File(std::fs::File),
Cursor(io::Cursor<String>),
}
impl Read for Readers {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self {
Readers::Stdin => io::stdin().read(buf),
Readers::File(it) => it.read(buf),
Readers::Cursor(it) => it.read(buf),
}
}
}
fn main() -> io::Result<()> {
// Create a ChainReader that starts with stdin
let mut chain = ChainReader::new(
|e| match e.kind() {
io::ErrorKind::Interrupted => ErrorAction::Retry,
_ => ErrorAction::RetryAndSkip,
},
);
chain.push(Readers::Stdin);
// Add a file to the chain
chain.push(Readers::File(std::fs::File::open("Cargo.toml")?));
chain.push_iter(vec![
Readers::Cursor(io::Cursor::new("hello ".to_string())),
Readers::Cursor(io::Cursor::new("world!".to_string())),
]);
// Read from the chain - first from stdin, then from the file
let mut content = Vec::new();
chain.read_to_end(&mut content)?;
Ok(())
}Implementations§
Source§impl<R, F, I> ChainReader<'_, R, F, I>
impl<R, F, I> ChainReader<'_, R, F, I>
Sourcepub fn new(error_handle: F) -> Self
pub fn new(error_handle: F) -> Self
Creates a new ChainReader with the given error handler and an empty reader queue.
Readers can be added to the queue using the Self::push and Self::push_iter methods.
The error_handle callback determines behavior on I/O errors during reading.
§Parameters
error_handle: Error handling strategy callback
Sourcepub fn replace_handle(&mut self, error_handle: F)
pub fn replace_handle(&mut self, error_handle: F)
Replaces the current error handler with a new one.
This method allows changing the error handling strategy at runtime.
§Parameters
error_handle: New error handling strategy callback
Sourcepub fn push(&mut self, reader: R)
pub fn push(&mut self, reader: R)
Appends a single reader to the end of the processing queue.
The reader will be processed after all existing readers in the queue have either reached EOF or been skipped due to errors.
§Parameters
reader: Reader to add to the end of the queue
Sourcepub fn push_iter<II: IntoIterator<IntoIter = I>>(&mut self, iter: II)
pub fn push_iter<II: IntoIterator<IntoIter = I>>(&mut self, iter: II)
Appends an iterator of readers to the end of the processing queue.
The readers produced by the iterator will be processed in order after all existing readers in the queue have been processed.
§Parameters
iter: Iterator that produces readers to add to the end of the queue
Trait Implementations§
Source§impl<R, F, I> Read for ChainReader<'_, R, F, I>
impl<R, F, I> Read for ChainReader<'_, R, F, I>
Source§fn read(&mut self, buf: &mut [u8]) -> Result<usize>
fn read(&mut self, buf: &mut [u8]) -> Result<usize>
Reads data from the current reader, handling errors and EOF according to the configured strategy.
This implementation follows the chain reading pattern:
- Attempt to read from the current reader
- On success, return the read data
- On EOF, automatically advance to the next reader
- On error, invoke the error handler to determine the appropriate action
The method will continue this process until either:
- Data is successfully read
- All readers are exhausted (returning Ok(0))
- An unhandled error occurs (returning Err)
§Parameters
buf: Buffer to read data into
§Returns
Ok(n): Successfully readnbytesErr(e): IO error that couldn’t be handled by the error strategy
1.36.0 · Source§fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize, Error>
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> Result<usize, Error>
read, except that it reads into a slice of buffers. Read moreSource§fn is_read_vectored(&self) -> bool
fn is_read_vectored(&self) -> bool
can_vector)1.0.0 · Source§fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error>
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize, Error>
buf. Read more1.0.0 · Source§fn read_to_string(&mut self, buf: &mut String) -> Result<usize, Error>
fn read_to_string(&mut self, buf: &mut String) -> Result<usize, Error>
buf. Read more1.6.0 · Source§fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Error>
fn read_exact(&mut self, buf: &mut [u8]) -> Result<(), Error>
buf. Read moreSource§fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<(), Error>
fn read_buf(&mut self, buf: BorrowedCursor<'_>) -> Result<(), Error>
read_buf)Source§fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> Result<(), Error>
fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> Result<(), Error>
read_buf)cursor. Read more1.0.0 · Source§fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
fn by_ref(&mut self) -> &mut Selfwhere
Self: Sized,
Read. Read more