nautilus_core/
collections.rs1use std::{
19 collections::{HashMap, HashSet},
20 fmt::{Debug, Display},
21 hash::Hash,
22};
23
24pub trait SetLike {
26 type Item: Hash + Eq + Display + Clone;
28
29 fn contains(&self, item: &Self::Item) -> bool;
31 fn is_empty(&self) -> bool;
33}
34
35impl<T, S> SetLike for HashSet<T, S>
36where
37 T: Eq + Hash + Display + Clone,
38 S: std::hash::BuildHasher,
39{
40 type Item = T;
41
42 #[inline]
43 fn contains(&self, v: &T) -> bool {
44 Self::contains(self, v)
45 }
46
47 #[inline]
48 fn is_empty(&self) -> bool {
49 Self::is_empty(self)
50 }
51}
52
53impl<T, S> SetLike for indexmap::IndexSet<T, S>
54where
55 T: Eq + Hash + Display + Clone,
56 S: std::hash::BuildHasher,
57{
58 type Item = T;
59
60 #[inline]
61 fn contains(&self, v: &T) -> bool {
62 Self::contains(self, v)
63 }
64
65 #[inline]
66 fn is_empty(&self) -> bool {
67 Self::is_empty(self)
68 }
69}
70
71impl<T, S> SetLike for ahash::AHashSet<T, S>
72where
73 T: Eq + Hash + Display + Clone,
74 S: std::hash::BuildHasher,
75{
76 type Item = T;
77
78 #[inline]
79 fn contains(&self, v: &T) -> bool {
80 self.get(v).is_some()
81 }
82
83 #[inline]
84 fn is_empty(&self) -> bool {
85 self.len() == 0
86 }
87}
88
89pub trait MapLike {
91 type Key: Hash + Eq + Display + Clone;
93 type Value: Debug;
95
96 fn contains_key(&self, key: &Self::Key) -> bool;
98 fn is_empty(&self) -> bool;
100}
101
102impl<K, V, S> MapLike for HashMap<K, V, S>
103where
104 K: Eq + Hash + Display + Clone,
105 V: Debug,
106 S: std::hash::BuildHasher,
107{
108 type Key = K;
109 type Value = V;
110
111 #[inline]
112 fn contains_key(&self, k: &K) -> bool {
113 self.contains_key(k)
114 }
115
116 #[inline]
117 fn is_empty(&self) -> bool {
118 self.is_empty()
119 }
120}
121
122impl<K, V, S> MapLike for indexmap::IndexMap<K, V, S>
123where
124 K: Eq + Hash + Display + Clone,
125 V: Debug,
126 S: std::hash::BuildHasher,
127{
128 type Key = K;
129 type Value = V;
130
131 #[inline]
132 fn contains_key(&self, k: &K) -> bool {
133 self.get(k).is_some()
134 }
135
136 #[inline]
137 fn is_empty(&self) -> bool {
138 self.is_empty()
139 }
140}
141
142impl<K, V, S> MapLike for ahash::AHashMap<K, V, S>
143where
144 K: Eq + Hash + Display + Clone,
145 V: Debug,
146 S: std::hash::BuildHasher,
147{
148 type Key = K;
149 type Value = V;
150
151 #[inline]
152 fn contains_key(&self, k: &K) -> bool {
153 self.get(k).is_some()
154 }
155
156 #[inline]
157 fn is_empty(&self) -> bool {
158 self.len() == 0
159 }
160}
161
162#[cfg(test)]
166#[allow(clippy::unnecessary_to_owned)]
167mod tests {
168 use std::collections::{HashMap, HashSet};
169
170 use ahash::{AHashMap, AHashSet};
171 use indexmap::{IndexMap, IndexSet};
172 use rstest::*;
173
174 use super::*;
175
176 #[rstest]
177 fn test_hashset_setlike() {
178 let mut set: HashSet<String> = HashSet::new();
179 set.insert("test".to_string());
180 set.insert("value".to_string());
181
182 assert!(set.contains(&"test".to_string()));
183 assert!(!set.contains(&"missing".to_string()));
184 assert!(!set.is_empty());
185
186 let empty_set: HashSet<String> = HashSet::new();
187 assert!(empty_set.is_empty());
188 }
189
190 #[rstest]
191 fn test_indexset_setlike() {
192 let mut set: IndexSet<String> = IndexSet::new();
193 set.insert("test".to_string());
194 set.insert("value".to_string());
195
196 assert!(set.contains(&"test".to_string()));
197 assert!(!set.contains(&"missing".to_string()));
198 assert!(!set.is_empty());
199
200 let empty_set: IndexSet<String> = IndexSet::new();
201 assert!(empty_set.is_empty());
202 }
203
204 #[rstest]
205 fn test_ahashset_setlike() {
206 let mut set: AHashSet<String> = AHashSet::new();
207 set.insert("test".to_string());
208 set.insert("value".to_string());
209
210 assert!(set.contains(&"test".to_string()));
211 assert!(!set.contains(&"missing".to_string()));
212 assert!(!set.is_empty());
213
214 let empty_set: AHashSet<String> = AHashSet::new();
215 assert!(empty_set.is_empty());
216 }
217
218 #[rstest]
219 fn test_hashmap_maplike() {
220 let mut map: HashMap<String, i32> = HashMap::new();
221 map.insert("key1".to_string(), 42);
222 map.insert("key2".to_string(), 100);
223
224 assert!(map.contains_key(&"key1".to_string()));
225 assert!(!map.contains_key(&"missing".to_string()));
226 assert!(!map.is_empty());
227
228 let empty_map: HashMap<String, i32> = HashMap::new();
229 assert!(empty_map.is_empty());
230 }
231
232 #[rstest]
233 fn test_indexmap_maplike() {
234 let mut map: IndexMap<String, i32> = IndexMap::new();
235 map.insert("key1".to_string(), 42);
236 map.insert("key2".to_string(), 100);
237
238 assert!(map.contains_key(&"key1".to_string()));
239 assert!(!map.contains_key(&"missing".to_string()));
240 assert!(!map.is_empty());
241
242 let empty_map: IndexMap<String, i32> = IndexMap::new();
243 assert!(empty_map.is_empty());
244 }
245
246 #[rstest]
247 fn test_ahashmap_maplike() {
248 let mut map: AHashMap<String, i32> = AHashMap::new();
249 map.insert("key1".to_string(), 42);
250 map.insert("key2".to_string(), 100);
251
252 assert!(map.contains_key(&"key1".to_string()));
253 assert!(!map.contains_key(&"missing".to_string()));
254 assert!(!map.is_empty());
255
256 let empty_map: AHashMap<String, i32> = AHashMap::new();
257 assert!(empty_map.is_empty());
258 }
259
260 #[rstest]
261 fn test_trait_object_setlike() {
262 let mut hashset: HashSet<String> = HashSet::new();
263 hashset.insert("test".to_string());
264
265 let mut indexset: IndexSet<String> = IndexSet::new();
266 indexset.insert("test".to_string());
267
268 let sets: Vec<&dyn SetLike<Item = String>> = vec![&hashset, &indexset];
269
270 for set in sets {
271 assert!(set.contains(&"test".to_string()));
272 assert!(!set.is_empty());
273 }
274 }
275
276 #[rstest]
277 fn test_trait_object_maplike() {
278 let mut hashmap: HashMap<String, i32> = HashMap::new();
279 hashmap.insert("key".to_string(), 42);
280
281 let mut indexmap: IndexMap<String, i32> = IndexMap::new();
282 indexmap.insert("key".to_string(), 42);
283
284 let maps: Vec<&dyn MapLike<Key = String, Value = i32>> = vec![&hashmap, &indexmap];
285
286 for map in maps {
287 assert!(map.contains_key(&"key".to_string()));
288 assert!(!map.is_empty());
289 }
290 }
291}