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}