1use 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}