1use crate::prelude::*;
2
3#[derive(Clone, Debug, Serialize)]
11pub struct Type {
12 #[serde(skip_serializing_if = "<[_]>::is_empty")]
13 normalizers: &'static [TypeNormalizer],
14
15 #[serde(skip_serializing_if = "<[_]>::is_empty")]
16 validators: &'static [TypeValidator],
17
18 #[serde(skip_serializing_if = "<[_]>::is_empty")]
19 rules: &'static [SourceRule],
20}
21
22impl Type {
23 #[must_use]
24 pub const fn new(
25 normalizers: &'static [TypeNormalizer],
26 validators: &'static [TypeValidator],
27 rules: &'static [SourceRule],
28 ) -> Self {
29 Self {
30 normalizers,
31 validators,
32 rules,
33 }
34 }
35
36 #[must_use]
37 pub const fn normalizers(&self) -> &'static [TypeNormalizer] {
38 self.normalizers
39 }
40
41 #[must_use]
42 pub const fn validators(&self) -> &'static [TypeValidator] {
43 self.validators
44 }
45
46 #[must_use]
48 pub const fn rules(&self) -> &'static [SourceRule] {
49 self.rules
50 }
51}
52
53impl ValidateNode for Type {}
54
55impl VisitableNode for Type {
56 fn drive<V: Visitor>(&self, v: &mut V) {
57 for node in self.normalizers() {
58 node.accept(v);
59 }
60 for node in self.validators() {
61 node.accept(v);
62 }
63 for node in self.rules() {
64 node.accept(v);
65 }
66 }
67}
68
69#[derive(Clone, Debug, Serialize)]
78pub struct SourceRule {
79 name: &'static str,
80 kind: SourceRuleKind,
81 args: Args,
82}
83
84impl SourceRule {
85 #[must_use]
87 pub const fn new(name: &'static str, kind: SourceRuleKind, args: Args) -> Self {
88 Self { name, kind, args }
89 }
90
91 #[must_use]
93 pub const fn name(&self) -> &'static str {
94 self.name
95 }
96
97 #[must_use]
99 pub const fn kind(&self) -> SourceRuleKind {
100 self.kind
101 }
102
103 #[must_use]
105 pub const fn args(&self) -> &Args {
106 &self.args
107 }
108}
109
110impl ValidateNode for SourceRule {
111 fn validate(&self) -> Result<(), ErrorTree> {
112 let mut errs = ErrorTree::new();
113 validate_source_name(
114 &mut errs,
115 "rule",
116 self.name(),
117 icydb_schema::RuleSourceKey::try_new,
118 );
119 let expected_args = match self.kind() {
120 SourceRuleKind::NumericMinimum => 1,
121 SourceRuleKind::LengthRange | SourceRuleKind::NumericRange => 2,
122 };
123 if self.args().0.len() != expected_args
124 || self
125 .args()
126 .0
127 .iter()
128 .any(|arg| !matches!(arg, Arg::Number(_)))
129 {
130 err!(
131 errs,
132 "rule '{}' requires {expected_args} numeric argument(s)",
133 self.name(),
134 );
135 }
136 errs.result()
137 }
138}
139
140impl VisitableNode for SourceRule {}
141
142#[derive(Clone, Copy, Debug, Serialize)]
151pub enum SourceRuleKind {
152 LengthRange,
154 NumericMinimum,
156 NumericRange,
158}
159
160#[derive(Clone, Debug, Serialize)]
167pub struct TypeNormalizer {
168 path: &'static str,
169 args: Args,
170}
171
172impl TypeNormalizer {
173 #[must_use]
174 pub const fn new(path: &'static str, args: Args) -> Self {
175 Self { path, args }
176 }
177
178 #[must_use]
179 pub const fn path(&self) -> &'static str {
180 self.path
181 }
182
183 #[must_use]
184 pub const fn args(&self) -> &Args {
185 &self.args
186 }
187}
188
189impl ValidateNode for TypeNormalizer {
190 fn validate(&self) -> Result<(), ErrorTree> {
191 let mut errs = ErrorTree::new();
192
193 let res = schema_read().check_node_as::<Normalizer>(self.path());
195 if let Err(e) = res {
196 errs.add(e.to_string());
197 }
198
199 errs.result()
200 }
201}
202
203impl VisitableNode for TypeNormalizer {}
204
205#[derive(Clone, Debug, Serialize)]
212pub struct TypeValidator {
213 path: &'static str,
214 args: Args,
215}
216
217impl TypeValidator {
218 #[must_use]
219 pub const fn new(path: &'static str, args: Args) -> Self {
220 Self { path, args }
221 }
222
223 #[must_use]
224 pub const fn path(&self) -> &'static str {
225 self.path
226 }
227
228 #[must_use]
229 pub const fn args(&self) -> &Args {
230 &self.args
231 }
232}
233
234impl ValidateNode for TypeValidator {
235 fn validate(&self) -> Result<(), ErrorTree> {
236 let mut errs = ErrorTree::new();
237
238 let res = schema_read().check_node_as::<Validator>(self.path());
240 if let Err(e) = res {
241 errs.add(e.to_string());
242 }
243
244 errs.result()
245 }
246}
247
248impl VisitableNode for TypeValidator {}