Skip to main content

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}