1use 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}