1use crate::ConcatRead;
2use std::fmt;
3use std::io::{Read, Result};
4
5pub struct ConcatReader<I: IntoIterator> {
40 curr: Option<I::Item>,
41 iter: I::IntoIter,
42}
43
44impl<I> ConcatReader<I>
45where
46 I: IntoIterator,
47 I::Item: Read,
48{
49 pub fn new(iter: I) -> Self {
58 let mut iter = iter.into_iter();
59 let curr = iter.next();
60 Self { iter, curr }
61 }
62}
63
64impl<I> ConcatRead for ConcatReader<I>
65where
66 I: IntoIterator,
67 I::Item: Read,
68{
69 type Item = I::Item;
70
71 fn current(&self) -> Option<&Self::Item> {
72 self.curr.as_ref()
73 }
74
75 fn skip(&mut self) -> bool {
76 self.curr = self.iter.next();
77 self.curr.is_some()
78 }
79}
80
81impl<I> From<I> for ConcatReader<I>
82where
83 I: IntoIterator,
84 I::Item: Read,
85{
86 fn from(iter: I) -> ConcatReader<I> {
87 Self::new(iter)
88 }
89}
90
91impl<I> Read for ConcatReader<I>
92where
93 I: IntoIterator,
94 I::Item: Read,
95{
96 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
97 let n = match self.curr {
98 None => 0,
99 Some(ref mut r) => r.read(buf)?,
100 };
101
102 if n > 0 || buf.is_empty() || self.curr.is_none() {
103 Ok(n)
104 } else {
105 self.curr = self.iter.next();
106 self.read(buf)
107 }
108 }
109}
110
111impl<I> fmt::Debug for ConcatReader<I>
112where
113 I: IntoIterator,
114 I::Item: fmt::Debug,
115 I::IntoIter: Clone,
116{
117 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
118 let rest: Vec<_> = self.iter.clone().collect();
119 f.debug_struct("Concat")
120 .field("curr", &self.curr)
121 .field("rest", &rest)
122 .finish()
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use crate::ConcatReader;
129 use std::io::prelude::*;
130
131 #[test]
132 fn reads_from_multiple_readers() {
133 let bytes: Vec<&[u8]> = vec![b"1", b"22", b"333", b"4444"];
134 let mut reader = ConcatReader::new(bytes);
135
136 let mut buf = [0; 5];
137 reader.read_exact(&mut buf).unwrap();
138 assert_eq!(&buf, b"12233");
139 }
140}