2020-09-30 14:22:54 +00:00
|
|
|
use crate::preproc::rga_preproc;
|
2020-09-30 15:26:42 +00:00
|
|
|
use crate::{adapted_iter::AdaptedFilesIterBox, adapters::*};
|
2020-09-30 14:22:54 +00:00
|
|
|
|
|
|
|
use anyhow::*;
|
|
|
|
use std::io::Read;
|
|
|
|
|
|
|
|
pub struct RecursingConcattyReader<'a> {
|
2020-09-30 15:26:42 +00:00
|
|
|
inp: AdaptedFilesIterBox<'a>,
|
2020-09-30 14:22:54 +00:00
|
|
|
cur: Option<ReadBox<'a>>,
|
|
|
|
}
|
|
|
|
impl<'a> RecursingConcattyReader<'a> {
|
2020-09-30 15:26:42 +00:00
|
|
|
pub fn concat(inp: AdaptedFilesIterBox<'a>) -> Result<Box<dyn Read + 'a>> {
|
2020-09-30 14:22:54 +00:00
|
|
|
let mut r = RecursingConcattyReader { inp, cur: None };
|
|
|
|
r.ascend()?;
|
|
|
|
Ok(Box::new(r))
|
|
|
|
}
|
|
|
|
pub fn ascend(&mut self) -> Result<()> {
|
|
|
|
let inp = &mut self.inp;
|
|
|
|
// get next inner file from inp
|
|
|
|
// we only need to access the inp: ReadIter when the inner reader is done, so this should be safe
|
|
|
|
let ai = unsafe {
|
|
|
|
// would love to make this safe, but how? something like OwnedRef<inp, cur>
|
2020-09-30 15:26:42 +00:00
|
|
|
(*(inp as *mut AdaptedFilesIterBox<'a>)).next()
|
2020-09-30 14:22:54 +00:00
|
|
|
};
|
|
|
|
self.cur = match ai {
|
|
|
|
Some(ai) => Some(rga_preproc(ai)?),
|
|
|
|
None => None,
|
|
|
|
};
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl<'a> Read for RecursingConcattyReader<'a> {
|
|
|
|
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
|
|
|
|
match &mut self.cur {
|
|
|
|
None => Ok(0), // last file ended
|
|
|
|
Some(cur) => match cur.read(buf) {
|
|
|
|
Err(e) => Err(e),
|
|
|
|
Ok(0) => {
|
|
|
|
// current file ended, go to next file
|
|
|
|
self.ascend()
|
|
|
|
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
|
|
|
self.read(buf)
|
|
|
|
}
|
|
|
|
Ok(n) => Ok(n),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|