1use super::JSONEval;
2use crate::jsoneval::eval_data::EvalData;
3use crate::jsoneval::json_parser;
4use crate::jsoneval::parsed_schema::ParsedSchema;
5use crate::jsoneval::parsed_schema_cache::PARSED_SCHEMA_CACHE;
6use crate::parse_schema;
7use crate::rlogic::{RLogic, RLogicConfig};
8
9use crate::time_block;
10
11use indexmap::IndexMap;
12use serde::de::Error as _;
13use serde_json::Value;
14use std::collections::HashMap;
15use std::sync::{Arc, Mutex, RwLock};
16
17impl Clone for JSONEval {
18 fn clone(&self) -> Self {
19 Self {
20 schema: Arc::clone(&self.schema),
21 engine: Arc::clone(&self.engine),
22 evaluations: self.evaluations.clone(),
23 tables: self.tables.clone(),
24 table_metadata: self.table_metadata.clone(),
25 dependencies: self.dependencies.clone(),
26 sorted_evaluations: self.sorted_evaluations.clone(),
27 dependents_evaluations: self.dependents_evaluations.clone(),
28 rules_evaluations: self.rules_evaluations.clone(),
29 fields_with_rules: self.fields_with_rules.clone(),
30 others_evaluations: self.others_evaluations.clone(),
31 value_evaluations: self.value_evaluations.clone(),
32 layout_paths: self.layout_paths.clone(),
33 options_templates: self.options_templates.clone(),
34 subforms: self.subforms.clone(),
35 reffed_by: self.reffed_by.clone(),
36 dep_formula_triggers: self.dep_formula_triggers.clone(),
37 context: self.context.clone(),
38 data: self.data.clone(),
39 evaluated_schema: self.evaluated_schema.clone(),
40 eval_data: self.eval_data.clone(),
41 eval_cache: self.eval_cache.clone(),
42 eval_lock: Mutex::new(()), cached_msgpack_schema: self.cached_msgpack_schema.clone(),
44 resolved_layout_cache: None,
45 conditional_hidden_fields: self.conditional_hidden_fields.clone(),
46 conditional_readonly_fields: self.conditional_readonly_fields.clone(),
47 static_arrays: self.static_arrays.clone(),
48 regex_cache: RwLock::new(HashMap::new()),
49 layout_synced_paths: Vec::new(),
50 }
51 }
52}
53
54impl JSONEval {
55 pub fn new(
56 schema: &str,
57 context: Option<&str>,
58 data: Option<&str>,
59 ) -> Result<Self, serde_json::Error> {
60 time_block!("JSONEval::new() [total]", {
61 let mut schema_val: Value =
63 time_block!(" parse schema JSON", { serde_json::from_str(schema)? });
64 let context: Value = time_block!(" parse context JSON", {
65 json_parser::parse_json_str(context.unwrap_or("{}"))
66 .map_err(serde_json::Error::custom)?
67 });
68 let data: Value = time_block!(" parse data JSON", {
69 json_parser::parse_json_str(data.unwrap_or("{}"))
70 .map_err(serde_json::Error::custom)?
71 });
72
73 let static_arrays = if let Some(params) = schema_val
75 .get_mut("$params")
76 .and_then(|v| v.as_object_mut())
77 {
78 crate::jsoneval::static_arrays::extract_from_params(params)
79 } else {
80 IndexMap::new()
81 };
82 let static_arrays = Arc::new(static_arrays);
83 let evaluated_schema = schema_val.clone();
84
85 let engine_config = RLogicConfig::default();
87 let mut engine = RLogic::with_config(engine_config);
88 engine.set_static_arrays(Arc::clone(&static_arrays));
89
90 let mut instance = time_block!(" create instance struct", {
91 Self {
92 schema: Arc::new(schema_val),
93 evaluations: Arc::new(IndexMap::new()),
94 tables: Arc::new(IndexMap::new()),
95 table_metadata: Arc::new(IndexMap::new()),
96 dependencies: Arc::new(IndexMap::new()),
97 sorted_evaluations: Arc::new(Vec::new()),
98 dependents_evaluations: Arc::new(IndexMap::new()),
99 rules_evaluations: Arc::new(Vec::new()),
100 fields_with_rules: Arc::new(Vec::new()),
101 others_evaluations: Arc::new(Vec::new()),
102 value_evaluations: Arc::new(Vec::new()),
103 layout_paths: Arc::new(Vec::new()),
104 options_templates: Arc::new(Vec::new()),
105 subforms: IndexMap::new(),
106 engine: Arc::new(engine),
107 reffed_by: Arc::new(IndexMap::new()),
108 dep_formula_triggers: Arc::new(IndexMap::new()),
109 context: context.clone(),
110 data: data.clone(),
111 evaluated_schema: evaluated_schema.clone(),
112 eval_data: EvalData::with_schema_data_context(
113 &evaluated_schema,
114 &data,
115 &context,
116 ),
117 eval_cache: crate::jsoneval::eval_cache::EvalCache::new(),
118 eval_lock: Mutex::new(()),
119 cached_msgpack_schema: None,
120 resolved_layout_cache: None,
121 conditional_hidden_fields: Arc::new(Vec::new()),
122 conditional_readonly_fields: Arc::new(Vec::new()),
123 static_arrays,
124 regex_cache: RwLock::new(HashMap::new()),
125 layout_synced_paths: Vec::new(),
126 }
127 });
128 time_block!(" parse_schema", {
129 parse_schema::legacy::parse_schema(&mut instance)
130 .map_err(serde_json::Error::custom)?
131 });
132 Ok(instance)
133 })
134 }
135
136 pub(crate) fn new_subform(
138 schema_val: Value,
139 context: Value,
140 static_arrays: Arc<IndexMap<String, Arc<Value>>>,
141 ) -> Result<Self, serde_json::Error> {
142 time_block!("JSONEval::new_subform() [total]", {
143 let data = Value::Object(serde_json::Map::new());
145 let evaluated_schema = schema_val.clone();
146
147 let engine_config = RLogicConfig::default();
149 let mut engine = RLogic::with_config(engine_config);
150 engine.set_static_arrays(Arc::clone(&static_arrays));
151
152 let mut instance = time_block!(" create instance struct", {
153 Self {
154 schema: Arc::new(schema_val),
155 evaluations: Arc::new(IndexMap::new()),
156 tables: Arc::new(IndexMap::new()),
157 table_metadata: Arc::new(IndexMap::new()),
158 dependencies: Arc::new(IndexMap::new()),
159 sorted_evaluations: Arc::new(Vec::new()),
160 dependents_evaluations: Arc::new(IndexMap::new()),
161 rules_evaluations: Arc::new(Vec::new()),
162 fields_with_rules: Arc::new(Vec::new()),
163 others_evaluations: Arc::new(Vec::new()),
164 value_evaluations: Arc::new(Vec::new()),
165 layout_paths: Arc::new(Vec::new()),
166 options_templates: Arc::new(Vec::new()),
167 subforms: IndexMap::new(),
168 engine: Arc::new(engine),
169 reffed_by: Arc::new(IndexMap::new()),
170 dep_formula_triggers: Arc::new(IndexMap::new()),
171 context: context.clone(),
172 data: data.clone(),
173 evaluated_schema: evaluated_schema.clone(),
174 eval_data: EvalData::with_schema_data_context(
175 &evaluated_schema,
176 &data,
177 &context,
178 ),
179 eval_cache: crate::jsoneval::eval_cache::EvalCache::new(),
180 eval_lock: Mutex::new(()),
181 cached_msgpack_schema: None,
182 resolved_layout_cache: None,
183 conditional_hidden_fields: Arc::new(Vec::new()),
184 conditional_readonly_fields: Arc::new(Vec::new()),
185 static_arrays,
186 regex_cache: RwLock::new(HashMap::new()),
187 layout_synced_paths: Vec::new(),
188 }
189 });
190 time_block!(" parse_schema", {
191 parse_schema::legacy::parse_schema(&mut instance)
192 .map_err(serde_json::Error::custom)?
193 });
194 Ok(instance)
195 })
196 }
197
198 pub fn new_from_msgpack(
210 schema_msgpack: &[u8],
211 context: Option<&str>,
212 data: Option<&str>,
213 ) -> Result<Self, String> {
214 let cached_msgpack = schema_msgpack.to_vec();
216
217 let mut schema_val: Value = rmp_serde::from_slice(schema_msgpack)
219 .map_err(|e| format!("Failed to deserialize MessagePack schema: {}", e))?;
220
221 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))
222 .map_err(|e| format!("Failed to parse context: {}", e))?;
223 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))
224 .map_err(|e| format!("Failed to parse data: {}", e))?;
225
226 let static_arrays = if let Some(params) = schema_val
228 .get_mut("$params")
229 .and_then(|v| v.as_object_mut())
230 {
231 crate::jsoneval::static_arrays::extract_from_params(params)
232 } else {
233 IndexMap::new()
234 };
235 let static_arrays = Arc::new(static_arrays);
236 let evaluated_schema = schema_val.clone();
237
238 let engine_config = RLogicConfig::default();
239 let mut engine = RLogic::with_config(engine_config);
240 engine.set_static_arrays(Arc::clone(&static_arrays));
241
242 let mut instance = Self {
243 schema: Arc::new(schema_val),
244 evaluations: Arc::new(IndexMap::new()),
245 tables: Arc::new(IndexMap::new()),
246 table_metadata: Arc::new(IndexMap::new()),
247 dependencies: Arc::new(IndexMap::new()),
248 sorted_evaluations: Arc::new(Vec::new()),
249 dependents_evaluations: Arc::new(IndexMap::new()),
250 rules_evaluations: Arc::new(Vec::new()),
251 fields_with_rules: Arc::new(Vec::new()),
252 others_evaluations: Arc::new(Vec::new()),
253 value_evaluations: Arc::new(Vec::new()),
254 layout_paths: Arc::new(Vec::new()),
255 options_templates: Arc::new(Vec::new()),
256 subforms: IndexMap::new(),
257 engine: Arc::new(engine),
258 reffed_by: Arc::new(IndexMap::new()),
259 dep_formula_triggers: Arc::new(IndexMap::new()),
260 context: context.clone(),
261 data: data.clone(),
262 evaluated_schema: evaluated_schema.clone(),
263 eval_data: EvalData::with_schema_data_context(&evaluated_schema, &data, &context),
264 eval_cache: crate::jsoneval::eval_cache::EvalCache::new(),
265 eval_lock: Mutex::new(()),
266 cached_msgpack_schema: Some(cached_msgpack),
267 resolved_layout_cache: None,
268 conditional_hidden_fields: Arc::new(Vec::new()),
269 conditional_readonly_fields: Arc::new(Vec::new()),
270 static_arrays,
271 regex_cache: RwLock::new(HashMap::new()),
272 layout_synced_paths: Vec::new(),
273 };
274 parse_schema::legacy::parse_schema(&mut instance)?;
275 Ok(instance)
276 }
277
278 pub fn with_parsed_schema(
306 parsed: Arc<ParsedSchema>,
307 context: Option<&str>,
308 data: Option<&str>,
309 ) -> Result<Self, String> {
310 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))
311 .map_err(|e| format!("Failed to parse context: {}", e))?;
312 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))
313 .map_err(|e| format!("Failed to parse data: {}", e))?;
314
315 let evaluated_schema = parsed.schema.clone();
316
317 let engine = parsed.engine.clone();
320
321 let mut subforms = IndexMap::new();
324 for (path, subform_parsed) in &parsed.subforms {
325 let subform_eval =
327 JSONEval::with_parsed_schema(subform_parsed.clone(), Some("{}"), None)?;
328 subforms.insert(path.clone(), Box::new(subform_eval));
329 }
330
331 let instance = Self {
332 schema: Arc::clone(&parsed.schema),
333 evaluations: Arc::clone(&parsed.evaluations),
334 tables: Arc::clone(&parsed.tables),
335 table_metadata: Arc::clone(&parsed.table_metadata),
336 dependencies: Arc::clone(&parsed.dependencies),
337 sorted_evaluations: Arc::clone(&parsed.sorted_evaluations),
338 dependents_evaluations: Arc::clone(&parsed.dependents_evaluations),
339 rules_evaluations: Arc::clone(&parsed.rules_evaluations),
340 fields_with_rules: Arc::clone(&parsed.fields_with_rules),
341 others_evaluations: Arc::clone(&parsed.others_evaluations),
342 value_evaluations: Arc::clone(&parsed.value_evaluations),
343 layout_paths: Arc::clone(&parsed.layout_paths),
344 options_templates: Arc::clone(&parsed.options_templates),
345 subforms,
346 engine,
347 reffed_by: Arc::clone(&parsed.reffed_by),
348 dep_formula_triggers: Arc::clone(&parsed.dep_formula_triggers),
349 context: context.clone(),
350 data: data.clone(),
351 evaluated_schema: (*evaluated_schema).clone(),
352 eval_data: EvalData::with_schema_data_context(&evaluated_schema, &data, &context),
353 eval_cache: crate::jsoneval::eval_cache::EvalCache::new(),
354 eval_lock: Mutex::new(()),
355 cached_msgpack_schema: None,
356 resolved_layout_cache: None,
357 conditional_hidden_fields: Arc::clone(&parsed.conditional_hidden_fields),
358 conditional_readonly_fields: Arc::clone(&parsed.conditional_readonly_fields),
359 static_arrays: Arc::clone(&parsed.static_arrays),
360 regex_cache: RwLock::new(HashMap::new()),
361 layout_synced_paths: Vec::new(),
362 };
363 Ok(instance)
364 }
365
366 pub fn reload_schema(
367 &mut self,
368 schema: &str,
369 context: Option<&str>,
370 data: Option<&str>,
371 ) -> Result<(), String> {
372 let mut schema_val: Value =
374 serde_json::from_str(schema).map_err(|e| format!("failed to parse schema: {e}"))?;
375 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))?;
376 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))?;
377 self.context = context.clone();
378 self.data = data.clone();
379
380 let static_arrays = if let Some(params) = schema_val
381 .get_mut("$params")
382 .and_then(|v| v.as_object_mut())
383 {
384 crate::jsoneval::static_arrays::extract_from_params(params)
385 } else {
386 IndexMap::new()
387 };
388 let static_arrays = Arc::new(static_arrays);
389 self.static_arrays = Arc::clone(&static_arrays);
390 self.schema = Arc::new(schema_val);
391 self.evaluated_schema = (*self.schema).clone();
392
393 let mut engine = RLogic::new();
394 engine.set_static_arrays(static_arrays);
395 self.engine = Arc::new(engine);
396
397 self.evaluations = Arc::new(IndexMap::new());
398 self.tables = Arc::new(IndexMap::new());
399 self.table_metadata = Arc::new(IndexMap::new());
400 self.dependencies = Arc::new(IndexMap::new());
401 self.sorted_evaluations = Arc::new(Vec::new());
402 self.dependents_evaluations = Arc::new(IndexMap::new());
403 self.rules_evaluations = Arc::new(Vec::new());
404 self.fields_with_rules = Arc::new(Vec::new());
405 self.others_evaluations = Arc::new(Vec::new());
406 self.value_evaluations = Arc::new(Vec::new());
407 self.layout_paths = Arc::new(Vec::new());
408 self.options_templates = Arc::new(Vec::new());
409 self.reffed_by = Arc::new(IndexMap::new());
410 self.dep_formula_triggers = Arc::new(IndexMap::new());
411 self.conditional_hidden_fields = Arc::new(Vec::new());
412 self.conditional_readonly_fields = Arc::new(Vec::new());
413 self.subforms.clear();
414 parse_schema::legacy::parse_schema(self)?;
415
416 self.eval_data =
418 EvalData::with_schema_data_context(&self.evaluated_schema, &data, &context);
419 self.eval_cache.clear();
420 if let Ok(mut cache) = self.regex_cache.write() {
421 cache.clear();
422 }
423
424 self.cached_msgpack_schema = None;
426 self.resolved_layout_cache = None;
427 self.layout_synced_paths.clear();
428
429 Ok(())
430 }
431
432 pub fn set_timezone_offset(&mut self, offset_minutes: Option<i32>) {
454 let mut config = RLogicConfig::default();
456 if let Some(offset) = offset_minutes {
457 config = config.with_timezone_offset(offset);
458 }
459
460 let mut engine = RLogic::with_config(config);
463 engine.set_static_arrays(Arc::clone(&self.static_arrays));
464 self.engine = Arc::new(engine);
465
466 let _ = parse_schema::legacy::parse_schema(self);
467 }
468
469 pub fn reload_schema_msgpack(
481 &mut self,
482 schema_msgpack: &[u8],
483 context: Option<&str>,
484 data: Option<&str>,
485 ) -> Result<(), String> {
486 let mut schema_val: Value = rmp_serde::from_slice(schema_msgpack)
488 .map_err(|e| format!("failed to deserialize MessagePack schema: {e}"))?;
489
490 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))?;
491 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))?;
492
493 self.context = context.clone();
494 self.data = data.clone();
495
496 let static_arrays = if let Some(params) = schema_val
497 .get_mut("$params")
498 .and_then(|v| v.as_object_mut())
499 {
500 crate::jsoneval::static_arrays::extract_from_params(params)
501 } else {
502 IndexMap::new()
503 };
504 let static_arrays = Arc::new(static_arrays);
505 self.static_arrays = Arc::clone(&static_arrays);
506 self.schema = Arc::new(schema_val);
507 self.evaluated_schema = (*self.schema).clone();
508
509 let mut engine = RLogic::new();
510 engine.set_static_arrays(static_arrays);
511 self.engine = Arc::new(engine);
512 self.evaluations = Arc::new(IndexMap::new());
513 self.tables = Arc::new(IndexMap::new());
514 self.table_metadata = Arc::new(IndexMap::new());
515 self.dependencies = Arc::new(IndexMap::new());
516 self.sorted_evaluations = Arc::new(Vec::new());
517 self.dependents_evaluations = Arc::new(IndexMap::new());
518 self.rules_evaluations = Arc::new(Vec::new());
519 self.fields_with_rules = Arc::new(Vec::new());
520 self.others_evaluations = Arc::new(Vec::new());
521 self.value_evaluations = Arc::new(Vec::new());
522 self.layout_paths = Arc::new(Vec::new());
523 self.options_templates = Arc::new(Vec::new());
524 self.reffed_by = Arc::new(IndexMap::new());
525 self.dep_formula_triggers = Arc::new(IndexMap::new());
526 self.conditional_hidden_fields = Arc::new(Vec::new());
527 self.conditional_readonly_fields = Arc::new(Vec::new());
528 self.subforms.clear();
529 parse_schema::legacy::parse_schema(self)?;
530
531 self.eval_data =
533 EvalData::with_schema_data_context(&self.evaluated_schema, &data, &context);
534 self.eval_cache.clear();
535 if let Ok(mut cache) = self.regex_cache.write() {
536 cache.clear();
537 }
538
539 self.cached_msgpack_schema = Some(schema_msgpack.to_vec());
541 self.resolved_layout_cache = None;
542 self.layout_synced_paths.clear();
543
544 Ok(())
545 }
546
547 pub fn reload_schema_parsed(
561 &mut self,
562 parsed: Arc<ParsedSchema>,
563 context: Option<&str>,
564 data: Option<&str>,
565 ) -> Result<(), String> {
566 let context: Value = json_parser::parse_json_str(context.unwrap_or("{}"))?;
567 let data: Value = json_parser::parse_json_str(data.unwrap_or("{}"))?;
568
569 self.schema = Arc::clone(&parsed.schema);
571 self.evaluations = parsed.evaluations.clone();
572 self.tables = parsed.tables.clone();
573 self.table_metadata = parsed.table_metadata.clone();
574 self.dependencies = parsed.dependencies.clone();
575 self.sorted_evaluations = parsed.sorted_evaluations.clone();
576 self.dependents_evaluations = parsed.dependents_evaluations.clone();
577 self.rules_evaluations = parsed.rules_evaluations.clone();
578 self.fields_with_rules = parsed.fields_with_rules.clone();
579 self.others_evaluations = parsed.others_evaluations.clone();
580 self.value_evaluations = parsed.value_evaluations.clone();
581 self.layout_paths = parsed.layout_paths.clone();
582 self.options_templates = parsed.options_templates.clone();
583 self.static_arrays = parsed.static_arrays.clone();
584 self.dep_formula_triggers = parsed.dep_formula_triggers.clone();
585
586 self.engine = parsed.engine.clone();
588
589 let mut subforms = IndexMap::new();
591 for (path, subform_parsed) in &parsed.subforms {
592 let subform_eval =
593 JSONEval::with_parsed_schema(subform_parsed.clone(), Some("{}"), None)?;
594 subforms.insert(path.clone(), Box::new(subform_eval));
595 }
596 self.subforms = subforms;
597
598 self.context = context.clone();
599 self.data = data.clone();
600 self.evaluated_schema = (*self.schema).clone();
601
602 self.eval_data =
604 EvalData::with_schema_data_context(&self.evaluated_schema, &data, &context);
605 self.eval_cache.clear();
606 self.engine.clear_indices();
607 if let Ok(mut cache) = self.regex_cache.write() {
608 cache.clear();
609 }
610
611 self.cached_msgpack_schema = None;
613 self.resolved_layout_cache = None;
614 self.layout_synced_paths.clear();
615
616 Ok(())
617 }
618
619 pub fn reload_schema_from_cache(
633 &mut self,
634 cache_key: &str,
635 context: Option<&str>,
636 data: Option<&str>,
637 ) -> Result<(), String> {
638 let parsed = PARSED_SCHEMA_CACHE
640 .get(cache_key)
641 .ok_or_else(|| format!("Schema '{}' not found in cache", cache_key))?;
642
643 self.reload_schema_parsed(parsed, context, data)
645 }
646}