metamap/
lib.rs

1#![doc = include_str!("../readme.md")]
2use std::{
3    any::{Any, TypeId},
4    collections::{HashMap, HashSet},
5    fmt::Debug,
6    ops::{Deref, DerefMut},
7    sync::Arc,
8};
9
10#[derive(Debug, Clone)]
11pub struct RefMeta(pub Arc<Metamap>);
12
13impl RefMeta {
14    pub fn new(meta: Metamap) -> Self {
15        RefMeta(Arc::new(meta))
16    }
17}
18
19impl Deref for RefMeta {
20    type Target = Metamap;
21
22    fn deref(&self) -> &Self::Target {
23        &self.0
24    }
25}
26
27impl DerefMut for RefMeta {
28    fn deref_mut(&mut self) -> &mut Self::Target {
29        Arc::get_mut(&mut self.0).expect("Cannot mutate a shared reference")
30    }
31}
32
33/// Represents a Metamap object.
34///
35/// This struct contains a map that associates keys of type `String` with values of type `Box<dyn Any + Send + Sync>`.
36/// It also has an optional field `extend` that holds a boxed `Metamap` object.
37#[derive(Default)]
38pub struct Metamap {
39    map: HashMap<String, Box<dyn Any + Send + Sync>>,
40    extend: Option<RefMeta>,
41}
42
43impl Debug for Metamap {
44    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45        let mut keys = self.map.keys().collect::<HashSet<&String>>();
46        if let Some(p) = &self.extend {
47            let keys2 = p.0.map.keys().collect::<HashSet<&String>>();
48            keys.extend(keys2);
49        }
50        f.debug_struct("Metamap").field("keys", &keys.iter()).finish()
51    }
52}
53
54impl Metamap {
55    pub fn new() -> Self {
56        Metamap { map: HashMap::new(), extend: None }
57    }
58
59    pub fn inner(&self) -> &HashMap<String, Box<dyn Any + Send + Sync>> {
60        &self.map
61    }
62
63    #[inline]
64    pub fn with_capacity(capacity: usize) -> Self {
65        Metamap { map: HashMap::with_capacity(capacity), extend: None }
66    }
67
68    pub fn capacity(&self) -> usize {
69        self.map.capacity()
70    }
71
72    pub fn set<V: Any + Send + Sync>(&mut self, key: impl Into<String>, value: V) -> &mut Self {
73        self.map.insert(key.into(), Box::new(value));
74        self
75    }
76
77    pub fn get<V: Any + Send + Sync>(&self, key: impl Into<String>) -> Option<&V> {
78        let key: String = key.into();
79        let t = self.map.get(&key).and_then(|v| v.downcast_ref::<V>());
80        let r = match t {
81            Some(v) => Some(v),
82            None => match &self.extend {
83                Some(p) => p.get::<V>(key),
84                None => None,
85            },
86        };
87        r
88    }
89
90    pub fn get_mut<V: Any + Send + Sync>(&mut self, key: impl Into<String>) -> Option<&mut V> {
91        let key = key.into();
92        let t = self.map.get_mut(&key).and_then(|v| v.downcast_mut::<V>());
93        match t {
94            Some(v) => Some(v),
95            None => None,
96        }
97    }
98
99    pub fn set_data<V: Any + Send + Sync>(&mut self, value: V) -> &mut Self {
100        self.set(type_key::<V>(), value)
101    }
102
103    pub fn get_data<V: Any + Send + Sync>(&self) -> Option<&V> {
104        self.get(type_key::<V>())
105    }
106
107    pub fn get_mut_data<V: Any + Send + Sync>(&mut self) -> Option<&mut V> {
108        self.get_mut(type_key::<V>())
109    }
110
111    pub fn take<V: Any + Send + Sync>(&mut self, key: impl Into<String>) -> Option<V> {
112        let key: String = key.into();
113        let t = self.map.remove(&key).and_then(|v| v.downcast::<V>().ok());
114        t.map(|v| *v)
115    }
116
117    pub fn take_data<V: Any + Send + Sync>(&mut self) -> Option<V> {
118        self.take(type_key::<V>())
119    }
120
121    pub fn contains(&self, key: impl Into<String>) -> bool {
122        self.map.contains_key(&key.into())
123    }
124
125    pub fn contains_value<V: Any + Send + Sync>(&self) -> bool {
126        self.contains(type_key::<V>())
127    }
128
129    pub fn remove(&mut self, key: impl Into<String>) -> Option<Box<dyn Any + Send + Sync>> {
130        let key: String = key.into();
131        let t = self.map.remove(&key);
132        match t {
133            Some(v) => Some(v),
134            None => None,
135        }
136    }
137
138    pub fn remove_value<V: Any + Send + Sync>(&mut self) -> Option<Box<dyn Any + Send + Sync>> {
139        self.remove(type_key::<V>())
140    }
141
142    pub fn merge(&mut self, meta: Metamap) -> &mut Self {
143        for (k, v) in meta.map {
144            self.map.insert(k, v);
145        }
146        self
147    }
148
149    pub fn extend(&mut self, ref_meta: RefMeta) -> &mut Self {
150        self.extend = Some(ref_meta);
151        self
152    }
153
154    pub fn iter(&self) -> std::collections::hash_map::Iter<String, Box<dyn Any + Send + Sync>> {
155        self.map.iter()
156    }
157
158    pub fn iter_mut(&mut self) -> std::collections::hash_map::IterMut<String, Box<dyn Any + Send + Sync>> {
159        self.map.iter_mut()
160    }
161
162    pub fn keys(&self) -> Vec<String> {
163        let mut keys = self.map.keys().collect::<HashSet<&String>>();
164        if let Some(p) = &self.extend {
165            let keys2 = p.map.keys().collect::<HashSet<&String>>();
166            keys.extend(keys2);
167        }
168        keys.iter().map(|k| k.to_string()).collect()
169    }
170
171    pub fn len(&self) -> usize {
172        self.map.len()
173    }
174
175    pub fn is_empty(&self) -> bool {
176        self.map.is_empty()
177    }
178
179    pub fn clear(&mut self) {
180        self.map.clear();
181    }
182}
183
184pub fn type_key<T: 'static>() -> String {
185    format!("{:?}", TypeId::of::<T>())
186}
187
188#[cfg(test)]
189mod tests {
190    use super::*;
191
192    #[test]
193    fn test_metadata() {
194        #[derive(Debug, PartialEq, Eq)]
195        enum TestEnum {
196            A,
197            B,
198        }
199
200        #[derive(Debug, PartialEq, Eq)]
201        struct TestData {
202            pub name: String,
203        }
204
205        #[derive(Debug, PartialEq, Eq)]
206        struct TupleData(i32, String);
207
208        let mut meta = Metamap::new();
209        meta.set_data(TestEnum::A);
210        meta.set_data(TestData { name: "test".to_string() });
211        meta.set_data(TupleData(1, "tuple".to_string()));
212
213        assert_eq!(*meta.get_data::<TestEnum>().unwrap(), TestEnum::A);
214        assert_ne!(*meta.get_data::<TestEnum>().unwrap(), TestEnum::B);
215        assert_eq!(*meta.get_data::<TestData>().unwrap(), TestData { name: "test".to_string() });
216        assert_eq!(*meta.get_data::<TupleData>().unwrap(), TupleData(1, "tuple".to_string()));
217
218        assert_eq!(meta.take_data::<TestData>().unwrap(), TestData { name: "test".to_string() });
219        assert_eq!(meta.take_data::<TestEnum>().unwrap(), TestEnum::A);
220        assert_eq!(meta.take_data::<TupleData>().unwrap(), TupleData(1, "tuple".to_string()));
221
222        assert!(meta.get_data::<TestData>().is_none());
223        assert!(meta.get_data::<TestEnum>().is_none());
224        assert!(meta.get_data::<TupleData>().is_none());
225    }
226
227    #[test]
228    fn test_meta() {
229        let mut meta = Metamap::new();
230        meta.set("a", 1);
231        meta.set("b", "2");
232        meta.set("c", 3.0);
233        meta.set("d", "4".to_string());
234        meta.set("e", vec![1, 2, 3]);
235        meta.set("f", vec!["1", "2", "3"]);
236        meta.set("g", vec![1.0, 2.0, 3.0]);
237        meta.set("h", vec!["1".to_string(), "2".to_string(), "3".to_string()]);
238        meta.set("i", vec![vec![1, 2], vec![3, 4]]);
239        meta.set("j", vec![vec!["1", "2"], vec!["3", "4"]]);
240        meta.set("k", vec![vec![1.0, 2.0], vec![3.0, 4.0]]);
241        meta.set("l", vec![vec!["1".to_string(), "2".to_string()], vec!["3".to_string(), "4".to_string()]]);
242
243        assert_eq!(*meta.get::<i32>("a").unwrap(), 1);
244        assert_eq!(*meta.get::<&str>("b").unwrap(), "2");
245        assert_eq!(*meta.get::<f64>("c").unwrap(), 3.0);
246        assert_eq!(*meta.get::<String>("d").unwrap(), "4".to_string());
247        assert_eq!(*meta.get::<Vec<i32>>("e").unwrap(), vec![1, 2, 3]);
248        assert_eq!(*meta.get::<Vec<&str>>("f").unwrap(), vec!["1", "2", "3"]);
249        assert_eq!(*meta.get::<Vec<f64>>("g").unwrap(), vec![1.0, 2.0, 3.0]);
250        assert_eq!(*meta.get::<Vec<String>>("h").unwrap(), vec!["1".to_string(), "2".to_string(), "3".to_string()]);
251        assert_eq!(*meta.get::<Vec<Vec<i32>>>("i").unwrap(), vec![vec![1, 2], vec![3, 4]]);
252        assert_eq!(*meta.get::<Vec<Vec<&str>>>("j").unwrap(), vec![vec!["1", "2"], vec!["3", "4"]]);
253    }
254
255    #[test]
256    fn test_mut_meta() {
257        let mut meta = Metamap::new();
258        meta.set("a", 1);
259        meta.set("b", "2");
260        meta.set("c", 3.0);
261        meta.set("d", "4".to_string());
262        meta.set("e", vec![1, 2, 3]);
263        meta.set("f", vec!["1", "2", "3"]);
264        meta.set("g", vec![1.0, 2.0, 3.0]);
265        meta.set("h", vec!["1".to_string(), "2".to_string(), "3".to_string()]);
266        meta.set("i", vec![vec![1, 2], vec![3, 4]]);
267        meta.set("j", vec![vec!["1", "2"], vec!["3", "4"]]);
268        meta.set("k", vec![vec![1.0, 2.0], vec![3.0, 4.0]]);
269        meta.set("l", vec![vec!["1".to_string(), "2".to_string()], vec!["3".to_string(), "4".to_string()]]);
270
271        *meta.get_mut::<i32>("a").unwrap() = 2;
272        *meta.get_mut::<&str>("b").unwrap() = "3";
273        *meta.get_mut::<f64>("c").unwrap() = 4.0;
274        *meta.get_mut::<String>("d").unwrap() = "5".to_string();
275        *meta.get_mut::<Vec<i32>>("e").unwrap() = vec![2, 3, 4];
276        *meta.get_mut::<Vec<&str>>("f").unwrap() = vec!["2", "3", "4"];
277        *meta.get_mut::<Vec<f64>>("g").unwrap() = vec![2.0, 3.0, 4.0];
278        *meta.get_mut::<Vec<String>>("h").unwrap() = vec!["2".to_string(), "3".to_string(), "4".to_string()];
279        *meta.get_mut::<Vec<Vec<i32>>>("i").unwrap() = vec![vec![2, 3], vec![4, 5]];
280        *meta.get_mut::<Vec<Vec<&str>>>("j").unwrap() = vec![vec!["2", "3"], vec!["4", "5"]];
281
282        assert_eq!(*meta.get::<i32>("a").unwrap(), 2);
283        assert_eq!(*meta.get::<&str>("b").unwrap(), "3");
284        assert_eq!(*meta.get::<f64>("c").unwrap(), 4.0);
285        assert_eq!(*meta.get::<String>("d").unwrap(), "5".to_string());
286        assert_eq!(*meta.get::<Vec<i32>>("e").unwrap(), vec![2, 3, 4]);
287        assert_eq!(*meta.get::<Vec<&str>>("f").unwrap(), vec!["2", "3", "4"]);
288        assert_eq!(*meta.get::<Vec<f64>>("g").unwrap(), vec![2.0, 3.0, 4.0]);
289        assert_eq!(*meta.get::<Vec<String>>("h").unwrap(), vec!["2".to_string(), "3".to_string(), "4".to_string()]);
290        assert_eq!(*meta.get::<Vec<Vec<i32>>>("i").unwrap(), vec![vec![2, 3], vec![4, 5]]);
291        assert_eq!(*meta.get::<Vec<Vec<&str>>>("j").unwrap(), vec![vec!["2", "3"], vec!["4", "5"]]);
292    }
293
294    #[test]
295    fn test_meta_merge() {
296        let mut meta1 = Metamap::new();
297        meta1.set("a", 1);
298        meta1.set("b", "2");
299        meta1.set("c", 3.0);
300        meta1.set("d", "4".to_string());
301        meta1.set("e", vec![1, 2, 3]);
302        meta1.set("f", vec!["1", "2", "3"]);
303        meta1.set("g", vec![1.0, 2.0, 3.0]);
304        meta1.set("h", vec!["1".to_string(), "2".to_string(), "3".to_string()]);
305        meta1.set("i", vec![vec![1, 2], vec![3, 4]]);
306        meta1.set("j", vec![vec!["1", "2"], vec!["3", "4"]]);
307        meta1.set("k", vec![vec![1.0, 2.0], vec![3.0, 4.0]]);
308        meta1.set("l", vec![vec!["1".to_string(), "2".to_string()], vec!["3".to_string(), "4".to_string()]]);
309
310        let mut meta2 = Metamap::new();
311        meta2.set("e", vec![2, 3, 4]);
312        meta2.set("f", vec!["2", "3", "4"]);
313        meta2.set("g", vec![2.0, 3.0, 4.0]);
314        meta2.set("h", vec!["2".to_string(), "3".to_string(), "4".to_string()]);
315        meta2.set("i", vec![vec![2, 3], vec![4, 5]]);
316        meta2.set("j", vec![vec!["2", "3"], vec!["4", "5"]]);
317
318        meta1.merge(meta2);
319
320        assert_eq!(*meta1.get::<i32>("a").unwrap(), 1);
321        assert_eq!(*meta1.get::<&str>("b").unwrap(), "2");
322        assert_eq!(*meta1.get::<f64>("c").unwrap(), 3.0);
323        assert_eq!(*meta1.get::<String>("d").unwrap(), "4".to_string());
324        assert_eq!(*meta1.get::<Vec<i32>>("e").unwrap(), vec![2, 3, 4]);
325        assert_eq!(*meta1.get::<Vec<&str>>("f").unwrap(), vec!["2", "3", "4"]);
326        assert_eq!(*meta1.get::<Vec<f64>>("g").unwrap(), vec![2.0, 3.0, 4.0]);
327        assert_eq!(*meta1.get::<Vec<String>>("h").unwrap(), vec!["2".to_string(), "3".to_string(), "4".to_string()]);
328        assert_eq!(*meta1.get::<Vec<Vec<i32>>>("i").unwrap(), vec![vec![2, 3], vec![4, 5]]);
329        assert_eq!(*meta1.get::<Vec<Vec<&str>>>("j").unwrap(), vec![vec!["2", "3"], vec!["4", "5"]]);
330    }
331
332    #[test]
333    fn test_meta_extend() {
334        let mut meta1 = Metamap::new();
335        meta1.set("a", 1);
336        meta1.set("b", "2");
337        meta1.set("c", 3.0);
338        meta1.set("d", "4".to_string());
339        meta1.set("e", vec![1, 2, 3]);
340        meta1.set("f", vec!["1", "2", "3"]);
341        meta1.set("g", vec![1.0, 2.0, 3.0]);
342
343        let mut meta2 = Metamap::new();
344        meta2.set("e", vec![2, 3, 4]);
345        meta2.set("i", vec![vec![2, 3], vec![4, 5]]);
346        meta2.set("j", vec![vec!["2", "3"], vec!["4", "5"]]);
347
348        meta1.extend(RefMeta::new(meta2));
349
350        assert_eq!(*meta1.get::<i32>("a").unwrap(), 1);
351        assert_eq!(*meta1.get::<&str>("b").unwrap(), "2");
352        assert_eq!(*meta1.get::<f64>("c").unwrap(), 3.0);
353        assert_eq!(*meta1.get::<String>("d").unwrap(), "4".to_string());
354        assert_eq!(*meta1.get::<Vec<i32>>("e").unwrap(), vec![1, 2, 3]);
355        assert_eq!(*meta1.get::<Vec<&str>>("f").unwrap(), vec!["1", "2", "3"]);
356        assert_eq!(*meta1.get::<Vec<f64>>("g").unwrap(), vec![1.0, 2.0, 3.0]);
357        assert_eq!(*meta1.get::<Vec<Vec<i32>>>("i").unwrap(), vec![vec![2, 3], vec![4, 5]]);
358        assert_eq!(*meta1.get::<Vec<Vec<&str>>>("j").unwrap(), vec![vec!["2", "3"], vec!["4", "5"]]);
359    }
360}