poolshark/
pooled.rs

1//! Implementations of Poolable on various standard types
2use super::{Discriminant, IsoPoolable, Poolable, location_id};
3#[cfg(feature = "indexmap")]
4use indexmap::{IndexMap, IndexSet};
5use std::{
6    alloc::Layout,
7    cmp::Eq,
8    collections::{HashMap, HashSet, VecDeque},
9    default::Default,
10    hash::{BuildHasher, Hash},
11};
12
13macro_rules! impl_hashmap {
14    ($ty:ident) => {
15        impl<K, V, R> Poolable for $ty<K, V, R>
16        where
17            K: Hash + Eq,
18            R: Default + BuildHasher,
19        {
20            fn empty() -> Self {
21                $ty::default()
22            }
23
24            fn reset(&mut self) {
25                self.clear()
26            }
27
28            fn capacity(&self) -> usize {
29                $ty::capacity(self)
30            }
31        }
32
33        unsafe impl<K, V, R> IsoPoolable for $ty<K, V, R>
34        where
35            K: Hash + Eq,
36            R: Default + BuildHasher,
37        {
38            const DISCRIMINANT: Option<Discriminant> = {
39                assert!(Layout::new::<R>().size() == 0);
40                Discriminant::new_p2::<K, V>(location_id!())
41            };
42        }
43    };
44}
45
46impl_hashmap!(HashMap);
47#[cfg(feature = "indexmap")]
48impl_hashmap!(IndexMap);
49
50macro_rules! impl_hashset {
51    ($ty:ident) => {
52        impl<K, R> Poolable for $ty<K, R>
53        where
54            K: Hash + Eq,
55            R: Default + BuildHasher,
56        {
57            fn empty() -> Self {
58                $ty::default()
59            }
60
61            fn reset(&mut self) {
62                self.clear()
63            }
64
65            fn capacity(&self) -> usize {
66                $ty::capacity(self)
67            }
68        }
69
70        unsafe impl<K, R> IsoPoolable for $ty<K, R>
71        where
72            K: Hash + Eq,
73            R: Default + BuildHasher,
74        {
75            const DISCRIMINANT: Option<Discriminant> = Discriminant::new_p2::<K, R>(location_id!());
76        }
77    };
78}
79
80impl_hashset!(HashSet);
81#[cfg(feature = "indexmap")]
82impl_hashset!(IndexSet);
83
84impl<T> Poolable for Vec<T> {
85    fn empty() -> Self {
86        Vec::new()
87    }
88
89    fn reset(&mut self) {
90        self.clear()
91    }
92
93    fn capacity(&self) -> usize {
94        Vec::capacity(self)
95    }
96}
97
98unsafe impl<T> IsoPoolable for Vec<T> {
99    const DISCRIMINANT: Option<Discriminant> = Discriminant::new_p1::<T>(location_id!());
100}
101
102impl<T> Poolable for VecDeque<T> {
103    fn empty() -> Self {
104        VecDeque::new()
105    }
106
107    fn reset(&mut self) {
108        self.clear()
109    }
110
111    fn capacity(&self) -> usize {
112        VecDeque::capacity(self)
113    }
114}
115
116unsafe impl<T> IsoPoolable for VecDeque<T> {
117    const DISCRIMINANT: Option<Discriminant> = Discriminant::new_p1::<T>(location_id!());
118}
119
120impl Poolable for String {
121    fn empty() -> Self {
122        String::new()
123    }
124
125    fn reset(&mut self) {
126        self.clear()
127    }
128
129    fn capacity(&self) -> usize {
130        self.capacity()
131    }
132}
133
134unsafe impl IsoPoolable for String {
135    const DISCRIMINANT: Option<Discriminant> = Discriminant::new(location_id!());
136}
137
138impl<T: Poolable> Poolable for Option<T> {
139    fn empty() -> Self {
140        None
141    }
142
143    fn reset(&mut self) {
144        if let Some(inner) = self {
145            inner.reset()
146        }
147    }
148
149    fn capacity(&self) -> usize {
150        self.as_ref().map(|i| i.capacity()).unwrap_or(0)
151    }
152
153    fn really_dropped(&mut self) -> bool {
154        self.as_mut().map(|i| i.really_dropped()).unwrap_or(true)
155    }
156}