zen_engine/model/
decision_content.rs1use serde::{Deserialize, Serialize};
2use std::sync::Arc;
3use zen_expression::{ExpressionKind, Isolate, OpcodeCache};
4use zen_types::decision::{DecisionEdge, DecisionNode, DecisionNodeKind};
5
6#[derive(Clone, Debug, PartialEq, Deserialize, Serialize, Default)]
7#[serde(rename_all = "camelCase")]
8pub struct DecisionContent {
9 pub nodes: Vec<Arc<DecisionNode>>,
10 pub edges: Vec<Arc<DecisionEdge>>,
11
12 #[serde(skip)]
13 pub compiled_cache: Option<Arc<OpcodeCache>>,
14}
15
16impl DecisionContent {
17 pub fn compile(&mut self) {
18 let mut sources: Vec<(Arc<str>, ExpressionKind)> = Vec::new();
19
20 for node in &self.nodes {
21 match &node.kind {
22 DecisionNodeKind::ExpressionNode { content } => {
23 for expr in content.expressions.iter() {
24 if !expr.key.is_empty() && !expr.value.is_empty() {
25 sources.push((expr.value.clone(), ExpressionKind::Standard));
26 }
27 }
28 }
29 DecisionNodeKind::DecisionTableNode { content } => {
30 for rule in content.rules.iter() {
31 for input in content.inputs.iter() {
32 let Some(rule_value) = rule.get(&input.id) else {
33 continue;
34 };
35
36 let kind = if input.field.is_some() {
37 ExpressionKind::Unary
38 } else {
39 ExpressionKind::Standard
40 };
41
42 sources.push((rule_value.clone(), kind));
43 }
44
45 for output in content.outputs.iter() {
46 let Some(rule_value) = rule.get(&output.id) else {
47 continue;
48 };
49
50 sources.push((rule_value.clone(), ExpressionKind::Standard));
51 }
52 }
53 }
54 _ => {}
55 }
56 }
57
58 let mut cache: OpcodeCache = OpcodeCache::new();
59 let mut isolate = Isolate::new();
60
61 for (source, kind) in &sources {
62 let map = match kind {
63 ExpressionKind::Standard => &mut cache.standard,
64 ExpressionKind::Unary => &mut cache.unary,
65 };
66 if map.contains_key(source) {
67 continue;
68 }
69
70 let result = match kind {
71 ExpressionKind::Standard => isolate
72 .compile_standard(source)
73 .map(|e| e.bytecode().to_vec()),
74 ExpressionKind::Unary => {
75 isolate.compile_unary(source).map(|e| e.bytecode().to_vec())
76 }
77 };
78 if let Ok(bytecode) = result {
79 map.insert(source.clone(), Arc::from(bytecode));
80 }
81 }
82
83 self.compiled_cache.replace(Arc::new(cache));
84 }
85}