pflow_tokenmodel/
snapshot.rs1use std::collections::HashMap;
4
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8use crate::schema::Schema;
9
10#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct Snapshot {
13 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
14 pub tokens: HashMap<String, i64>,
15
16 #[serde(default, skip_serializing_if = "HashMap::is_empty")]
17 pub data: HashMap<String, Value>,
18}
19
20impl Snapshot {
21 pub fn new() -> Self {
22 Self {
23 tokens: HashMap::new(),
24 data: HashMap::new(),
25 }
26 }
27
28 pub fn from_schema(s: &Schema) -> Self {
30 let mut snap = Self::new();
31 for st in &s.states {
32 if st.is_token() {
33 snap.tokens.insert(st.id.clone(), st.initial_tokens());
34 } else if let Some(initial) = &st.initial {
35 snap.data.insert(st.id.clone(), initial.clone());
36 } else {
37 snap.data
38 .insert(st.id.clone(), Value::Object(Default::default()));
39 }
40 }
41 snap
42 }
43
44 pub fn get_tokens(&self, state_id: &str) -> i64 {
45 self.tokens.get(state_id).copied().unwrap_or(0)
46 }
47
48 pub fn set_tokens(&mut self, state_id: &str, count: i64) {
49 self.tokens.insert(state_id.to_string(), count);
50 }
51
52 pub fn add_tokens(&mut self, state_id: &str, delta: i64) {
53 let entry = self.tokens.entry(state_id.to_string()).or_insert(0);
54 *entry += delta;
55 }
56
57 pub fn get_data(&self, state_id: &str) -> Option<&Value> {
58 self.data.get(state_id)
59 }
60
61 pub fn set_data(&mut self, state_id: &str, value: Value) {
62 self.data.insert(state_id.to_string(), value);
63 }
64
65 pub fn get_data_map(&self, state_id: &str) -> Option<&serde_json::Map<String, Value>> {
67 self.data.get(state_id).and_then(|v| v.as_object())
68 }
69
70 pub fn get_data_map_value(&self, state_id: &str, key: &str) -> Option<&Value> {
72 self.get_data_map(state_id).and_then(|m| m.get(key))
73 }
74
75 pub fn set_data_map_value(&mut self, state_id: &str, key: &str, value: Value) {
77 let entry = self
78 .data
79 .entry(state_id.to_string())
80 .or_insert_with(|| Value::Object(Default::default()));
81 if let Value::Object(map) = entry {
82 map.insert(key.to_string(), value);
83 }
84 }
85}
86
87impl Default for Snapshot {
88 fn default() -> Self {
89 Self::new()
90 }
91}
92
93pub type Bindings = HashMap<String, Value>;
95
96pub trait BindingsExt {
98 fn get_string(&self, key: &str) -> String;
99 fn get_i64(&self, key: &str) -> i64;
100}
101
102impl BindingsExt for Bindings {
103 fn get_string(&self, key: &str) -> String {
104 self.get(key)
105 .and_then(|v| v.as_str())
106 .unwrap_or("")
107 .to_string()
108 }
109
110 fn get_i64(&self, key: &str) -> i64 {
111 self.get(key)
112 .and_then(|v| {
113 v.as_i64()
114 .or_else(|| v.as_f64().map(|f| f as i64))
115 .or_else(|| v.as_str().and_then(|s| s.parse::<i64>().ok()))
116 })
117 .unwrap_or(0)
118 }
119}