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 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}