1use std::{
2 any::{Any, TypeId},
3 collections::{hash_map::RandomState, HashMap},
4};
5
6pub struct TypePools<H = RandomState> {
8 pools: HashMap<TypeId, Box<dyn TypePoolTrait>, H>,
9}
10
11impl TypePools {
12 pub fn new() -> Self {
13 TypePools { pools: HashMap::new() }
14 }
15
16 pub fn type_pool<T: 'static>(&self) -> Option<&TypePool<T>> {
18 self.pools.get(&TypeId::of::<T>())
19 .map(|pool| {
20 unsafe { TypePool::<T>::cast_unchecked(pool.as_ref()) } })
22 }
23
24 pub fn type_pool_mut<T: 'static>(&mut self) -> Option<&mut TypePool<T>> {
26 self.pools.get_mut(&TypeId::of::<T>())
27 .map(|pool| {
28 unsafe { TypePool::<T>::cast_mut_unchecked(pool.as_mut()) } })
30 }
31
32 pub fn push<T: 'static>(&mut self, value: T) {
34 let pools = self.pools.get_mut(&TypeId::of::<T>());
35 if let Some(pools) = pools {
36 unsafe { TypePool::<T>::cast_mut_unchecked(pools.as_mut()) }
37 .values.push(value);
38 } else {
39 self.pools.insert(TypeId::of::<T>(), Box::new(TypePool::<T>::new()));
40 unsafe { TypePool::<T>::cast_mut_unchecked(self.pools.get_mut(&TypeId::of::<T>()).unwrap_unchecked().as_mut()) } .values.push(value)
42 }
43 }
44
45 pub fn pop<T: 'static>(&mut self) -> Option<T> {
47 self.type_pool_mut()
48 .and_then(|p| p.values.pop())
49 }
50
51 pub fn remove<T: 'static>(&mut self, idx: usize) -> Option<T> {
53 self.type_pool_mut()
54 .and_then(|p| p.values.remove(idx))
55 }
56
57 pub fn get<T: 'static>(&self, idx: usize) -> Option<&T> {
62 self.type_pool()
63 .and_then(|p| p.values.get(idx))
64 }
65
66 pub fn get_mut<T: 'static>(&mut self, idx: usize) -> Option<&mut T> {
68 self.type_pool_mut()
69 .and_then(|p| p.values.get_mut(idx))
70 }
71
72 pub fn len<T: 'static>(&self) -> Option<usize> {
73 self.type_pool()
74 .map(|f: &TypePool<T>| f.values.len())
75 }
76
77 pub fn types_count(&self) -> usize {
79 self.pools.keys().len()
80 }
81
82 pub fn types(&self) -> Vec<&TypeId> {
84 self.pools.keys().collect()
85 }
86
87 pub fn remove_type<T: 'static>(&mut self) {
89 self.pools.remove(&TypeId::of::<T>());
90 }
91
92 pub fn remove_empty(&mut self) {
94 let to_remove = self.pools.keys()
95 .filter(|key| unsafe{ self.pools.get(key).unwrap_unchecked() }.is_empty())
97 .map(|key| *key)
98 .collect::<Vec<TypeId>>();
99
100 for id in to_remove {
101 self.pools.remove(&id);
102 }
103 }
104
105 pub fn shrink_to_fit(&mut self) {
107 self.pools.shrink_to_fit()
108 }
109
110
111
112 }
140
141trait TypePoolTrait {
142 fn as_any(&self) -> &dyn Any;
143 fn as_any_mut(&mut self) -> &mut dyn Any;
144 fn is_empty(&self) -> bool;
145}
146
147pub struct TypePool<T> {
148 pub values: Vec<T>,
149}
150
151impl<T: 'static> TypePool<T> {
152 fn new() -> Self {
153 Self { values: Vec::new() }
154 }
155
156 unsafe fn cast_unchecked(pool: &dyn TypePoolTrait) -> &Self {
169 pool.as_any()
170 .downcast_ref::<TypePool<T>>()
171 .unwrap_unchecked()
172 }
173
174 unsafe fn cast_mut_unchecked(pool: &mut dyn TypePoolTrait) -> &mut Self {
175 pool.as_any_mut()
176 .downcast_mut::<TypePool<T>>()
177 .unwrap_unchecked()
178 }
179}
180
181impl<T: 'static> TypePoolTrait for TypePool<T> {
182 fn as_any(&self) -> &dyn Any {
183 self
184 }
185
186 fn as_any_mut(&mut self) -> &mut dyn Any {
187 self
188 }
189
190 fn is_empty(&self) -> bool {
191 self.values.is_empty()
192 }
193}
194
195#[cfg(test)]
196mod tests {
197 use crate::TypePools;
198
199 #[test]
200 fn test_add() {
201 let mut pools = TypePools::new();
202 pools.push(1 as u32);
203 pools.push(2 as u32);
204 pools.push("Hello");
205 pools.push("World");
206
207 assert_eq!(*pools.get::<u32>(0).unwrap(), 1);
208 assert_eq!(*pools.get::<u32>(1).unwrap(), 2);
209 assert_eq!(*pools.get::<&str>(0).unwrap(), "Hello");
210 assert_eq!(*pools.get::<&str>(1).unwrap(), "World");
211 }
212}
213