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}