/rust/registry/src/index.crates.io-1949cf8c6b5b557f/flurry-0.5.2/src/set.rs
Line | Count | Source |
1 | | //! A concurrent hash set. |
2 | | //! |
3 | | //! See `HashSet` for details. |
4 | | |
5 | | use crate::iter::Keys; |
6 | | use crate::reclaim::Guard; |
7 | | use crate::HashMap; |
8 | | use std::borrow::Borrow; |
9 | | use std::fmt::{self, Debug, Formatter}; |
10 | | use std::hash::{BuildHasher, Hash}; |
11 | | |
12 | | /// A concurrent hash set implemented as a `HashMap` where the value is `()`. |
13 | | /// |
14 | | /// # Examples |
15 | | /// |
16 | | /// ``` |
17 | | /// use flurry::HashSet; |
18 | | /// |
19 | | /// // Initialize a new hash set. |
20 | | /// let books = HashSet::new(); |
21 | | /// let guard = books.guard(); |
22 | | /// |
23 | | /// // Add some books |
24 | | /// books.insert("Fight Club", &guard); |
25 | | /// books.insert("Three Men In A Raft", &guard); |
26 | | /// books.insert("The Book of Dust", &guard); |
27 | | /// books.insert("The Dry", &guard); |
28 | | /// |
29 | | /// // Check for a specific one. |
30 | | /// if !books.contains(&"The Drunken Botanist", &guard) { |
31 | | /// println!("We don't have The Drunken Botanist."); |
32 | | /// } |
33 | | /// |
34 | | /// // Remove a book. |
35 | | /// books.remove(&"Three Men In A Raft", &guard); |
36 | | /// |
37 | | /// // Iterate over everything. |
38 | | /// for book in books.iter(&guard) { |
39 | | /// println!("{}", book); |
40 | | /// } |
41 | | /// ``` |
42 | | pub struct HashSet<T, S = crate::DefaultHashBuilder> { |
43 | | pub(crate) map: HashMap<T, (), S>, |
44 | | } |
45 | | |
46 | | impl<T> HashSet<T, crate::DefaultHashBuilder> { |
47 | | /// Creates an empty `HashSet`. |
48 | | /// |
49 | | /// The hash set is initially created with a capacity of 0, so it will not allocate until it |
50 | | /// is first inserted into. |
51 | | /// |
52 | | /// # Examples |
53 | | /// |
54 | | /// ``` |
55 | | /// use flurry::HashSet; |
56 | | /// let set: HashSet<i32> = HashSet::new(); |
57 | | /// ``` |
58 | 0 | pub fn new() -> Self { |
59 | 0 | Self::default() |
60 | 0 | } |
61 | | |
62 | | /// Creates an empty `HashSet` with the specified capacity. |
63 | | /// |
64 | | /// The hash map will be able to hold at least `capacity` elements without |
65 | | /// reallocating. If `capacity` is 0, the hash map will not allocate. |
66 | | /// |
67 | | /// # Examples |
68 | | /// |
69 | | /// ``` |
70 | | /// use flurry::HashSet; |
71 | | /// let map: HashSet<&str, _> = HashSet::with_capacity(10); |
72 | | /// ``` |
73 | | /// |
74 | | /// # Notes |
75 | | /// |
76 | | /// There is no guarantee that the HashSet will not resize if `capacity` |
77 | | /// elements are inserted. The set will resize based on key collision, so |
78 | | /// bad key distribution may cause a resize before `capacity` is reached. |
79 | | /// For more information see the [`resizing behavior`] of HashMap. |
80 | | /// |
81 | | /// [`resizing behavior`]: index.html#resizing-behavior |
82 | 0 | pub fn with_capacity(capacity: usize) -> Self { |
83 | 0 | Self::with_capacity_and_hasher(capacity, crate::DefaultHashBuilder::default()) |
84 | 0 | } |
85 | | } |
86 | | |
87 | | impl<T, S> Default for HashSet<T, S> |
88 | | where |
89 | | S: Default, |
90 | | { |
91 | 0 | fn default() -> Self { |
92 | 0 | Self::with_hasher(S::default()) |
93 | 0 | } |
94 | | } |
95 | | |
96 | | impl<T, S> HashSet<T, S> { |
97 | | /// Creates an empty set which will use `hash_builder` to hash values. |
98 | | /// |
99 | | /// The created set has the default initial capacity. |
100 | | /// |
101 | | /// Warning: `hash_builder` is normally randomly generated, and is designed to |
102 | | /// allow the set to be resistant to attacks that cause many collisions and |
103 | | /// very poor performance. Setting it manually using this |
104 | | /// function can expose a DoS attack vector. |
105 | | /// |
106 | | /// # Examples |
107 | | /// |
108 | | /// ``` |
109 | | /// use flurry::{HashSet, DefaultHashBuilder}; |
110 | | /// |
111 | | /// let set = HashSet::with_hasher(DefaultHashBuilder::default()); |
112 | | /// let guard = set.guard(); |
113 | | /// set.insert(1, &guard); |
114 | | /// ``` |
115 | 0 | pub fn with_hasher(hash_builder: S) -> Self { |
116 | 0 | Self { |
117 | 0 | map: HashMap::with_hasher(hash_builder), |
118 | 0 | } |
119 | 0 | } |
120 | | |
121 | | /// Creates an empty set with the specified `capacity`, using `hash_builder` to hash the |
122 | | /// values. |
123 | | /// |
124 | | /// The set will be sized to accommodate `capacity` elements with a low chance of reallocating |
125 | | /// (assuming uniformly distributed hashes). If `capacity` is 0, the call will not allocate, |
126 | | /// and is equivalent to [`HashSet::new`]. |
127 | | /// |
128 | | /// Warning: `hash_builder` is normally randomly generated, and is designed to allow the set |
129 | | /// to be resistant to attacks that cause many collisions and very poor performance. |
130 | | /// Setting it manually using this function can expose a DoS attack vector. |
131 | | /// |
132 | | /// # Examples |
133 | | /// |
134 | | /// ``` |
135 | | /// use flurry::HashSet; |
136 | | /// use std::collections::hash_map::RandomState; |
137 | | /// |
138 | | /// let s = RandomState::new(); |
139 | | /// let set = HashSet::with_capacity_and_hasher(10, s); |
140 | | /// let guard = set.guard(); |
141 | | /// set.insert(1, &guard); |
142 | | /// ``` |
143 | 0 | pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self { |
144 | 0 | Self { |
145 | 0 | map: HashMap::with_capacity_and_hasher(capacity, hash_builder), |
146 | 0 | } |
147 | 0 | } |
148 | | |
149 | | /// Pin a `Guard` for use with this set. |
150 | | /// |
151 | | /// Keep in mind that for as long as you hold onto this `Guard`, you are preventing the |
152 | | /// collection of garbage generated by the set. |
153 | 0 | pub fn guard(&self) -> Guard<'_> { |
154 | 0 | self.map.guard() |
155 | 0 | } |
156 | | |
157 | | /// Returns the number of elements in the set. |
158 | | /// |
159 | | /// # Examples |
160 | | /// |
161 | | /// ``` |
162 | | /// use flurry::HashSet; |
163 | | /// |
164 | | /// let set = HashSet::new(); |
165 | | /// |
166 | | /// let guard = set.guard(); |
167 | | /// set.insert(1, &guard); |
168 | | /// set.insert(2, &guard); |
169 | | /// assert_eq!(set.len(), 2); |
170 | | /// ``` |
171 | 0 | pub fn len(&self) -> usize { |
172 | 0 | self.map.len() |
173 | 0 | } |
174 | | |
175 | | /// Returns `true` if the set is empty. Otherwise returns `false`. |
176 | | /// |
177 | | /// # Examples |
178 | | /// |
179 | | /// ``` |
180 | | /// use flurry::HashSet; |
181 | | /// |
182 | | /// let set = HashSet::new(); |
183 | | /// assert!(set.is_empty()); |
184 | | /// set.insert("a", &set.guard()); |
185 | | /// assert!(!set.is_empty()); |
186 | | /// ``` |
187 | 0 | pub fn is_empty(&self) -> bool { |
188 | 0 | self.len() == 0 |
189 | 0 | } |
190 | | |
191 | | /// An iterator visiting all elements in arbitrary order. |
192 | | /// |
193 | | /// The iterator element type is `&'g T`. |
194 | | /// |
195 | | /// See [`HashMap::keys`] for details. |
196 | | /// |
197 | | /// # Examples |
198 | | /// |
199 | | /// ``` |
200 | | /// use flurry::HashSet; |
201 | | /// |
202 | | /// let set = HashSet::new(); |
203 | | /// let guard = set.guard(); |
204 | | /// set.insert(1, &guard); |
205 | | /// set.insert(2, &guard); |
206 | | /// |
207 | | /// for x in set.iter(&guard) { |
208 | | /// println!("{}", x); |
209 | | /// } |
210 | | /// ``` |
211 | 0 | pub fn iter<'g>(&'g self, guard: &'g Guard<'_>) -> Keys<'g, T, ()> { |
212 | 0 | self.map.keys(guard) |
213 | 0 | } |
214 | | } |
215 | | |
216 | | impl<T, S> HashSet<T, S> |
217 | | where |
218 | | T: Hash + Ord, |
219 | | S: BuildHasher, |
220 | | { |
221 | | /// Returns `true` if the given value is an element of this set. |
222 | | /// |
223 | | /// The value may be any borrowed form of the set's value type, but |
224 | | /// [`Hash`] and [`Ord`] on the borrowed form *must* match those for |
225 | | /// the value type. |
226 | | /// |
227 | | /// [`Ord`]: std::cmp::Ord |
228 | | /// [`Hash`]: std::hash::Hash |
229 | | /// |
230 | | /// # Examples |
231 | | /// |
232 | | /// ``` |
233 | | /// use flurry::HashSet; |
234 | | /// |
235 | | /// let set = HashSet::new(); |
236 | | /// let guard = set.guard(); |
237 | | /// set.insert(2, &guard); |
238 | | /// |
239 | | /// assert!(set.contains(&2, &guard)); |
240 | | /// assert!(!set.contains(&1, &guard)); |
241 | | /// ``` |
242 | | #[inline] |
243 | 0 | pub fn contains<Q>(&self, value: &Q, guard: &Guard<'_>) -> bool |
244 | 0 | where |
245 | 0 | T: Borrow<Q>, |
246 | 0 | Q: ?Sized + Hash + Ord, |
247 | | { |
248 | 0 | self.map.contains_key(value, guard) |
249 | 0 | } |
250 | | |
251 | | /// Returns a reference to the element in the set, if any, that is equal to the given value. |
252 | | /// |
253 | | /// The value may be any borrowed form of the set's value type, but |
254 | | /// [`Hash`] and [`Ord`] on the borrowed form *must* match those for |
255 | | /// the value type. |
256 | | /// |
257 | | /// [`Ord`]: std::cmp::Ord |
258 | | /// [`Hash`]: std::hash::Hash |
259 | | /// |
260 | | /// # Examples |
261 | | /// |
262 | | /// ``` |
263 | | /// use flurry::HashSet; |
264 | | /// |
265 | | /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); |
266 | | /// let guard = set.guard(); |
267 | | /// assert_eq!(set.get(&2, &guard), Some(&2)); |
268 | | /// assert_eq!(set.get(&4, &guard), None); |
269 | | /// ``` |
270 | 0 | pub fn get<'g, Q>(&'g self, value: &Q, guard: &'g Guard<'_>) -> Option<&'g T> |
271 | 0 | where |
272 | 0 | T: Borrow<Q>, |
273 | 0 | Q: ?Sized + Hash + Ord, |
274 | | { |
275 | 0 | self.map.get_key_value(value, guard).map(|(k, _)| k) |
276 | 0 | } |
277 | | |
278 | | /// Returns `true` if `self` has no elements in common with `other`. |
279 | | /// |
280 | | /// This is equivalent to checking for an empty intersection. |
281 | | /// |
282 | | /// # Examples |
283 | | /// |
284 | | /// ``` |
285 | | /// use std::iter::FromIterator; |
286 | | /// use flurry::HashSet; |
287 | | /// |
288 | | /// let a = HashSet::from_iter(&[1, 2, 3]); |
289 | | /// let b = HashSet::new(); |
290 | | /// |
291 | | /// assert!(a.pin().is_disjoint(&b.pin())); |
292 | | /// b.pin().insert(4); |
293 | | /// assert!(a.pin().is_disjoint(&b.pin())); |
294 | | /// b.pin().insert(1); |
295 | | /// assert!(!a.pin().is_disjoint(&b.pin())); |
296 | | /// |
297 | | /// ``` |
298 | 0 | pub fn is_disjoint( |
299 | 0 | &self, |
300 | 0 | other: &HashSet<T, S>, |
301 | 0 | our_guard: &Guard<'_>, |
302 | 0 | their_guard: &Guard<'_>, |
303 | 0 | ) -> bool { |
304 | 0 | for value in self.iter(our_guard) { |
305 | 0 | if other.contains(value, their_guard) { |
306 | 0 | return false; |
307 | 0 | } |
308 | | } |
309 | | |
310 | 0 | true |
311 | 0 | } |
312 | | |
313 | | /// Returns `true` if the set is a subset of another, i.e., `other` contains at least all the values in `self`. |
314 | | /// |
315 | | /// # Examples |
316 | | /// |
317 | | /// ``` |
318 | | /// use std::iter::FromIterator; |
319 | | /// use flurry::HashSet; |
320 | | /// |
321 | | /// let sup = HashSet::from_iter(&[1, 2, 3]); |
322 | | /// let set = HashSet::new(); |
323 | | /// |
324 | | /// assert!(set.pin().is_subset(&sup.pin())); |
325 | | /// set.pin().insert(2); |
326 | | /// assert!(set.pin().is_subset(&sup.pin())); |
327 | | /// set.pin().insert(4); |
328 | | /// assert!(!set.pin().is_subset(&sup.pin())); |
329 | | /// ``` |
330 | 0 | pub fn is_subset( |
331 | 0 | &self, |
332 | 0 | other: &HashSet<T, S>, |
333 | 0 | our_guard: &Guard<'_>, |
334 | 0 | their_guard: &Guard<'_>, |
335 | 0 | ) -> bool { |
336 | 0 | for value in self.iter(our_guard) { |
337 | 0 | if !other.contains(value, their_guard) { |
338 | 0 | return false; |
339 | 0 | } |
340 | | } |
341 | | |
342 | 0 | true |
343 | 0 | } |
344 | | |
345 | | /// Returns `true` if the set is a superset of another, i.e., `self` contains at least all the values in `other`. |
346 | | /// |
347 | | /// # Examples |
348 | | /// |
349 | | /// ``` |
350 | | /// use std::iter::FromIterator; |
351 | | /// use flurry::HashSet; |
352 | | /// |
353 | | /// let sub = HashSet::from_iter(&[1, 2]); |
354 | | /// let set = HashSet::new(); |
355 | | /// |
356 | | /// assert!(!set.pin().is_superset(&sub.pin())); |
357 | | /// |
358 | | /// set.pin().insert(0); |
359 | | /// set.pin().insert(1); |
360 | | /// assert!(!set.pin().is_superset(&sub.pin())); |
361 | | /// |
362 | | /// set.pin().insert(2); |
363 | | /// assert!(set.pin().is_superset(&sub.pin())); |
364 | | /// ``` |
365 | 0 | pub fn is_superset( |
366 | 0 | &self, |
367 | 0 | other: &HashSet<T, S>, |
368 | 0 | our_guard: &Guard<'_>, |
369 | 0 | their_guard: &Guard<'_>, |
370 | 0 | ) -> bool { |
371 | 0 | other.is_subset(self, their_guard, our_guard) |
372 | 0 | } |
373 | | |
374 | 0 | pub(crate) fn guarded_eq( |
375 | 0 | &self, |
376 | 0 | other: &Self, |
377 | 0 | our_guard: &Guard<'_>, |
378 | 0 | their_guard: &Guard<'_>, |
379 | 0 | ) -> bool { |
380 | 0 | self.map.guarded_eq(&other.map, our_guard, their_guard) |
381 | 0 | } |
382 | | } |
383 | | |
384 | | impl<T, S> HashSet<T, S> |
385 | | where |
386 | | T: Sync + Send + Clone + Hash + Ord, |
387 | | S: BuildHasher, |
388 | | { |
389 | | /// Adds a value to the set. |
390 | | /// |
391 | | /// If the set did not have this value present, `true` is returned. |
392 | | /// |
393 | | /// If the set did have this value present, `false` is returned. |
394 | | /// |
395 | | /// # Examples |
396 | | /// |
397 | | /// ``` |
398 | | /// use flurry::HashSet; |
399 | | /// |
400 | | /// let set = HashSet::new(); |
401 | | /// let guard = set.guard(); |
402 | | /// |
403 | | /// assert_eq!(set.insert(2, &guard), true); |
404 | | /// assert_eq!(set.insert(2, &guard), false); |
405 | | /// assert!(set.contains(&2, &guard)); |
406 | | /// ``` |
407 | 0 | pub fn insert(&self, value: T, guard: &Guard<'_>) -> bool { |
408 | 0 | let old = self.map.insert(value, (), guard); |
409 | 0 | old.is_none() |
410 | 0 | } |
411 | | |
412 | | /// Removes a value from the set. |
413 | | /// |
414 | | /// If the set did not have this value present, `false` is returned. |
415 | | /// |
416 | | /// If the set did have this value present, `true` is returned. |
417 | | /// |
418 | | /// The value may be any borrowed form of the set's value type, but |
419 | | /// [`Hash`] and [`Ord`] on the borrowed form *must* match those for |
420 | | /// the value type. |
421 | | /// |
422 | | /// [`Ord`]: std::cmp::Ord |
423 | | /// [`Hash`]: std::hash::Hash |
424 | | /// |
425 | | /// # Examples |
426 | | /// |
427 | | /// ``` |
428 | | /// use flurry::HashSet; |
429 | | /// |
430 | | /// let set = HashSet::new(); |
431 | | /// let guard = set.guard(); |
432 | | /// set.insert(2, &guard); |
433 | | /// |
434 | | /// assert_eq!(set.remove(&2, &guard), true); |
435 | | /// assert!(!set.contains(&2, &guard)); |
436 | | /// assert_eq!(set.remove(&2, &guard), false); |
437 | | /// ``` |
438 | 0 | pub fn remove<Q>(&self, value: &Q, guard: &Guard<'_>) -> bool |
439 | 0 | where |
440 | 0 | T: Borrow<Q>, |
441 | 0 | Q: ?Sized + Hash + Ord, |
442 | | { |
443 | 0 | let removed = self.map.remove(value, guard); |
444 | 0 | removed.is_some() |
445 | 0 | } |
446 | | |
447 | | /// Removes and returns the value in the set, if any, that is equal to the given one. |
448 | | /// |
449 | | /// The value may be any borrowed form of the set's value type, but |
450 | | /// [`Hash`] and [`Ord`] on the borrowed form *must* match those for |
451 | | /// the value type. |
452 | | /// |
453 | | /// [`Ord`]: std::cmp::Ord |
454 | | /// [`Hash`]: std::hash::Hash |
455 | | /// |
456 | | /// # Examples |
457 | | /// |
458 | | /// ``` |
459 | | /// use flurry::HashSet; |
460 | | /// |
461 | | /// let mut set: HashSet<_> = [1, 2, 3].iter().cloned().collect(); |
462 | | /// let guard = set.guard(); |
463 | | /// assert_eq!(set.take(&2, &guard), Some(&2)); |
464 | | /// assert_eq!(set.take(&2, &guard), None); |
465 | | /// ``` |
466 | 0 | pub fn take<'g, Q>(&'g self, value: &Q, guard: &'g Guard<'_>) -> Option<&'g T> |
467 | 0 | where |
468 | 0 | T: Borrow<Q>, |
469 | 0 | Q: ?Sized + Hash + Ord, |
470 | | { |
471 | 0 | self.map.remove_entry(value, guard).map(|(k, _)| k) |
472 | 0 | } |
473 | | |
474 | | /// Retains only the elements specified by the predicate. |
475 | | /// |
476 | | /// In other words, remove all elements `e` such that `f(&e)` returns `false`. |
477 | | /// |
478 | | /// # Examples |
479 | | /// |
480 | | /// ``` |
481 | | /// use flurry::HashSet; |
482 | | /// |
483 | | /// let set = HashSet::new(); |
484 | | /// |
485 | | /// for i in 0..8 { |
486 | | /// set.pin().insert(i); |
487 | | /// } |
488 | | /// set.pin().retain(|&e| e % 2 == 0); |
489 | | /// assert_eq!(set.pin().len(), 4); |
490 | | /// ``` |
491 | 0 | pub fn retain<F>(&self, mut f: F, guard: &Guard<'_>) |
492 | 0 | where |
493 | 0 | F: FnMut(&T) -> bool, |
494 | | { |
495 | 0 | self.map.retain(|value, ()| f(value), guard) |
496 | 0 | } |
497 | | } |
498 | | |
499 | | impl<T, S> HashSet<T, S> |
500 | | where |
501 | | T: Clone + Ord, |
502 | | { |
503 | | /// Clears the set, removing all elements. |
504 | | /// |
505 | | /// # Examples |
506 | | /// |
507 | | /// ``` |
508 | | /// use flurry::HashSet; |
509 | | /// |
510 | | /// let set = HashSet::new(); |
511 | | /// |
512 | | /// set.pin().insert("a"); |
513 | | /// set.pin().clear(); |
514 | | /// assert!(set.pin().is_empty()); |
515 | | /// ``` |
516 | 0 | pub fn clear(&self, guard: &Guard<'_>) { |
517 | 0 | self.map.clear(guard) |
518 | 0 | } |
519 | | |
520 | | /// Tries to reserve capacity for at least `additional` more elements to |
521 | | /// be inserted in the `HashSet`. |
522 | | /// |
523 | | /// The collection may reserve more space to avoid frequent reallocations. |
524 | 0 | pub fn reserve(&self, additional: usize, guard: &Guard<'_>) { |
525 | 0 | self.map.reserve(additional, guard) |
526 | 0 | } |
527 | | } |
528 | | |
529 | | impl<T, S> PartialEq for HashSet<T, S> |
530 | | where |
531 | | T: Ord + Hash, |
532 | | S: BuildHasher, |
533 | | { |
534 | 0 | fn eq(&self, other: &Self) -> bool { |
535 | 0 | self.map == other.map |
536 | 0 | } |
537 | | } |
538 | | |
539 | | impl<T, S> Eq for HashSet<T, S> |
540 | | where |
541 | | T: Ord + Hash, |
542 | | S: BuildHasher, |
543 | | { |
544 | | } |
545 | | |
546 | | impl<T, S> fmt::Debug for HashSet<T, S> |
547 | | where |
548 | | T: Debug, |
549 | | { |
550 | 0 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
551 | 0 | let guard = self.guard(); |
552 | 0 | f.debug_set().entries(self.iter(&guard)).finish() |
553 | 0 | } |
554 | | } |
555 | | |
556 | | impl<T, S> Extend<T> for &HashSet<T, S> |
557 | | where |
558 | | T: Sync + Send + Clone + Hash + Ord, |
559 | | S: BuildHasher, |
560 | | { |
561 | 0 | fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { |
562 | 0 | Extend::extend(&mut &self.map, iter.into_iter().map(|v| (v, ()))) |
563 | 0 | } |
564 | | } |
565 | | |
566 | | impl<'a, T, S> Extend<&'a T> for &HashSet<T, S> |
567 | | where |
568 | | T: Sync + Send + Copy + Hash + Ord, |
569 | | S: BuildHasher, |
570 | | { |
571 | 0 | fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) { |
572 | 0 | Extend::extend(&mut &self.map, iter.into_iter().map(|&v| (v, ()))) |
573 | 0 | } |
574 | | } |
575 | | |
576 | | impl<T, S> FromIterator<T> for HashSet<T, S> |
577 | | where |
578 | | T: Sync + Send + Clone + Hash + Ord, |
579 | | S: BuildHasher + Default, |
580 | | { |
581 | 0 | fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self { |
582 | | Self { |
583 | 0 | map: iter.into_iter().map(|v| (v, ())).collect(), |
584 | | } |
585 | 0 | } |
586 | | } |
587 | | |
588 | | impl<'a, T, S> FromIterator<&'a T> for HashSet<T, S> |
589 | | where |
590 | | T: Sync + Send + Copy + Hash + Ord, |
591 | | S: BuildHasher + Default, |
592 | | { |
593 | 0 | fn from_iter<I: IntoIterator<Item = &'a T>>(iter: I) -> Self { |
594 | | Self { |
595 | 0 | map: iter.into_iter().map(|&v| (v, ())).collect(), |
596 | | } |
597 | 0 | } |
598 | | } |
599 | | |
600 | | impl<T, S> Clone for HashSet<T, S> |
601 | | where |
602 | | T: Sync + Send + Clone + Hash + Ord, |
603 | | S: BuildHasher + Clone, |
604 | | { |
605 | 0 | fn clone(&self) -> HashSet<T, S> { |
606 | 0 | Self { |
607 | 0 | map: self.map.clone(), |
608 | 0 | } |
609 | 0 | } |
610 | | } |