use std::path::Path; use globset::GlobBuilder; use serde::Deserialize; #[derive(Debug, Deserialize)] #[serde(try_from = "String")] pub struct Pattern { inner: globset::GlobMatcher, is_star: bool, is_folder: bool, } impl Pattern { #[inline] pub fn match_mime(&self, str: impl AsRef) -> bool { self.inner.is_match(str.as_ref()) } #[inline] pub fn match_path(&self, path: impl AsRef, is_folder: bool) -> bool { is_folder == self.is_folder && (self.is_star || self.inner.is_match(path)) } #[inline] pub fn any_file(&self) -> bool { self.is_star && !self.is_folder } #[inline] pub fn any_dir(&self) -> bool { self.is_star && self.is_folder } } impl TryFrom<&str> for Pattern { type Error = anyhow::Error; fn try_from(s: &str) -> Result { let a = s.trim_start_matches("\\s"); let b = a.trim_end_matches('/'); let inner = GlobBuilder::new(b) .case_insensitive(a.len() == s.len()) .literal_separator(b.contains('/')) .backslash_escape(false) .empty_alternates(false) .build()? .compile_matcher(); Ok(Self { inner, is_star: b == "*", is_folder: b.len() < a.len() }) } } impl TryFrom for Pattern { type Error = anyhow::Error; fn try_from(s: String) -> Result { Self::try_from(s.as_str()) } }