Simple tool for automatic file management
1use std::fmt; 2use std::path::Path; 3 4use serde::{de, Deserialize}; 5use wildmatch::WildMatch; 6 7/// Patterns that can be matched against files 8#[derive(Debug, Deserialize)] 9pub enum Pattern { 10 #[serde(deserialize_with = "deserialize_wildcard")] 11 Wildcard(WildMatch), 12 #[serde(deserialize_with = "deserialize_regex")] 13 Regex(regex::Regex), 14 Exact(Box<Path>), 15} 16 17impl Pattern { 18 pub fn matches(&self, path: &Path) -> bool { 19 match *self { 20 Self::Wildcard(ref pattern) => pattern.matches(path.to_str().unwrap()), 21 Self::Regex(ref pattern) => pattern.is_match(path.to_str().unwrap()), 22 Self::Exact(ref pattern) => **pattern == *path, 23 } 24 } 25} 26 27struct RegexVisitor; 28 29impl<'de> de::Visitor<'de> for RegexVisitor { 30 type Value = regex::Regex; 31 32 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 33 write!(formatter, "expected regex string") 34 } 35 36 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> 37 where 38 E: de::Error, 39 { 40 match regex::Regex::new(s) { 41 Ok(regex) => Ok(regex), 42 Err(regex::Error::Syntax(ref desc)) => { 43 Err(E::invalid_value(de::Unexpected::Str(s), &desc.as_str())) 44 } 45 Err(_) => unreachable!(), 46 } 47 } 48} 49 50fn deserialize_regex<'de, D>(des: D) -> Result<regex::Regex, D::Error> 51where 52 D: serde::Deserializer<'de>, 53{ 54 des.deserialize_str(RegexVisitor) 55} 56 57struct WildcardVisitor; 58 59impl<'de> de::Visitor<'de> for WildcardVisitor { 60 type Value = WildMatch; 61 62 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 63 write!(formatter, "expected regex string") 64 } 65 66 fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> 67 where 68 E: de::Error, 69 { 70 Ok(WildMatch::new(s)) 71 } 72} 73 74fn deserialize_wildcard<'de, D>(des: D) -> Result<WildMatch, D::Error> 75where 76 D: serde::Deserializer<'de>, 77{ 78 des.deserialize_str(WildcardVisitor) 79}