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 is_match: state.is_match,
45 path: state.path_arr.to_vec(),
46 paths: true,
47 };
48 let kept = validate_node_with(
49 state.node,
50 &self.befores,
51 &self.afters,
52 state.node.silent,
53 Cur::Mut(&mut val),
54 state.key,
55 state.parent_is_array,
56 &mut w,
57 &mut sub,
58 );
59 if !kept {
60 val = Value::Undefined;
61 }
62 (val, sub)
63 }
64}
65
66fn take_inner(n: &mut Node) -> Arc<Inner> {
67 Arc::new(Inner {
68 befores: std::mem::take(&mut n.befores),
69 afters: std::mem::take(&mut n.afters),
70 })
71}
72
73pub(crate) fn catch_node(mut n: Node, fallback: Value) -> Node {
76 let inner = take_inner(&mut n);
77 let suffix = format!(
78 "{}Catch({})",
79 inner.desc(),
80 crate::stringify::inline_value(&fallback)
81 );
82 let run = Arc::clone(&inner);
83 let fb = fallback.clone();
84 n.befores = vec![Validator {
85 name: "Catch".to_string(),
86 func: Arc::new(move |state: &mut State<'_>, update: &mut Update| {
87 let (mut out, sub) = run.probe(state);
88 if sub.has_any() {
89 out = fb.clone();
90 }
91 update.val = Some(out);
92 update.done = true;
93 true
94 }),
95 args: vec![fallback],
96 suffix: Some(suffix),
97 inner: Some(inner),
98 }];
99 n
100}
101
102pub type TransformFn = dyn Fn(Value, &mut State<'_>) -> Value + Send + Sync;
105
106pub(crate) fn transform_node(mut n: Node, f: Arc<TransformFn>) -> Node {
109 let inner = take_inner(&mut n);
110 let suffix = format!("{}Transform", inner.desc());
111 let run = Arc::clone(&inner);
112 n.befores = vec![Validator {
113 name: "Transform".to_string(),
114 func: Arc::new(move |state: &mut State<'_>, update: &mut Update| {
115 let (out, sub) = run.probe(state);
116 if sub.has_any() {
117 update.err = Some(UpdateErr::Fields(sub.issues));
118 return false;
119 }
120 update.val = Some(f(out, state));
121 update.done = true;
122 true
123 }),
124 args: Vec::new(),
125 suffix: Some(suffix),
126 inner: Some(inner),
127 }];
128 n
129}