atom_engine/context.rs
1//! Context chain for provide/inject pattern.
2//!
3//! This module implements a hierarchical context system similar to Vue.js
4//! where values can be provided at any level and injected by descendants.
5
6use serde_json::Value;
7use std::collections::HashMap;
8
9/// A chain of context layers supporting provide/inject pattern.
10///
11/// Context values are searched from innermost (most recent) to outermost.
12#[derive(Clone)]
13pub struct ContextChain {
14 layers: Vec<HashMap<String, Value>>,
15}
16
17impl ContextChain {
18 /// Creates a new ContextChain with a single empty layer.
19 pub fn new() -> Self {
20 ContextChain {
21 layers: vec![HashMap::new()],
22 }
23 }
24
25 /// Provides a value to the current (innermost) context layer.
26 pub fn provide(&mut self, key: &str, value: Value) {
27 if let Some(last) = self.layers.last_mut() {
28 last.insert(key.to_string(), value);
29 }
30 }
31
32 /// Injects a value from the context chain.
33 ///
34 /// Searches from innermost to outermost layer and returns the first match.
35 pub fn inject(&self, key: &str) -> Option<&Value> {
36 // Search from innermost to outermost
37 for layer in self.layers.iter().rev() {
38 if let Some(value) = layer.get(key) {
39 return Some(value);
40 }
41 }
42 None
43 }
44
45 /// Pushes a new context layer onto the chain.
46 pub fn push_layer(&mut self) {
47 self.layers.push(HashMap::new());
48 }
49
50 /// Pops the outermost context layer from the chain.
51 ///
52 /// Ensures at least one layer remains.
53 pub fn pop_layer(&mut self) {
54 if self.layers.len() > 1 {
55 self.layers.pop();
56 }
57 }
58
59 /// Returns all context values from all layers merged into a single map.
60 pub fn all(&self) -> HashMap<String, Value> {
61 let mut result = HashMap::new();
62 for layer in &self.layers {
63 for (k, v) in layer {
64 result.insert(k.clone(), v.clone());
65 }
66 }
67 result
68 }
69}
70
71impl Default for ContextChain {
72 fn default() -> Self {
73 Self::new()
74 }
75}