pub struct TeeReader<R, W> { /* private fields */ }Expand description
Reader wrapper that mirrors read bytes into a branch writer.
TeeReader forwards reads to the source reader and writes every
successfully read byte into the branch writer while the stream is consumed.
If the branch writer fails, the source bytes have already been read from the
inner reader and the branch error is returned.
Seeking a TeeReader seeks only the source reader. It does not seek or
otherwise modify the branch writer; bytes mirrored after the seek are simply
appended or written according to the branch writer’s own state.
TeeReader intentionally does not implement std::io::BufRead. Mirroring
from fill_buf would copy bytes before the caller commits to consuming
them, while mirroring from consume could not report branch write failures
because BufRead::consume has no error return.
If buffered access is needed, wrap this reader outside the tee layer, for
example BufReader<TeeReader<R, W>>. In that composition bytes are mirrored
when the outer BufReader refills its internal buffer, which may be earlier
than the application later consuming those bytes from fill_buf.
§Failure and retry semantics
A branch error does not restore bytes already consumed from the source. Callers should therefore treat a branch write error as terminal unless they can reposition or otherwise recover the source. An outer buffering layer may discard a failed refill even though the source has already advanced:
source before refill: "abcdef"
refill reads "abc": source advances to "def", branch returns an error
retry: reading resumes at "def"; "abc" may be unavailableAfter a branch error, the source and branch may be out of sync. This wrapper does not retain the consumed bytes or provide rollback.
§Examples
use std::io::{
Cursor,
Read,
};
use qubit_io::TeeReader;
let source = Cursor::new(b"abc".to_vec());
let branch = Vec::new();
let mut reader = TeeReader::new(source, branch);
let mut data = Vec::new();
reader.read_to_end(&mut data)?;
let (_source, branch) = reader.into_inner();
assert_eq!(b"abc", data.as_slice());
assert_eq!(b"abc", branch.as_slice());Implementations§
Source§impl<R, W> TeeReader<R, W>
impl<R, W> TeeReader<R, W>
Sourcepub fn with_sync_branch_seek(reader: R, branch: W) -> SyncSeekTeeReader<R, W> ⓘ
pub fn with_sync_branch_seek(reader: R, branch: W) -> SyncSeekTeeReader<R, W> ⓘ
Creates a tee reader that synchronizes branch seeks with source seeks.
The returned wrapper mirrors read bytes like TeeReader, but its
Seek implementation also seeks the branch writer to the source
reader’s resulting absolute position. If the branch seek fails, the
source reader may already have moved.
§Parameters
reader: Source reader.branch: Writer that receives bytes successfully read and is sought to the same absolute position as the source reader.
§Returns
A sync-seek tee reader.
Sourcepub fn branch_mut(&mut self) -> &mut W
pub fn branch_mut(&mut self) -> &mut W
Sourcepub fn into_inner(self) -> (R, W)
pub fn into_inner(self) -> (R, W)
Consumes this wrapper and returns the source reader and branch writer.
§Returns
A tuple containing the source reader and branch writer.
Trait Implementations§
Source§impl<R, W> Read for TeeReader<R, W>
impl<R, W> Read for TeeReader<R, W>
Source§fn read(&mut self, buffer: &mut [u8]) -> Result<usize>
fn read(&mut self, buffer: &mut [u8]) -> Result<usize>
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<'_, u8>) -> Result<(), Error>
fn read_buf(&mut self, buf: BorrowedCursor<'_, u8>) -> Result<(), Error>
read_buf)Source§fn read_buf_exact(
&mut self,
cursor: BorrowedCursor<'_, u8>,
) -> Result<(), Error>
fn read_buf_exact( &mut self, cursor: BorrowedCursor<'_, u8>, ) -> 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 more1.0.0 · Source§fn chain<R>(self, next: R) -> Chain<Self, R>
fn chain<R>(self, next: R) -> Chain<Self, R>
1.0.0 · Source§fn take(self, limit: u64) -> Take<Self>where
Self: Sized,
fn take(self, limit: u64) -> Take<Self>where
Self: Sized,
limit bytes from it. Read moreSource§fn read_array<const N: usize>(&mut self) -> Result<[u8; N], Error>where
Self: Sized,
fn read_array<const N: usize>(&mut self) -> Result<[u8; N], Error>where
Self: Sized,
read_array)Source§impl<R, W> Seek for TeeReader<R, W>where
R: Seek,
impl<R, W> Seek for TeeReader<R, W>where
R: Seek,
1.55.0 · Source§fn rewind(&mut self) -> Result<(), Error>
fn rewind(&mut self) -> Result<(), Error>
Source§fn stream_len(&mut self) -> Result<u64, Error>
fn stream_len(&mut self) -> Result<u64, Error>
seek_stream_len)Auto Trait Implementations§
impl<R, W> Freeze for TeeReader<R, W>
impl<R, W> RefUnwindSafe for TeeReader<R, W>where
R: RefUnwindSafe,
W: RefUnwindSafe,
impl<R, W> Send for TeeReader<R, W>
impl<R, W> Sync for TeeReader<R, W>
impl<R, W> Unpin for TeeReader<R, W>
impl<R, W> UnsafeUnpin for TeeReader<R, W>where
R: UnsafeUnpin,
W: UnsafeUnpin,
impl<R, W> UnwindSafe for TeeReader<R, W>where
R: UnwindSafe,
W: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<R> Input for R
impl<R> Input for R
Source§unsafe fn read_unchecked(
&mut self,
output: &mut [u8],
index: usize,
count: usize,
) -> Result<usize, Error>
unsafe fn read_unchecked( &mut self, output: &mut [u8], index: usize, count: usize, ) -> Result<usize, Error>
Reads bytes from a standard Read value into an indexed range.
Source§fn read(&mut self, output: &mut [<R as Input>::Item]) -> Result<usize, Error>
fn read(&mut self, output: &mut [<R as Input>::Item]) -> Result<usize, Error>
Reads items into the full output slice.
Source§fn is_buffered(&self) -> bool
fn is_buffered(&self) -> bool
Source§impl<T> ReadExt for T
impl<T> ReadExt for T
Source§unsafe fn read_unchecked(
&mut self,
buffer: &mut [u8],
start_index: usize,
count: usize,
) -> Result<usize, Error>
unsafe fn read_unchecked( &mut self, buffer: &mut [u8], start_index: usize, count: usize, ) -> Result<usize, Error>
buffer without checking the range bounds
in release builds. Read moreSource§unsafe fn read_exact_or_eof_unchecked(
&mut self,
buffer: &mut [u8],
start_index: usize,
count: usize,
) -> Result<usize, Error>
unsafe fn read_exact_or_eof_unchecked( &mut self, buffer: &mut [u8], start_index: usize, count: usize, ) -> Result<usize, Error>
buffer until that range is full or EOF is
reached, without checking the range bounds in release builds. Read moreSource§unsafe fn read_exact_unchecked(
&mut self,
buffer: &mut [u8],
start_index: usize,
count: usize,
) -> Result<(), Error>
unsafe fn read_exact_unchecked( &mut self, buffer: &mut [u8], start_index: usize, count: usize, ) -> Result<(), Error>
count bytes into a range of buffer without checking
the range bounds in release builds. Read moreSource§fn read_exact_or_eof(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
fn read_exact_or_eof(&mut self, buffer: &mut [u8]) -> Result<usize, Error>
buffer is full or EOF is reached. Read moreSource§fn read_exact_array<const N: usize>(&mut self) -> Result<[u8; N], Error>
fn read_exact_array<const N: usize>(&mut self) -> Result<[u8; N], Error>
N bytes into a stack-allocated array. Read moreSource§fn read_exact_vec_limited(
&mut self,
len: usize,
max_len: usize,
) -> Result<Vec<u8>, Error>
fn read_exact_vec_limited( &mut self, len: usize, max_len: usize, ) -> Result<Vec<u8>, Error>
len bytes into a new vector after checking a limit. Read moreSource§fn read_exact_vec_limited_into(
&mut self,
output: &mut Vec<u8>,
len: usize,
max_len: usize,
) -> Result<(), Error>
fn read_exact_vec_limited_into( &mut self, output: &mut Vec<u8>, len: usize, max_len: usize, ) -> Result<(), Error>
Source§fn discard_exact_or_eof(&mut self, bytes: u64) -> Result<u64, Error>
fn discard_exact_or_eof(&mut self, bytes: u64) -> Result<u64, Error>
bytes bytes from this reader. Read moreSource§fn copy_to(&mut self, writer: &mut dyn Write) -> Result<u64, Error>
fn copy_to(&mut self, writer: &mut dyn Write) -> Result<u64, Error>
writer. Read moreSource§fn copy_to_at_most(
&mut self,
writer: &mut dyn Write,
max_bytes: u64,
) -> Result<u64, Error>
fn copy_to_at_most( &mut self, writer: &mut dyn Write, max_bytes: u64, ) -> Result<u64, Error>
Source§fn copy_to_end_limited(
&mut self,
writer: &mut dyn Write,
max_bytes: u64,
) -> Result<u64, Error>
fn copy_to_end_limited( &mut self, writer: &mut dyn Write, max_bytes: u64, ) -> Result<u64, Error>
max_bytes. Read moreSource§fn read_to_end_limited(&mut self, max_len: usize) -> Result<Vec<u8>, Error>
fn read_to_end_limited(&mut self, max_len: usize) -> Result<Vec<u8>, Error>
Source§fn read_to_end_limited_into(
&mut self,
output: &mut Vec<u8>,
max_len: usize,
) -> Result<usize, Error>
fn read_to_end_limited_into( &mut self, output: &mut Vec<u8>, max_len: usize, ) -> Result<usize, Error>
output with a maximum accepted length. Read more