node_flow/
storage.rs

1use std::{
2    any::{Any, TypeId},
3    collections::HashMap,
4};
5
6/// Storage that is used in [`Node`](crate::node::Node).
7#[derive(Default)]
8pub struct Storage {
9    inner: HashMap<TypeId, Box<dyn Any + Send>>,
10}
11
12impl Storage {
13    /// Constructs new `Storage`.
14    #[must_use]
15    pub fn new() -> Self {
16        Self::default()
17    }
18
19    /// Gets reference of a value with type T from storage if it is present.
20    // should never panic
21    #[allow(clippy::missing_panics_doc)]
22    #[must_use]
23    pub fn get<T>(&self) -> Option<&T>
24    where
25        T: Any + Send,
26    {
27        self.inner.get(&TypeId::of::<T>()).map(|val| {
28            let any_debug_ref: &(dyn Any + Send) = &**val;
29            any_debug_ref.downcast_ref::<T>().unwrap()
30        })
31    }
32
33    /// Gets mutable reference of a value with type T from storage if it is present.
34    // should never panic
35    #[allow(clippy::missing_panics_doc)]
36    #[must_use]
37    pub fn get_mut<T>(&mut self) -> Option<&mut T>
38    where
39        T: Any + Send,
40    {
41        self.inner.get_mut(&TypeId::of::<T>()).map(|val| {
42            let any_debug_ref: &mut (dyn Any + Send) = &mut **val;
43            any_debug_ref.downcast_mut::<T>().unwrap()
44        })
45    }
46
47    /// Inserts value with type T to storage and returns the value that was there previously if it was there.
48    // should never panic
49    #[allow(clippy::missing_panics_doc)]
50    pub fn insert<T>(&mut self, val: T) -> Option<T>
51    where
52        T: Any + Send,
53    {
54        self.inner
55            .insert(TypeId::of::<T>(), Box::new(val))
56            .map(|val: Box<dyn Any + Send>| *val.downcast::<T>().unwrap())
57    }
58
59    /// Removes and returns value with type T from storage if it is present.
60    // should never panic
61    #[allow(clippy::missing_panics_doc)]
62    pub fn remove<T>(&mut self) -> Option<T>
63    where
64        T: Any + Send,
65    {
66        self.inner
67            .remove(&TypeId::of::<T>())
68            .map(|val: Box<dyn Any + Send>| *val.downcast::<T>().unwrap())
69    }
70}
71
72#[test]
73fn works() {
74    #[derive(Debug)]
75    #[allow(dead_code)]
76    struct MyVal(String);
77
78    let mut s = Storage::new();
79    s.insert(MyVal("test".into()));
80    //println!("{s:#?}");
81    let v = s.get::<MyVal>();
82    assert!(v.is_some());
83    assert_eq!(v.unwrap().0, "test".to_string());
84
85    let v = s.get_mut::<MyVal>();
86    assert!(v.is_some());
87    assert_eq!(v.as_ref().unwrap().0, "test".to_string());
88    *v.unwrap() = MyVal("hmm".into());
89
90    let v = s.insert(MyVal("jop".into()));
91    assert!(v.is_some());
92    assert_eq!(v.unwrap().0, "hmm".to_string());
93
94    let v = s.remove::<MyVal>();
95    assert!(v.is_some());
96    assert_eq!(v.unwrap().0, "jop".to_string());
97}