use std::path::PathBuf;
use std::sync::Arc;
use std::fmt::Debug;
use failure::Fallible as Result;
use crate::storeid::StoreIdWithBase;
use crate::file_abstraction::FileAbstraction;
pub(crate) trait PathIterBuilder : Debug {
fn build_iter(&self) -> Box<dyn Iterator<Item = Result<PathBuf>>>;
fn in_collection(&mut self, c: &str) -> Result<()>;
}
pub(crate) struct PathIterator<'a> {
iter_builder: Box<dyn PathIterBuilder>,
iter: Box<dyn Iterator<Item = Result<PathBuf>>>,
storepath: &'a PathBuf,
backend: Arc<dyn FileAbstraction>,
}
impl<'a> PathIterator<'a> {
pub fn new(iter_builder: Box<dyn PathIterBuilder>,
storepath: &'a PathBuf,
backend: Arc<dyn FileAbstraction>)
-> PathIterator<'a>
{
trace!("Generating iterator object with PathIterBuilder: {:?}", iter_builder);
let iter = iter_builder.build_iter();
PathIterator { iter_builder, iter, storepath, backend }
}
pub fn in_collection(mut self, c: &str) -> Result<Self> {
trace!("Generating iterator object for collection: {}", c);
self.iter_builder.in_collection(c)?;
self.iter = self.iter_builder.build_iter();
trace!("Set new iterator");
Ok(self)
}
pub(crate) fn into_inner(self) -> Box<dyn Iterator<Item = Result<PathBuf>>> {
self.iter
}
}
impl<'a> Iterator for PathIterator<'a> {
type Item = Result<StoreIdWithBase<'a>>;
fn next(&mut self) -> Option<Self::Item> {
while let Some(next) = self.iter.next() {
trace!("Iterating over item = {:?}", next);
match next {
Err(e) => return Some(Err(e)),
Ok(next) => match self.backend.is_file(&next) {
Err(e) => return Some(Err(e)),
Ok(true) => return Some(StoreIdWithBase::from_full_path(&self.storepath, next)),
Ok(false) => { continue },
}
}
}
None
}
}