use crate::ConcatRead;
use std::fmt;
use std::io::{Read, Result};
pub struct ConcatReader<I: IntoIterator> {
curr: Option<I::Item>,
iter: I::IntoIter,
}
impl<I> ConcatReader<I>
where
I: IntoIterator,
I::Item: Read,
{
pub fn new(iter: I) -> Self {
let mut iter = iter.into_iter();
let curr = iter.next();
Self { iter, curr }
}
}
impl<I> ConcatRead for ConcatReader<I>
where
I: IntoIterator,
I::Item: Read,
{
type Item = I::Item;
fn current(&self) -> Option<&Self::Item> {
self.curr.as_ref()
}
fn skip(&mut self) -> bool {
self.curr = self.iter.next();
self.curr.is_some()
}
}
impl<I> From<I> for ConcatReader<I>
where
I: IntoIterator,
I::Item: Read,
{
fn from(iter: I) -> ConcatReader<I> {
Self::new(iter)
}
}
impl<I> Read for ConcatReader<I>
where
I: IntoIterator,
I::Item: Read,
{
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let n = match self.curr {
None => 0,
Some(ref mut r) => r.read(buf)?,
};
if n > 0 || buf.is_empty() || self.curr.is_none() {
Ok(n)
} else {
self.curr = self.iter.next();
self.read(buf)
}
}
}
impl<I> fmt::Debug for ConcatReader<I>
where
I: IntoIterator,
I::Item: fmt::Debug,
I::IntoIter: Clone,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let rest: Vec<_> = self.iter.clone().collect();
f.debug_struct("Concat")
.field("curr", &self.curr)
.field("rest", &rest)
.finish()
}
}
#[cfg(test)]
mod tests {
use crate::ConcatReader;
use std::io::prelude::*;
#[test]
fn reads_from_multiple_readers() {
let bytes: Vec<&[u8]> = vec![b"1", b"22", b"333", b"4444"];
let mut reader = ConcatReader::new(bytes);
let mut buf = [0; 5];
reader.read_exact(&mut buf).unwrap();
assert_eq!(&buf, b"12233");
}
}