Browse Source

Added a filter to the directory iterator

master
Julio Biason 1 day ago
parent
commit
08b0ed961f
  1. 47
      diritertest/src/diriter.rs
  2. 34
      diritertest/src/main.rs

47
diritertest/src/diriter.rs

@ -1,21 +1,39 @@
//! Iterator over directories //! Iterator over directories
use std::collections::VecDeque; use std::collections::VecDeque;
use std::fs::DirEntry;
use std::fs::ReadDir; use std::fs::ReadDir;
use std::marker::PhantomData;
use std::path::Path; use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
pub struct DirIter { pub trait Accept {
/// Accept a directory and return it as a result. Note that this stops the processing of any
/// other entries in the directory.
fn accept_dir(_: &Path) -> bool {
false
}
/// Accept a file and return it as a result.
fn accept_file(_: &Path) -> bool {
false
}
}
pub struct DirIter<A: Accept> {
curr_dir: ReadDir, curr_dir: ReadDir,
remaining_dirs: VecDeque<PathBuf>, remaining_dirs: VecDeque<PathBuf>,
accept: PhantomData<A>,
} }
impl DirIter { impl<A> DirIter<A>
where
A: Accept,
{
pub fn new(start: &Path) -> std::io::Result<Self> { pub fn new(start: &Path) -> std::io::Result<Self> {
Ok(Self { Ok(Self {
curr_dir: start.read_dir()?, curr_dir: start.read_dir()?,
remaining_dirs: VecDeque::new(), remaining_dirs: VecDeque::new(),
accept: PhantomData,
}) })
} }
@ -23,23 +41,32 @@ impl DirIter {
let next = self.curr_dir.next(); let next = self.curr_dir.next();
match next { match next {
Some(Ok(x)) => { Some(Ok(x)) => {
if x.path().is_dir() { let x = x.path();
self.remaining_dirs.push_back(x.path()); if x.is_dir() {
self.advance() if A::accept_dir(&x) {
Some(x)
} else {
self.remaining_dirs.push_back(x);
self.advance()
}
} else { } else {
Some(x.path()) if A::accept_file(&x) {
Some(x)
} else {
self.advance()
}
} }
} }
Some(Err(_)) | None => { _ => {
let next_dir = self.remaining_dirs.pop_front()?; let next_dir = self.remaining_dirs.pop_front()?;
self.curr_dir = std::fs::read_dir(next_dir).ok()?; self.curr_dir = next_dir.read_dir().ok()?;
self.advance() self.advance()
} }
} }
} }
} }
impl Iterator for DirIter { impl<A: Accept> Iterator for DirIter<A> {
type Item = PathBuf; type Item = PathBuf;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {

34
diritertest/src/main.rs

@ -1,21 +1,39 @@
use std::ffi::OsStr;
use std::path::Path; use std::path::Path;
use crate::diriter::DirIter; use diriter::Accept;
use diriter::DirIter;
mod diriter; mod diriter;
struct AllFiles;
impl Accept for AllFiles {
fn accept_file(_: &Path) -> bool {
true
}
fn accept_dir(_: &Path) -> bool {
false
}
}
struct Sources;
impl Accept for Sources {
fn accept_dir(p: &Path) -> bool {
p.file_name().unwrap() == OsStr::new("src")
}
}
fn main() { fn main() {
let mut all_iter = DirIter::new(&Path::new(".")).unwrap(); let mut all_iter = DirIter::<AllFiles>::new(&Path::new(".")).unwrap();
while let Some(path) = all_iter.next() { while let Some(path) = all_iter.next() {
println!(">> {:?}", path); println!(">> {:?}", path);
} }
println!("-----------------------"); println!("{}", std::iter::repeat('-').take(80).collect::<String>());
let all_iter = DirIter::new(&Path::new(".")).unwrap(); let iter = DirIter::<Sources>::new(&Path::new(".")).unwrap();
for path in all_iter { for name in iter {
println!(">>> {:?}", path); println!(">> {:?}", name);
} }
println!("Hello, world!");
} }

Loading…
Cancel
Save