diff options
Diffstat (limited to 'src/path/special_path.rs')
-rw-r--r-- | src/path/special_path.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/src/path/special_path.rs b/src/path/special_path.rs new file mode 100644 index 0000000..9462654 --- /dev/null +++ b/src/path/special_path.rs @@ -0,0 +1,84 @@ +use { + glob, + 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(); + // we remove non letters so to accept eg "no-enter" + 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 + } +} |