Skip to main content

zen_engine/model/
decision_content.rs

1use 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}