use std::fs;
use std::path::{Path, PathBuf};
macro_rules! some(
($option:expr) => (
match $option {
Some(some) => some,
None => return false,
}
);
);
pub enum Verdict {
AcceptMore,
AcceptStop,
RejectMore,
RejectStop,
}
pub fn all<F>(directory: &Path, condition: F) -> Vec<PathBuf> where F: Fn(&Path) -> bool {
some(directory, |path| {
if condition(path) { Verdict::AcceptMore } else { Verdict::RejectMore }
})
}
pub fn all_with_extension(directory: &Path, extension: &str) -> Vec<PathBuf> {
use std::ascii::AsciiExt;
all(directory, |path| -> bool {
some!(some!(path.extension()).to_str()).to_ascii_lowercase() == extension
})
}
pub fn first<F>(directory: &Path, condition: F) -> Option<PathBuf> where F: Fn(&Path) -> bool {
some(directory, |path| {
if condition(path) { Verdict::AcceptStop } else { Verdict::RejectMore }
}).pop()
}
pub fn first_with_extension(directory: &Path, extension: &str) -> Option<PathBuf> {
use std::ascii::AsciiExt;
first(directory, |path| -> bool {
some!(some!(path.extension()).to_str()).to_ascii_lowercase() == extension
})
}
pub fn some<F>(directory: &Path, condition: F) -> Vec<PathBuf> where F: Fn(&Path) -> Verdict {
macro_rules! ok(
($result:expr) => (
match $result {
Ok(ok) => ok,
Err(_) => return Vec::new(),
}
);
);
let mut paths = Vec::new();
for entry in ok!(fs::read_dir(&directory)) {
let entry = ok!(entry);
if ok!(fs::metadata(entry.path())).is_dir() {
continue;
}
let path = entry.path();
match condition(&path) {
Verdict::AcceptMore => paths.push(path),
Verdict::AcceptStop => {
paths.push(path);
break;
},
Verdict::RejectMore => {},
Verdict::RejectStop => break,
}
}
paths
}