1use dyn_clone::DynClone;
25use std::any::{Any, TypeId};
26use std::collections::HashMap;
27use std::fmt::Debug;
28
29trait Data: Any + DynClone {}
31
32dyn_clone::clone_trait_object!(Data);
33
34impl<T: Clone + 'static> Data for T {}
35
36#[derive(Clone)]
38struct Entry(Box<dyn Data>);
39
40impl std::fmt::Debug for Entry {
41 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 f.debug_struct("Entry").finish_non_exhaustive()
43 }
44}
45
46#[derive(Clone, Debug, Default)]
52pub struct DataSet {
53 inner: HashMap<TypeId, Entry>,
54}
55
56impl DataSet {
57 #[must_use]
59 pub fn new() -> Self {
60 Self::default()
61 }
62
63 pub fn insert<T: Clone + 'static>(&mut self, data: Box<T>) -> Option<Box<T>> {
68 self.inner
69 .insert(TypeId::of::<T>(), Entry(data))
70 .map(|old| (old.0 as Box<dyn Any>).downcast().unwrap())
71 }
72
73 #[must_use]
75 pub fn get<T: 'static>(&self) -> Option<&T> {
76 self.inner
77 .get(&TypeId::of::<T>())
78 .map(|entry| (&*entry.0 as &dyn Any).downcast_ref().unwrap())
79 }
80
81 #[must_use]
83 pub fn get_mut<T: 'static>(&mut self) -> Option<&mut T> {
84 self.inner
85 .get_mut(&TypeId::of::<T>())
86 .map(|entry| (&mut *entry.0 as &mut dyn Any).downcast_mut().unwrap())
87 }
88
89 pub fn get_or_insert_with<T, F>(&mut self, f: F) -> &mut T
97 where
98 T: Clone + 'static,
99 F: FnOnce() -> Box<T>,
100 {
101 let entry = self
102 .inner
103 .entry(TypeId::of::<T>())
104 .or_insert_with(|| Entry(f()));
105 (&mut *entry.0 as &mut dyn Any).downcast_mut().unwrap()
106 }
107
108 pub fn remove<T: 'static>(&mut self) -> Option<Box<T>> {
112 self.inner
113 .remove(&TypeId::of::<T>())
114 .map(|entry| (entry.0 as Box<dyn Any>).downcast().unwrap())
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn insert_and_get() {
124 let mut data_set = DataSet::new();
125 let old = data_set.insert(Box::new(42i32));
126 assert_eq!(old, None);
127 assert_eq!(data_set.get::<i32>(), Some(&42));
128 }
129
130 #[test]
131 fn insert_again() {
132 let mut data_set = DataSet::new();
133 data_set.insert(Box::new(42i32));
134 let old = data_set.insert(Box::new(43i32));
135 assert_eq!(old, Some(Box::new(42)));
136 assert_eq!(data_set.get::<i32>(), Some(&43));
137 }
138
139 #[test]
140 fn get_mut() {
141 let mut data_set = DataSet::new();
142 data_set.insert(Box::new(42i32));
143 let data = data_set.get_mut::<i32>().unwrap();
144 assert_eq!(data, &42);
145 *data = 43;
146 assert_eq!(data_set.get::<i32>(), Some(&43));
147 }
148
149 #[test]
150 fn get_or_insert_with() {
151 let mut data_set = DataSet::new();
152 let data = data_set.get_or_insert_with(|| Box::new(0i8));
153 assert_eq!(data, &0);
154 *data = 1;
155 let data = data_set.get_or_insert_with::<i8, _>(|| unreachable!());
156 assert_eq!(data, &1);
157 }
158
159 #[test]
160 fn remove_existing() {
161 let mut data_set = DataSet::new();
162 data_set.insert(Box::new(42i32));
163 let data = data_set.remove::<i32>().unwrap();
164 assert_eq!(*data, 42);
165 }
166
167 #[test]
168 fn remove_nonexisting() {
169 let mut data_set = DataSet::new();
170 let data = data_set.remove::<i32>();
171 assert_eq!(data, None);
172 }
173
174 #[test]
175 fn clone() {
176 let mut data_set = DataSet::new();
177 data_set.insert::<i32>(Box::new(42));
178 let clone = data_set.clone();
179 assert_eq!(clone.get::<i32>(), Some(&42));
180 }
181}