Skip to main content

agm_core/model/
schema.rs

1//! Type schema definitions (spec S14).
2
3use serde::{Deserialize, Serialize};
4use std::fmt;
5use std::str::FromStr;
6
7use super::fields::ParseEnumError;
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10#[serde(rename_all = "snake_case")]
11pub enum EnforcementLevel {
12    Strict,
13    Standard,
14    Permissive,
15}
16
17impl fmt::Display for EnforcementLevel {
18    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
19        match self {
20            Self::Strict => write!(f, "strict"),
21            Self::Standard => write!(f, "standard"),
22            Self::Permissive => write!(f, "permissive"),
23        }
24    }
25}
26
27impl FromStr for EnforcementLevel {
28    type Err = ParseEnumError;
29
30    fn from_str(s: &str) -> Result<Self, Self::Err> {
31        match s {
32            "strict" => Ok(Self::Strict),
33            "standard" => Ok(Self::Standard),
34            "permissive" => Ok(Self::Permissive),
35            _ => Err(ParseEnumError {
36                type_name: "EnforcementLevel",
37                value: s.to_owned(),
38            }),
39        }
40    }
41}
42
43#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
44pub struct TypeSchema {
45    pub required: Vec<String>,
46    pub recommended: Vec<String>,
47    pub allowed: Vec<String>,
48    pub disallowed: Vec<String>,
49}
50
51#[cfg(test)]
52mod tests {
53    use super::*;
54
55    #[test]
56    fn test_enforcement_level_from_str_valid_returns_ok() {
57        assert_eq!(
58            "strict".parse::<EnforcementLevel>().unwrap(),
59            EnforcementLevel::Strict
60        );
61        assert_eq!(
62            "standard".parse::<EnforcementLevel>().unwrap(),
63            EnforcementLevel::Standard
64        );
65        assert_eq!(
66            "permissive".parse::<EnforcementLevel>().unwrap(),
67            EnforcementLevel::Permissive
68        );
69    }
70
71    #[test]
72    fn test_enforcement_level_from_str_invalid_returns_error() {
73        let err = "lenient".parse::<EnforcementLevel>().unwrap_err();
74        assert_eq!(err.type_name, "EnforcementLevel");
75    }
76
77    #[test]
78    fn test_enforcement_level_display_roundtrip() {
79        for e in [
80            EnforcementLevel::Strict,
81            EnforcementLevel::Standard,
82            EnforcementLevel::Permissive,
83        ] {
84            let text = e.to_string();
85            assert_eq!(text.parse::<EnforcementLevel>().unwrap(), e);
86        }
87    }
88
89    #[test]
90    fn test_type_schema_serde_roundtrip() {
91        let schema = TypeSchema {
92            required: vec!["summary".to_owned()],
93            recommended: vec!["items".to_owned(), "stability".to_owned()],
94            allowed: vec!["detail".to_owned(), "tags".to_owned()],
95            disallowed: vec!["steps".to_owned(), "parallel_groups".to_owned()],
96        };
97        let json = serde_json::to_string(&schema).unwrap();
98        let back: TypeSchema = serde_json::from_str(&json).unwrap();
99        assert_eq!(schema, back);
100    }
101}