ndn_transport/
any_map.rs

1use std::any::{Any, TypeId};
2use std::collections::HashMap;
3
4/// A type-erased map keyed by `TypeId`.
5///
6/// Each concrete type can appear at most once (like a typed slot).
7/// Used by `PacketContext::tags` for inter-stage communication and by
8/// `StrategyContext::extensions` for cross-layer enrichment data.
9pub struct AnyMap(HashMap<TypeId, Box<dyn Any + Send + Sync>>);
10
11impl AnyMap {
12    /// Create an empty map.
13    pub fn new() -> Self {
14        Self(HashMap::new())
15    }
16
17    /// Insert a value, replacing any previous value of the same type.
18    pub fn insert<T: Any + Send + Sync>(&mut self, val: T) {
19        self.0.insert(TypeId::of::<T>(), Box::new(val));
20    }
21
22    /// Retrieve a reference to a value by type, if present.
23    pub fn get<T: Any + Send + Sync>(&self) -> Option<&T> {
24        self.0.get(&TypeId::of::<T>())?.downcast_ref()
25    }
26
27    /// Remove and return a value by type, if present.
28    pub fn remove<T: Any + Send + Sync>(&mut self) -> Option<T> {
29        self.0
30            .remove(&TypeId::of::<T>())
31            .and_then(|b| b.downcast().ok())
32            .map(|b| *b)
33    }
34}
35
36impl Default for AnyMap {
37    fn default() -> Self {
38        Self::new()
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45
46    #[test]
47    fn insert_get_roundtrip() {
48        let mut m = AnyMap::new();
49        m.insert(42u32);
50        assert_eq!(m.get::<u32>(), Some(&42u32));
51        assert!(m.get::<u64>().is_none());
52    }
53
54    #[test]
55    fn insert_overwrite() {
56        let mut m = AnyMap::new();
57        m.insert(1u32);
58        m.insert(2u32);
59        assert_eq!(m.get::<u32>(), Some(&2u32));
60    }
61
62    #[test]
63    fn remove_takes_value() {
64        let mut m = AnyMap::new();
65        m.insert(99u32);
66        let v = m.remove::<u32>();
67        assert_eq!(v, Some(99u32));
68        assert!(m.get::<u32>().is_none());
69    }
70
71    #[test]
72    fn different_types_coexist() {
73        let mut m = AnyMap::new();
74        m.insert(1u32);
75        m.insert("hello");
76        assert_eq!(m.get::<u32>(), Some(&1u32));
77        assert_eq!(m.get::<&str>(), Some(&"hello"));
78    }
79
80    #[test]
81    fn default_is_empty() {
82        let m = AnyMap::default();
83        assert!(m.get::<u32>().is_none());
84    }
85}