ripgrep-all/src/recurse.rs

49 lines
1.5 KiB
Rust
Raw Normal View History

2020-09-30 14:22:54 +00:00
use crate::adapters::*;
use crate::preproc::rga_preproc;
use anyhow::*;
use std::io::Read;
pub struct RecursingConcattyReader<'a> {
inp: Box<dyn ReadIter + 'a>,
cur: Option<ReadBox<'a>>,
}
impl<'a> RecursingConcattyReader<'a> {
pub fn concat(inp: Box<dyn ReadIter + 'a>) -> Result<Box<dyn Read + 'a>> {
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>
(*(inp as *mut Box<dyn ReadIter + '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<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),
},
}
}
}