Skip to main content

shape/
builders.rs

1//! The builders: functions that take a spec and return a node with the
2//! builder's rule applied, and the same as methods on a node so they chain.
3//!
4//! A builder given a wrong argument returns a node that accepts nothing and
5//! says why at validation, since a Rust builder cannot throw as the
6//! canonical one does; a chain method on such an argument turns its node
7//! into that fault.
8
9use crate::coerce::coerce_validator;
10use crate::context::{State, Update, UpdateErr};
11use crate::error::{MARK_CHECK_TYPE, WHY_CHECK};
12use crate::format::{
13    with_format, FMT_DATE_TIME, FMT_EMAIL, FMT_IP, FMT_IPV4, FMT_IPV6, FMT_URL, FMT_UUID,
14};
15use crate::isolate::{catch_node, transform_node, TransformFn};
16use crate::node::{Kind, ListMode, Node, Token, Validator};
17use crate::normalize::{normalize, type_token_node};
18use crate::spec::Spec;
19use crate::value::{is_integer, js_date_string, js_number, json_render, json_text, Value};
20use regex::Regex;
21use std::sync::Arc;
22
23/// A spec as a node: what every builder starts from.
24pub fn buildize(spec: impl Into<Spec>) -> Node {
25    normalize(spec.into())
26}
27
28/// An optional `Any`, the node a builder with no spec starts from.
29pub fn any() -> Node {
30    Node::of(Kind::Any)
31}
32
33/// A node that accepts nothing and says why: what a builder returns when
34/// called wrongly.
35pub(crate) fn fault_node(msg: impl Into<String>) -> Node {
36    let mut n = Node::of(Kind::Never);
37    n.fault_msg = Some(msg.into());
38    n.arg_fault = true;
39    n
40}
41
42pub(crate) fn is_fault(n: &Node) -> bool {
43    n.arg_fault
44}
45
46fn validator(
47    name: &str,
48    suffix: Option<String>,
49    args: Vec<Value>,
50    f: impl Fn(&mut State<'_>, &mut Update) -> bool + Send + Sync + 'static,
51) -> Validator {
52    Validator {
53        name: name.to_string(),
54        func: Arc::new(f),
55        args,
56        suffix,
57        inner: None,
58    }
59}
60
61// The free functions: each takes the spec it applies to. Pass `any()` for
62// the bare form.
63
64/// The value must be present.
65pub fn required(spec: impl Into<Spec>) -> Node {
66    buildize(spec).required()
67}
68
69/// The value may be absent; the default is injected.
70pub fn optional(spec: impl Into<Spec>) -> Node {
71    buildize(spec).optional()
72}
73
74/// Optional, with an explicit default. The node is the spec's, so an object
75/// or array shape keeps its children; an untyped spec takes the default's
76/// kind.
77pub fn default(dval: impl Into<Value>, spec: impl Into<Spec>) -> Node {
78    buildize(spec).default_to(dval)
79}
80
81/// A default with no spec: the node takes the default's kind.
82pub fn default_of(dval: impl Into<Value>) -> Node {
83    let dval = dval.into();
84    normalize(Spec::Value(dval.clone())).default_to(dval)
85}
86
87/// Optional, and an absent value leaves the key out.
88pub fn skip(spec: impl Into<Spec>) -> Node {
89    buildize(spec).skip()
90}
91
92/// Like `skip`, and a value that fails is dropped with its errors.
93pub fn ignore(spec: impl Into<Spec>) -> Node {
94    buildize(spec).ignore()
95}
96
97/// The empty string is allowed. Untyped when bare: `empty(any())` allows
98/// the empty string without also demanding a string.
99pub fn empty(spec: impl Into<Spec>) -> Node {
100    buildize(spec).empty()
101}
102
103/// An explicit null is accepted as the value.
104pub fn nullable(spec: impl Into<Spec>) -> Node {
105    buildize(spec).nullable()
106}
107
108/// An object accepts keys it does not declare.
109pub fn open(spec: impl Into<Spec>) -> Node {
110    buildize(spec).open()
111}
112
113/// An object rejects keys it does not declare; a single-shape array becomes
114/// a tuple of one.
115pub fn closed(spec: impl Into<Spec>) -> Node {
116    buildize(spec).closed()
117}
118
119/// The shape of every unknown object value, or of every array element.
120pub fn child(child: impl Into<Spec>, spec: impl Into<Spec>) -> Node {
121    buildize(spec).child(child)
122}
123
124/// The shape of the array elements past the tuple positions.
125pub fn rest(child: impl Into<Spec>, spec: impl Into<Spec>) -> Node {
126    buildize(spec).rest(child)
127}
128
129/// A `Fault` message overriding the structural text.
130pub fn fault(msg: impl Into<String>, spec: impl Into<Spec>) -> Node {
131    buildize(spec).fault(msg)
132}
133
134/// A node that accepts nothing.
135pub fn never(spec: impl Into<Spec>) -> Node {
136    buildize(spec).never()
137}
138
139/// The kind the node asserts, given a kind, a token, a kind name or a node
140/// to take it from.
141pub fn type_(kind: impl Into<TypeRef>, spec: impl Into<Spec>) -> Node {
142    buildize(spec).type_(kind)
143}
144
145/// A function-typed value. A builder, not a type token, so it does not
146/// require a value of itself.
147pub fn func(spec: impl Into<Spec>) -> Node {
148    buildize(spec).func()
149}
150
151/// The value must equal one of the literals.
152pub fn exact<I>(vals: I) -> Node
153where
154    I: IntoIterator,
155    I::Item: Into<Value>,
156{
157    any().exact(vals)
158}
159
160/// A minimum value, or length.
161pub fn min(bound: impl Into<Value>, spec: impl Into<Spec>) -> Node {
162    buildize(spec).min(bound)
163}
164
165/// A maximum value, or length.
166pub fn max(bound: impl Into<Value>, spec: impl Into<Spec>) -> Node {
167    buildize(spec).max(bound)
168}
169
170/// A strict lower bound on value, or length.
171pub fn above(bound: impl Into<Value>, spec: impl Into<Spec>) -> Node {
172    buildize(spec).above(bound)
173}
174
175/// A strict upper bound on value, or length.
176pub fn below(bound: impl Into<Value>, spec: impl Into<Spec>) -> Node {
177    buildize(spec).below(bound)
178}
179
180/// An exact value, or length.
181pub fn len(length: impl Into<Value>, spec: impl Into<Spec>) -> Node {
182    buildize(spec).len(length)
183}
184
185/// A custom check, run before the structural check.
186pub fn check<F>(f: F, spec: impl Into<Spec>) -> Node
187where
188    F: Fn(&mut State<'_>, &mut Update) -> bool + Send + Sync + 'static,
189{
190    let mut n = buildize(spec);
191    if n.kind == Kind::Any {
192        n.kind = Kind::Check;
193    }
194    n.required = true;
195    n.required_set = true;
196    n.check(f)
197}
198
199/// A regexp check: the value must be a string matching it. A failure reads
200/// `check "/re/" failed`.
201pub fn check_re(re: Regex, spec: impl Into<Spec>) -> Node {
202    check_re_src(re.as_str(), spec)
203}
204
205/// `check_re` from a pattern text.
206pub(crate) fn check_re_src(src: &str, spec: impl Into<Spec>) -> Node {
207    let mut n = buildize(spec);
208    if n.kind == Kind::Any {
209        n.kind = Kind::Check;
210    }
211    n.required = true;
212    n.required_set = true;
213    n.check_re_src(src)
214}
215
216/// A custom validator run before the structural check.
217pub fn before<F>(f: F, spec: impl Into<Spec>) -> Node
218where
219    F: Fn(&mut State<'_>, &mut Update) -> bool + Send + Sync + 'static,
220{
221    buildize(spec).before(f)
222}
223
224/// A custom validator run after the structural check.
225pub fn after<F>(f: F, spec: impl Into<Spec>) -> Node
226where
227    F: Fn(&mut State<'_>, &mut Update) -> bool + Send + Sync + 'static,
228{
229    buildize(spec).after(f)
230}
231
232/// The value must satisfy exactly one of the shapes.
233pub fn one<I>(shapes: I) -> Node
234where
235    I: IntoIterator,
236    I::Item: Into<Spec>,
237{
238    list_node(ListMode::One, shapes)
239}
240
241/// The value must satisfy at least one of the shapes.
242pub fn some<I>(shapes: I) -> Node
243where
244    I: IntoIterator,
245    I::Item: Into<Spec>,
246{
247    list_node(ListMode::Some, shapes)
248}
249
250/// The value must satisfy every shape.
251pub fn all<I>(shapes: I) -> Node
252where
253    I: IntoIterator,
254    I::Item: Into<Spec>,
255{
256    list_node(ListMode::All, shapes)
257}
258
259fn list_node<I>(mode: ListMode, shapes: I) -> Node
260where
261    I: IntoIterator,
262    I::Item: Into<Spec>,
263{
264    let mut n = Node::of(Kind::List);
265    n.required = true;
266    n.required_set = true;
267    n.list_mode = mode;
268    n.list = shapes.into_iter().map(|s| normalize(s.into())).collect();
269    n
270}
271
272/// Name the node so a later `refer` can substitute it.
273pub fn define(name: impl Into<String>, spec: impl Into<Spec>) -> Node {
274    buildize(spec).define(name)
275}
276
277/// Substitute the named node at validation time.
278pub fn refer(name: impl Into<String>, spec: impl Into<Spec>) -> Node {
279    buildize(spec).refer_with(name, ReferOptions::default())
280}
281
282/// `refer` with options.
283pub fn refer_with(name: impl Into<String>, opts: ReferOptions, spec: impl Into<Spec>) -> Node {
284    buildize(spec).refer_with(name, opts)
285}
286
287/// Rename the property after validation. For object children only.
288pub fn rename(name: impl Into<String>, spec: impl Into<Spec>) -> Node {
289    buildize(spec).rename_with(name, RenameOptions::default())
290}
291
292/// `rename` with options.
293pub fn rename_with(name: impl Into<String>, opts: RenameOptions, spec: impl Into<Spec>) -> Node {
294    buildize(spec).rename_with(name, opts)
295}
296
297/// The value is replaced with the key of the property it sits under.
298pub fn key() -> Node {
299    key_args(&[])
300}
301
302/// The value is replaced with the path `depth` levels up, as an array.
303pub fn key_depth(depth: i64) -> Node {
304    key_args(&[Value::from(depth)])
305}
306
307/// The value is replaced with the path `depth` levels up, joined by `sep`.
308pub fn key_join(depth: i64, sep: impl Into<String>) -> Node {
309    key_args(&[Value::from(depth), Value::Str(sep.into())])
310}
311
312/// `key` from raw arguments: a numeric argument is the depth, a string the
313/// separator, as the string form of a spec supplies them.
314pub fn key_args(args: &[Value]) -> Node {
315    let mut depth: Option<i64> = None;
316    let mut sep: Option<String> = None;
317    for a in args {
318        match a {
319            Value::Str(s) => sep = Some(s.clone()),
320            Value::Num(f) if f.is_finite() => depth = Some(f.trunc() as i64),
321            _ => {}
322        }
323    }
324    // A depth without a separator yields a path slice, so the node must be
325    // an array to accept it.
326    let mut n = Node::of(if depth.is_some() && sep.is_none() {
327        Kind::Array
328    } else {
329        Kind::String
330    });
331    n.befores.push(validator(
332        "Key",
333        Some("Key()".to_string()),
334        args.to_vec(),
335        move |state, update| {
336            // The canonical path is [root, k1, ..., kn]; the leading root
337            // slot is kept so the index and slice arithmetic match.
338            let path = state.path_keys();
339            let mut ts_path: Vec<Value> = Vec::with_capacity(path.len() + 1);
340            ts_path.push(Value::Undefined);
341            ts_path.extend(path.iter().cloned().map(Value::Str));
342            let l = ts_path.len() as i64;
343            match (depth, &sep) {
344                (None, None) => {
345                    // The parent key. With no parent (the root, or a top-level
346                    // property) the slot is the root, and the value is left.
347                    if path.len() >= 2 {
348                        update.val = Some(Value::Str(path[path.len() - 2].clone()));
349                    }
350                }
351                (Some(d), sep) => {
352                    let lo = if d >= 0 { l - 1 - d } else { l - 1 };
353                    let hi = if d < 0 { l } else { l - 1 };
354                    let sl = js_slice(&ts_path, lo, hi);
355                    update.val = Some(match sep {
356                        Some(sep) => {
357                            let parts: Vec<String> = sl
358                                .iter()
359                                .map(|e| match e {
360                                    Value::Str(s) => s.clone(),
361                                    _ => String::new(),
362                                })
363                                .collect();
364                            Value::Str(parts.join(sep))
365                        }
366                        None => Value::Arr(sl),
367                    });
368                }
369                (None, Some(_)) => {}
370            }
371            true
372        },
373    ));
374    n
375}
376
377/// `Array.prototype.slice` index semantics: a negative bound counts from
378/// the end, out-of-range bounds clamp, and an empty range is empty.
379fn js_slice(arr: &[Value], start: i64, end: i64) -> Vec<Value> {
380    let n = arr.len() as i64;
381    let clamp = |i: i64| if i < 0 { (n + i).max(0) } else { i.min(n) };
382    let (s, e) = (clamp(start), clamp(end));
383    if s >= e {
384        return Vec::new();
385    }
386    arr[s as usize..e as usize].to_vec()
387}
388
389/// Whatever fails inside is replaced with the fallback, raising nothing.
390pub fn catch(fallback: impl Into<Value>, spec: impl Into<Spec>) -> Node {
391    buildize(spec).catch(fallback)
392}
393
394/// A valid value is replaced with a function of it.
395pub fn transform<F>(f: F, spec: impl Into<Spec>) -> Node
396where
397    F: Fn(Value, &mut State<'_>) -> Value + Send + Sync + 'static,
398{
399    buildize(spec).transform(f)
400}
401
402/// A description, read back from the node's meta.
403pub fn describe(description: impl Into<String>, spec: impl Into<Spec>) -> Node {
404    buildize(spec).describe(description)
405}
406
407/// The value is converted to the node's kind where the conversion is
408/// unambiguous, before the type check.
409pub fn coerce(spec: impl Into<Spec>) -> Node {
410    buildize(spec).coerce()
411}
412
413/// A string in email address form.
414pub fn email(spec: impl Into<Spec>) -> Node {
415    buildize(spec).email()
416}
417
418/// An absolute URL.
419pub fn url(spec: impl Into<Spec>) -> Node {
420    buildize(spec).url()
421}
422
423/// A UUID in 8-4-4-4-12 hex form.
424pub fn uuid(spec: impl Into<Spec>) -> Node {
425    buildize(spec).uuid()
426}
427
428/// A strict ISO 8601 date-time string.
429pub fn date_time(spec: impl Into<Spec>) -> Node {
430    buildize(spec).date_time()
431}
432
433/// An IPv4 or IPv6 address.
434pub fn ip(spec: impl Into<Spec>) -> Node {
435    buildize(spec).ip()
436}
437
438/// A dotted-quad IPv4 address.
439pub fn ipv4(spec: impl Into<Spec>) -> Node {
440    buildize(spec).ipv4()
441}
442
443/// An IPv6 address in RFC 4291 text form.
444pub fn ipv6(spec: impl Into<Spec>) -> Node {
445    buildize(spec).ipv6()
446}
447
448/// What `type_` takes its kind from.
449pub enum TypeRef {
450    Kind(Kind),
451    Node(Box<Node>),
452}
453
454impl From<Kind> for TypeRef {
455    fn from(k: Kind) -> Self {
456        TypeRef::Kind(k)
457    }
458}
459impl From<Token> for TypeRef {
460    fn from(t: Token) -> Self {
461        TypeRef::Kind(t.kind())
462    }
463}
464impl From<&str> for TypeRef {
465    fn from(name: &str) -> Self {
466        TypeRef::Kind(Kind::from_name(name).unwrap_or(Kind::Any))
467    }
468}
469impl From<Node> for TypeRef {
470    fn from(n: Node) -> Self {
471        TypeRef::Node(Box::new(n))
472    }
473}
474
475/// `refer` options.
476#[derive(Clone, Debug, Default)]
477pub struct ReferOptions {
478    /// Substitute even when the value is absent (not for self-recursion).
479    pub fill: bool,
480    /// A name with no `define` is an error, rather than a `refer` that does
481    /// nothing.
482    pub strict: bool,
483}
484
485/// `rename` options.
486#[derive(Clone, Debug, Default)]
487pub struct RenameOptions {
488    /// Keep the original key as well as writing under the new name.
489    pub keep: bool,
490    /// Alternative source keys to read from when the renamed key is missing.
491    pub claim: Vec<String>,
492}
493
494/// Whether a bound is a finite number: a number, a date, or a string that
495/// reads as a number, as the canonical `+size` reads it.
496pub(crate) fn bound_arg(v: &Value) -> Option<f64> {
497    match v {
498        Value::Num(f) if f.is_finite() => Some(*f),
499        Value::Date(ms) => Some(*ms as f64),
500        Value::Str(s) => s.trim().parse::<f64>().ok().filter(|f| f.is_finite()),
501        _ => None,
502    }
503}
504
505/// A bound argument rendered as JavaScript renders it.
506pub(crate) fn num_text(v: &Value) -> String {
507    match v {
508        Value::Num(f) => js_number(*f),
509        Value::Str(s) => s.clone(),
510        Value::Date(ms) => js_date_string(*ms),
511        other => json_render(other),
512    }
513}
514
515/// Whether a bound compares the value itself (a number, or a date by its
516/// time value) rather than a length or key count.
517pub(crate) fn is_numeric(v: &Value) -> bool {
518    matches!(v, Value::Num(_) | Value::Date(_))
519}
520
521/// The size a bound measures: a number itself, a date's time value, the
522/// length of a string (in UTF-16 units, as JavaScript counts) or array, the
523/// key count of an object. None when the value has no size.
524pub(crate) fn value_len(v: &Value) -> Option<f64> {
525    match v {
526        Value::Date(ms) => Some(*ms as f64),
527        Value::Num(f) => Some(*f),
528        // An ASCII string is one UTF-16 unit per byte.
529        Value::Str(s) => Some(if s.is_ascii() {
530            s.len()
531        } else {
532            s.encode_utf16().count()
533        } as f64),
534        Value::Arr(a) => Some(a.len() as f64),
535        Value::Obj(m) => Some(m.len() as f64),
536        _ => None,
537    }
538}
539
540/// A measured size, or NaN when the value has none: a boolean or null has
541/// no length, and the message says "(was NaN)" rather than nothing.
542fn size_text(size: Option<f64>) -> String {
543    size.map(js_number).unwrap_or_else(|| "NaN".to_string())
544}
545
546/// Whether the node declares a concrete type that this value does not have.
547pub(crate) fn type_will_fail(n: &Node, v: &Value) -> bool {
548    match n.kind {
549        Kind::String | Kind::Regexp => !matches!(v, Value::Str(_)),
550        Kind::Number => !matches!(v, Value::Num(f) if !f.is_nan()),
551        Kind::Boolean => !matches!(v, Value::Bool(_)),
552        Kind::Object => !matches!(v, Value::Obj(_)),
553        Kind::Array => !matches!(v, Value::Arr(_)),
554        Kind::Function => !matches!(v, Value::Func(_)),
555        Kind::Null => !v.is_null(),
556        Kind::NaN => !matches!(v, Value::Num(f) if f.is_nan()),
557        Kind::Integer => !matches!(v, Value::Num(f) if is_integer(*f)),
558        Kind::Date => !matches!(v, Value::Date(_)),
559        Kind::BigInt => !matches!(v, Value::BigInt(_)),
560        _ => false,
561    }
562}
563
564/// Whether a size bound should stand aside and let the rest of validation
565/// speak: the value is of the wrong type, so the structural check is about
566/// to report that and a bound message would mask it; or the value is absent
567/// on a node that does not require it, which is dropped.
568pub(crate) fn bound_defers(state: &State<'_>) -> bool {
569    let n = state.node;
570    (state.absent && (n.skippable || !n.required)) || type_will_fail(n, state.value)
571}
572
573#[derive(Clone, Copy)]
574enum Bound {
575    Min,
576    Max,
577    Above,
578    Below,
579}
580
581impl Bound {
582    fn name(self) -> &'static str {
583        match self {
584            Bound::Min => "Min",
585            Bound::Max => "Max",
586            Bound::Above => "Above",
587            Bound::Below => "Below",
588        }
589    }
590
591    fn mark(self) -> i64 {
592        match self {
593            Bound::Min => 4011,
594            Bound::Max => 4012,
595            Bound::Above => 4013,
596            Bound::Below => 4014,
597        }
598    }
599
600    fn holds(self, limit: f64, size: f64) -> bool {
601        match self {
602            Bound::Min => limit <= size,
603            Bound::Max => size <= limit,
604            Bound::Above => limit < size,
605            Bound::Below => size < limit,
606        }
607    }
608
609    fn text(self, numeric: bool, bound: &str, size: &str) -> String {
610        match self {
611            Bound::Min | Bound::Max => {
612                let lenpart = if numeric { "" } else { "length " };
613                let word = if matches!(self, Bound::Min) {
614                    "minimum"
615                } else {
616                    "maximum"
617                };
618                format!(
619                    "Value \"$VALUE\" for property \"$PATH\" must be a {} {}of {} (was {}).",
620                    word, lenpart, bound, size
621                )
622            }
623            Bound::Above | Bound::Below => {
624                let verb = if numeric { "be" } else { "have length" };
625                let word = if matches!(self, Bound::Above) {
626                    "above"
627                } else {
628                    "below"
629                };
630                format!(
631                    "Value \"$VALUE\" for property \"$PATH\" must {} {} {} (was {}).",
632                    verb, word, bound, size
633                )
634            }
635        }
636    }
637}
638
639fn bound_node(kind: Bound, bound: Value) -> Node {
640    let Some(limit) = bound_arg(&bound) else {
641        return fault_node(format!("Shape: {} needs a number", kind.name()));
642    };
643    let text = num_text(&bound);
644    let mut n = any();
645    n.befores.push(validator(
646        kind.name(),
647        Some(format!("{}({})", kind.name(), text)),
648        vec![bound],
649        move |state, update| {
650            if bound_defers(state) {
651                return true;
652            }
653            let size = value_len(state.value);
654            if let Some(s) = size {
655                if kind.holds(limit, s) {
656                    return true;
657                }
658            }
659            update.done = true;
660            update.mark = kind.mark();
661            // A verdict-only call counts the failure and reads no message.
662            if !state.ctx.terse {
663                update.why = Some(kind.name().to_string());
664                update.err = Some(UpdateErr::Text(kind.text(
665                    is_numeric(state.value),
666                    &text,
667                    &size_text(size),
668                )));
669            }
670            false
671        },
672    ));
673    n
674}
675
676fn len_node(length: Value) -> Node {
677    let whole = match &length {
678        Value::Num(f) if f.is_finite() && *f >= 0.0 && f.fract() == 0.0 => Some(*f),
679        _ => None,
680    };
681    let Some(limit) = whole else {
682        return fault_node("Shape: Len needs a whole number of zero or more");
683    };
684    let text = js_number(limit);
685    let mut n = any();
686    n.befores.push(validator(
687        "Len",
688        Some(format!("Len({})", text)),
689        vec![length],
690        move |state, update| {
691            if bound_defers(state) {
692                return true;
693            }
694            let size = value_len(state.value);
695            if size == Some(limit) {
696                return true;
697            }
698            update.done = true;
699            update.mark = 4015;
700            // A verdict-only call counts the failure and reads no message.
701            if !state.ctx.terse {
702                let suffix = if is_numeric(state.value) {
703                    ""
704                } else {
705                    " in length"
706                };
707                update.why = Some("Len".to_string());
708                update.err = Some(UpdateErr::Text(format!(
709                    "Value \"$VALUE\" for property \"$PATH\" must be exactly {}{} (was {}).",
710                    text,
711                    suffix,
712                    size_text(size)
713                )));
714            }
715            false
716        },
717    ));
718    n
719}
720
721/// The literals of an Exact, dequoted: `admin, user`; `1, a, true, null`.
722pub(crate) fn format_list(vals: &[Value]) -> String {
723    vals.iter()
724        .map(|v| match v {
725            Value::Null => "null".to_string(),
726            Value::Str(s) => s.clone(),
727            Value::Num(f) => js_number(*f),
728            Value::Undefined => "undefined".to_string(),
729            other => json_render(other),
730        })
731        .collect::<Vec<_>>()
732        .join(", ")
733}
734
735impl Node {
736    /// Fold another builder's result in: its validators, or the fault it
737    /// became when its argument was wrong.
738    fn adopt(mut self, other: Node) -> Node {
739        if is_fault(&other) {
740            self.kind = Kind::Never;
741            self.fault_msg = other.fault_msg;
742            self.arg_fault = true;
743            return self;
744        }
745        self.befores.extend(other.befores);
746        self
747    }
748
749    pub fn required(mut self) -> Node {
750        self.required = true;
751        self.required_set = true;
752        self.skippable = false;
753        self
754    }
755
756    pub fn optional(mut self) -> Node {
757        self.required = false;
758        self.required_set = true;
759        self
760    }
761
762    /// Optional with the default; named to leave `Default::default` alone.
763    /// An untyped node is built over the default instead, and so takes the
764    /// default's kind, keeping the checks and flags it carried.
765    pub fn default_to(mut self, dval: impl Into<Value>) -> Node {
766        let dval = dval.into();
767        if self.kind == Kind::Any && !dval.is_undefined() {
768            let mut base = normalize(Spec::Value(dval.clone()));
769            let mut befores = std::mem::take(&mut self.befores);
770            befores.append(&mut base.befores);
771            base.befores = befores;
772            let mut afters = std::mem::take(&mut self.afters);
773            afters.append(&mut base.afters);
774            base.afters = afters;
775            base.has_exact = self.has_exact;
776            base.exact_vals = std::mem::take(&mut self.exact_vals);
777            base.empty = self.empty;
778            base.nullable = self.nullable;
779            base.silent = self.silent;
780            base.fault_msg = self.fault_msg.take();
781            base.arg_fault = self.arg_fault;
782            base.meta.extend(std::mem::take(&mut self.meta));
783            self = base;
784        }
785        self.required = false;
786        self.required_set = true;
787        self.skippable = false;
788        self.has_default = true;
789        self.default = dval;
790        self
791    }
792
793    pub fn skip(mut self) -> Node {
794        self.required = false;
795        self.required_set = true;
796        self.skippable = true;
797        self
798    }
799
800    pub fn ignore(mut self) -> Node {
801        self.required = false;
802        self.required_set = true;
803        self.skippable = true;
804        self.silent = true;
805        self
806    }
807
808    pub fn empty(mut self) -> Node {
809        self.empty = true;
810        self
811    }
812
813    pub fn nullable(mut self) -> Node {
814        self.nullable = true;
815        self
816    }
817
818    pub fn open(mut self) -> Node {
819        if self.kind == Kind::Object && self.obj_rest.is_none() {
820            self.obj_rest = Some(Box::new(Node::of(Kind::Any)));
821        }
822        self
823    }
824
825    pub fn closed(mut self) -> Node {
826        self.obj_rest = None;
827        if self.kind == Kind::Array && self.arr_children.is_empty() {
828            if let Some(c) = self.arr_child.take() {
829                // A single-shape array made fixed: a tuple of one.
830                self.arr_children = vec![*c];
831            }
832        }
833        self
834    }
835
836    pub fn child(mut self, child: impl Into<Spec>) -> Node {
837        let cn = Box::new(buildize(child));
838        match self.kind {
839            Kind::Array => self.arr_child = Some(cn),
840            Kind::Object => self.obj_rest = Some(cn),
841            _ => {
842                self.kind = Kind::Object;
843                self.obj_rest = Some(cn);
844            }
845        }
846        self
847    }
848
849    pub fn rest(mut self, child: impl Into<Spec>) -> Node {
850        self.kind = Kind::Array;
851        // The rest replaces a plain element shape, as it does in TypeScript,
852        // where Rest sets the one child an array has: Rest(Number, [String])
853        // is an array of numbers. Fixed positions are a tuple, and are kept.
854        self.arr_child = None;
855        self.arr_rest = Some(Box::new(buildize(child)));
856        self
857    }
858
859    pub fn fault(mut self, msg: impl Into<String>) -> Node {
860        self.fault_msg = Some(msg.into());
861        self
862    }
863
864    pub fn never(mut self) -> Node {
865        self.kind = Kind::Never;
866        self
867    }
868
869    /// The value may be anything.
870    pub fn any(mut self) -> Node {
871        self.kind = Kind::Any;
872        self
873    }
874
875    /// Adopt the reference type's kind and its required, skippable and
876    /// default state. Structural children are deliberately not copied:
877    /// `type_(Object)` is a closed object and `type_(Array)` accepts any
878    /// elements.
879    pub fn type_(mut self, kind: impl Into<TypeRef>) -> Node {
880        let tn = match kind.into() {
881            TypeRef::Kind(k) => type_token_node(k),
882            TypeRef::Node(n) => *n,
883        };
884        // Any keeps the value it is given as its default, as `Any(0)` does
885        // in TypeScript; the other tokens bring their own.
886        let keep = tn.kind == Kind::Any && self.has_default && !self.default.is_undefined();
887        self.kind = tn.kind;
888        self.kind_set = true;
889        self.required = tn.required;
890        self.required_set = tn.required_set;
891        self.skippable = tn.skippable;
892        if !keep {
893            self.has_default = tn.has_default;
894            self.default = tn.default;
895            self.literal = tn.literal;
896        }
897        self
898    }
899
900    pub fn string(self) -> Node {
901        self.type_(Kind::String)
902    }
903    pub fn number(self) -> Node {
904        self.type_(Kind::Number)
905    }
906    pub fn boolean(self) -> Node {
907        self.type_(Kind::Boolean)
908    }
909    pub fn object(self) -> Node {
910        self.type_(Kind::Object)
911    }
912    pub fn array(self) -> Node {
913        self.type_(Kind::Array)
914    }
915    pub fn function(self) -> Node {
916        self.type_(Kind::Function)
917    }
918    pub fn integer(self) -> Node {
919        self.type_(Kind::Integer)
920    }
921    pub fn date(self) -> Node {
922        self.type_(Kind::Date)
923    }
924
925    /// A function-typed value; the required state is kept.
926    pub fn func(mut self) -> Node {
927        self.kind = Kind::Function;
928        self
929    }
930
931    pub fn exact<I>(mut self, vals: I) -> Node
932    where
933        I: IntoIterator,
934        I::Item: Into<Value>,
935    {
936        let vals: Vec<Value> = vals.into_iter().map(Into::into).collect();
937        self.has_exact = true;
938        self.exact_vals = vals.clone();
939        let list = format_list(&vals);
940        let wanted = vals.clone();
941        self.befores.push(validator(
942            "Exact",
943            Some(format!("Exact({})", list)),
944            vals,
945            move |state, update| {
946                if wanted.iter().any(|w| w == state.value) {
947                    return true;
948                }
949                // The default stands in for an absent value only; a present
950                // null is a value in its own right.
951                if state.absent && state.node.has_default && wanted.contains(&state.node.default) {
952                    return true;
953                }
954                update.why = Some("Exact".to_string());
955                update.mark = 4010;
956                update.err = Some(UpdateErr::Text(format!(
957                    "Value \"$VALUE\" for property \"$PATH\" must be exactly one of: {}",
958                    list
959                )));
960                update.done = true;
961                false
962            },
963        ));
964        self
965    }
966
967    pub fn min(self, bound: impl Into<Value>) -> Node {
968        self.adopt(bound_node(Bound::Min, bound.into()))
969    }
970
971    pub fn max(self, bound: impl Into<Value>) -> Node {
972        self.adopt(bound_node(Bound::Max, bound.into()))
973    }
974
975    pub fn above(self, bound: impl Into<Value>) -> Node {
976        self.adopt(bound_node(Bound::Above, bound.into()))
977    }
978
979    pub fn below(self, bound: impl Into<Value>) -> Node {
980        self.adopt(bound_node(Bound::Below, bound.into()))
981    }
982
983    pub fn len(self, length: impl Into<Value>) -> Node {
984        self.adopt(len_node(length.into()))
985    }
986
987    pub fn check<F>(mut self, f: F) -> Node
988    where
989        F: Fn(&mut State<'_>, &mut Update) -> bool + Send + Sync + 'static,
990    {
991        self.befores.push(validator(
992            "Check",
993            Some("Check()".to_string()),
994            Vec::new(),
995            // An absent value is left to the required check, as in TypeScript.
996            move |state: &mut State<'_>, update: &mut Update| state.absent || f(state, update),
997        ));
998        self
999    }
1000
1001    pub fn check_re(self, re: Regex) -> Node {
1002        self.check_re_src(re.as_str())
1003    }
1004
1005    pub(crate) fn check_re_src(mut self, src: &str) -> Node {
1006        let src = src.to_string();
1007        let re = match crate::regexp::compile_regexp(&src) {
1008            Ok(engine) => engine,
1009            Err(msg) => return self.adopt(fault_node(msg)),
1010        };
1011        let name = format!("/{}/", src);
1012        let suffix = format!("Check({})", name);
1013        self.befores.push(validator(
1014            &name,
1015            Some(suffix),
1016            Vec::new(),
1017            move |state, update| {
1018                if state.absent {
1019                    return true;
1020                }
1021                if let Value::Str(s) = state.value {
1022                    if re.is_match(s) {
1023                        return true;
1024                    }
1025                }
1026                // No custom text: the default `check "/re/" failed` speaks.
1027                update.why = Some(WHY_CHECK.to_string());
1028                update.mark = MARK_CHECK_TYPE;
1029                false
1030            },
1031        ));
1032        self
1033    }
1034
1035    pub fn before<F>(mut self, f: F) -> Node
1036    where
1037        F: Fn(&mut State<'_>, &mut Update) -> bool + Send + Sync + 'static,
1038    {
1039        self.befores.push(validator(
1040            "Before",
1041            Some("Before()".to_string()),
1042            Vec::new(),
1043            f,
1044        ));
1045        self
1046    }
1047
1048    pub fn after<F>(mut self, f: F) -> Node
1049    where
1050        F: Fn(&mut State<'_>, &mut Update) -> bool + Send + Sync + 'static,
1051    {
1052        self.afters.push(validator(
1053            "After",
1054            Some("After()".to_string()),
1055            Vec::new(),
1056            f,
1057        ));
1058        self
1059    }
1060
1061    pub fn define(mut self, name: impl Into<String>) -> Node {
1062        let name = name.into();
1063        if name.is_empty() {
1064            return fault_node("Shape: Define needs a name");
1065        }
1066        self.define_name = Some(name.clone());
1067        let suffix = format!("Define({})", json_text(&name));
1068        self.befores.push(validator(
1069            "Define",
1070            Some(suffix),
1071            vec![Value::Str(name.clone())],
1072            move |state, _update| {
1073                // The definition met on this call, for a later refer on the
1074                // same context, is the compiled one of this name.
1075                if let Some(d) = state.defs.get(&name).cloned() {
1076                    state.ctx.refs.insert(name.clone(), d);
1077                }
1078                true
1079            },
1080        ));
1081        self
1082    }
1083
1084    pub fn refer(self, name: impl Into<String>) -> Node {
1085        self.refer_with(name, ReferOptions::default())
1086    }
1087
1088    pub fn refer_with(mut self, name: impl Into<String>, opts: ReferOptions) -> Node {
1089        let name = name.into();
1090        if name.is_empty() {
1091            return fault_node("Shape: Refer needs a name");
1092        }
1093        self.refer_name = Some(name.clone());
1094        self.refer_fill = opts.fill;
1095        self.refer_strict = opts.strict;
1096        let suffix = format!("Refer({})", json_text(&name));
1097        self.befores.push(validator(
1098            "Refer",
1099            Some(suffix),
1100            vec![Value::Str(name.clone())],
1101            move |state, update| {
1102                // An absent value is left alone unless fill asks; a present
1103                // null is a value.
1104                if state.absent && !opts.fill {
1105                    return true;
1106                }
1107                // A define met on this call first, then the schema's own.
1108                let found = state
1109                    .ctx
1110                    .refs
1111                    .get(&name)
1112                    .cloned()
1113                    .or_else(|| state.defs.get(&name).cloned());
1114                match found {
1115                    Some(rn) => update.node = Some(rn),
1116                    None if opts.strict => {
1117                        update.err = Some(UpdateErr::Text(format!(
1118                            "Value \"$VALUE\" for property \"$PATH\" refers to \"{}\", which is not defined.",
1119                            name
1120                        )));
1121                        return false;
1122                    }
1123                    None => {}
1124                }
1125                true
1126            },
1127        ));
1128        self
1129    }
1130
1131    pub fn rename(self, name: impl Into<String>) -> Node {
1132        self.rename_with(name, RenameOptions::default())
1133    }
1134
1135    pub fn rename_with(mut self, name: impl Into<String>, opts: RenameOptions) -> Node {
1136        let name = name.into();
1137        if name.is_empty() {
1138            return fault_node("Shape: Rename needs a name");
1139        }
1140        self.rename_to = Some(name);
1141        self.rename_keep = opts.keep;
1142        self.rename_claim = opts.claim;
1143        self
1144    }
1145
1146    pub fn catch(self, fallback: impl Into<Value>) -> Node {
1147        catch_node(self, fallback.into())
1148    }
1149
1150    pub fn transform<F>(self, f: F) -> Node
1151    where
1152        F: Fn(Value, &mut State<'_>) -> Value + Send + Sync + 'static,
1153    {
1154        let f: Arc<TransformFn> = Arc::new(f);
1155        transform_node(self, f)
1156    }
1157
1158    pub fn describe(mut self, description: impl Into<String>) -> Node {
1159        self.meta
1160            .insert("description".to_string(), Value::Str(description.into()));
1161        self
1162    }
1163
1164    pub fn coerce(mut self) -> Node {
1165        self.befores.insert(0, coerce_validator());
1166        self
1167    }
1168
1169    pub fn email(self) -> Node {
1170        with_format(self, FMT_EMAIL)
1171    }
1172    pub fn url(self) -> Node {
1173        with_format(self, FMT_URL)
1174    }
1175    pub fn uuid(self) -> Node {
1176        with_format(self, FMT_UUID)
1177    }
1178    pub fn date_time(self) -> Node {
1179        with_format(self, FMT_DATE_TIME)
1180    }
1181    pub fn ip(self) -> Node {
1182        with_format(self, FMT_IP)
1183    }
1184    pub fn ipv4(self) -> Node {
1185        with_format(self, FMT_IPV4)
1186    }
1187    pub fn ipv6(self) -> Node {
1188        with_format(self, FMT_IPV6)
1189    }
1190}
1191
1192#[cfg(test)]
1193mod tests {
1194    use super::*;
1195    use crate::context::Context;
1196    use crate::spec::{arr, null, obj};
1197    use crate::stringify::stringify_node;
1198    use crate::Schema;
1199
1200    fn j(s: &str) -> Value {
1201        Value::from(serde_json::from_str::<serde_json::Value>(s).unwrap())
1202    }
1203
1204    fn run(s: &Schema, input: &str) -> String {
1205        match s.validate(j(input)) {
1206            Ok(v) => serde_json::Value::from(v).to_string(),
1207            Err(e) => format!("ERR {}", e),
1208        }
1209    }
1210
1211    fn at_a(n: impl Into<Spec>) -> Schema {
1212        Schema::new(obj([("a", n.into())]))
1213    }
1214
1215    fn a(s: &str) -> String {
1216        format!("{{\"a\":{}}}", s)
1217    }
1218
1219    #[test]
1220    fn bounds_on_numbers_strings_and_containers() {
1221        let cases: Vec<(Node, &str, &str)> = vec![
1222            (min(3, Token::Number), "5", "{\"a\":5}"),
1223            (min(3, Token::Number), "1", "ERR Value \"1\" for property \"a\" must be a minimum of 3 (was 1)."),
1224            (max(3, Token::Number), "9", "ERR Value \"9\" for property \"a\" must be a maximum of 3 (was 9)."),
1225            (above(3, Token::Number), "3", "ERR Value \"3\" for property \"a\" must be above 3 (was 3)."),
1226            (below(3, Token::Number), "3", "ERR Value \"3\" for property \"a\" must be below 3 (was 3)."),
1227            (len(3, Token::Number), "4", "ERR Value \"4\" for property \"a\" must be exactly 3 (was 4)."),
1228            (min(3, Token::String), "\"hi\"", "ERR Value \"hi\" for property \"a\" must be a minimum length of 3 (was 2)."),
1229            (max(2, Token::String), "\"hey\"", "ERR Value \"hey\" for property \"a\" must be a maximum length of 2 (was 3)."),
1230            (len(3, Token::String), "\"abc\"", "{\"a\":\"abc\"}"),
1231            (len(3, Token::String), "\"ab\"", "ERR Value \"ab\" for property \"a\" must be exactly 3 in length (was 2)."),
1232            (min(2, any()), "[1]", "ERR Value \"[1]\" for property \"a\" must be a minimum length of 2 (was 1)."),
1233            (above(1, any()), "\"a\"", "ERR Value \"a\" for property \"a\" must have length above 1 (was 1)."),
1234            (below(1, any()), "\"ab\"", "ERR Value \"ab\" for property \"a\" must have length below 1 (was 2)."),
1235            (min(2, Token::Object), "{\"x\":1}", "ERR Value \"{x:1}\" for property \"a\" must be a minimum length of 2 (was 1)."),
1236            (min(2, null()), "null", "ERR Value \"null\" for property \"a\" must be a minimum length of 2 (was NaN)."),
1237            (min(2, null()), "1", "ERR Validation failed for property \"a\" with number \"1\" because the number is not of type null."),
1238            (min(2, Token::String), "1", "ERR Validation failed for property \"a\" with number \"1\" because the number is not of type string."),
1239            (min(2, Token::Integer), "1.5", "ERR Validation failed for property \"a\" with number \"1.5\" because the number is not of type integer."),
1240            (min(2, Token::Integer), "1", "ERR Value \"1\" for property \"a\" must be a minimum of 2 (was 1)."),
1241            (min("2", Token::Number), "1", "ERR Value \"1\" for property \"a\" must be a minimum of 2 (was 1)."),
1242            (min(2, Token::Boolean), "\"x\"", "ERR Validation failed for property \"a\" with string \"x\" because the string is not of type boolean."),
1243            (min(2, true), "true", "ERR Value \"true\" for property \"a\" must be a minimum length of 2 (was NaN)."),
1244            (min(2, Token::Function), "1", "ERR Validation failed for property \"a\" with number \"1\" because the number is not of type function."),
1245            (min(2, Token::Array), "1", "ERR Validation failed for property \"a\" with number \"1\" because the number is not of type array."),
1246            (min(2, Token::Object), "1", "ERR Validation failed for property \"a\" with number \"1\" because the number is not of type object."),
1247            (min(2, f64::NAN), "1", "ERR Validation failed for property \"a\" with number \"1\" because the number is not of type nan."),
1248            (min(2, Token::Date), "1", "ERR Validation failed for property \"a\" with number \"1\" because the number is not of type date."),
1249            (min(2, Token::BigInt), "1", "ERR Validation failed for property \"a\" with number \"1\" because the number is not of type bigint."),
1250            (min(2, buildize(Regex::new("^a").unwrap())), "1", "ERR Validation failed for property \"a\" with number \"1\" because the number is not of type string."),
1251            (min(2, buildize(Regex::new("^a").unwrap())), "\"abc\"", "{\"a\":\"abc\"}"),
1252            (optional(min(2, Token::Number)), "{}", "{}"),
1253            (optional(len(2, Token::Number)), "{}", "{}"),
1254            (max(3, Token::String), "\"hi\"", "{\"a\":\"hi\"}"),
1255            (above(3, Token::Number), "4", "{\"a\":4}"),
1256            (below(3, Token::Number), "2", "{\"a\":2}"),
1257            (len(2, any()), "[1,2]", "{\"a\":[1,2]}"),
1258        ];
1259        for (n, input, want) in cases {
1260            let s = at_a(n);
1261            let got = if input == "{}" {
1262                run(&s, "{}")
1263            } else {
1264                run(&s, &a(input))
1265            };
1266            assert_eq!(got, want.replace("{}", "{\"a\":0}"), "{}", input);
1267        }
1268        let s = at_a(min(3, Token::Number));
1269        assert!(!s.valid(&j(&a("1"))));
1270        let e = &s.error(&j(&a("1")))[0];
1271        assert_eq!((e.why.as_str(), e.mark), ("Min", 4011));
1272        assert_eq!(s.error(&j(&a("\"x\"")))[0].why, "type");
1273        assert_eq!(at_a(max(3, any())).error(&j(&a("9")))[0].mark, 4012);
1274        assert_eq!(at_a(above(3, any())).error(&j(&a("1")))[0].mark, 4013);
1275        assert_eq!(at_a(below(3, any())).error(&j(&a("9")))[0].mark, 4014);
1276        assert_eq!(at_a(len(3, any())).error(&j(&a("9")))[0].mark, 4015);
1277        // A verdict on a failing bound counts it and builds no message.
1278        assert!(!at_a(len(3, any())).valid(&j(&a("9"))));
1279        assert!(!at_a(min(3, any())).valid(&j(&a("1"))));
1280        assert!(!at_a(max(3, any())).valid(&j(&a("9"))));
1281        assert!(!at_a(above(3, any())).valid(&j(&a("1"))));
1282        assert!(!at_a(below(3, any())).valid(&j(&a("9"))));
1283
1284        // Dates compare by their time value.
1285        let s = at_a(min(Value::Date(1000), Token::Date));
1286        let dated =
1287            |ms: i64| Value::Obj([("a".to_string(), Value::Date(ms))].into_iter().collect());
1288        assert!(s.valid(&dated(2000)));
1289        assert!(!s.valid(&dated(5)));
1290        assert_eq!(num_text(&Value::Date(0)), "1970-01-01T00:00:00.000Z");
1291        assert_eq!(num_text(&Value::Bool(true)), "true");
1292        assert_eq!(value_len(&Value::Bool(true)), None);
1293        assert_eq!(value_len(&Value::Str("é😀".into())), Some(3.0));
1294        assert_eq!(bound_arg(&Value::Bool(true)), None);
1295        assert_eq!(bound_arg(&Value::Str("inf".into())), None);
1296        assert_eq!(bound_arg(&Value::Str(" 2.5 ".into())), Some(2.5));
1297        assert!(!is_numeric(&Value::Str("x".into())));
1298        assert!(!type_will_fail(&any(), &Value::Null));
1299    }
1300
1301    #[test]
1302    fn bad_bound_arguments_become_faults() {
1303        for (n, msg) in [
1304            (min("x", Token::Number), "Shape: Min needs a number"),
1305            (max(true, Token::Number), "Shape: Max needs a number"),
1306            (
1307                above(Value::Null, Token::Number),
1308                "Shape: Above needs a number",
1309            ),
1310            (
1311                below(f64::NAN, Token::Number),
1312                "Shape: Below needs a number",
1313            ),
1314            (
1315                len(-1, Token::Number),
1316                "Shape: Len needs a whole number of zero or more",
1317            ),
1318            (
1319                len(1.5, Token::Number),
1320                "Shape: Len needs a whole number of zero or more",
1321            ),
1322            (
1323                buildize(Token::Number).min("x"),
1324                "Shape: Min needs a number",
1325            ),
1326            (
1327                buildize(Token::Number).max("x"),
1328                "Shape: Max needs a number",
1329            ),
1330            (
1331                buildize(Token::Number).above("x"),
1332                "Shape: Above needs a number",
1333            ),
1334            (
1335                buildize(Token::Number).below("x"),
1336                "Shape: Below needs a number",
1337            ),
1338            (
1339                buildize(Token::Number).len("x"),
1340                "Shape: Len needs a whole number of zero or more",
1341            ),
1342            (define("", Token::Number), "Shape: Define needs a name"),
1343            (refer("", Token::Number), "Shape: Refer needs a name"),
1344            (rename("", Token::Number), "Shape: Rename needs a name"),
1345        ] {
1346            assert_eq!(run(&at_a(n), &a("1")), format!("ERR {}", msg));
1347        }
1348    }
1349
1350    #[test]
1351    fn exact_literals() {
1352        let s = Schema::new(obj([("role", exact(["admin", "user"]))]));
1353        assert_eq!(run(&s, r#"{"role":"user"}"#), r#"{"role":"user"}"#);
1354        assert_eq!(
1355            run(&s, r#"{"role":"root"}"#),
1356            "ERR Value \"root\" for property \"role\" must be exactly one of: admin, user"
1357        );
1358        let e = &s.error(&j(r#"{"role":"root"}"#))[0];
1359        assert_eq!((e.why.as_str(), e.mark), ("Exact", 4010));
1360        assert_eq!(
1361            run(&at_a(exact([Value::from(1), Value::Null])), &a("0")),
1362            "ERR Value \"0\" for property \"a\" must be exactly one of: 1, null"
1363        );
1364        assert_eq!(
1365            run(
1366                &at_a(exact([
1367                    Value::from(1),
1368                    Value::from("a"),
1369                    Value::from(true),
1370                    Value::Null
1371                ])),
1372                &a("0")
1373            ),
1374            "ERR Value \"0\" for property \"a\" must be exactly one of: 1, a, true, null"
1375        );
1376        assert_eq!(
1377            format_list(&[Value::Arr(vec![Value::from(1)]), Value::Undefined]),
1378            "[1], undefined"
1379        );
1380        // The default stands in for an absent value.
1381        let s = at_a(default(2, exact([2, 3])));
1382        assert_eq!(run(&s, "{}"), a("2"));
1383        assert_eq!(run(&s, &a("3")), a("3"));
1384        assert_eq!(
1385            run(&s, &a("4")),
1386            "ERR Value \"4\" for property \"a\" must be exactly one of: 2, 3"
1387        );
1388        assert_eq!(
1389            run(&s, &a("null")),
1390            "ERR Value \"null\" for property \"a\" must be exactly one of: 2, 3"
1391        );
1392        let s = at_a(buildize(Token::String).exact(["x"]));
1393        assert_eq!(run(&s, &a("\"x\"")), a("\"x\""));
1394        assert!(s.node().obj_children["a"].has_exact);
1395        assert_eq!(stringify_node(&exact(["a", "b"]), false), "Exact(a, b)");
1396    }
1397
1398    #[test]
1399    fn checks() {
1400        let s = at_a(check(|st, _| st.value.as_f64().unwrap_or(0.0) > 1.0, any()));
1401        assert_eq!(s.node().obj_children["a"].kind, Kind::Check);
1402        assert_eq!(run(&s, &a("2")), a("2"));
1403        assert_eq!(
1404            run(&s, &a("1")),
1405            "ERR Validation failed for property \"a\" with number \"1\" because check \"Check\" failed."
1406        );
1407        // A check is not called for an absent value: the required check speaks.
1408        assert_eq!(
1409            run(&s, "{}"),
1410            "ERR Validation failed for property \"a\" because the property is missing."
1411        );
1412        let s = at_a(check(|_, _| true, Token::Number));
1413        assert_eq!(
1414            run(&s, "{}"),
1415            "ERR Validation failed for property \"a\" because the property is missing."
1416        );
1417        assert_eq!(s.node().obj_children["a"].kind, Kind::Number);
1418        let re = || Regex::new("^a.+").unwrap();
1419        let s = at_a(check_re(re(), any()));
1420        assert_eq!(run(&s, &a("\"abc\"")), a("\"abc\""));
1421        assert_eq!(
1422            run(&s, &a("\"zzz\"")),
1423            "ERR Validation failed for property \"a\" with string \"zzz\" because check \"/^a.+/\" failed."
1424        );
1425        assert_eq!(
1426            run(&s, &a("1")),
1427            "ERR Validation failed for property \"a\" with number \"1\" because check \"/^a.+/\" failed."
1428        );
1429        assert_eq!(s.error(&j(&a("1")))[0].mark, MARK_CHECK_TYPE);
1430        let s = at_a(check_re(re(), Token::String));
1431        assert_eq!(s.node().obj_children["a"].kind, Kind::String);
1432        assert_eq!(
1433            stringify_node(&check_re(re(), any()), false),
1434            "Check.Check(/^a.+/)"
1435        );
1436        let s = at_a(before(
1437            |_, u| {
1438                u.val = Some(Value::from(9));
1439                true
1440            },
1441            Token::Number,
1442        ));
1443        assert_eq!(run(&s, &a("1")), a("9"));
1444        let s = at_a(after(|_, _| false, Token::Number));
1445        assert_eq!(s.error(&j(&a("1")))[0].check, "After");
1446        assert_eq!(
1447            stringify_node(&after(|_, _| true, before(|_, _| true, any())), false),
1448            "Before().After()"
1449        );
1450    }
1451
1452    #[test]
1453    fn composition() {
1454        let one_ns = || one([Spec::from(Token::Number), Spec::from(Token::String)]);
1455        assert_eq!(run(&at_a(one_ns()), &a("\"x\"")), a("\"x\""));
1456        assert_eq!(
1457            run(&at_a(one_ns()), &a("true")),
1458            "ERR Value \"true\" for property \"a\" does not satisfy one of: Number, String"
1459        );
1460        assert!(!at_a(one_ns()).valid(&j(&a("true"))));
1461        assert!(at_a(one_ns()).valid(&j(&a("1"))));
1462        let e = &at_a(one_ns()).error(&j(&a("true")))[0];
1463        assert_eq!((e.why.as_str(), e.mark), ("One", 4030));
1464        let some_ns = || some([Spec::from(Token::Number), Spec::from(Token::String)]);
1465        assert_eq!(run(&at_a(some_ns()), &a("5")), a("5"));
1466        assert_eq!(
1467            run(&at_a(some_ns()), &a("true")),
1468            "ERR Value \"true\" for property \"a\" does not satisfy any of: Number, String"
1469        );
1470        assert_eq!(at_a(some_ns()).error(&j(&a("true")))[0].mark, 4031);
1471        let all_nm = || all([Spec::from(Token::Number), Spec::from(min(2, any()))]);
1472        assert_eq!(
1473            run(&at_a(all_nm()), &a("1")),
1474            "ERR Value \"1\" for property \"a\" does not satisfy all of: Number, Min(2)"
1475        );
1476        assert_eq!(run(&at_a(all_nm()), &a("5")), a("5"));
1477        assert_eq!(at_a(all_nm()).error(&j(&a("1")))[0].mark, 4032);
1478        assert_eq!(
1479            run(
1480                &at_a(one([Spec::from(Token::Number), Spec::from(min(2, any()))])),
1481                &a("\"x\"")
1482            ),
1483            "ERR Value \"x\" for property \"a\" does not satisfy one of: Number, Min(2)"
1484        );
1485        assert_eq!(
1486            run(
1487                &at_a(all([Spec::from(Token::String), Spec::from(Token::Any)])),
1488                &a("1")
1489            ),
1490            "ERR Value \"1\" for property \"a\" does not satisfy all of: String, Any"
1491        );
1492        assert_eq!(
1493            run(
1494                &at_a(one([
1495                    Spec::from(ignore(min(2, Token::Number))),
1496                    Spec::from(Token::String)
1497                ])),
1498                &a("1")
1499            ),
1500            a("1")
1501        );
1502        assert_eq!(
1503            run(
1504                &at_a(all([
1505                    Spec::from(ignore(min(2, Token::Number))),
1506                    Spec::from(Token::Number)
1507                ])),
1508                &a("1")
1509            ),
1510            a("1")
1511        );
1512        assert_eq!(run(&at_a(optional(one_ns())), "{}"), "{}");
1513        let re = || Regex::new("^a").unwrap();
1514        let one_rn = || one([Spec::from(re()), Spec::from(Token::Number)]);
1515        assert_eq!(run(&at_a(one_rn()), &a("\"abc\"")), a("\"abc\""));
1516        assert_eq!(run(&at_a(one_rn()), &a("5")), a("5"));
1517        assert_eq!(
1518            run(&at_a(one_rn()), &a("true")),
1519            "ERR Value \"true\" for property \"a\" does not satisfy one of: /^a/, Number"
1520        );
1521        assert_eq!(
1522            run(
1523                &at_a(some([Spec::from(re()), Spec::from(Token::Number)])),
1524                &a("true")
1525            ),
1526            "ERR Value \"true\" for property \"a\" does not satisfy any of: /^a/, Number"
1527        );
1528        // Fault applies to One and Some, not All.
1529        assert_eq!(run(&at_a(fault("F", one_ns())), &a("true")), "ERR F");
1530        assert_eq!(run(&at_a(fault("F", some_ns())), &a("true")), "ERR F");
1531        assert_eq!(
1532            run(&at_a(fault("F", all_nm())), &a("1")),
1533            "ERR Value \"1\" for property \"a\" does not satisfy all of: Number, Min(2)"
1534        );
1535        assert!(!at_a(fault("F", one_ns())).valid(&j(&a("true"))));
1536        // Every matching Some branch produces from the original; the last
1537        // one's result stands.
1538        let s = at_a(some([
1539            Spec::from(Token::Number),
1540            Spec::from(coerce(Token::String)),
1541        ]));
1542        assert_eq!(run(&s, &a("5")), a("\"5\""));
1543        // All threads the value through its branches.
1544        let s = at_a(all([
1545            Spec::from(coerce(Token::Number)),
1546            Spec::from(min(2, any())),
1547        ]));
1548        assert_eq!(run(&s, &a("\"5\"")), a("5"));
1549        let s = at_a(all([
1550            Spec::from(coerce(Token::Number)),
1551            Spec::from(min(9, any())),
1552        ]));
1553        assert_eq!(
1554            run(&s, &a("\"5\"")),
1555            "ERR Value \"5\" for property \"a\" does not satisfy all of: Number, Min(9)"
1556        );
1557        // A branch that produces nothing leaves a required composition with
1558        // no value, so the missing property is reported.
1559        let missing = "ERR Validation failed for property \"a\" because the property is missing.";
1560        assert_eq!(
1561            run(&at_a(one([Spec::from(skip(Token::Number))])), "{}"),
1562            missing
1563        );
1564        assert_eq!(
1565            run(&at_a(some([Spec::from(skip(Token::Number))])), "{}"),
1566            missing
1567        );
1568        assert_eq!(
1569            run(&at_a(all([Spec::from(skip(Token::Number))])), "{}"),
1570            missing
1571        );
1572        let mut quiet = one_ns();
1573        quiet.silent = true;
1574        assert_eq!(run(&at_a(quiet), &a("true")), a("true"));
1575    }
1576
1577    #[test]
1578    fn define_and_refer() {
1579        let s = |strict: bool, fill: bool| {
1580            Schema::new(obj([
1581                ("a", Spec::from(define("d", Token::Number))),
1582                (
1583                    "b",
1584                    Spec::from(refer_with("d", ReferOptions { strict, fill }, any())),
1585                ),
1586            ]))
1587        };
1588        assert_eq!(
1589            run(&s(false, false), r#"{"a":1,"b":2}"#),
1590            r#"{"a":1,"b":2}"#
1591        );
1592        assert_eq!(run(&s(true, false), r#"{"a":1,"b":2}"#), r#"{"a":1,"b":2}"#);
1593        assert_eq!(
1594            run(&s(true, false), r#"{"a":1,"b":"x"}"#),
1595            "ERR Validation failed for property \"b\" with string \"x\" because the string is not of type number."
1596        );
1597        assert_eq!(run(&s(false, false), r#"{"a":1}"#), r#"{"a":1}"#);
1598        assert_eq!(
1599            run(&s(false, true), r#"{"a":1}"#),
1600            "ERR Validation failed for property \"b\" because the property is missing."
1601        );
1602        assert!(s(false, false).defs().contains_key("d"));
1603        let lax = at_a(any().refer("nope"));
1604        assert_eq!(run(&lax, &a("2")), a("2"));
1605        let strict = |fill| {
1606            at_a(refer_with(
1607                "nope",
1608                ReferOptions { strict: true, fill },
1609                any(),
1610            ))
1611        };
1612        assert_eq!(
1613            run(&strict(false), &a("2")),
1614            "ERR Value \"2\" for property \"a\" refers to \"nope\", which is not defined."
1615        );
1616        assert_eq!(run(&strict(false), "{}"), "{}");
1617        assert_eq!(run(&strict(true), "{}"), "{}");
1618        assert_eq!(
1619            stringify_node(&define("d", Token::Number), false),
1620            "Number.Define(\"d\")"
1621        );
1622        assert_eq!(stringify_node(&refer("d", any()), false), "Refer(\"d\")");
1623        // A define met on one schema's call serves a refer on another, when
1624        // the calls share a context.
1625        let mut ctx = Context::new();
1626        let first = at_a(define("shared", Token::Number));
1627        first.validate_ctx(j(&a("1")), &mut ctx).unwrap();
1628        let second = at_a(refer("shared", any()));
1629        assert!(second.validate_ctx(j(&a("\"x\"")), &mut ctx).is_err());
1630        assert!(second.validate_ctx(j(&a("3")), &mut ctx).is_ok());
1631    }
1632
1633    #[test]
1634    fn renames() {
1635        let s = at_a(buildize(Token::Number).rename("b"));
1636        assert_eq!(run(&s, &a("1")), r#"{"b":1}"#);
1637        assert_eq!(run(&s, r#"{"a":1,"b":2}"#), r#"{"b":1}"#);
1638        assert!(s.valid(&j(&a("1"))));
1639        let s = at_a(rename_with(
1640            "b",
1641            RenameOptions {
1642                keep: true,
1643                claim: vec![],
1644            },
1645            Token::Number,
1646        ));
1647        assert_eq!(run(&s, &a("1")), r#"{"a":1,"b":1}"#);
1648        let claim = |keep| {
1649            at_a(rename_with(
1650                "b",
1651                RenameOptions {
1652                    keep,
1653                    claim: vec!["old".into(), "older".into()],
1654                },
1655                Token::Number,
1656            ))
1657        };
1658        assert_eq!(run(&claim(false), r#"{"older":1}"#), r#"{"b":1}"#);
1659        assert_eq!(
1660            run(&claim(true), r#"{"old":1}"#),
1661            r#"{"old":1,"a":1,"b":1}"#
1662        );
1663        assert_eq!(run(&claim(false), &a("2")), r#"{"b":2}"#);
1664        assert_eq!(
1665            run(&claim(false), "{}"),
1666            "ERR Validation failed for property \"a\" because the property is missing."
1667        );
1668        assert!(claim(false).valid(&j(r#"{"old":1}"#)));
1669        assert!(!claim(false).valid(&j(r#"{"old":"x"}"#)));
1670        assert!(!claim(false).valid(&j("{}")));
1671        // A renamed child that produced nothing has nothing to move.
1672        assert_eq!(run(&at_a(rename("b", skip(Token::Number))), "{}"), "{}");
1673        assert_eq!(run(&at_a(rename("a", Token::Number)), &a("1")), a("1"));
1674    }
1675
1676    #[test]
1677    fn keys() {
1678        let nested = |n: Node| Schema::new(obj([("a", obj([("b", Spec::from(n))]))]));
1679        assert_eq!(
1680            run(&nested(key()), r#"{"a":{"b":"V"}}"#),
1681            r#"{"a":{"b":"a"}}"#
1682        );
1683        assert_eq!(
1684            run(&nested(key_depth(1)), r#"{"a":{"b":"V"}}"#),
1685            r#"{"a":{"b":["a"]}}"#
1686        );
1687        assert_eq!(
1688            run(&nested(key_join(1, "/")), r#"{"a":{"b":"V"}}"#),
1689            r#"{"a":{"b":"a"}}"#
1690        );
1691        assert_eq!(
1692            run(&nested(key_depth(-1)), r#"{"a":{"b":"V"}}"#),
1693            r#"{"a":{"b":["b"]}}"#
1694        );
1695        assert_eq!(
1696            run(&nested(key_join(0, "/")), r#"{"a":{"b":"V"}}"#),
1697            "ERR Validation failed for property \"a.b\" with string \"\" because an empty string is not allowed."
1698        );
1699        assert_eq!(
1700            run(&nested(key_join(2, "/")), r#"{"a":{"b":"V"}}"#),
1701            r#"{"a":{"b":"/a"}}"#
1702        );
1703        assert_eq!(
1704            run(&nested(key_join(5, ".")), r#"{"a":{"b":"V"}}"#),
1705            r#"{"a":{"b":".a"}}"#
1706        );
1707        assert_eq!(run(&at_a(key()), &a("\"V\"")), a("\"V\""));
1708        assert_eq!(
1709            run(&at_a(key_args(&[Value::from("/")])), &a("\"V\"")),
1710            a("\"V\"")
1711        );
1712        assert_eq!(key_args(&[Value::Null]).kind, Kind::String);
1713        assert_eq!(
1714            js_slice(&[Value::from(1), Value::from(2)], 5, 9),
1715            Vec::<Value>::new()
1716        );
1717        assert_eq!(
1718            js_slice(&[Value::from(1), Value::from(2)], -9, -1),
1719            vec![Value::from(1)]
1720        );
1721        assert_eq!(stringify_node(&key(), false), "String.Key()");
1722    }
1723
1724    #[test]
1725    fn catch_and_transform() {
1726        assert_eq!(run(&at_a(catch(0, Token::Number)), &a("\"x\"")), a("0"));
1727        assert_eq!(run(&at_a(catch(0, Token::Number)), &a("5")), a("5"));
1728        assert_eq!(
1729            run(&at_a(catch("none", min(2, Token::String))), &a("\"x\"")),
1730            a("\"none\"")
1731        );
1732        assert_eq!(
1733            run(&at_a(min(2, catch(0, Token::Number))), &a("\"x\"")),
1734            "ERR Value \"0\" for property \"a\" must be a minimum of 2 (was 0)."
1735        );
1736        assert_eq!(run(&at_a(catch(7, Token::Number)), "{}"), a("7"));
1737        assert_eq!(run(&at_a(optional(catch(7, Token::Number))), "{}"), a("0"));
1738        assert_eq!(
1739            run(&at_a(catch(Value::Null, Token::Number)), &a("\"x\"")),
1740            a("null")
1741        );
1742        assert!(at_a(catch(0, Token::Number)).valid(&j(&a("\"x\""))));
1743        let s = at_a(catch(
1744            Value::Obj(Default::default()),
1745            obj([("x", Spec::from(Token::Number))]),
1746        ));
1747        assert_eq!(run(&s, r#"{"a":{"x":"bad"}}"#), r#"{"a":{}}"#);
1748        assert_eq!(run(&s, r#"{"a":{"x":1}}"#), r#"{"a":{"x":1}}"#);
1749        assert_eq!(
1750            stringify_node(&catch(0, min(2, Token::Number)), false),
1751            "Number.Min(2).Catch(0)"
1752        );
1753        assert_eq!(
1754            stringify_node(&after(|_, _| true, Token::Number).catch("z"), false),
1755            "Number.After().Catch(z)"
1756        );
1757        let dbl = |n: Node| transform(|v, _| Value::Num(v.as_f64().unwrap_or(0.0) * 2.0), n);
1758        assert_eq!(run(&at_a(dbl(buildize(Token::Number))), &a("2")), a("4"));
1759        assert_eq!(
1760            run(&at_a(dbl(buildize(Token::Number))), &a("\"x\"")),
1761            "ERR Validation failed for property \"a\" with string \"x\" because the string is not of type number."
1762        );
1763        assert_eq!(
1764            run(&at_a(dbl(min(2, Token::Number))), &a("1")),
1765            "ERR Value \"1\" for property \"a\" must be a minimum of 2 (was 1)."
1766        );
1767        assert!(at_a(dbl(buildize(Token::Number))).valid(&j(&a("2"))));
1768        assert!(!at_a(dbl(buildize(Token::Number))).valid(&j(&a("\"x\""))));
1769        assert_eq!(
1770            stringify_node(&dbl(min(2, Token::Number)), false),
1771            "Number.Min(2).Transform"
1772        );
1773        assert!(catch(0, Token::Number).befores[0].inner.is_some());
1774        // A transform of an absent optional value: nothing produced, nothing
1775        // transformed.
1776        assert_eq!(run(&at_a(dbl(skip(Token::Number))), "{}"), a("0"));
1777    }
1778
1779    #[test]
1780    fn describe_coerce_and_formats() {
1781        let s = at_a(describe("a number", Token::Number));
1782        assert_eq!(
1783            s.node().obj_children["a"].meta.get("description"),
1784            Some(&Value::from("a number"))
1785        );
1786        assert_eq!(
1787            run(&s, &a("\"x\"")),
1788            "ERR Validation failed for property \"a\" with string \"x\" because the string is not of type number."
1789        );
1790        let cases: Vec<(Node, &str, &str)> = vec![
1791            (coerce(Token::Number), "\"5\"", "5"),
1792            (coerce(Token::Number), "true", "1"),
1793            (coerce(Token::Number), "\"x\"", "ERR Validation failed for property \"a\" with string \"x\" because the string is not of type number."),
1794            (coerce(Token::Number), "\"0x10\"", "ERR Validation failed for property \"a\" with string \"0x10\" because the string is not of type number."),
1795            (coerce(Token::Integer), "\"5.5\"", "ERR Validation failed for property \"a\" with number \"5.5\" because the number is not of type integer."),
1796            (coerce(Token::String), "1.5", "\"1.5\""),
1797            (coerce(Token::String), "1000000", "\"1000000\""),
1798            (coerce(Token::String), "false", "\"false\""),
1799            (coerce(Token::Boolean), "\" TRUE \"", "true"),
1800            (coerce(Token::Boolean), "0", "false"),
1801            (coerce(Token::Boolean), "\"yes\"", "ERR Validation failed for property \"a\" with string \"yes\" because the string is not of type boolean."),
1802            (coerce(Token::Date), "\"2020-01-01T00:00:00Z\"", "\"2020-01-01T00:00:00.000Z\""),
1803            (coerce(Token::Date), "\"2020-01-01T12:30:00.5+02:00\"", "\"2020-01-01T10:30:00.500Z\""),
1804            (coerce(Token::Date), "\"2020-02-30T00:00:00Z\"", "ERR Validation failed for property \"a\" with string \"2020-02-30T00:00:00Z\" because the string is not of type date."),
1805            (coerce(Token::Date), "1577836800000", "\"2020-01-01T00:00:00.000Z\""),
1806            (coerce(min(2, Token::Number)), "\"1\"", "ERR Value \"1\" for property \"a\" must be a minimum of 2 (was 1)."),
1807            (email(any()), "\"a@b.co\"", "\"a@b.co\""),
1808            (email(any()), "\"nope\"", "ERR Value \"nope\" for property \"a\" is not a valid email address."),
1809            (email(any()), "1", "ERR Validation failed for property \"a\" with number \"1\" because the number is not of type string."),
1810            (url(any()), "\"https://example.com/a?b=c#d\"", "\"https://example.com/a?b=c#d\""),
1811            (url(any()), "\"example.com\"", "ERR Value \"example.com\" for property \"a\" is not a valid URL."),
1812            (uuid(any()), "\"123e4567-e89b-12d3-a456-426614174000\"", "\"123e4567-e89b-12d3-a456-426614174000\""),
1813            (uuid(any()), "\"123e4567e89b12d3a456426614174000\"", "ERR Value \"123e4567e89b12d3a456426614174000\" for property \"a\" is not a valid UUID."),
1814            (date_time(any()), "\"2020-01-01T00:00:00Z\"", "\"2020-01-01T00:00:00Z\""),
1815            (date_time(any()), "\"2021-02-29T00:00:00Z\"", "ERR Value \"2021-02-29T00:00:00Z\" for property \"a\" is not a valid ISO 8601 date-time."),
1816            (ip(any()), "\"127.0.0.1\"", "\"127.0.0.1\""),
1817            (ip(any()), "\"::1\"", "\"::1\""),
1818            (ip(any()), "\"1.2.3\"", "ERR Value \"1.2.3\" for property \"a\" is not a valid IP address."),
1819            (ipv4(any()), "\"::1\"", "ERR Value \"::1\" for property \"a\" is not a valid IPv4 address."),
1820            (ipv6(any()), "\"1.2.3.4\"", "ERR Value \"1.2.3.4\" for property \"a\" is not a valid IPv6 address."),
1821            (ipv6(any()), "\"::ffff:192.168.1.1\"", "\"::ffff:192.168.1.1\""),
1822            (email(min(10, Token::String)), "\"nope\"", "ERR Value \"nope\" for property \"a\" must be a minimum length of 10 (was 4).\nValue \"nope\" for property \"a\" is not a valid email address."),
1823            (fault("boom", min(2, Token::Number)), "1", "ERR Value \"1\" for property \"a\" must be a minimum of 2 (was 1)."),
1824            (fault("boom", email(any())), "1", "ERR boom"),
1825            (
1826                email(Token::Number),
1827                "1",
1828                "ERR Value \"1\" for property \"a\" is not a valid email address.",
1829            ),
1830            (
1831                email(Token::Number),
1832                "\"x\"",
1833                "ERR Validation failed for property \"a\" with string \"x\" because the string is not of type number.",
1834            ),
1835            (buildize(Token::String).email().url().uuid().date_time().ip().ipv4().ipv6(), "1", "ERR Validation failed for property \"a\" with number \"1\" because the number is not of type string."),
1836            (buildize(Token::Number).coerce(), "\"7\"", "7"),
1837            (buildize(Token::Number).describe("n"), "7", "7"),
1838        ];
1839        for (n, input, want) in cases {
1840            let got = run(&at_a(n), &a(input));
1841            let want = if want.starts_with("ERR") {
1842                want.to_string()
1843            } else {
1844                a(want)
1845            };
1846            assert_eq!(got, want, "{}", input);
1847        }
1848        assert_eq!(
1849            run(&at_a(email(any())), "{}"),
1850            "ERR Validation failed for property \"a\" because the property is missing."
1851        );
1852        assert_eq!(run(&at_a(optional(email(any()))), "{}"), a("\"\""));
1853        let e = &at_a(email(any())).error(&j(&a("\"nope\"")))[0];
1854        assert_eq!((e.why.as_str(), e.mark), ("Email", 4000));
1855        assert!(!at_a(email(any())).valid(&j(&a("\"nope\""))));
1856        assert_eq!(stringify_node(&email(any()), false), "String.Email");
1857    }
1858
1859    #[test]
1860    fn types_and_structure() {
1861        assert_eq!(run(&at_a(type_(Kind::Number, any())), &a("3")), a("3"));
1862        assert_eq!(
1863            run(&at_a(type_(Token::Number, any())), &a("\"x\"")),
1864            "ERR Validation failed for property \"a\" with string \"x\" because the string is not of type number."
1865        );
1866        assert_eq!(
1867            run(&at_a(type_("String", any())), &a("3")),
1868            "ERR Validation failed for property \"a\" with number \"3\" because the number is not of type string."
1869        );
1870        assert_eq!(
1871            run(&Schema::new(type_("Object", any())), "1"),
1872            "ERR Validation failed for number \"1\" because the number is not of type object."
1873        );
1874        assert_eq!(
1875            run(&Schema::new(type_("Object", any())), r#"{"z":1}"#),
1876            "ERR Validation failed for object \"{z:1}\" because the property \"z\" is not allowed."
1877        );
1878        assert_eq!(type_("nonsense", any()).kind, Kind::Any);
1879        assert_eq!(type_(buildize(Token::Integer), any()).kind, Kind::Integer);
1880        assert_eq!(type_(min(2, any()), any()).kind, Kind::Any);
1881        for (n, k) in [
1882            (any().string(), Kind::String),
1883            (any().number(), Kind::Number),
1884            (any().boolean(), Kind::Boolean),
1885            (any().object(), Kind::Object),
1886            (any().array(), Kind::Array),
1887            (any().function(), Kind::Function),
1888            (any().integer(), Kind::Integer),
1889            (any().date(), Kind::Date),
1890            (buildize(Token::Number).any(), Kind::Any),
1891        ] {
1892            assert_eq!(n.kind, k);
1893        }
1894        assert_eq!(
1895            run(&Schema::new(obj([("n", Spec::from(func(any())))])), "{}"),
1896            "{}"
1897        );
1898        assert_eq!(
1899            run(
1900                &Schema::new(obj([("n", Spec::from(Token::Function))])),
1901                "{}"
1902            ),
1903            "ERR Validation failed for property \"n\" because the property is missing."
1904        );
1905        assert_eq!(buildize(Token::Number).func().kind, Kind::Function);
1906
1907        assert!(!open(Token::Number).is_open());
1908        let tuple = closed(arr([Spec::from(Token::Number)]));
1909        assert_eq!(tuple.arr_children.len(), 1);
1910        assert_eq!(run(&at_a(tuple.clone()), &a("[1]")), a("[1]"));
1911        assert!(!at_a(tuple).valid(&j(&a("[1,2]"))));
1912        assert!(closed(arr([Spec::from(1), Spec::from(2)]))
1913            .arr_child
1914            .is_none());
1915        let c = child(Token::Number, Token::Number);
1916        assert!(c.kind == Kind::Object && c.obj_rest.is_some());
1917        assert!(buildize(Token::Array)
1918            .child(Token::Number)
1919            .arr_child
1920            .is_some());
1921        assert!(buildize(Token::Object)
1922            .child(Token::Number)
1923            .obj_rest
1924            .is_some());
1925        assert_eq!(
1926            run(
1927                &at_a(rest(Token::Number, arr([Spec::from(1)]))),
1928                &a("[1,2,3]")
1929            ),
1930            a("[1,2,3]")
1931        );
1932        assert_eq!(run(&at_a(rest(Token::Number, any())), &a("[2]")), a("[2]"));
1933        assert!(!at_a(rest(Token::Number, arr([Spec::from(1)]))).valid(&j(&a("[1,\"x\"]"))));
1934        assert_eq!(default_of("x").kind, Kind::String);
1935        assert_eq!(run(&at_a(default_of("x")), "{}"), a("\"x\""));
1936        assert_eq!(run(&at_a(empty(any())), &a("\"\"")), a("\"\""));
1937        assert_eq!(run(&at_a(empty(any())), &a("0")), a("0"));
1938        assert_eq!(run(&at_a(ignore(empty(any()))), &a("0")), a("0"));
1939        assert_eq!(
1940            run(&at_a(required(null())), "{}"),
1941            "ERR Validation failed for property \"a\" because the property is missing."
1942        );
1943        assert_eq!(run(&at_a(skip(null())), "{}"), "{}");
1944        assert_eq!(run(&at_a(min(2, null())), "{}"), a("null"));
1945        assert_eq!(
1946            run(&at_a(required(f64::NAN)), "{}"),
1947            "ERR Validation failed for property \"a\" because the property is missing."
1948        );
1949        assert_eq!(run(&at_a(min(2, f64::NAN)), "{}"), a("null"));
1950        assert_eq!(run(&at_a(never(Token::String)), "{}"), "ERR Validation failed for property \"a\" with value \"undefined\" because no value is allowed.");
1951        assert_eq!(
1952            run(&at_a(nullable(closed(obj::<&str, Spec>([])))), &a("null")),
1953            a("null")
1954        );
1955        assert_eq!(run(&at_a(optional(nullable(Token::Number))), "{}"), a("0"));
1956    }
1957
1958    #[test]
1959    fn untyped_defaults_take_the_default_kind() {
1960        let cases: Vec<(Node, &str, &str)> = vec![
1961            (default(2, required(any())), "\"x\"", "ERR Validation failed for property \"a\" with string \"x\" because the string is not of type number."),
1962            (default(2, required(any())), "{}", "2"),
1963            (default(2, describe("two", required(any()))), "3", "3"),
1964            (default(2, fault("not two", exact([2]))), "3", "ERR Value \"3\" for property \"a\" must be exactly one of: 2"),
1965            (default(2, exact([2, 3])), "3", "3"),
1966            (default(2, nullable(required(any()))), "null", "null"),
1967            (default("x", empty(required(any()))), "\"\"", "\"\""),
1968            (default(2, after(|_, _| false, any())), "3", "ERR Validation failed for property \"a\" with number \"3\" because check \"After\" failed."),
1969            // Default clears skippable, so an Ignore's silence remains alone.
1970            (default(2, ignore(any())), "\"x\"", "\"x\""),
1971            (default(Value::Undefined, any()), "\"x\"", "\"x\""),
1972            (default(7, Token::Number), "{}", "7"),
1973        ];
1974        for (n, input, want) in cases {
1975            let got = if input == "{}" {
1976                run(&at_a(n), "{}")
1977            } else {
1978                run(&at_a(n), &a(input))
1979            };
1980            let want = if want.starts_with("ERR") || want == "{}" {
1981                want.to_string()
1982            } else {
1983                a(want)
1984            };
1985            assert_eq!(got, want, "{}", input);
1986        }
1987        let d = default(2, describe("two", any()));
1988        assert_eq!(d.meta.get("description"), Some(&Value::from("two")));
1989    }
1990}