Skip to main content

openpathresolver/types/
resolver.rs

1use serde::Deserialize;
2
3/// The resolver for the placeholders.
4#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
5pub enum Resolver {
6    /// This is an undefined resolver and should be assumed to be a string.
7    Default,
8    /// This is a string resolver and may also have a shape.
9    #[serde(
10        serialize_with = "serialize_regex",
11        deserialize_with = "deserialize_regex"
12    )]
13    String {
14        /// The shape of a valid string.
15        pattern: Option<std::sync::Arc<regex::Regex>>,
16    },
17    /// This is an integer resolver.
18    Integer {
19        /// The zero padding to use for the integer, and the minimum number of numerical characters
20        /// to search for.
21        padding: u8,
22    },
23}
24
25impl Resolver {
26    pub(crate) fn pattern(&self) -> std::borrow::Cow<'_, str> {
27        match self {
28            Self::Default => ".+?".into(),
29            Self::String { pattern } => match pattern {
30                Some(pattern) => pattern.to_string().into(),
31                None => ".+?".into(),
32            },
33            Self::Integer { padding } => format!("\\d{{{},}}?", padding.max(&1)).into(),
34        }
35    }
36
37    pub(crate) fn to_path_value(&self, value: &str) -> Result<crate::PathValue, crate::Error> {
38        match self {
39            Self::Default => Ok(crate::PathValue::String(value.into())),
40            Self::String { .. } => Ok(crate::PathValue::String(value.into())),
41            Self::Integer { .. } => Ok(crate::PathValue::Integer(value.parse()?)),
42        }
43    }
44}
45
46fn serialize_regex<S: serde::Serializer>(
47    regex: &Option<std::sync::Arc<regex::Regex>>,
48    serializer: S,
49) -> Result<S::Ok, S::Error> {
50    match regex {
51        Some(regex) => serializer.serialize_some(regex.as_str()),
52        None => serializer.serialize_none(),
53    }
54}
55
56fn deserialize_regex<'de, D: serde::Deserializer<'de>>(
57    deserializer: D,
58) -> Result<Option<std::sync::Arc<regex::Regex>>, D::Error> {
59    let regex = match Option::<String>::deserialize(deserializer)? {
60        Some(regex) => Some(crate::cache::regex(&regex).map_err(serde::de::Error::custom)?),
61        None => None,
62    };
63
64    Ok(regex)
65}