1use serde_json::Value;
2use std::collections::{HashMap, HashSet};
3use crate::manifest::Manifest;
4use crate::common::pool::{StateValueList, STATE_OFFSET_KEY, STATE_MASK_KEY};
5use crate::common::bit;
6use crate::store::Store;
7use crate::load::Load;
8use crate::ports::provided::StateError;
9
10pub struct State<'a> {
11 manifest: Manifest,
12 state_values: StateValueList,
13 store: Store<'a>,
14 load: Load<'a>,
15 max_recursion: usize,
16 called_keys: HashSet<String>,
17}
18
19impl<'a> State<'a> {
20 pub fn new(manifest_dir: &str, load: Load<'a>) -> Self {
31 Self {
32 manifest: Manifest::new(manifest_dir),
33 state_values: StateValueList::new(),
34 store: Store::new(),
35 load,
36 max_recursion: 20,
37 called_keys: HashSet::new(),
38 }
39 }
40
41 pub fn with_in_memory(mut self, client: &'a mut dyn crate::ports::required::InMemoryClient) -> Self {
42 self.store = self.store.with_in_memory(client);
43 self
44 }
45
46 pub fn with_kvs_client(mut self, client: &'a mut dyn crate::ports::required::KVSClient) -> Self {
47 self.store = self.store.with_kvs_client(client);
48 self
49 }
50
51 fn split_key<'k>(key: &'k str) -> (&'k str, &'k str) {
53 match key.find('.') {
54 Some(pos) => (&key[..pos], &key[pos + 1..]),
55 None => (key, ""),
56 }
57 }
58
59 fn resolve_value(&mut self, value_idx: u16) -> Option<Value> {
63 crate::fn_log!("State", "resolve_value", &value_idx.to_string());
64 let vo = self.manifest.values.get(value_idx)?;
65 let is_template = bit::get(vo[0], bit::VO_OFFSET_IS_TEMPLATE, bit::VO_MASK_IS_TEMPLATE) == 1;
66 let is_path = bit::get(vo[0], bit::VO_OFFSET_T0_IS_PATH, bit::VO_MASK_IS_PATH) == 1;
67 let dyn_idx = bit::get(vo[0], bit::VO_OFFSET_T0_DYNAMIC, bit::VO_MASK_DYNAMIC) as u16;
68
69 if is_path && dyn_idx != 0 && !is_template {
70 let path_segments = self.manifest.path_map.get(dyn_idx)?.to_vec();
71 let path_key: String = path_segments.iter()
72 .filter_map(|&seg_idx| self.manifest.dynamic.get(seg_idx).map(|s| s.to_string()))
73 .collect::<Vec<_>>()
74 .join(".");
75 return self.get(&path_key).ok().flatten();
76 }
77
78 self.resolve_value_to_string(value_idx).map(Value::String)
79 }
80
81 fn resolve_value_to_string(&mut self, value_idx: u16) -> Option<String> {
83 crate::fn_log!("State", "resolve_value_to_string", &value_idx.to_string());
84 let vo = self.manifest.values.get(value_idx)?;
85
86 let is_template = bit::get(vo[0], bit::VO_OFFSET_IS_TEMPLATE, bit::VO_MASK_IS_TEMPLATE) == 1;
87
88 const TOKEN_OFFSETS: [(u32, u32); 6] = [
89 (bit::VO_OFFSET_T0_IS_PATH, bit::VO_OFFSET_T0_DYNAMIC),
90 (bit::VO_OFFSET_T1_IS_PATH, bit::VO_OFFSET_T1_DYNAMIC),
91 (bit::VO_OFFSET_T2_IS_PATH, bit::VO_OFFSET_T2_DYNAMIC),
92 (bit::VO_OFFSET_T3_IS_PATH, bit::VO_OFFSET_T3_DYNAMIC),
93 (bit::VO_OFFSET_T4_IS_PATH, bit::VO_OFFSET_T4_DYNAMIC),
94 (bit::VO_OFFSET_T5_IS_PATH, bit::VO_OFFSET_T5_DYNAMIC),
95 ];
96
97 let mut result = String::new();
98
99 for (i, (off_is_path, off_dynamic)) in TOKEN_OFFSETS.iter().enumerate() {
100 let word = if i < 3 { 0 } else { 1 };
101 let is_path = bit::get(vo[word], *off_is_path, bit::VO_MASK_IS_PATH) == 1;
102 let dyn_idx = bit::get(vo[word], *off_dynamic, bit::VO_MASK_DYNAMIC) as u16;
103
104 if dyn_idx == 0 {
105 break;
106 }
107
108 if is_path {
109 let path_segments = self.manifest.path_map.get(dyn_idx)?.to_vec();
110 let path_key: String = path_segments.iter()
111 .filter_map(|&seg_idx| self.manifest.dynamic.get(seg_idx).map(|s| s.to_string()))
112 .collect::<Vec<_>>()
113 .join(".");
114 crate::fn_log!("State", "resolve/get", &path_key);
115 let resolved = self.get(&path_key).ok().flatten();
116 crate::fn_log!("State", "resolve/got", if resolved.is_some() { "Some" } else { "None" });
117 let resolved = resolved?;
118 let s = match &resolved {
119 Value::String(s) => s.clone(),
120 Value::Number(n) => n.to_string(),
121 Value::Bool(b) => b.to_string(),
122 _ => return None,
123 };
124 result.push_str(&s);
125 } else {
126 let s = self.manifest.dynamic.get(dyn_idx)?.to_string();
127 result.push_str(&s);
128 }
129
130 if !is_template {
131 break;
132 }
133 }
134
135 Some(result)
136 }
137
138 fn build_config(&mut self, meta_idx: u16) -> Option<HashMap<String, Value>> {
140 crate::fn_log!("State", "build_config", &meta_idx.to_string());
141 let record = self.manifest.keys.get(meta_idx)?;
142 let child_idx = bit::get(record, bit::OFFSET_CHILD, bit::MASK_CHILD) as u16;
143 if child_idx == 0 { return None; }
144 let has_children = bit::get(record, bit::OFFSET_HAS_CHILDREN, bit::MASK_HAS_CHILDREN);
145 let children = if has_children == 1 {
146 self.manifest.children_map.get(child_idx)?.to_vec()
147 } else {
148 vec![child_idx]
149 };
150
151 let mut config = HashMap::new();
152
153 for &child_idx in &children {
154 let record = match self.manifest.keys.get(child_idx) {
155 Some(r) => r,
156 None => continue,
157 };
158 let prop = bit::get(record, bit::OFFSET_PROP, bit::MASK_PROP) as u8;
159 let client = bit::get(record, bit::OFFSET_CLIENT, bit::MASK_CLIENT) as u8;
160 let is_leaf = bit::get(record, bit::OFFSET_IS_LEAF, bit::MASK_IS_LEAF) == 1;
161 let value_idx = if is_leaf {
162 bit::get(record, bit::OFFSET_CHILD, bit::MASK_CHILD) as u16
163 } else { 0 };
164
165 if client != 0 {
166 config.insert("client".to_string(), Value::Number(client.into()));
167 continue;
168 }
169
170 let prop_name = match prop as u64 {
171 bit::PROP_KEY => "key",
172 bit::PROP_CONNECTION => "connection",
173 bit::PROP_MAP => "map",
174 bit::PROP_TTL => "ttl",
175 bit::PROP_TABLE => "table",
176 bit::PROP_WHERE => "where",
177 _ => continue,
178 };
179
180 if prop_name == "map" {
181 if let Some(map_val) = self.build_map_config(child_idx) {
182 config.insert("map".to_string(), map_val);
183 }
184 } else if prop_name == "connection" {
185 if value_idx != 0 {
186 if let Some(v) = self.resolve_value(value_idx) {
187 config.insert("connection".to_string(), v);
188 }
189 }
190 } else if value_idx != 0 {
191 if let Some(s) = self.resolve_value_to_string(value_idx) {
192 config.insert(prop_name.to_string(), Value::String(s));
193 }
194 }
195 }
196
197 Some(config)
198 }
199
200 fn build_map_config(&self, map_idx: u16) -> Option<Value> {
202 let record = self.manifest.keys.get(map_idx)?;
203 let child_idx = bit::get(record, bit::OFFSET_CHILD, bit::MASK_CHILD) as u16;
204 if child_idx == 0 { return Some(Value::Object(serde_json::Map::new())); }
205
206 let has_children = bit::get(record, bit::OFFSET_HAS_CHILDREN, bit::MASK_HAS_CHILDREN);
207 let children = if has_children == 1 {
208 self.manifest.children_map.get(child_idx)?.to_vec()
209 } else {
210 vec![child_idx]
211 };
212
213 let mut map = serde_json::Map::new();
214 for &c in &children {
215 let child = self.manifest.keys.get(c)?;
216 let dyn_idx = bit::get(child, bit::OFFSET_DYNAMIC, bit::MASK_DYNAMIC) as u16;
217 let value_idx = bit::get(child, bit::OFFSET_CHILD, bit::MASK_CHILD) as u16;
218 let is_path = bit::get(child, bit::OFFSET_IS_PATH, bit::MASK_IS_PATH) == 1;
219
220 let key_str = if is_path {
221 let segs = self.manifest.path_map.get(dyn_idx)?;
222 segs.iter()
223 .filter_map(|&s| self.manifest.dynamic.get(s).map(|x| x.to_string()))
224 .collect::<Vec<_>>()
225 .join(".")
226 } else {
227 self.manifest.dynamic.get(dyn_idx)?.to_string()
228 };
229
230 let val_vo = self.manifest.values.get(value_idx)?;
231 let col_dyn = bit::get(val_vo[0], bit::VO_OFFSET_T0_DYNAMIC, bit::VO_MASK_DYNAMIC) as u16;
232 let col_str = self.manifest.dynamic.get(col_dyn)?.to_string();
233
234 map.insert(key_str, Value::String(col_str));
235 }
236
237 Some(Value::Object(map))
238 }
239
240 fn find_state_value(&self, key_idx: u16) -> Option<u16> {
242 let mut i = 1u16;
243 loop {
244 let record = self.state_values.get_record(i)?;
245 if record == 0 { i += 1; continue; }
246 let k = ((record >> STATE_OFFSET_KEY) & (STATE_MASK_KEY as u32)) as u16;
247 if k == key_idx { return Some(i); }
248 i += 1;
249 }
250 }
251
252 pub fn get(&mut self, key: &str) -> Result<Option<Value>, StateError> {
279 crate::fn_log!("State", "get", key);
280 if self.called_keys.len() >= self.max_recursion {
281 return Err(StateError::RecursionLimitExceeded);
282 }
283 if self.called_keys.contains(&key.to_string()) {
284 return Err(StateError::RecursionLimitExceeded);
285 }
286
287 self.called_keys.insert(key.to_string());
288
289 let (file, path) = Self::split_key(key);
290 let file = file.to_string();
291 let path = path.to_string();
292
293 if let Err(e) = self.manifest.load(&file) {
294 self.called_keys.remove(key);
295 return Err(StateError::ManifestLoadFailed(e.to_string()));
296 }
297
298 let key_idx = match self.manifest.find(&file, &path) {
299 Some(idx) => idx,
300 None => {
301 self.called_keys.remove(key);
302 return Err(StateError::KeyNotFound(key.to_string()));
303 }
304 };
305
306 if let Some(sv_idx) = self.find_state_value(key_idx) {
308 let val = self.state_values.get_value(sv_idx).cloned();
309 self.called_keys.remove(key);
310 return Ok(val);
311 }
312
313 let meta = self.manifest.get_meta(&file, &path);
314
315 let has_state_client = meta.load.and_then(|load_idx| {
317 self.manifest.keys.get(load_idx)
318 .map(|r| bit::get(r, bit::OFFSET_CLIENT, bit::MASK_CLIENT) == bit::CLIENT_STATE)
319 }).unwrap_or(false);
320
321 if !has_state_client {
322 if let Some(store_idx) = meta.store {
323 if let Some(config) = self.build_config(store_idx) {
324 if let Some(value) = self.store.get(&config) {
325 self.state_values.push(key_idx, value.clone());
326 self.called_keys.remove(key);
327 return Ok(Some(value));
328 }
329 }
330 }
331 }
332
333 let result = if let Some(load_idx) = meta.load {
335 if let Some(mut config) = self.build_config(load_idx) {
336 if !config.contains_key("client") {
337 self.called_keys.remove(key);
338 return Ok(None);
339 }
340
341 if let Some(Value::Object(map_obj)) = config.get("map").cloned() {
343 let mut unqualified = serde_json::Map::new();
344 for (qk, v) in map_obj {
345 let field = qk.rfind('.').map_or(qk.as_str(), |p| &qk[p+1..]);
346 unqualified.insert(field.to_string(), v);
347 }
348 config.insert("map".to_string(), Value::Object(unqualified));
349 }
350
351 match self.load.handle(&config) {
352 Ok(loaded) => {
353 if let Some(store_idx) = meta.store {
354 if let Some(store_config) = self.build_config(store_idx) {
355 if self.store.set(&store_config, loaded.clone(), None) {
356 self.state_values.push(key_idx, loaded.clone());
357 }
358 }
359 } else {
360 self.state_values.push(key_idx, loaded.clone());
361 }
362 Ok(Some(loaded))
363 }
364 Err(e) => Err(StateError::LoadFailed(e)),
365 }
366 } else { Ok(None) }
367 } else { Ok(None) };
368
369 self.called_keys.remove(key);
370 result
371 }
372
373 pub fn set(&mut self, key: &str, value: Value, ttl: Option<u64>) -> Result<bool, StateError> {
396 crate::fn_log!("State", "set", key);
397 let (file, path) = Self::split_key(key);
398 let file = file.to_string();
399 let path = path.to_string();
400
401 if let Err(e) = self.manifest.load(&file) {
402 return Err(StateError::ManifestLoadFailed(e.to_string()));
403 }
404
405 let key_idx = match self.manifest.find(&file, &path) {
406 Some(idx) => idx,
407 None => return Err(StateError::KeyNotFound(key.to_string())),
408 };
409
410 let meta = self.manifest.get_meta(&file, &path);
411
412 if let Some(store_idx) = meta.store {
413 if let Some(config) = self.build_config(store_idx) {
414 let ok = self.store.set(&config, value.clone(), ttl);
415 if ok {
416 if let Some(sv_idx) = self.find_state_value(key_idx) {
417 self.state_values.update(sv_idx, value);
418 } else {
419 self.state_values.push(key_idx, value);
420 }
421 }
422 return Ok(ok);
423 }
424 }
425 Ok(false)
426 }
427
428 pub fn delete(&mut self, key: &str) -> Result<bool, StateError> {
454 crate::fn_log!("State", "delete", key);
455 let (file, path) = Self::split_key(key);
456 let file = file.to_string();
457 let path = path.to_string();
458
459 if let Err(e) = self.manifest.load(&file) {
460 return Err(StateError::ManifestLoadFailed(e.to_string()));
461 }
462
463 let key_idx = match self.manifest.find(&file, &path) {
464 Some(idx) => idx,
465 None => return Err(StateError::KeyNotFound(key.to_string())),
466 };
467
468 let meta = self.manifest.get_meta(&file, &path);
469
470 if let Some(store_idx) = meta.store {
471 if let Some(config) = self.build_config(store_idx) {
472 let ok = self.store.delete(&config);
473 if ok {
474 if let Some(sv_idx) = self.find_state_value(key_idx) {
475 self.state_values.remove(sv_idx);
476 }
477 }
478 return Ok(ok);
479 }
480 }
481 Ok(false)
482 }
483
484 pub fn exists(&mut self, key: &str) -> Result<bool, StateError> {
510 crate::fn_log!("State", "exists", key);
511 let (file, path) = Self::split_key(key);
512 let file = file.to_string();
513 let path = path.to_string();
514
515 if let Err(e) = self.manifest.load(&file) {
516 return Err(StateError::ManifestLoadFailed(e.to_string()));
517 }
518
519 let key_idx = match self.manifest.find(&file, &path) {
520 Some(idx) => idx,
521 None => return Err(StateError::KeyNotFound(key.to_string())),
522 };
523
524 if let Some(sv_idx) = self.find_state_value(key_idx) {
525 return Ok(!self.state_values.get_value(sv_idx)
526 .map_or(true, |v| v.is_null()));
527 }
528
529 let meta = self.manifest.get_meta(&file, &path);
530 if let Some(store_idx) = meta.store {
531 if let Some(config) = self.build_config(store_idx) {
532 return Ok(self.store.get(&config).is_some());
533 }
534 }
535 Ok(false)
536 }
537}