oca_bundle_semantics/state/
standard.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use lazy_static::lazy_static;
use regex::Regex;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::HashMap;
use std::str::FromStr;

#[derive(Clone, Debug)]
pub struct Standard {
    value: String,
}

impl Standard {
    pub fn new(value: String) -> Self {
        Self {
            value: value.to_lowercase(),
        }
    }

    fn regexes(nid: &str) -> Option<Regex> {
        lazy_static! {
            static ref REGEXES: HashMap<String, String> = {
                let standards_str = include_str!("../../config/standards.yml");
                serde_yaml::from_str(standards_str).unwrap()
            };
        }
        match REGEXES.get(nid) {
            Some(re_str) => regex::Regex::new(re_str).ok(),
            None => None,
        }
    }

    pub fn validate(&self) -> Result<&Self, String> {
        let urn = urn::Urn::from_str(self.value.as_ref()).map_err(|e| e.to_string())?;
        match Self::regexes(urn.nid()) {
            Some(regex) => {
                if regex.is_match(urn.nss()) {
                    Ok(self)
                } else {
                    Err(format!(
                        "{} nss is invalid for {} namespace",
                        urn.nss(),
                        urn.nid()
                    ))
                }
            }
            None => Err(format!("{} namespace is unsupported", urn.nid())),
        }
    }
}

impl Serialize for Standard {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(self.value.as_str())
    }
}

impl<'de> Deserialize<'de> for Standard {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let de_standard = serde_value::Value::deserialize(deserializer)?;

        if let serde_value::Value::String(value) = de_standard {
            Ok(Standard::new(value)
                .validate()
                .map_err(serde::de::Error::custom)?
                .clone())
        } else {
            Err(serde::de::Error::custom("standard must be a string"))
        }
    }
}