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