/// In-memory storage backend for environments without a filesystem. /// /// Used when the `wasm` feature is enabled (e.g. browser via wasm-bindgen). /// Implements the same logical interface as the sled-backed `storage` module /// so that `EngramDb` can work identically in both environments. /// /// All state lives in a `MemStore` that is held by `EngramDb` under a `RwLock` /// so concurrent reads are fine and writes are serialised. use crate::error::{EngramError, EngramResult}; use crate::types::{Edge, Node}; use std::collections::HashMap; use uuid::Uuid; #[derive(Default)] pub struct MemStore { pub nodes: HashMap, /// from_id → list of edges pub edges_from: HashMap>, /// to_id → list of edges pub edges_to: HashMap>, } impl MemStore { pub fn new() -> Self { Self::default() } // ── Node operations ─────────────────────────────────────────────────────── pub fn write_node(&mut self, node: &Node) -> EngramResult<()> { self.nodes.insert(node.id, node.clone()); Ok(()) } pub fn read_node(&self, id: Uuid) -> EngramResult> { Ok(self.nodes.get(&id).cloned()) } pub fn scan_nodes(&self) -> EngramResult> { Ok(self.nodes.values().cloned().collect()) } pub fn node_count(&self) -> usize { self.nodes.len() } // ── Edge operations ─────────────────────────────────────────────────────── pub fn write_edge(&mut self, edge: &Edge) -> EngramResult<()> { self.edges_from .entry(edge.from_id) .or_default() .push(edge.clone()); self.edges_to .entry(edge.to_id) .or_default() .push(edge.clone()); Ok(()) } pub fn read_edges_from(&self, from_id: Uuid) -> EngramResult> { Ok(self .edges_from .get(&from_id) .cloned() .unwrap_or_default()) } pub fn read_edges_to(&self, to_id: Uuid) -> EngramResult> { Ok(self .edges_to .get(&to_id) .cloned() .unwrap_or_default()) } pub fn edge_count(&self) -> usize { self.edges_from.values().map(|v| v.len()).sum() } // ── Vector operations ───────────────────────────────────────────────────── pub fn scan_vectors(&self) -> EngramResult)>> { Ok(self .nodes .iter() .map(|(id, n)| (*id, n.embedding.clone())) .collect()) } // ── Salience ────────────────────────────────────────────────────────────── pub fn write_salience(&mut self, id: Uuid, salience: f32) -> EngramResult<()> { if let Some(node) = self.nodes.get_mut(&id) { node.salience = salience; } Ok(()) } }