#![allow(dead_code)]
mod filter;
#[cfg(test)]
mod test;
use std::*;
type Result<T> = io::Result<T>;
#[derive(Default)]
pub struct DirIterator {
stack: Vec<fs::ReadDir>,
config: DirIteratorConfig,
}
impl DirIterator {
pub fn current() -> DirIteratorBuilder {
Self::try_current().expect("invalid current directory")
}
pub fn try_current() -> Result<DirIteratorBuilder> {
Self::from_path(env::current_dir()?)
}
pub fn build_current() -> impl Iterator<Item = fs::DirEntry> {
Self::current().build()
}
pub fn try_build_current() -> Result<impl Iterator<Item = fs::DirEntry>> {
Ok(Self::try_current()?.build())
}
pub fn from_path(path: impl AsRef<path::Path>) -> Result<DirIteratorBuilder> {
Ok(DirIteratorBuilder(Self {
stack: vec![fs::read_dir(path)?],
..Default::default()
}))
}
pub fn build_from_path(
path: impl AsRef<path::Path>,
) -> Result<impl Iterator<Item = fs::DirEntry>> {
Ok(Self::from_path(path)?.build())
}
fn from_builder(builder: DirIteratorBuilder) -> Self {
builder.0
}
}
impl Iterator for DirIterator {
type Item = Result<fs::DirEntry>;
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(it) = self.stack.last_mut() {
match it.next() {
Some(Ok(item)) => {
match item.file_type() {
Ok(file_type) => {
if self.config.ignore.iter().any(|ignore| {
ignore.is_match(item.file_name().as_encoded_bytes())
}) {
continue;
}
if file_type.is_dir() {
match fs::read_dir(item.path()) {
Ok(dir_entry) => self.stack.push(dir_entry),
Err(err) => return Some(Err(err)),
}
}
return Some(Ok(item));
}
Err(err) => return Some(Err(err)),
}
}
None => {
self.stack.pop()?;
}
err => return err,
}
} else {
return None;
}
}
}
}
#[derive(Default)]
struct DirIteratorConfig {
ignore: Vec<wc::Wildcard<'static>>,
}
#[derive(Default)]
pub struct DirIteratorBuilder(DirIterator);
impl DirIteratorBuilder {
pub fn build(self) -> impl Iterator<Item = fs::DirEntry> {
DirIterator::from_builder(self).flatten()
}
pub fn ignore(mut self, wildcard: &'static str) -> Self {
self.0
.config
.ignore
.push(wc::Wildcard::new(wildcard.as_bytes()).expect("misformed wildcard"));
self
}
}