Skip to main content

edge_core/
registry.rs

1//! In-memory glyph registry populated from `ConfigFull`.
2//!
3//! Consumers look up patterns by name (e.g. "play", "pause", "volume_bar").
4//! `builtin` glyphs carry an empty pattern; the consumer is expected to
5//! render them programmatically (`volume_bar` scales with percentage).
6
7use std::collections::HashMap;
8use std::sync::Arc;
9
10use tokio::sync::RwLock;
11use weave_contracts::Glyph;
12
13#[derive(Default, Clone)]
14pub struct GlyphRegistry {
15    inner: Arc<RwLock<HashMap<String, Glyph>>>,
16}
17
18impl GlyphRegistry {
19    pub fn new() -> Self {
20        Self::default()
21    }
22
23    pub async fn replace_all(&self, glyphs: Vec<Glyph>) {
24        let map: HashMap<String, Glyph> = glyphs.into_iter().map(|g| (g.name.clone(), g)).collect();
25        *self.inner.write().await = map;
26    }
27
28    pub async fn get(&self, name: &str) -> Option<Glyph> {
29        self.inner.read().await.get(name).cloned()
30    }
31
32    pub async fn len(&self) -> usize {
33        self.inner.read().await.len()
34    }
35
36    pub async fn is_empty(&self) -> bool {
37        self.inner.read().await.is_empty()
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44
45    #[tokio::test]
46    async fn replace_all_overwrites() {
47        let r = GlyphRegistry::new();
48        assert!(r.is_empty().await);
49        r.replace_all(vec![Glyph {
50            name: "play".into(),
51            pattern: "*".into(),
52            builtin: false,
53        }])
54        .await;
55        assert_eq!(r.len().await, 1);
56        assert_eq!(r.get("play").await.unwrap().pattern, "*");
57
58        r.replace_all(vec![Glyph {
59            name: "pause".into(),
60            pattern: "**".into(),
61            builtin: false,
62        }])
63        .await;
64        assert_eq!(r.len().await, 1);
65        assert!(r.get("play").await.is_none());
66    }
67}