use crate::preproc::rga_preproc; use crate::{adapters::*, read_iter::ReadIterBox}; use anyhow::*; use std::io::Read; pub struct RecursingConcattyReader<'a> { inp: ReadIterBox<'a>, cur: Option>, } impl<'a> RecursingConcattyReader<'a> { pub fn concat(inp: ReadIterBox<'a>) -> Result> { 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 as *mut ReadIterBox<'a>)).next() }; 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 { 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), }, } } }