use regex::Regex;
use std::{
fs,
io,
path::{
Path,
PathBuf,
},
};
const WILDCARD_CHAR: char = '*';
pub trait PathExt {
fn expand_wildcards(&self) -> io::Result<PathBuf>;
}
impl PathExt for Path {
fn expand_wildcards(&self) -> io::Result<PathBuf> {
let mut real_path = PathBuf::from("/");
for component in self.iter() {
let component_s = component.to_str().unwrap();
let mut wildcards = component_s.matches(WILDCARD_CHAR).peekable();
if let Some(_) = wildcards.peek() {
trace!("Found wildcard component: {:?}", component_s);
let r = {
let pattern = format!("^{}$", component_s.replace(WILDCARD_CHAR, ".*"));
Regex::new(&pattern)
.expect(&format!("Failed to compile regular expression while evaluating wildcard path component: \"{:?}\"", component))
};
let entries = fs::read_dir(&real_path)?;
let found_entry = entries.filter_map(|entry| {
if let Ok(entry) = entry {
let entry_s = entry.file_name().to_str().map(String::from).unwrap();
if r.is_match(&entry_s) {
Some(entry_s)
} else {
None
}
} else {
None
}
}).next();
if let Some(found_entry) = found_entry {
real_path.push(found_entry);
} else {
real_path.push(component);
}
} else {
trace!("There were no wildcards in path component: \"{}\"", component_s);
real_path.push(component);
}
}
Ok(real_path)
}
}