oca_bundle/state/
standard.rs1use 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}