use std::fs::{read_dir, ReadDir, DirEntry};
use std::path::Path;
use {Error, ScanDir};
use filter::matches;
pub struct Iter<'a> {
settings: &'a ScanDir,
error: &'a mut Result<(), Error>,
path: &'a Path,
iter: Option<ReadDir>,
}
pub fn new<'x>(settings: &'x ScanDir, error: &'x mut Result<(), Error>,
path: &'x Path)
-> Iter<'x>
{
let iter = read_dir(path).map_err(|e| {
*error = Err(Error::Io(e, path.to_path_buf()));
}).ok();
Iter {
settings: settings,
error: error,
path: path,
iter: iter,
}
}
impl<'a> Iterator for Iter<'a> {
type Item = (DirEntry, String);
fn next(&mut self) -> Option<(DirEntry, String)> {
loop {
if let Some(ref mut iter) = self.iter {
match iter.next() {
Some(Ok(entry)) => {
let osname = entry.file_name();
if let Ok(name) = osname.into_string() {
match matches(self.settings, &entry, &name) {
Ok(true) => return Some((entry, name)),
Ok(false) => {},
Err(e) => {
error(self.error,
Error::Io(e, entry.path()));
}
}
} else {
error(self.error,
Error::Decode(entry.path()));
}
}
Some(Err(e)) => {
error(self.error,
Error::Io(e, self.path.to_path_buf()));
}
None => return None,
}
} else {
return None
}
}
}
}
fn error(old: &mut Result<(), Error>, new: Error) {
let overwrite = match (&old, &new) {
(&&mut Ok(()), _) => true,
(&&mut Err(Error::Decode(_)), &Error::Io(_, _)) => true,
_ => false,
};
if overwrite {
*old = Err(new);
}
}