Skip to main content

qubit_io/wrappers/
tee_reader.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10use std::io::{
11    Read,
12    Result,
13    Seek,
14    SeekFrom,
15    Write,
16};
17
18/// Reader wrapper that mirrors read bytes into a branch writer.
19///
20/// `TeeReader` forwards reads to the source reader and writes every
21/// successfully read byte into the branch writer while the stream is consumed.
22/// If the branch writer fails, the source bytes have already been read from the
23/// inner reader and the branch error is returned.
24///
25/// # Examples
26/// ```
27/// use std::io::{
28///     Cursor,
29///     Read,
30/// };
31///
32/// use qubit_io::TeeReader;
33///
34/// let source = Cursor::new(b"abc".to_vec());
35/// let branch = Vec::new();
36/// let mut reader = TeeReader::new(source, branch);
37///
38/// let mut data = Vec::new();
39/// reader.read_to_end(&mut data)?;
40/// let (_source, branch) = reader.into_inner();
41///
42/// assert_eq!(b"abc", data.as_slice());
43/// assert_eq!(b"abc", branch.as_slice());
44/// # Ok::<(), std::io::Error>(())
45/// ```
46pub struct TeeReader<R, W> {
47    reader: R,
48    branch: W,
49}
50
51impl<R, W> TeeReader<R, W> {
52    /// Creates a tee reader.
53    ///
54    /// # Parameters
55    /// - `reader`: Source reader.
56    /// - `branch`: Writer that receives the bytes successfully read.
57    ///
58    /// # Returns
59    /// A new tee reader.
60    #[inline]
61    pub fn new(reader: R, branch: W) -> Self {
62        Self { reader, branch }
63    }
64
65    /// Returns an immutable reference to the source reader.
66    ///
67    /// # Returns
68    /// The source reader reference.
69    #[inline]
70    pub fn reader_ref(&self) -> &R {
71        &self.reader
72    }
73
74    /// Returns a mutable reference to the source reader.
75    ///
76    /// # Returns
77    /// The source reader reference.
78    #[inline]
79    pub fn reader_mut(&mut self) -> &mut R {
80        &mut self.reader
81    }
82
83    /// Returns an immutable reference to the branch writer.
84    ///
85    /// # Returns
86    /// The branch writer reference.
87    #[inline]
88    pub fn branch_ref(&self) -> &W {
89        &self.branch
90    }
91
92    /// Returns a mutable reference to the branch writer.
93    ///
94    /// # Returns
95    /// The branch writer reference.
96    #[inline]
97    pub fn branch_mut(&mut self) -> &mut W {
98        &mut self.branch
99    }
100
101    /// Consumes this wrapper and returns the source reader and branch writer.
102    ///
103    /// # Returns
104    /// A tuple containing the source reader and branch writer.
105    #[inline]
106    pub fn into_inner(self) -> (R, W) {
107        (self.reader, self.branch)
108    }
109}
110
111impl<R, W> Read for TeeReader<R, W>
112where
113    R: Read,
114    W: Write,
115{
116    fn read(&mut self, buffer: &mut [u8]) -> Result<usize> {
117        let count = self.reader.read(buffer)?;
118        self.branch.write_all(&buffer[..count])?;
119        Ok(count)
120    }
121}
122
123impl<R, W> Seek for TeeReader<R, W>
124where
125    R: Seek,
126{
127    #[inline]
128    fn seek(&mut self, position: SeekFrom) -> Result<u64> {
129        self.reader.seek(position)
130    }
131}