oca_bundle/state/
standard.rs

1use lazy_static::lazy_static;
2use regex::Regex;
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4use std::collections::HashMap;
5use std::str::FromStr;
6
7#[derive(Clone, Debug)]
8pub struct Standard {
9    value: String,
10}
11
12impl Standard {
13    pub fn new(value: String) -> Self {
14        Self {
15            value: value.to_lowercase(),
16        }
17    }
18
19    fn regexes(nid: &str) -> Option<Regex> {
20        lazy_static! {
21            static ref REGEXES: HashMap<String, String> = {
22                let standards_str = include_str!("../../config/standards.yml");
23                serde_yaml::from_str(standards_str).unwrap()
24            };
25        }
26        match REGEXES.get(nid) {
27            Some(re_str) => regex::Regex::new(re_str).ok(),
28            None => None,
29        }
30    }
31
32    pub fn validate(&self) -> Result<&Self, String> {
33        let urn = urn::Urn::from_str(self.value.as_ref()).map_err(|e| e.to_string())?;
34        match Self::regexes(urn.nid()) {
35            Some(regex) => {
36                if regex.is_match(urn.nss()) {
37                    Ok(self)
38                } else {
39                    Err(format!(
40                        "{} nss is invalid for {} namespace",
41                        urn.nss(),
42                        urn.nid()
43                    ))
44                }
45            }
46            None => Err(format!("{} namespace is unsupported", urn.nid())),
47        }
48    }
49}
50
51impl Serialize for Standard {
52    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
53    where
54        S: Serializer,
55    {
56        serializer.serialize_str(self.value.as_str())
57    }
58}
59
60impl<'de> Deserialize<'de> for Standard {
61    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
62    where
63        D: Deserializer<'de>,
64    {
65        let de_standard = serde_value::Value::deserialize(deserializer)?;
66
67        if let serde_value::Value::String(value) = de_standard {
68            Ok(Standard::new(value)
69                .validate()
70                .map_err(serde::de::Error::custom)?
71                .clone())
72        } else {
73            Err(serde::de::Error::custom("standard must be a string"))
74        }
75    }
76}