json_eval_rs/jsoneval/
subform_methods.rs

1// Subform methods for isolated array field evaluation
2
3use crate::JSONEval;
4use crate::ReturnFormat;
5use crate::jsoneval::cancellation::CancellationToken;
6use serde_json::Value;
7
8impl JSONEval {
9    /// Evaluate a subform with data
10    /// Evaluate a subform with data and optional selective paths
11    pub fn evaluate_subform(
12        &mut self,
13        subform_path: &str,
14        data: &str,
15        context: Option<&str>,
16        paths: Option<&[String]>,
17        token: Option<&CancellationToken>,
18    ) -> Result<(), String> {
19        let subform = self
20            .subforms
21            .get_mut(subform_path)
22            .ok_or_else(|| format!("Subform not found: {}", subform_path))?;
23
24        subform.evaluate(data, context, paths, token)
25    }
26
27    /// Validate subform data against its schema rules
28    pub fn validate_subform(
29        &mut self,
30        subform_path: &str,
31        data: &str,
32        context: Option<&str>,
33        paths: Option<&[String]>,
34        token: Option<&CancellationToken>,
35    ) -> Result<crate::ValidationResult, String> {
36        let subform = self
37            .subforms
38            .get_mut(subform_path)
39            .ok_or_else(|| format!("Subform not found: {}", subform_path))?;
40
41        subform.validate(data, context, paths, token)
42    }
43
44    /// Evaluate dependents in subform when a field changes
45    pub fn evaluate_dependents_subform(
46        &mut self,
47        subform_path: &str,
48        changed_paths: &[String],
49        data: Option<&str>,
50        context: Option<&str>,
51        re_evaluate: bool,
52        token: Option<&CancellationToken>,
53        canceled_paths: Option<&mut Vec<String>>,
54    ) -> Result<Value, String> {
55        let subform = self
56            .subforms
57            .get_mut(subform_path)
58            .ok_or_else(|| format!("Subform not found: {}", subform_path))?;
59
60        subform.evaluate_dependents(changed_paths, data, context, re_evaluate, token, canceled_paths)
61    }
62
63    /// Resolve layout for subform
64    pub fn resolve_layout_subform(
65        &mut self,
66        subform_path: &str,
67        evaluate: bool,
68    ) -> Result<(), String> {
69        let subform = self
70            .subforms
71            .get_mut(subform_path)
72            .ok_or_else(|| format!("Subform not found: {}", subform_path))?;
73
74        let _ = subform.resolve_layout(evaluate);
75        Ok(())
76    }
77
78    /// Get evaluated schema from subform
79    pub fn get_evaluated_schema_subform(
80        &mut self,
81        subform_path: &str,
82        resolve_layout: bool,
83    ) -> Value {
84        if let Some(subform) = self.subforms.get_mut(subform_path) {
85            subform.get_evaluated_schema(resolve_layout)
86        } else {
87            Value::Null
88        }
89    }
90
91    /// Get schema value from subform (all .value fields)
92    pub fn get_schema_value_subform(&mut self, subform_path: &str) -> Value {
93        if let Some(subform) = self.subforms.get_mut(subform_path) {
94            subform.get_schema_value()
95        } else {
96            Value::Null
97        }
98    }
99
100    /// Get evaluated schema without $params from subform
101    pub fn get_evaluated_schema_without_params_subform(
102        &mut self,
103        subform_path: &str,
104        resolve_layout: bool,
105    ) -> Value {
106        if let Some(subform) = self.subforms.get_mut(subform_path) {
107            subform.get_evaluated_schema_without_params(resolve_layout)
108        } else {
109            Value::Null
110        }
111    }
112
113    /// Get evaluated schema by specific path from subform
114    pub fn get_evaluated_schema_by_path_subform(
115        &mut self,
116        subform_path: &str,
117        schema_path: &str,
118        skip_layout: bool,
119    ) -> Option<Value> {
120        if let Some(subform) = self.subforms.get_mut(subform_path) {
121            Some(subform.get_evaluated_schema_by_paths(&[schema_path.to_string()], skip_layout, Some(ReturnFormat::Nested)))
122        } else {
123            None
124        }
125    }
126
127    /// Get evaluated schema by multiple paths from subform
128    pub fn get_evaluated_schema_by_paths_subform(
129        &mut self,
130        subform_path: &str,
131        schema_paths: &[String],
132        skip_layout: bool,
133        format: Option<crate::ReturnFormat>,
134    ) -> Value {
135        if let Some(subform) = self.subforms.get_mut(subform_path) {
136            subform.get_evaluated_schema_by_paths(schema_paths, skip_layout, Some(format.unwrap_or(ReturnFormat::Flat)))
137        } else {
138            match format.unwrap_or_default() {
139                crate::ReturnFormat::Array => Value::Array(vec![]),
140                _ => Value::Object(serde_json::Map::new()),
141            }
142        }
143    }
144
145    /// Get schema by specific path from subform
146    pub fn get_schema_by_path_subform(
147        &self,
148        subform_path: &str,
149        schema_path: &str,
150    ) -> Option<Value> {
151        if let Some(subform) = self.subforms.get(subform_path) {
152            subform.get_schema_by_path(schema_path)
153        } else {
154            None
155        }
156    }
157
158    /// Get schema by multiple paths from subform
159    pub fn get_schema_by_paths_subform(
160        &self,
161        subform_path: &str,
162        schema_paths: &[String],
163        format: Option<crate::ReturnFormat>,
164    ) -> Value {
165        if let Some(subform) = self.subforms.get(subform_path) {
166            subform.get_schema_by_paths(schema_paths, Some(format.unwrap_or(ReturnFormat::Flat)))
167        } else {
168            match format.unwrap_or_default() {
169                crate::ReturnFormat::Array => Value::Array(vec![]),
170                _ => Value::Object(serde_json::Map::new()),
171            }
172        }
173    }
174
175    /// Get list of available subform paths
176    pub fn get_subform_paths(&self) -> Vec<String> {
177        self.subforms.keys().cloned().collect()
178    }
179
180    /// Check if a subform exists at the given path
181    pub fn has_subform(&self, subform_path: &str) -> bool {
182        self.subforms.contains_key(subform_path)
183    }
184}