chain_reader/
lib.rs

1use std::{
2    collections::VecDeque,
3    io::{self, Read},
4};
5
6/// A sequential chaining reader that combines multiple [`Read`] instances with configurable error handling.
7///
8/// # Behavior
9///
10/// - Readers are consumed in FIFO (first-in, first-out) order.
11/// - Automatically switches to the next reader when the current one reaches EOF (returns `Ok(0)`).
12/// - Allows custom error handling to decide whether to retry or skip on I/O errors.
13///
14/// # Comparison with [`io::Chain`]
15///
16/// - Supports a dynamic queue of readers instead of a fixed pair.
17/// - Configurable error handling strategies: Retry or Skip
18/// - Automatically advances to the next reader on EOF.
19///
20/// ---
21///
22/// 顺序管道读取器,将多个 [`Read`] 实例组合为具有可配置错误处理的顺序读取管道。
23///
24/// # 行为特性:
25///
26/// - 按先进先出顺序消费读取器。
27/// - 当前读取器到达 EOF 时(返回 `Ok(0)`)自动切换至下一个。
28/// - 允许自定义错误处理策略,决定在 I/O 错误时重试或跳过。
29///
30/// # 与 [`io::Chain`] 的区别:
31///
32/// - 支持动态读取器队列而非固定两个。
33/// - 可配置错误处理策略:重试或跳过。
34/// - EOF 时自动管理读取器切换。
35#[derive(Debug, Clone)]
36pub struct ChainReader<R, F>
37where
38    R: Read,
39    F: FnMut(io::Error) -> ErrorAction,
40{
41    /// Reader queue managed as FIFO buffer (first-in, first-out).
42    ///
43    /// Implemented with [`VecDeque`] for O(1) pop-front operations. The front reader
44    /// remains active until it returns EOF (`Ok(0)`), encounters an error handled by [`ErrorAction::Skip`],
45    /// or is explicitly removed.
46    ///
47    /// ---
48    ///
49    /// 先进先出读取器队列。
50    ///
51    /// 使用 [`VecDeque`] 实现 O(1) 复杂度前端弹出操作。队列首部的读取器保持激活状态,
52    /// 直到返回 EOF(`Ok(0)`)、遇到由 [`ErrorAction::Skip`] 处理的错误,或被显式移除。
53    fifo: VecDeque<R>,
54    /// Error handling callback for read operations.
55    ///
56    /// When a read error occurs, this callback is invoked with the encountered [`io::Error`].
57    /// The chaining behavior is determined by the returned [`ErrorAction`]:
58    /// - [`ErrorAction::Retry`]: Propagate the error but retain the current reader for retries.
59    /// - [`ErrorAction::Skip`]: Discard the current reader and proceed to the next.
60    ///
61    /// ---
62    ///
63    /// 读取操作错误处理回调。
64    ///
65    /// 当读取错误发生时,此回调函数接收遇到的 [`io::Error`],
66    /// 并通过返回的 [`ErrorAction`] 决定链式读取行为:
67    /// - [`ErrorAction::Retry`]:传播错误但保留当前读取器以供重试。
68    /// - [`ErrorAction::Skip`]:跳过当前读取器并继续下一个。
69    handle: F,
70}
71
72impl<R, F> ChainReader<R, F>
73where
74    R: Read,
75    F: FnMut(io::Error) -> ErrorAction,
76{
77    /// Creates a new `ChainReader` with the given reader queue and error handler.
78    ///
79    /// The readers will be consumed in the order they appear in the `readers` queue.
80    /// The `handle` callback determines behavior on I/O errors during reading.
81    ///
82    /// # Parameters
83    /// - `readers`: Queue of readers to process sequentially
84    /// - `handle`: Error handling strategy callback
85    ///
86    /// # Examples
87    /// ```
88    /// use std::collections::VecDeque;
89    /// use std::io;
90    /// use chain_reader::{ChainReader, ErrorAction};
91    ///
92    /// let mut readers = VecDeque::new();
93    /// readers.push_back("hello".as_bytes());
94    /// let error_handler = |e: io::Error| ErrorAction::Skip;
95    /// let chain = ChainReader::new(readers, error_handler);
96    /// ```
97    ///
98    /// ---
99    ///
100    /// 使用指定的读取器队列和错误处理回调创建新的 `ChainReader`
101    ///
102    /// 读取器将按照队列中的顺序被消费。`handle` 回调用于决定读取时遇到 I/O 错误的处理策略
103    ///
104    /// # 参数
105    /// - `readers`: 要顺序处理的读取器队列
106    /// - `handle`: 错误处理策略回调
107    ///
108    /// # 示例
109    /// ```
110    /// use std::collections::VecDeque;
111    /// use std::io;
112    /// use chain_reader::{ChainReader, ErrorAction};
113    ///
114    /// let mut readers = VecDeque::new();
115    /// readers.push_back("hello".as_bytes());
116    /// let error_handler = |e: io::Error| ErrorAction::Skip;
117    /// let chain = ChainReader::new(readers, error_handler);
118    /// ```
119    pub fn new(readers: VecDeque<R>, handle: F) -> Self {
120        ChainReader {
121            fifo: readers,
122            handle,
123        }
124    }
125
126    /// Appends a reader to the end of the processing queue
127    ///
128    /// The reader will be processed after all existing readers in the queue
129    /// have either reached EOF or been skipped due to errors.
130    ///
131    /// # Parameters
132    /// - `reader`: Reader to add to the end of the queue
133    ///
134    /// # Examples
135    /// ```
136    /// use std::collections::VecDeque;
137    /// use std::io;
138    /// use chain_reader::{ChainReader, ErrorAction};
139    ///
140    /// let mut chain = ChainReader::new(VecDeque::new(), |e| ErrorAction::Skip);
141    /// chain.push_back(std::io::empty());
142    /// ```
143    ///
144    /// ---
145    ///
146    /// 将读取器追加到处理队列末尾
147    ///
148    /// 该读取器将在队列中所有现有读取器处理完毕(到达 EOF 或因为错误被跳过)后进行处理
149    ///
150    /// # 参数
151    /// - `reader`: 要添加到队列末尾的读取器
152    ///
153    /// # 示例
154    /// ```
155    /// use std::collections::VecDeque;
156    /// use std::io;
157    /// use chain_reader::{ChainReader, ErrorAction};
158    /// let mut chain = ChainReader::new(VecDeque::new(), |e| ErrorAction::Skip);
159    /// chain.push_back(std::io::empty());
160    /// ```
161    pub fn push_back(&mut self, reader: R) {
162        self.fifo.push_back(reader);
163    }
164
165    /// Removes and returns the front reader from the queue
166    ///
167    /// Used internally when advancing to the next reader. Maintains
168    /// O(1) time complexity for queue operations.
169    ///
170    /// ---
171    ///
172    /// 移除并返回队列前端的读取器
173    ///
174    /// 内部用于切换到下一个读取器,保持队列操作的 O(1) 时间复杂度
175    fn pop_front(&mut self) -> Option<R> {
176        self.fifo.pop_front()
177    }
178}
179
180impl<R, F> Read for ChainReader<R, F>
181where
182    R: Read,
183    F: FnMut(io::Error) -> ErrorAction,
184{
185    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
186        loop {
187            let reader = match self.fifo.front_mut() {
188                Some(it) => it,
189                None => return Ok(0),
190            };
191
192            match reader.read(buf) {
193                Ok(0) => {
194                    let _ = self.pop_front();
195                }
196                Ok(it) => {
197                    return Ok(it);
198                }
199                Err(it) => {
200                    let r: ErrorAction = (self.handle)(it);
201                    match r {
202                        ErrorAction::Retry(it) => return Err(it),
203                        ErrorAction::Skip => {
204                            let _ = self.pop_front();
205                        }
206                    }
207                }
208            }
209        }
210    }
211}
212
213/// Defines the action to take when a read error occurs.
214///
215/// ---
216///
217/// 定义读取错误发生时的处理动作。
218pub enum ErrorAction {
219    /// Propagate the error but retain the current reader.
220    ///
221    /// The next read operation will retry the same reader. This is useful for
222    /// transient errors where retrying might succeed.
223    ///
224    /// ---
225    ///
226    /// 传播错误但保留当前读取器。
227    ///
228    /// 下次读取操作将继续尝试同一读取器。适用于可能通过重试解决的临时错误。
229    Retry(io::Error),
230    /// Discard the current reader and proceed to the next one.
231    ///
232    /// The problematic reader is removed from the queue immediately.
233    ///
234    /// ---
235    ///
236    /// 丢弃当前读取器并继续下一个。
237    ///
238    /// 有问题的读取器将立即从队列中移除。
239    Skip,
240}