shex_ast/ast/
xs_facet.rs

1use std::result;
2
3use rust_decimal::prelude::*;
4use serde::ser::SerializeMap;
5use serde::{Deserialize, Serialize, Serializer};
6use srdf::numeric_literal::NumericLiteral;
7use void::Void;
8
9use crate::ast::serde_string_or_struct::*;
10
11#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
12#[serde(untagged)]
13pub enum XsFacet {
14    StringFacet(StringFacet),
15    NumericFacet(NumericFacet),
16}
17
18impl XsFacet {
19    pub fn pattern(pat: &str) -> XsFacet {
20        XsFacet::StringFacet(StringFacet::Pattern(Pattern::new(pat)))
21    }
22
23    pub fn pattern_flags(pat: &str, flags: &str) -> XsFacet {
24        XsFacet::StringFacet(StringFacet::Pattern(Pattern::new_flags(pat, flags)))
25    }
26
27    pub fn length(len: usize) -> XsFacet {
28        XsFacet::StringFacet(StringFacet::Length(len))
29    }
30
31    pub fn min_length(len: usize) -> XsFacet {
32        XsFacet::StringFacet(StringFacet::MinLength(len))
33    }
34
35    pub fn max_length(len: usize) -> XsFacet {
36        XsFacet::StringFacet(StringFacet::MaxLength(len))
37    }
38
39    pub fn min_inclusive(nl: NumericLiteral) -> XsFacet {
40        XsFacet::NumericFacet(NumericFacet::MinInclusive(nl))
41    }
42
43    pub fn max_inclusive(nl: NumericLiteral) -> XsFacet {
44        XsFacet::NumericFacet(NumericFacet::MaxInclusive(nl))
45    }
46
47    pub fn min_exclusive(nl: NumericLiteral) -> XsFacet {
48        XsFacet::NumericFacet(NumericFacet::MinExclusive(nl))
49    }
50
51    pub fn max_exclusive(nl: NumericLiteral) -> XsFacet {
52        XsFacet::NumericFacet(NumericFacet::MaxExclusive(nl))
53    }
54
55    pub fn totaldigits(n: usize) -> XsFacet {
56        XsFacet::NumericFacet(NumericFacet::TotalDigits(n))
57    }
58
59    pub fn fractiondigits(n: usize) -> XsFacet {
60        XsFacet::NumericFacet(NumericFacet::FractionDigits(n))
61    }
62}
63
64#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
65#[serde(untagged)]
66pub enum StringFacet {
67    Length(usize),
68    MinLength(usize),
69    MaxLength(usize),
70
71    #[serde(
72        serialize_with = "serialize_pattern",
73        deserialize_with = "deserialize_string_or_struct"
74    )]
75    Pattern(Pattern),
76}
77
78fn serialize_pattern<S>(p: &Pattern, serializer: S) -> result::Result<S::Ok, S::Error>
79where
80    S: Serializer,
81{
82    match p {
83        Pattern { str, flags: None } => {
84            let mut map = serializer.serialize_map(Some(1))?;
85            map.serialize_entry("pattern", str)?;
86            map.end()
87        }
88        // str.serialize(serializer),
89        Pattern {
90            str,
91            flags: Some(fs),
92        } => {
93            let mut map = serializer.serialize_map(Some(2))?;
94            map.serialize_entry("pattern", str)?;
95            map.serialize_entry("flags", fs)?;
96            map.end()
97        }
98    }
99}
100
101#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
102pub struct Pattern {
103    pub str: String,
104    pub flags: Option<String>,
105}
106
107impl Pattern {
108    pub fn new(str: &str) -> Pattern {
109        Pattern {
110            str: str.to_string(),
111            flags: None,
112        }
113    }
114
115    pub fn new_flags(str: &str, flags: &str) -> Pattern {
116        Pattern {
117            str: str.to_string(),
118            flags: Some(flags.to_string()),
119        }
120    }
121}
122
123impl FromStr for Pattern {
124    type Err = Void;
125
126    fn from_str(s: &str) -> Result<Self, Self::Err> {
127        Ok(Pattern {
128            str: s.to_string(),
129            flags: None,
130        })
131    }
132}
133
134#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
135pub enum NumericFacet {
136    MinInclusive(NumericLiteral),
137    MinExclusive(NumericLiteral),
138    MaxInclusive(NumericLiteral),
139    MaxExclusive(NumericLiteral),
140    TotalDigits(usize),
141    FractionDigits(usize),
142}
143
144#[cfg(test)]
145mod tests {
146    use super::*;
147
148    #[test]
149    fn test_serde_xsfacet_pattern() {
150        let pattern = StringFacet::Pattern(Pattern {
151            str: "o*".to_string(),
152            flags: None,
153        });
154
155        let json_pattern = serde_json::to_string(&pattern).unwrap();
156        assert_eq!(json_pattern, "{\"pattern\":\"o*\"}");
157    }
158
159    #[test]
160    fn test_serde_xsfacet_pattern_flags() {
161        let pattern = StringFacet::Pattern(Pattern {
162            str: "o*".to_string(),
163            flags: Some("i".to_string()),
164        });
165
166        let json_pattern = serde_json::to_string(&pattern).unwrap();
167        assert_eq!(json_pattern, "{\"pattern\":\"o*\",\"flags\":\"i\"}");
168    }
169}