1use crate::context::{State, Update};
5use crate::value::Value;
6use indexmap::IndexMap;
7use regex::Regex;
8use std::fmt;
9use std::sync::Arc;
10
11#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
14pub enum Kind {
15 #[default]
16 Any,
17 String,
18 Number,
19 Boolean,
20 Object,
21 Array,
22 Null,
23 NaN,
24 Function,
25 Never,
26 Check,
27 Regexp,
28 Integer,
29 Date,
30 BigInt,
31 List,
32}
33
34impl Kind {
35 pub fn as_str(self) -> &'static str {
36 match self {
37 Kind::Any => "any",
38 Kind::String => "string",
39 Kind::Number => "number",
40 Kind::Boolean => "boolean",
41 Kind::Object => "object",
42 Kind::Array => "array",
43 Kind::Null => "null",
44 Kind::NaN => "nan",
45 Kind::Function => "function",
46 Kind::Never => "never",
47 Kind::Check => "check",
48 Kind::Regexp => "regexp",
49 Kind::Integer => "integer",
50 Kind::Date => "date",
51 Kind::BigInt => "bigint",
52 Kind::List => "list",
53 }
54 }
55}
56
57impl Kind {
58 pub fn from_name(name: &str) -> Option<Kind> {
61 ALL_KINDS
62 .iter()
63 .copied()
64 .find(|k| k.as_str() == name || k.as_str().eq_ignore_ascii_case(name))
65 }
66}
67
68const ALL_KINDS: [Kind; 16] = [
69 Kind::Any,
70 Kind::String,
71 Kind::Number,
72 Kind::Boolean,
73 Kind::Object,
74 Kind::Array,
75 Kind::Null,
76 Kind::NaN,
77 Kind::Function,
78 Kind::Never,
79 Kind::Check,
80 Kind::Regexp,
81 Kind::Integer,
82 Kind::Date,
83 Kind::BigInt,
84 Kind::List,
85];
86
87impl fmt::Display for Kind {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 f.write_str(self.as_str())
90 }
91}
92
93#[derive(Clone, Copy, Debug, PartialEq, Eq)]
96pub enum Token {
97 Any,
98 String,
99 Number,
100 Boolean,
101 Object,
102 Array,
103 Function,
104 Integer,
105 Date,
106 BigInt,
107}
108
109impl Token {
110 pub fn kind(self) -> Kind {
111 match self {
112 Token::Any => Kind::Any,
113 Token::String => Kind::String,
114 Token::Number => Kind::Number,
115 Token::Boolean => Kind::Boolean,
116 Token::Object => Kind::Object,
117 Token::Array => Kind::Array,
118 Token::Function => Kind::Function,
119 Token::Integer => Kind::Integer,
120 Token::Date => Kind::Date,
121 Token::BigInt => Kind::BigInt,
122 }
123 }
124}
125
126#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
128pub enum ListMode {
129 #[default]
130 None,
131 One,
132 Some,
133 All,
134}
135
136pub type ValidatorFn = dyn Fn(&mut State<'_>, &mut Update) -> bool + Send + Sync;
139
140#[derive(Clone)]
142pub struct Validator {
143 pub name: String,
144 pub func: Arc<ValidatorFn>,
145 pub args: Vec<Value>,
146 pub suffix: Option<String>,
148 pub inner: Option<Arc<crate::isolate::Inner>>,
150}
151
152impl fmt::Debug for Validator {
153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154 write!(f, "Validator({})", self.name)
155 }
156}
157
158#[derive(Clone, Debug, Default)]
160pub struct Node {
161 pub kind: Kind,
162 pub required: bool,
163 pub required_set: bool,
164 pub kind_set: bool,
168 pub skippable: bool,
170 pub silent: bool,
172 pub empty: bool,
174 pub nullable: bool,
176 pub has_default: bool,
177 pub default: Value,
179 pub literal: Option<Value>,
181
182 pub obj_children: IndexMap<String, Node>,
184 pub obj_rest: Option<Box<Node>>,
186 pub consumed: std::collections::HashSet<String>,
190 pub obj_keys: Vec<Arc<str>>,
193 pub plain: bool,
197
198 pub arr_children: Vec<Node>,
200 pub arr_child: Option<Box<Node>>,
202 pub arr_rest: Option<Box<Node>>,
204
205 pub befores: Vec<Validator>,
206 pub afters: Vec<Validator>,
207
208 pub regexp: Option<Regex>,
210 pub regexp_src: String,
212 pub fault_msg: Option<String>,
214 pub arg_fault: bool,
217
218 pub list_mode: ListMode,
219 pub list: Vec<Node>,
220 pub disc: Option<crate::discriminated::Disc>,
223
224 pub exact_vals: Vec<Value>,
225 pub has_exact: bool,
226
227 pub define_name: Option<String>,
228 pub refer_name: Option<String>,
229 pub refer_fill: bool,
230 pub refer_strict: bool,
231
232 pub rename_to: Option<String>,
233 pub rename_keep: bool,
234 pub rename_claim: Vec<String>,
235
236 pub meta: IndexMap<String, Value>,
238}
239
240impl Node {
241 pub fn of(kind: Kind) -> Node {
242 Node {
243 kind,
244 ..Default::default()
245 }
246 }
247
248 pub fn is_open(&self) -> bool {
250 self.obj_rest.is_some()
251 }
252
253 pub fn is_ignore(&self) -> bool {
255 self.silent && self.skippable
256 }
257
258 pub fn zero_for(kind: Kind) -> Value {
260 match kind {
261 Kind::String => Value::Str(String::new()),
262 Kind::Number | Kind::Integer => Value::Num(0.0),
263 Kind::Boolean => Value::Bool(false),
264 Kind::Object => Value::Obj(Default::default()),
265 Kind::Array => Value::Arr(Vec::new()),
266 _ => Value::Undefined,
267 }
268 }
269}
270
271#[cfg(test)]
272mod tests {
273 use super::*;
274
275 #[test]
276 fn kinds_and_tokens_name_themselves() {
277 let all = [
278 Kind::Any,
279 Kind::String,
280 Kind::Number,
281 Kind::Boolean,
282 Kind::Object,
283 Kind::Array,
284 Kind::Null,
285 Kind::NaN,
286 Kind::Function,
287 Kind::Never,
288 Kind::Check,
289 Kind::Regexp,
290 Kind::Integer,
291 Kind::Date,
292 Kind::BigInt,
293 Kind::List,
294 ];
295 let names: Vec<String> = all.iter().map(|k| k.to_string()).collect();
296 assert_eq!(names.join(","), "any,string,number,boolean,object,array,null,nan,function,never,check,regexp,integer,date,bigint,list");
297 let tokens = [
298 Token::Any,
299 Token::String,
300 Token::Number,
301 Token::Boolean,
302 Token::Object,
303 Token::Array,
304 Token::Function,
305 Token::Integer,
306 Token::Date,
307 Token::BigInt,
308 ];
309 let kinds: Vec<&str> = tokens.iter().map(|t| t.kind().as_str()).collect();
310 assert_eq!(
311 kinds.join(","),
312 "any,string,number,boolean,object,array,function,integer,date,bigint"
313 );
314 assert_eq!(Node::default().kind, Kind::Any);
315 assert_eq!(Node::default().list_mode, ListMode::None);
316 assert!(!Node::of(Kind::Object).is_open());
317 let v = Validator {
318 name: "x".into(),
319 func: Arc::new(|_, _| true),
320 args: vec![],
321 suffix: None,
322 inner: None,
323 };
324 assert_eq!(format!("{:?}", v), "Validator(x)");
325 assert_eq!(Node::zero_for(Kind::String), Value::Str(String::new()));
326 assert_eq!(Node::zero_for(Kind::Integer), Value::Num(0.0));
327 assert_eq!(Node::zero_for(Kind::Boolean), Value::Bool(false));
328 assert_eq!(Node::zero_for(Kind::Object), Value::Obj(Default::default()));
329 assert_eq!(Node::zero_for(Kind::Array), Value::Arr(vec![]));
330 assert_eq!(Node::zero_for(Kind::Date), Value::Undefined);
331 }
332}