1use crate::context::{State, Update, UpdateErr};
10use crate::error::ValidationError;
11use crate::node::{Node, Validator};
12use crate::validate::{validate_node_with, Cur, Walk};
13use crate::value::Value;
14use std::sync::Arc;
15
16#[derive(Clone, Debug, Default)]
18pub struct Inner {
19 pub befores: Vec<Validator>,
20 pub afters: Vec<Validator>,
21}
22
23impl Inner {
24 fn desc(&self) -> String {
27 let mut out = String::new();
28 for v in self.befores.iter().chain(self.afters.iter()) {
29 if let Some(s) = &v.suffix {
30 out.push_str(s);
31 out.push('.');
32 }
33 }
34 out
35 }
36
37 fn probe(&self, state: &mut State<'_>) -> (Value, ValidationError) {
40 let mut val = state.value.clone();
41 let mut sub = ValidationError::default();
42 let mut w = Walk {
43 ctx: state.ctx,
44 defs: state.defs,
45 is_match: state.is_match,
46 path: state.path_arr.to_vec(),
47 paths: true,
48 };
49 let kept = validate_node_with(
50 state.node,
51 &self.befores,
52 &self.afters,
53 state.node.silent,
54 Cur::Mut(&mut val),
55 state.key,
56 state.parent_is_array,
57 &mut w,
58 &mut sub,
59 );
60 if !kept {
61 val = Value::Undefined;
62 }
63 (val, sub)
64 }
65}
66
67fn take_inner(n: &mut Node) -> Arc<Inner> {
68 Arc::new(Inner {
69 befores: std::mem::take(&mut n.befores),
70 afters: std::mem::take(&mut n.afters),
71 })
72}
73
74pub(crate) fn catch_node(mut n: Node, fallback: Value) -> Node {
77 let inner = take_inner(&mut n);
78 let suffix = format!(
79 "{}Catch({})",
80 inner.desc(),
81 crate::stringify::inline_value(&fallback)
82 );
83 let run = Arc::clone(&inner);
84 let fb = fallback.clone();
85 n.befores = vec![Validator {
86 name: "Catch".to_string(),
87 func: Arc::new(move |state: &mut State<'_>, update: &mut Update| {
88 let (mut out, sub) = run.probe(state);
89 if sub.has_any() {
90 out = fb.clone();
91 }
92 update.val = Some(out);
93 update.done = true;
94 true
95 }),
96 args: vec![fallback],
97 suffix: Some(suffix),
98 inner: Some(inner),
99 }];
100 n
101}
102
103pub type TransformFn = dyn Fn(Value, &mut State<'_>) -> Value + Send + Sync;
106
107pub(crate) fn transform_node(mut n: Node, f: Arc<TransformFn>) -> Node {
110 let inner = take_inner(&mut n);
111 let suffix = format!("{}Transform", inner.desc());
112 let run = Arc::clone(&inner);
113 n.befores = vec![Validator {
114 name: "Transform".to_string(),
115 func: Arc::new(move |state: &mut State<'_>, update: &mut Update| {
116 let (out, sub) = run.probe(state);
117 if sub.has_any() {
118 update.err = Some(UpdateErr::Fields(sub.issues));
119 return false;
120 }
121 update.val = Some(f(out, state));
122 update.done = true;
123 true
124 }),
125 args: Vec::new(),
126 suffix: Some(suffix),
127 inner: Some(inner),
128 }];
129 n
130}