1use super::JSONEval;
2use crate::jsoneval::eval_cache::EvalCache;
3use crate::jsoneval::eval_data::EvalData;
4use crate::jsoneval::json_parser;
5use crate::parse_schema;
6use crate::jsoneval::parsed_schema::ParsedSchema;
7use crate::jsoneval::parsed_schema_cache::PARSED_SCHEMA_CACHE;
8use crate::rlogic::{RLogic, RLogicConfig};
9
10use crate::time_block;
11
12use indexmap::IndexMap;
13use serde::de::Error as _;
14use serde_json::Value;
15use std::sync::{Arc, Mutex};
16
17
18impl Clone for JSONEval {
19 fn clone(&self) -> Self {
20 Self {
21 cache_enabled: self.cache_enabled,
22 schema: Arc::clone(&self.schema),
23 engine: Arc::clone(&self.engine),
24 evaluations: self.evaluations.clone(),
25 tables: self.tables.clone(),
26 table_metadata: self.table_metadata.clone(),
27 dependencies: self.dependencies.clone(),
28 sorted_evaluations: self.sorted_evaluations.clone(),
29 dependents_evaluations: self.dependents_evaluations.clone(),
30 rules_evaluations: self.rules_evaluations.clone(),
31 fields_with_rules: self.fields_with_rules.clone(),
32 others_evaluations: self.others_evaluations.clone(),
33 value_evaluations: self.value_evaluations.clone(),
34 layout_paths: self.layout_paths.clone(),
35 options_templates: self.options_templates.clone(),
36 subforms: self.subforms.clone(),
37 reffed_by: self.reffed_by.clone(),
38 context: self.context.clone(),
39 data: self.data.clone(),
40 evaluated_schema: self.evaluated_schema.clone(),
41 eval_data: self.eval_data.clone(),
42 eval_cache: EvalCache::new(), eval_lock: Mutex::new(()), cached_msgpack_schema: self.cached_msgpack_schema.clone(),
45 conditional_hidden_fields: self.conditional_hidden_fields.clone(),
46 conditional_readonly_fields: self.conditional_readonly_fields.clone(),
47 }
48 }
49}
50
51impl JSONEval {
52 pub fn new(
53 schema: &str,
54 context: Option<&str>,
55 data: Option<&str>,
56 ) -> Result<Self, serde_json::Error> {
57 time_block!("JSONEval::new() [total]", {
58 let schema_val: Value =
60 time_block!(" parse schema JSON", { serde_json::from_str(schema)? });
61 let context: Value = time_block!(" parse context JSON", {
62 json_parser::parse_json_str(context.unwrap_or("{}"))
63 .map_err(serde_json::Error::custom)?
64 });
65 let data: Value = time_block!(" parse data JSON", {
66 json_parser::parse_json_str(data.unwrap_or("{}"))
67 .map_err(serde_json::Error::custom)?
68 });
69 let evaluated_schema = schema_val.clone();
70 let engine_config = RLogicConfig::default();
72
73 let mut instance = time_block!(" create instance struct", {
74 Self {
75 schema: Arc::new(schema_val),
76 evaluations: Arc::new(IndexMap::new()),
77 tables: Arc::new(IndexMap::new()),
78 table_metadata: Arc::new(IndexMap::new()),
79 dependencies: Arc::new(IndexMap::new()),
80 sorted_evaluations: Arc::new(Vec::new()),
81 dependents_evaluations: Arc::new(IndexMap::new()),
82 rules_evaluations: Arc::new(Vec::new()),
83 fields_with_rules: Arc::new(Vec::new()),
84 others_evaluations: Arc::new(Vec::new()),
85 value_evaluations: Arc::new(Vec::new()),
86 layout_paths: Arc::new(Vec::new()),
87 options_templates: Arc::new(Vec::new()),
88 subforms: IndexMap::new(),
89 engine: Arc::new(RLogic::with_config(engine_config)),
90 reffed_by: Arc::new(IndexMap::new()),
91 context: context.clone(),
92 data: data.clone(),
93 evaluated_schema: evaluated_schema.clone(),
94 eval_data: EvalData::with_schema_data_context(
95 &evaluated_schema,
96 &data,
97 &context,
98 ),
99 eval_cache: EvalCache::new(),
100 cache_enabled: true, eval_lock: Mutex::new(()),
102 cached_msgpack_schema: None, conditional_hidden_fields: Arc::new(Vec::new()),
104 conditional_readonly_fields: Arc::new(Vec::new()),
105 }
106 });
107 time_block!(" parse_schema", {
108 parse_schema::legacy::parse_schema(&mut instance)
109 .map_err(serde_json::Error::custom)?
110 });
111 Ok(instance)
112 })
113 }
114
115 pub fn new_from_msgpack(
127 schema_msgpack: &[u8],
128 context: Option<&str>,
129 data: Option<&str>,
130 ) -> Result<Self, String> {
131 let cached_msgpack = schema_msgpack.to_vec();
133
134 let schema_val: Value = rmp_serde::from_slice(schema_msgpack)
136 .map_err(|e| format!("Failed to deserialize MessagePack schema: {}", e))?;
137
138 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))
139 .map_err(|e| format!("Failed to parse context: {}", e))?;
140 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))
141 .map_err(|e| format!("Failed to parse data: {}", e))?;
142 let evaluated_schema = schema_val.clone();
143 let engine_config = RLogicConfig::default();
144
145 let mut instance = Self {
146 schema: Arc::new(schema_val),
147 evaluations: Arc::new(IndexMap::new()),
148 tables: Arc::new(IndexMap::new()),
149 table_metadata: Arc::new(IndexMap::new()),
150 dependencies: Arc::new(IndexMap::new()),
151 sorted_evaluations: Arc::new(Vec::new()),
152 dependents_evaluations: Arc::new(IndexMap::new()),
153 rules_evaluations: Arc::new(Vec::new()),
154 fields_with_rules: Arc::new(Vec::new()),
155 others_evaluations: Arc::new(Vec::new()),
156 value_evaluations: Arc::new(Vec::new()),
157 layout_paths: Arc::new(Vec::new()),
158 options_templates: Arc::new(Vec::new()),
159 subforms: IndexMap::new(),
160 engine: Arc::new(RLogic::with_config(engine_config)),
161 reffed_by: Arc::new(IndexMap::new()),
162 context: context.clone(),
163 data: data.clone(),
164 evaluated_schema: evaluated_schema.clone(),
165 eval_data: EvalData::with_schema_data_context(&evaluated_schema, &data, &context),
166 eval_cache: EvalCache::new(),
167 cache_enabled: true, eval_lock: Mutex::new(()),
169 cached_msgpack_schema: Some(cached_msgpack), conditional_hidden_fields: Arc::new(Vec::new()),
171 conditional_readonly_fields: Arc::new(Vec::new()),
172 };
173 parse_schema::legacy::parse_schema(&mut instance)?;
174 Ok(instance)
175 }
176
177 pub fn with_parsed_schema(
205 parsed: Arc<ParsedSchema>,
206 context: Option<&str>,
207 data: Option<&str>,
208 ) -> Result<Self, String> {
209 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))
210 .map_err(|e| format!("Failed to parse context: {}", e))?;
211 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))
212 .map_err(|e| format!("Failed to parse data: {}", e))?;
213
214 let evaluated_schema = parsed.schema.clone();
215
216 let engine = parsed.engine.clone();
219
220 let mut subforms = IndexMap::new();
223 for (path, subform_parsed) in &parsed.subforms {
224 let subform_eval =
226 JSONEval::with_parsed_schema(subform_parsed.clone(), Some("{}"), None)?;
227 subforms.insert(path.clone(), Box::new(subform_eval));
228 }
229
230 let instance = Self {
231 schema: Arc::clone(&parsed.schema),
232 evaluations: Arc::clone(&parsed.evaluations),
234 tables: Arc::clone(&parsed.tables),
235 table_metadata: Arc::clone(&parsed.table_metadata),
236 dependencies: Arc::clone(&parsed.dependencies),
237 sorted_evaluations: Arc::clone(&parsed.sorted_evaluations),
238 dependents_evaluations: Arc::clone(&parsed.dependents_evaluations),
239 rules_evaluations: Arc::clone(&parsed.rules_evaluations),
240 fields_with_rules: Arc::clone(&parsed.fields_with_rules),
241 others_evaluations: Arc::clone(&parsed.others_evaluations),
242 value_evaluations: Arc::clone(&parsed.value_evaluations),
243 layout_paths: Arc::clone(&parsed.layout_paths),
244 options_templates: Arc::clone(&parsed.options_templates),
245 subforms,
246 engine,
247 reffed_by: Arc::clone(&parsed.reffed_by),
248 context: context.clone(),
249 data: data.clone(),
250 evaluated_schema: (*evaluated_schema).clone(),
251 eval_data: EvalData::with_schema_data_context(&evaluated_schema, &data, &context),
252 eval_cache: EvalCache::new(),
253 cache_enabled: true, eval_lock: Mutex::new(()),
255 cached_msgpack_schema: None, conditional_hidden_fields: Arc::clone(&parsed.conditional_hidden_fields),
257 conditional_readonly_fields: Arc::clone(&parsed.conditional_readonly_fields),
258 };
259
260 Ok(instance)
261 }
262
263 pub fn reload_schema(
264 &mut self,
265 schema: &str,
266 context: Option<&str>,
267 data: Option<&str>,
268 ) -> Result<(), String> {
269 let schema_val: Value =
271 serde_json::from_str(schema).map_err(|e| format!("failed to parse schema: {e}"))?;
272 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))?;
273 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))?;
274 self.schema = Arc::new(schema_val);
275 self.context = context.clone();
276 self.data = data.clone();
277 self.evaluated_schema = (*self.schema).clone();
278 self.engine = Arc::new(RLogic::new());
279 self.dependents_evaluations = Arc::new(IndexMap::new());
280 self.rules_evaluations = Arc::new(Vec::new());
281 self.fields_with_rules = Arc::new(Vec::new());
282 self.others_evaluations = Arc::new(Vec::new());
283 self.value_evaluations = Arc::new(Vec::new());
284 self.layout_paths = Arc::new(Vec::new());
285 self.options_templates = Arc::new(Vec::new());
286 self.subforms.clear();
287 parse_schema::legacy::parse_schema(self)?;
288
289 self.eval_data =
291 EvalData::with_schema_data_context(&self.evaluated_schema, &data, &context);
292
293 self.eval_cache.clear();
295
296 self.cached_msgpack_schema = None;
298
299 Ok(())
300 }
301
302 pub fn set_timezone_offset(&mut self, offset_minutes: Option<i32>) {
324 let mut config = RLogicConfig::default();
326 if let Some(offset) = offset_minutes {
327 config = config.with_timezone_offset(offset);
328 }
329
330 self.engine = Arc::new(RLogic::with_config(config));
333
334 let _ = parse_schema::legacy::parse_schema(self);
337
338 self.eval_cache.clear();
340 }
341
342 pub fn reload_schema_msgpack(
354 &mut self,
355 schema_msgpack: &[u8],
356 context: Option<&str>,
357 data: Option<&str>,
358 ) -> Result<(), String> {
359 let schema_val: Value = rmp_serde::from_slice(schema_msgpack)
361 .map_err(|e| format!("failed to deserialize MessagePack schema: {e}"))?;
362
363 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))?;
364 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))?;
365
366 self.schema = Arc::new(schema_val);
367 self.context = context.clone();
368 self.data = data.clone();
369 self.evaluated_schema = (*self.schema).clone();
370 self.engine = Arc::new(RLogic::new());
371 self.dependents_evaluations = Arc::new(IndexMap::new());
372 self.rules_evaluations = Arc::new(Vec::new());
373 self.fields_with_rules = Arc::new(Vec::new());
374 self.others_evaluations = Arc::new(Vec::new());
375 self.value_evaluations = Arc::new(Vec::new());
376 self.layout_paths = Arc::new(Vec::new());
377 self.options_templates = Arc::new(Vec::new());
378 self.subforms.clear();
379 parse_schema::legacy::parse_schema(self)?;
380
381 self.eval_data =
383 EvalData::with_schema_data_context(&self.evaluated_schema, &data, &context);
384
385 self.eval_cache.clear();
387
388 self.cached_msgpack_schema = Some(schema_msgpack.to_vec());
390
391 Ok(())
392 }
393
394 pub fn reload_schema_parsed(
408 &mut self,
409 parsed: Arc<ParsedSchema>,
410 context: Option<&str>,
411 data: Option<&str>,
412 ) -> Result<(), String> {
413 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))?;
414 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))?;
415
416 self.schema = Arc::clone(&parsed.schema);
418 self.evaluations = parsed.evaluations.clone();
419 self.tables = parsed.tables.clone();
420 self.table_metadata = parsed.table_metadata.clone();
421 self.dependencies = parsed.dependencies.clone();
422 self.sorted_evaluations = parsed.sorted_evaluations.clone();
423 self.dependents_evaluations = parsed.dependents_evaluations.clone();
424 self.rules_evaluations = parsed.rules_evaluations.clone();
425 self.fields_with_rules = parsed.fields_with_rules.clone();
426 self.others_evaluations = parsed.others_evaluations.clone();
427 self.value_evaluations = parsed.value_evaluations.clone();
428 self.layout_paths = parsed.layout_paths.clone();
429 self.options_templates = parsed.options_templates.clone();
430
431 self.engine = parsed.engine.clone();
433
434 let mut subforms = IndexMap::new();
436 for (path, subform_parsed) in &parsed.subforms {
437 let subform_eval =
438 JSONEval::with_parsed_schema(subform_parsed.clone(), Some("{}"), None)?;
439 subforms.insert(path.clone(), Box::new(subform_eval));
440 }
441 self.subforms = subforms;
442
443 self.context = context.clone();
444 self.data = data.clone();
445 self.evaluated_schema = (*self.schema).clone();
446
447 self.eval_data =
449 EvalData::with_schema_data_context(&self.evaluated_schema, &data, &context);
450
451 self.eval_cache.clear();
453
454 self.cached_msgpack_schema = None;
456
457 Ok(())
458 }
459
460 pub fn reload_schema_from_cache(
474 &mut self,
475 cache_key: &str,
476 context: Option<&str>,
477 data: Option<&str>,
478 ) -> Result<(), String> {
479 let parsed = PARSED_SCHEMA_CACHE
481 .get(cache_key)
482 .ok_or_else(|| format!("Schema '{}' not found in cache", cache_key))?;
483
484 self.reload_schema_parsed(parsed, context, data)
486 }
487}