Coverage Report

Created: 2025-12-28 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}