use {
glob,
lazy_regex::regex,
serde::{de::Error, Deserialize, Deserializer},
std::path::Path,
};
#[derive(Debug, Clone, PartialEq, Hash, Eq)]
pub struct Glob {
pattern: glob::Pattern,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum SpecialHandling {
None,
Enter,
NoEnter,
Hide,
}
#[derive(Debug, Clone)]
pub struct SpecialPath {
pub pattern: glob::Pattern,
pub handling: SpecialHandling,
}
pub trait SpecialPathList {
fn find(self, path: &Path) -> SpecialHandling;
}
impl<'de> Deserialize<'de> for SpecialHandling {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>
{
let s = String::deserialize(deserializer)?;
let s = s.to_lowercase();
let s = regex!(r"\W+").replace_all(&s, "");
match s.as_ref() {
"none" => Ok(SpecialHandling::None),
"enter" => Ok(SpecialHandling::Enter),
"noenter" => Ok(SpecialHandling::NoEnter),
"hide" => Ok(SpecialHandling::Hide),
_ => Err(D::Error::custom(format!(
"unrecognized special handling: {:?}",
s
))),
}
}
}
impl<'de> Deserialize<'de> for Glob {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de>
{
let s = String::deserialize(deserializer)?;
glob::Pattern::new(&s)
.map_err(|e| D::Error::custom(format!("invalid glob pattern {:?} : {:?}", s, e)))
.map(|pattern| Glob { pattern })
}
}
impl SpecialPath {
pub fn new(glob: Glob, handling: SpecialHandling) -> Self {
Self {
pattern: glob.pattern,
handling,
}
}
pub fn can_have_matches_in(&self, path: &Path) -> bool {
path.to_str()
.map_or(false, |p| self.pattern.as_str().starts_with(p))
}
}
impl SpecialPathList for &[SpecialPath] {
fn find(self, path: &Path) -> SpecialHandling {
for sp in self {
if sp.pattern.matches_path(path) {
return sp.handling;
}
}
SpecialHandling::None
}
}