hashbag/lib.rs
1//! An unordered multiset/bag implementation backed by `HashMap`.
2//!
3//! A bag, unlike a set, allows duplicate values, and keeps track of how many
4//! duplicates each value holds. This type of collection is often referred to
5//! as an unordered multiset (see also C++'s [`std::unordered_multiset`]).
6//!
7//! This multiset/bag is implemented using a `HashMap<T, usize>` and so requires
8//! that the stored type implements `Hash + Eq`.
9//!
10//! For usage examples, see the primary type [`HashBag`].
11//!
12//! If you want to use a hash table with [amortized resizes](https://github.com/jonhoo/griddle/),
13//! set the `amortize` feature.
14//!
15//! (De)serialization via serde is also available with the `serde` feature.
16//! Deserialization note: if the incoming data contains two instances of `T` that are the same, the resulting `HashBag` will merge
17//! the counts of those instances.
18//!
19//! [`std::unordered_multiset`]: http://www.cplusplus.com/reference/unordered_set/unordered_multiset/
20#![deny(missing_docs, missing_debug_implementations, unreachable_pub)]
21#![cfg_attr(doc, deny(rustdoc::broken_intra_doc_links))]
22#![warn(rust_2018_idioms)]
23
24#[cfg(feature = "amortize")]
25use griddle::HashMap;
26use std::borrow::Borrow;
27use std::collections::hash_map::RandomState;
28#[cfg(not(feature = "amortize"))]
29use std::collections::HashMap;
30use std::convert::TryFrom;
31use std::hash::{BuildHasher, Hash};
32
33#[cfg(feature = "serde")]
34mod serde;
35
36/// A hash bag implemented as a `HashMap` where the value is `usize`.
37///
38/// A bag, unlike a set, allows duplicate values, and keeps track of how many
39/// duplicates each value holds. This type of collection is often referred to
40/// as an unordered multiset.
41///
42/// As with the [`HashMap`] type, a `HashBag` requires that the elements
43/// implement the [`Eq`] and [`Hash`] traits. This can frequently be achieved by
44/// using `#[derive(PartialEq, Eq, Hash)]`. If you implement these yourself,
45/// it is important that the following property holds:
46///
47/// ```text
48/// k1 == k2 -> hash(k1) == hash(k2)
49/// ```
50///
51/// In other words, if two keys are equal, their hashes must be equal.
52///
53/// It is a logic error for an item to be modified in such a way that the
54/// item's hash, as determined by the [`Hash`] trait, or its equality, as
55/// determined by the [`Eq`] trait, changes while it is in the bag.
56///
57/// # Examples
58///
59/// ```
60/// use hashbag::HashBag;
61/// // Type inference lets us omit an explicit type signature (which
62/// // would be `HashBag<String>` in this example).
63/// let mut books = HashBag::new();
64///
65/// // Add some books.
66/// // Since we are a library, we have many copies.
67/// books.insert("A Dance With Dragons".to_string());
68/// books.insert("To Kill a Mockingbird".to_string());
69/// books.insert("To Kill a Mockingbird".to_string());
70/// books.insert("The Odyssey".to_string());
71/// books.insert("The Odyssey".to_string());
72/// books.insert("The Odyssey".to_string());
73/// books.insert("The Great Gatsby".to_string());
74/// books.insert("The Great Gatsby".to_string());
75/// books.insert("The Great Gatsby".to_string());
76/// books.insert("The Great Gatsby".to_string());
77///
78/// // When we count the number of books, duplicates are included.
79/// assert_eq!(books.len(), 10);
80///
81/// // Check for a specific one.
82/// if books.contains("The Winds of Winter") == 0 {
83/// println!("We have {} books, but The Winds of Winter ain't one.",
84/// books.len());
85/// }
86///
87/// // Remove a book.
88/// let had_copies = books.remove("The Odyssey");
89/// // Remove returns how many copies of that book we had.
90/// assert_eq!(had_copies, 3);
91///
92/// // Iterate over everything.
93/// // Duplicates will be listed multiple times.
94/// for book in &books {
95/// println!("{}", book);
96/// }
97///
98/// // Iterate over each distinct book.
99/// for (book, copies) in books.set_iter() {
100/// println!("{} ({} copies)", book, copies);
101/// }
102///
103/// // Extract the books and their counts.
104/// for (book, copies) in books {
105/// println!("{} ({} copies)", book, copies);
106/// }
107/// ```
108///
109/// The easiest way to use `HashBag` with a custom type is to derive
110/// [`Eq`] and [`Hash`]. We must also derive [`PartialEq`], this will in the
111/// future be implied by [`Eq`].
112///
113/// ```
114/// use hashbag::HashBag;
115/// #[derive(Hash, Eq, PartialEq, Debug, Clone)]
116/// struct Viking {
117/// name: String,
118/// power: usize,
119/// }
120///
121/// let mut vikings = HashBag::new();
122///
123/// vikings.insert(Viking { name: "Einar".to_string(), power: 9 });
124/// vikings.insert(Viking { name: "Einar".to_string(), power: 9 });
125/// vikings.insert(Viking { name: "Olaf".to_string(), power: 4 });
126/// vikings.insert(Viking { name: "Olaf".to_string(), power: 5 });
127/// vikings.insert(Viking { name: "Harald".to_string(), power: 8 });
128///
129/// // Use derived implementation to print the vikings.
130/// // Notice that all duplicates are printed.
131/// for v in &vikings {
132/// println!("{:?}", v);
133/// }
134///
135/// // Since the derived implementation compares all the fields,
136/// // vikings that share a name but not a power are not duplicates.
137/// for (v, n) in vikings.set_iter() {
138/// println!("{:?} ({} of them!)", v, n);
139/// }
140///
141/// // HashBags themselves can also be compared for equality,
142/// // and will do so by considering both the values and their counts.
143/// let mut vikings2 = vikings.clone();
144/// assert_eq!(vikings, vikings2);
145/// let fallen = vikings.iter().next().unwrap();
146/// vikings2.remove(fallen);
147/// assert_ne!(vikings, vikings2);
148/// vikings2.insert(Viking { name: "Snorre".to_string(), power: 1 });
149/// assert_ne!(vikings, vikings2);
150/// ```
151///
152/// A `HashBag` with fixed list of elements can be initialized from an array:
153///
154/// ```
155/// use hashbag::HashBag;
156///
157/// let mut viking_names: HashBag<&'static str> =
158/// [ "Einar", "Olaf", "Harald" ].iter().cloned().collect();
159/// // use the values stored in the bag
160/// ```
161///
162/// You can also extend the bag easily:
163///
164/// ```
165/// use hashbag::HashBag;
166///
167/// let mut vikings: HashBag<String> = HashBag::new();
168/// vikings.extend(std::iter::once("Snorre".to_string()));
169/// assert_eq!(vikings.contains("Snorre"), 1);
170///
171/// // You can extend with many instances at once:
172/// vikings.extend(std::iter::once(("Snorre".to_string(), 4)));
173/// assert_eq!(vikings.contains("Snorre"), 5);
174///
175/// // Extension also works with reference iterators if the type is Clone:
176/// let einar = String::from("Einar");
177/// vikings.extend(std::iter::once(&einar));
178/// assert_eq!(vikings.contains(&einar), 1);
179///
180/// // And extend with many instances at once:
181/// vikings.extend(std::iter::once((&einar, 4)));
182/// assert_eq!(vikings.contains(&einar), 5);
183/// ```
184pub struct HashBag<T, S = RandomState> {
185 items: HashMap<T, usize, S>,
186 count: usize,
187}
188
189impl<T: Clone + Hash, S: Clone + BuildHasher> Clone for HashBag<T, S> {
190 fn clone(&self) -> Self {
191 Self {
192 items: self.items.clone(),
193 count: self.count,
194 }
195 }
196
197 fn clone_from(&mut self, source: &Self) {
198 self.items.clone_from(&source.items);
199 self.count = source.count;
200 }
201}
202
203impl<T: Hash + Eq> HashBag<T, RandomState> {
204 /// Creates an empty `HashBag`.
205 ///
206 /// The hash bag is initially created with a capacity of 0, so it will not allocate until it
207 /// is first inserted into.
208 ///
209 /// # Examples
210 ///
211 /// ```
212 /// use hashbag::HashBag;
213 /// let bag: HashBag<i32> = HashBag::new();
214 /// ```
215 #[inline]
216 pub fn new() -> HashBag<T, RandomState> {
217 Self::with_hasher(RandomState::new())
218 }
219
220 /// Creates an empty `HashBag` with the specified capacity.
221 ///
222 /// The hash bag will be able to hold at least `capacity` distinct values without
223 /// reallocating. If `capacity` is 0, the hash bag will not allocate.
224 ///
225 /// # Examples
226 ///
227 /// ```
228 /// use hashbag::HashBag;
229 /// let bag: HashBag<i32> = HashBag::with_capacity(10);
230 /// assert!(bag.capacity() >= 10);
231 /// ```
232 #[inline]
233 pub fn with_capacity(capacity: usize) -> HashBag<T, RandomState> {
234 Self::with_capacity_and_hasher(capacity, RandomState::new())
235 }
236}
237
238impl<T, S> HashBag<T, S> {
239 /// Returns the number of distinct values the bag can hold without reallocating.
240 ///
241 /// # Examples
242 ///
243 /// ```
244 /// use hashbag::HashBag;
245 /// let bag: HashBag<i32> = HashBag::with_capacity(100);
246 /// assert!(bag.capacity() >= 100);
247 /// ```
248 #[inline]
249 pub fn capacity(&self) -> usize {
250 self.items.capacity()
251 }
252
253 /// An iterator visiting all elements in arbitrary order.
254 ///
255 /// The iterator element type is `&'a T`.
256 /// Duplicates are yielded as many times as they appear in the bag.
257 ///
258 /// # Examples
259 ///
260 /// ```
261 /// use hashbag::HashBag;
262 /// let mut bag = HashBag::new();
263 /// bag.insert("a");
264 /// bag.insert("b");
265 /// bag.insert("b");
266 ///
267 /// // Will print in an arbitrary order.
268 /// // b will be printed twice.
269 /// for x in bag.iter() {
270 /// println!("{}", x);
271 /// }
272 /// ```
273 #[inline]
274 pub fn iter(&self) -> Iter<'_, T> {
275 Iter::new(self.items.iter(), self.count)
276 }
277
278 /// An iterator visiting all distinct elements in arbitrary order.
279 ///
280 /// The iterator element type is `(&'a T, usize)`.
281 /// Duplicated values are yielded once along with a count of the number of occurrences.
282 ///
283 /// # Examples
284 ///
285 /// ```
286 /// use hashbag::HashBag;
287 /// let mut bag = HashBag::new();
288 /// bag.insert("a");
289 /// bag.insert("b");
290 /// bag.insert("b");
291 ///
292 /// // Will print in an arbitrary order.
293 /// for (x, n) in bag.set_iter() {
294 /// println!("{} {}", x, n);
295 /// }
296 /// ```
297 #[inline]
298 pub fn set_iter(&self) -> SetIter<'_, T> {
299 SetIter(self.items.iter())
300 }
301
302 /// Returns the number of elements in the bag.
303 ///
304 /// Duplicates are counted.
305 ///
306 /// # Examples
307 ///
308 /// ```
309 /// use hashbag::HashBag;
310 ///
311 /// let mut bag = HashBag::new();
312 /// assert_eq!(bag.len(), 0);
313 /// bag.insert(1);
314 /// assert_eq!(bag.len(), 1);
315 /// bag.insert(1);
316 /// assert_eq!(bag.len(), 2);
317 /// ```
318 #[inline]
319 pub fn len(&self) -> usize {
320 self.count
321 }
322
323 /// Returns the number of elements in the bag.
324 ///
325 /// Duplicates are not counted.
326 ///
327 /// # Examples
328 ///
329 /// ```
330 /// use hashbag::HashBag;
331 ///
332 /// let mut bag = HashBag::new();
333 /// assert_eq!(bag.set_len(), 0);
334 /// bag.insert(1);
335 /// assert_eq!(bag.set_len(), 1);
336 /// bag.insert(1);
337 /// assert_eq!(bag.set_len(), 1);
338 /// ```
339 #[inline]
340 pub fn set_len(&self) -> usize {
341 self.items.len()
342 }
343
344 /// Returns `true` if the bag contains no elements.
345 ///
346 /// # Examples
347 ///
348 /// ```
349 /// use hashbag::HashBag;
350 ///
351 /// let mut bag = HashBag::new();
352 /// assert!(bag.is_empty());
353 /// bag.insert(1);
354 /// assert!(!bag.is_empty());
355 /// ```
356 #[inline]
357 pub fn is_empty(&self) -> bool {
358 self.count == 0
359 }
360
361 /// Clears the bag, returning all elements in an iterator.
362 ///
363 /// Duplicates appear only in the count yielded for each element.
364 ///
365 /// # Examples
366 ///
367 /// ```
368 /// use hashbag::HashBag;
369 ///
370 /// let mut bag: HashBag<_> = [1, 2, 3, 3].iter().cloned().collect();
371 /// assert!(!bag.is_empty());
372 ///
373 /// // prints
374 /// // 1 1
375 /// // 2 1
376 /// // 3 2
377 /// // in an arbitrary order
378 /// for (i, n) in bag.drain() {
379 /// println!("{} {}", i, n);
380 /// }
381 ///
382 /// assert!(bag.is_empty());
383 /// ```
384 #[inline]
385 pub fn drain(&mut self) -> Drain<'_, T> {
386 self.count = 0;
387 Drain(self.items.drain())
388 }
389
390 /// Clears the bag, removing all values.
391 ///
392 /// # Examples
393 ///
394 /// ```
395 /// use hashbag::HashBag;
396 ///
397 /// let mut bag = HashBag::new();
398 /// bag.insert(1);
399 /// bag.clear();
400 /// assert!(bag.is_empty());
401 /// ```
402 #[inline]
403 pub fn clear(&mut self) {
404 self.count = 0;
405 self.items.clear();
406 }
407}
408
409impl<T, S> HashBag<T, S>
410where
411 T: Eq + Hash,
412 S: BuildHasher,
413{
414 /// Creates a new empty hash bag which will use the given hasher to hash
415 /// keys.
416 ///
417 /// The hash bag is also created with the default initial capacity.
418 ///
419 /// Warning: `hasher` is normally randomly generated, and
420 /// is designed to allow `HashBag`s to be resistant to attacks that
421 /// cause many collisions and very poor performance. Setting it
422 /// manually using this function can expose a DoS attack vector.
423 ///
424 /// # Examples
425 ///
426 /// ```
427 /// use hashbag::HashBag;
428 /// use std::collections::hash_map::RandomState;
429 ///
430 /// let s = RandomState::new();
431 /// let mut bag = HashBag::with_hasher(s);
432 /// bag.insert(2);
433 /// ```
434 #[inline]
435 pub fn with_hasher(hash_builder: S) -> HashBag<T, S> {
436 HashBag {
437 items: HashMap::with_hasher(hash_builder),
438 count: 0,
439 }
440 }
441
442 /// Creates an empty `HashBag` with the specified capacity, using
443 /// `hasher` to hash the keys.
444 ///
445 /// The hash bag will be able to hold at least `capacity` distinct values
446 /// without reallocating. If `capacity` is 0, the hash bag will not allocate.
447 ///
448 /// Warning: `hasher` is normally randomly generated, and
449 /// is designed to allow `HashBag`s to be resistant to attacks that
450 /// cause many collisions and very poor performance. Setting it
451 /// manually using this function can expose a DoS attack vector.
452 ///
453 /// # Examples
454 ///
455 /// ```
456 /// use hashbag::HashBag;
457 /// use std::collections::hash_map::RandomState;
458 ///
459 /// let s = RandomState::new();
460 /// let mut bag = HashBag::with_capacity_and_hasher(10, s);
461 /// bag.insert(1);
462 /// ```
463 #[inline]
464 pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashBag<T, S> {
465 HashBag {
466 items: HashMap::with_capacity_and_hasher(capacity, hash_builder),
467 count: 0,
468 }
469 }
470
471 /// Returns a reference to the bag's [`BuildHasher`].
472 ///
473 /// # Examples
474 ///
475 /// ```
476 /// use hashbag::HashBag;
477 /// use std::collections::hash_map::RandomState;
478 ///
479 /// let hasher = RandomState::new();
480 /// let bag: HashBag<i32> = HashBag::with_hasher(hasher);
481 /// let hasher: &RandomState = bag.hasher();
482 /// ```
483 #[inline]
484 pub fn hasher(&self) -> &S {
485 self.items.hasher()
486 }
487
488 /// Reserves capacity for at least `additional` more distinct values
489 /// to be inserted in the `HashBag`. The collection may reserve more
490 /// space to avoid frequent reallocations.
491 ///
492 /// # Panics
493 ///
494 /// Panics if the new allocation size overflows `usize`.
495 ///
496 /// # Examples
497 ///
498 /// ```
499 /// use hashbag::HashBag;
500 /// let mut bag: HashBag<i32> = HashBag::new();
501 /// bag.reserve(10);
502 /// assert!(bag.capacity() >= 10);
503 /// ```
504 #[inline]
505 pub fn reserve(&mut self, additional: usize) {
506 self.items.reserve(additional)
507 }
508
509 /// Shrinks the capacity of the ba as much as possible. It will drop
510 /// down as much as possible while maintaining the internal rules
511 /// and possibly leaving some space in accordance with the resize policy.
512 ///
513 /// # Examples
514 ///
515 /// ```
516 /// use hashbag::HashBag;
517 ///
518 /// let mut bag = HashBag::with_capacity(100);
519 /// bag.insert(1);
520 /// bag.insert(2);
521 /// assert!(bag.capacity() >= 100);
522 /// bag.shrink_to_fit();
523 /// assert!(bag.capacity() >= 2);
524 /// ```
525 #[inline]
526 pub fn shrink_to_fit(&mut self) {
527 self.items.shrink_to_fit()
528 }
529
530 /// Returns the number of instances of `value` in the bag.
531 ///
532 /// The value may be any borrowed form of the bag's value type, but
533 /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
534 /// the value type.
535 ///
536 /// # Examples
537 ///
538 /// ```
539 /// use hashbag::HashBag;
540 ///
541 /// let bag: HashBag<_> = [1, 2, 3, 3].iter().cloned().collect();
542 /// assert_eq!(bag.contains(&1), 1);
543 /// assert_eq!(bag.contains(&3), 2);
544 /// assert_eq!(bag.contains(&4), 0);
545 /// ```
546 #[inline]
547 pub fn contains<Q: ?Sized>(&self, value: &Q) -> usize
548 where
549 T: Borrow<Q>,
550 Q: Hash + Eq,
551 {
552 self.items.get(value).cloned().unwrap_or(0)
553 }
554
555 /// Returns a reference to the value in the bag, if any, that is equal to the given value,
556 /// along with its number of occurrences.
557 ///
558 /// The value may be any borrowed form of the bag's value type, but
559 /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
560 /// the value type.
561 ///
562 /// # Examples
563 ///
564 /// ```
565 /// use hashbag::HashBag;
566 ///
567 /// let bag: HashBag<_> = [1, 2, 3, 3].iter().cloned().collect();
568 /// assert_eq!(bag.get(&2), Some((&2, 1)));
569 /// assert_eq!(bag.get(&3), Some((&3, 2)));
570 /// assert_eq!(bag.get(&4), None);
571 /// ```
572 #[inline]
573 pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<(&T, usize)>
574 where
575 T: Borrow<Q>,
576 Q: Hash + Eq,
577 {
578 self.items
579 .get_key_value(value)
580 .map(|(t, count)| (t, *count))
581 }
582
583 /// Gets a given value's corresponding entry in the bag for in-place manipulation.
584 ///
585 /// # Examples
586 ///
587 /// ```
588 /// use hashbag::HashBag;
589 ///
590 /// let mut bag: HashBag<char> = ['a'].iter().cloned().collect();
591 /// let entry = bag.entry('a').and_modify(|n| *n += 1).or_insert();
592 /// assert_eq!(bag.get(&'a'), Some((&'a', 2)));
593 /// let entry = bag.entry('b').and_modify(|n| *n += 1).or_insert();
594 /// assert_eq!(bag.get(&'b'), Some((&'b', 1)));
595 /// let entry = bag.entry('c').and_modify(|n| *n += 1).or_insert_many(7);
596 /// assert_eq!(bag.get(&'c'), Some((&'c', 7)));
597 /// ```
598 #[inline]
599 pub fn entry(&mut self, value: T) -> Entry<'_, T, S> {
600 Entry((
601 ForiegnEntry::new(self.items.entry(value)),
602 &mut self.count,
603 PhantomData,
604 ))
605 }
606
607 /// Adds a value to the bag.
608 ///
609 /// The number of occurrences of the value previously in the bag is returned.
610 ///
611 /// # Examples
612 ///
613 /// ```
614 /// use hashbag::HashBag;
615 ///
616 /// let mut bag = HashBag::new();
617 ///
618 /// assert_eq!(bag.insert(2), 0);
619 /// assert_eq!(bag.insert(2), 1);
620 /// assert_eq!(bag.insert(2), 2);
621 /// assert_eq!(bag.set_len(), 1);
622 /// assert_eq!(bag.len(), 3);
623 /// ```
624 #[inline]
625 pub fn insert(&mut self, value: T) -> usize {
626 self.insert_many(value, 1)
627 }
628
629 /// Adds multiple occurrences of a value to the bag.
630 ///
631 /// The number of occurrences of the value previously in the bag is returned.
632 ///
633 /// # Examples
634 ///
635 /// ```
636 /// use hashbag::HashBag;
637 ///
638 /// let mut bag = HashBag::new();
639 ///
640 /// assert_eq!(bag.insert_many(2, 1), 0);
641 /// assert_eq!(bag.insert_many(2, 2), 1);
642 /// assert_eq!(bag.insert_many(2, 4), 3);
643 /// assert_eq!(bag.set_len(), 1);
644 /// assert_eq!(bag.len(), 7);
645 /// ```
646 #[inline]
647 pub fn insert_many(&mut self, value: T, count: usize) -> usize {
648 if count == 0 {
649 return self.contains(&value);
650 }
651 self.count += count;
652 let n = self.items.entry(value).or_insert(0);
653 let was_there = *n;
654 *n += count;
655 was_there
656 }
657
658 /// Adds a value to the bag, replacing all existing occurrences, if any, that equal the given
659 /// one.
660 ///
661 /// The number of occurrences of the value previously in the bag is returned.
662 ///
663 /// # Examples
664 ///
665 /// ```
666 /// use hashbag::HashBag;
667 ///
668 /// let mut bag = HashBag::new();
669 /// bag.insert(Vec::<i32>::new());
670 /// bag.insert(Vec::<i32>::new());
671 /// assert_eq!(bag.contains(&[][..]), 2);
672 /// assert_eq!(bag.get(&[][..]).unwrap().0.capacity(), 0);
673 ///
674 /// bag.replace(Vec::with_capacity(10));
675 /// assert_eq!(bag.contains(&[][..]), 1);
676 /// assert_eq!(bag.get(&[][..]).unwrap().0.capacity(), 10);
677 /// ```
678 #[inline]
679 pub fn replace(&mut self, value: T) -> usize {
680 let n = self.items.remove(&value).unwrap_or(0);
681 self.count -= n;
682 self.items.insert(value, 1);
683 self.count += 1;
684 n
685 }
686
687 /// Removes a value from the bag.
688 ///
689 /// The number of occurrences of the value previously in the bag is returned.
690 ///
691 /// The value may be any borrowed form of the bag's value type, but
692 /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
693 /// the value type.
694 ///
695 /// # Examples
696 ///
697 /// ```
698 /// use hashbag::HashBag;
699 ///
700 /// let mut bag = HashBag::new();
701 ///
702 /// bag.insert_many('x', 2);
703 /// assert_eq!(bag.contains(&'x'), 2);
704 /// assert_eq!(bag.remove(&'x'), 2);
705 /// assert_eq!(bag.contains(&'x'), 1);
706 /// assert_eq!(bag.remove(&'x'), 1);
707 /// assert_eq!(bag.contains(&'x'), 0);
708 /// assert_eq!(bag.remove(&'x'), 0);
709 /// ```
710 #[inline]
711 pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> usize
712 where
713 T: Borrow<Q>,
714 Q: Hash + Eq,
715 {
716 match self.items.get_mut(value) {
717 None => 0,
718 #[cfg(debug_assertions)]
719 Some(n) if *n == 0 => unreachable!(),
720 Some(n) if *n == 1 => {
721 self.count -= 1;
722 self.items.remove(value);
723 1
724 }
725 Some(n) => {
726 self.count -= 1;
727 *n -= 1;
728 *n + 1
729 }
730 }
731 }
732
733 /// Removes multiple of a value from the bag. If `quantity` is greater than the number of
734 /// occurences, zero occurances will remain.
735 ///
736 /// The number of occurrences of the value currently in the bag is returned.
737 ///
738 /// The value may be any borrowed form of the bag's value type, but
739 /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
740 /// the value type.
741 ///
742 /// # Examples
743 ///
744 /// ```
745 /// use hashbag::HashBag;
746 ///
747 /// let mut bag = HashBag::new();
748 ///
749 /// bag.insert_many('x', 10);
750 /// assert_eq!(bag.contains(&'x'), 10);
751 /// assert_eq!(bag.remove_up_to(&'x', 3), 7);
752 /// assert_eq!(bag.contains(&'x'), 7);
753 /// assert_eq!(bag.remove_up_to(&'x', 10), 0);
754 /// ```
755 #[inline]
756 pub fn remove_up_to<Q: ?Sized>(&mut self, value: &Q, quantity: usize) -> usize
757 where
758 T: Borrow<Q>,
759 Q: Hash + Eq,
760 {
761 match self.items.get_mut(value) {
762 None => 0,
763 Some(&mut n) if n <= quantity => {
764 self.count -= n;
765 self.items.remove(value);
766 0
767 }
768 Some(n) => {
769 self.count -= quantity;
770 *n -= quantity;
771 *n
772 }
773 }
774 }
775
776 /// Returns an iterator over all of the elements that are in `self` or `other`.
777 /// The iterator also yields the respective counts in `self` and `other` in that order.
778 /// Elements that are in `self` are yielded before any elements that are exclusively in `other`.
779 /// Each distinct element is yielded only once.
780 ///
781 /// # Examples
782 /// ```
783 /// use hashbag::HashBag;
784 /// use std::collections::HashSet;
785 /// use std::iter::FromIterator;
786 ///
787 /// let a: HashBag<_> = "hash".chars().collect();
788 /// let b: HashBag<_> = "math".chars().collect();
789 /// let expected: HashSet<_> = HashSet::from_iter([(&'h', 2, 1), (&'a', 1, 1), (&'s', 1, 0), (&'m', 0, 1), (&'t', 0, 1)]);
790 /// let actual: HashSet<_> = a.outer_join(&b).collect();
791 /// assert_eq!(expected, actual);
792 /// ```
793 pub fn outer_join<'a, OtherS>(
794 &'a self,
795 other: &'a HashBag<T, OtherS>,
796 ) -> impl Iterator<Item = (&'a T, usize, usize)>
797 where
798 OtherS: BuildHasher,
799 {
800 self.items
801 .iter()
802 .map(move |(x, &self_count)| (x, self_count, other.contains(x)))
803 .chain(other.items.iter().filter_map(move |(x, &other_count)| {
804 let self_count = self.contains(x);
805 if self_count == 0 {
806 Some((x, self_count, other_count))
807 } else {
808 None
809 }
810 }))
811 }
812
813 /// Returns an iterator over all the elements that are in `self` with a
814 /// higher occurrence count than in `other`. The count in the returned
815 /// iterator represents how many more of a given element are in `self` than
816 /// `other`.
817 ///
818 /// # Examples
819 ///
820 /// ```
821 /// use hashbag::HashBag;
822 /// use std::collections::HashSet;
823 /// use std::iter::FromIterator;
824 ///
825 /// let a: HashBag<_> = [1, 2, 3, 3].iter().cloned().collect();
826 /// let b: HashBag<_> = [2, 3].iter().cloned().collect();
827 /// let expected: HashSet<_> = HashSet::from_iter([(&1, 1), (&3, 1)]);
828 /// let actual: HashSet<_> = a.difference(&b).collect();
829 /// assert_eq!(expected, actual);
830 /// ```
831 pub fn difference<'a, OtherS>(
832 &'a self,
833 other: &'a HashBag<T, OtherS>,
834 ) -> impl Iterator<Item = (&'a T, usize)>
835 where
836 OtherS: BuildHasher,
837 {
838 self.outer_join(other)
839 .take_while(|(_, self_count, _)| self_count > &0)
840 .filter(|(_x, self_count, other_count)| self_count > other_count)
841 .map(|(x, self_count, other_count)| (x, self_count - other_count))
842 }
843
844 /// Returns an iterator over all the elements that are in `self` or `other`.
845 /// The iterator also yields the difference in counts between `self` and `other`.
846 ///
847 /// Unlike 'difference' which only yields elements that have a higher count in `self` than in `other`,
848 /// this iterator yields all elements that are in either of the `HashBag`s. Elements that have a higher
849 /// count in `other` than in self (including elements that are not in `self`) will have a negative count.
850 ///
851 /// If the difference can be represented as an `isize`, then it will be. Otherwise, the difference will be
852 /// clamped to `isize::MIN`/`isize::MAX`, thus keeping the sign of the difference, and as much of the
853 /// magnitude as possible.
854 ///
855 /// # Examples
856 ///
857 /// ```
858 /// use hashbag::HashBag;
859 /// use std::collections::HashSet;
860 /// use std::iter::FromIterator;
861 ///
862 /// let a: HashBag<_> = [1, 2, 3, 3].iter().cloned().collect();
863 /// let b: HashBag<_> = [2, 3, 4, 4].iter().cloned().collect();
864 /// let expected: HashSet<_> = HashSet::from_iter([(&1, 1), (&2, 0), (&3, 1), (&4, -2)]);
865 /// let actual: HashSet<_> = a.signed_difference(&b).collect();
866 /// assert_eq!(expected, actual);
867 /// ```
868 pub fn signed_difference<'a, OtherS>(
869 &'a self,
870 other: &'a HashBag<T, OtherS>,
871 ) -> impl Iterator<Item = (&'a T, isize)>
872 where
873 OtherS: BuildHasher,
874 {
875 self.outer_join(other).map(|(x, self_count, other_count)| {
876 let diff = if self_count >= other_count {
877 isize::try_from(self_count - other_count).unwrap_or(std::isize::MAX)
878 } else {
879 isize::try_from(other_count - self_count)
880 .map(|x| -x)
881 .unwrap_or(std::isize::MIN)
882 };
883 (x, diff)
884 })
885 }
886
887 /// Returns an iterator over all of the elements that are in `self` but not in `other`.
888 ///
889 /// # Examples
890 /// ```
891 /// use hashbag::HashBag;
892 /// use std::collections::HashSet;
893 /// use std::iter::FromIterator;
894 ///
895 /// let a: HashBag<_> = [1, 2, 3, 3].iter().cloned().collect();
896 /// let b: HashBag<_> = [2, 3].iter().cloned().collect();
897 /// let expected: HashSet<_> = HashSet::from_iter([(&1, 1)]);
898 /// let actual: HashSet<_> = a.not_in(&b).collect();
899 /// assert_eq!(expected, actual);
900 /// ```
901 pub fn not_in<'a, OtherS>(
902 &'a self,
903 other: &'a HashBag<T, OtherS>,
904 ) -> impl Iterator<Item = (&'a T, usize)>
905 where
906 OtherS: BuildHasher,
907 {
908 self.outer_join(other)
909 .take_while(|(_, self_count, _)| self_count > &0)
910 .filter_map(|(k, self_count, other_count)| {
911 if other_count == 0 {
912 Some((k, self_count))
913 } else {
914 None
915 }
916 })
917 }
918
919 /// Removes a value that is equal to the given one, and returns it if it was the last.
920 ///
921 /// If the matching value is not the last, a reference to the remainder is given, along with
922 /// the number of occurrences prior to the removal.
923 ///
924 /// The value may be any borrowed form of the bag's value type, but
925 /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
926 /// the value type.
927 ///
928 /// # Examples
929 ///
930 /// ```
931 /// use hashbag::HashBag;
932 ///
933 /// let mut bag: HashBag<_> = [1, 2, 3, 3].iter().cloned().collect();
934 /// assert_eq!(bag.try_take(&2), Ok(2));
935 /// assert_eq!(bag.try_take(&3), Err(Some((&3, 2))));
936 /// assert_eq!(bag.try_take(&3), Ok(3));
937 /// assert_eq!(bag.try_take(&4), Err(None));
938 /// ```
939 #[inline]
940 pub fn try_take<Q: ?Sized>(&mut self, value: &Q) -> Result<T, Option<(&T, usize)>>
941 where
942 T: Borrow<Q>,
943 Q: Hash + Eq,
944 {
945 // TODO: it should be possible to make this more efficient
946 match self.items.remove_entry(value) {
947 Some((t, 1)) => {
948 self.count -= 1;
949 Ok(t)
950 }
951 Some((t, n)) => {
952 self.count -= 1;
953 self.items.insert(t, n - 1);
954 Err(Some(
955 self.items
956 .get_key_value(value)
957 .map(|(t, n)| (t, *n + 1))
958 .unwrap(),
959 ))
960 }
961 None => Err(None),
962 }
963 }
964
965 /// Removes and returns all occurrences of the value, if any, that is equal to the given one.
966 ///
967 /// The value may be any borrowed form of the bag's value type, but
968 /// [`Hash`] and [`Eq`] on the borrowed form *must* match those for
969 /// the value type.
970 ///
971 /// # Examples
972 ///
973 /// ```
974 /// use hashbag::HashBag;
975 ///
976 /// let mut bag: HashBag<_> = [1, 2, 3, 3].iter().cloned().collect();
977 /// assert_eq!(bag.take_all(&2), Some((2, 1)));
978 /// assert_eq!(bag.take_all(&3), Some((3, 2)));
979 /// assert_eq!(bag.take_all(&2), None);
980 /// assert_eq!(bag.take_all(&3), None);
981 /// ```
982 #[inline]
983 pub fn take_all<Q: ?Sized>(&mut self, value: &Q) -> Option<(T, usize)>
984 where
985 T: Borrow<Q>,
986 Q: Hash + Eq,
987 {
988 let (t, n) = self.items.remove_entry(value)?;
989 self.count -= n;
990 Some((t, n))
991 }
992
993 /// Retains only the values specified by the predicate.
994 ///
995 /// In other words, for each value `v` retain only `f(&v)` occurrences.
996 ///
997 /// # Examples
998 ///
999 /// ```
1000 /// use hashbag::HashBag;
1001 ///
1002 /// let xs = [0,0,0,0,0,1,1,1,1,2,2,2,3,3,4];
1003 /// let mut bag: HashBag<i32> = xs.iter().cloned().collect();
1004 /// bag.retain(|&k, _| k as usize);
1005 /// assert_eq!(bag.set_len(), 4); // >= 1 of all but value 0
1006 /// assert_eq!(bag.len(), 6);
1007 /// assert_eq!(bag.contains(&0), 0);
1008 /// assert_eq!(bag.contains(&1), 1);
1009 /// assert_eq!(bag.contains(&2), 2);
1010 /// assert_eq!(bag.contains(&3), 2);
1011 /// assert_eq!(bag.contains(&4), 1);
1012 /// ```
1013 pub fn retain<F>(&mut self, mut f: F)
1014 where
1015 F: FnMut(&T, usize) -> usize,
1016 {
1017 let count = &mut self.count;
1018 self.items.retain(|t, n| {
1019 let keep = std::cmp::min(*n, f(t, *n));
1020 *count -= *n - keep;
1021 if keep == 0 {
1022 false
1023 } else {
1024 *n = keep;
1025 true
1026 }
1027 });
1028 }
1029}
1030
1031// ======== standard traits
1032
1033use std::fmt;
1034use std::marker::PhantomData;
1035
1036impl<T> fmt::Debug for HashBag<T>
1037where
1038 T: fmt::Debug,
1039{
1040 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1041 fmt.debug_set().entries(self.iter()).finish()
1042 }
1043}
1044
1045impl<T, S> Default for HashBag<T, S>
1046where
1047 T: Eq + Hash,
1048 S: BuildHasher + Default,
1049{
1050 fn default() -> Self {
1051 Self::with_hasher(S::default())
1052 }
1053}
1054
1055impl<T, S> PartialEq<HashBag<T, S>> for HashBag<T, S>
1056where
1057 T: Eq + Hash,
1058 S: BuildHasher,
1059{
1060 fn eq(&self, other: &Self) -> bool {
1061 self.count == other.count && self.items == other.items
1062 }
1063}
1064
1065impl<T, S> Eq for HashBag<T, S>
1066where
1067 T: Eq + Hash,
1068 S: BuildHasher,
1069{
1070}
1071
1072impl<'a, T, S> Extend<&'a T> for HashBag<T, S>
1073where
1074 T: 'a + Eq + Hash + Clone,
1075 S: BuildHasher,
1076{
1077 fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
1078 for e in iter {
1079 self.insert(e.clone());
1080 }
1081 }
1082}
1083
1084impl<'a, T, S> Extend<(&'a T, usize)> for HashBag<T, S>
1085where
1086 T: 'a + Eq + Hash + Clone,
1087 S: BuildHasher,
1088{
1089 fn extend<I: IntoIterator<Item = (&'a T, usize)>>(&mut self, iter: I) {
1090 for (e, n) in iter {
1091 self.count += n;
1092 *self.items.entry(e.clone()).or_insert(0) += n;
1093 }
1094 }
1095}
1096
1097impl<T, S> Extend<T> for HashBag<T, S>
1098where
1099 T: Eq + Hash,
1100 S: BuildHasher,
1101{
1102 fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
1103 for e in iter {
1104 self.insert(e);
1105 }
1106 }
1107}
1108
1109impl<T, S> Extend<(T, usize)> for HashBag<T, S>
1110where
1111 T: Eq + Hash,
1112 S: BuildHasher,
1113{
1114 fn extend<I: IntoIterator<Item = (T, usize)>>(&mut self, iter: I) {
1115 for (e, n) in iter {
1116 self.count += n;
1117 if n != 0 {
1118 *self.items.entry(e).or_insert(0) += n;
1119 }
1120 }
1121 }
1122}
1123
1124impl<T, S> std::iter::FromIterator<T> for HashBag<T, S>
1125where
1126 T: Eq + Hash,
1127 S: BuildHasher + Default,
1128{
1129 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1130 let mut bag = Self::default();
1131 bag.extend(iter);
1132 bag
1133 }
1134}
1135
1136impl<T, S> std::iter::FromIterator<(T, usize)> for HashBag<T, S>
1137where
1138 T: Eq + Hash,
1139 S: BuildHasher + Default,
1140{
1141 fn from_iter<I: IntoIterator<Item = (T, usize)>>(iter: I) -> Self {
1142 let mut bag = Self::default();
1143 bag.extend(iter);
1144 bag
1145 }
1146}
1147
1148impl<'a, T, S> IntoIterator for &'a HashBag<T, S> {
1149 type Item = &'a T;
1150 type IntoIter = Iter<'a, T>;
1151 fn into_iter(self) -> Iter<'a, T> {
1152 self.iter()
1153 }
1154}
1155
1156impl<T, S> IntoIterator for HashBag<T, S> {
1157 type Item = (T, usize);
1158 type IntoIter = IntoIter<T>;
1159 fn into_iter(self) -> IntoIter<T> {
1160 IntoIter(self.items.into_iter())
1161 }
1162}
1163
1164// ======== entry type
1165#[cfg(feature = "amortize")]
1166pub(crate) mod entry {
1167 use griddle::hash_map::Entry;
1168
1169 #[derive(Debug)]
1170 pub(crate) struct ForiegnEntry<'a, T, S> {
1171 pub(crate) entry: Entry<'a, T, usize, S>,
1172 }
1173
1174 impl<'a, T, S> ForiegnEntry<'a, T, S> {
1175 pub(crate) fn new(entry: Entry<'a, T, usize, S>) -> Self {
1176 Self { entry }
1177 }
1178
1179 pub(crate) fn get_mut(&mut self) -> Option<&mut usize> {
1180 match &mut self.entry {
1181 Entry::Occupied(entry) => Some(entry.get_mut()),
1182 Entry::Vacant(_) => None,
1183 }
1184 }
1185 }
1186}
1187#[cfg(not(feature = "amortize"))]
1188pub(crate) mod entry {
1189 use std::{collections::hash_map::Entry, marker::PhantomData};
1190
1191 #[derive(Debug)]
1192 pub(crate) struct ForiegnEntry<'a, T, S> {
1193 pub(crate) entry: Entry<'a, T, usize>,
1194 data: PhantomData<S>,
1195 }
1196
1197 impl<'a, T, S> ForiegnEntry<'a, T, S> {
1198 pub(crate) fn new(entry: Entry<'a, T, usize>) -> Self {
1199 Self {
1200 entry,
1201 data: PhantomData,
1202 }
1203 }
1204
1205 pub(crate) fn get_mut(&mut self) -> Option<&mut usize> {
1206 match &mut self.entry {
1207 Entry::Occupied(entry) => Some(entry.get_mut()),
1208 Entry::Vacant(_) => None,
1209 }
1210 }
1211 }
1212}
1213
1214use entry::ForiegnEntry;
1215
1216type EntryInner<'a, T, S> = (ForiegnEntry<'a, T, S>, &'a mut usize, PhantomData<S>);
1217
1218#[derive(Debug)]
1219/// A view into a single entry in the bag, which may either be vacant or occupied.
1220/// This `enum` is constructed from the [`entry`](HashBag::entry) method on [`HashBag`]
1221pub struct Entry<'a, T, S>(EntryInner<'a, T, S>);
1222
1223impl<'a, T, S> Entry<'a, T, S>
1224where
1225 T: Hash + Eq,
1226 S: BuildHasher,
1227{
1228 /// Provides in-place mutable access to an occupied entry before potential inserts into the
1229 /// map.
1230 pub fn and_modify<F>(mut self, f: F) -> Self
1231 where
1232 F: FnOnce(&mut usize),
1233 {
1234 if let Some(n) = self.0 .0.get_mut() {
1235 let init = *n;
1236 f(n);
1237 *self.0 .1 += *n;
1238 *self.0 .1 -= init;
1239 }
1240 Self((self.0 .0, self.0 .1, PhantomData))
1241 }
1242
1243 /// Returns a reference to the entry's value.
1244 pub fn value(&self) -> &T {
1245 self.0 .0.entry.key()
1246 }
1247
1248 /// Ensures there is at least one instance of the value before returning a mutable reference
1249 /// to the value's count
1250 pub fn or_insert(mut self) -> usize {
1251 if self.0 .0.get_mut().is_none() {
1252 *self.0 .1 += 1;
1253 }
1254 *self.0 .0.entry.or_insert(1)
1255 }
1256
1257 /// Ensures there is at least `quantity` instances of the value before returning a mutable reference
1258 /// to the value's count
1259 pub fn or_insert_many(mut self, quantity: usize) -> usize {
1260 if self.0 .0.get_mut().is_none() {
1261 *self.0 .1 += quantity;
1262 }
1263 *self.0 .0.entry.or_insert(quantity)
1264 }
1265}
1266
1267// ======== iterators
1268
1269#[cfg(feature = "amortize")]
1270type IterInner<'a, T> = griddle::hash_map::Iter<'a, T, usize>;
1271#[cfg(not(feature = "amortize"))]
1272type IterInner<'a, T> = std::collections::hash_map::Iter<'a, T, usize>;
1273
1274/// An iterator over the items of a `HashBag`.
1275///
1276/// Each value is repeated as many times as it occurs in the bag.
1277///
1278/// This `struct` is created by [`HashBag::iter`].
1279/// See its documentation for more.
1280pub struct Iter<'a, T> {
1281 iter: IterInner<'a, T>,
1282 repeat: Option<(&'a T, usize)>,
1283 left: usize,
1284}
1285
1286impl<'a, T> std::iter::FusedIterator for Iter<'a, T> where IterInner<'a, T>: std::iter::FusedIterator
1287{}
1288
1289impl<'a, T> ExactSizeIterator for Iter<'a, T> where IterInner<'a, T>: ExactSizeIterator {}
1290
1291impl<'a, T> Clone for Iter<'a, T> {
1292 fn clone(&self) -> Self {
1293 Iter {
1294 iter: self.iter.clone(),
1295 repeat: self.repeat,
1296 left: self.left,
1297 }
1298 }
1299}
1300
1301impl<T: fmt::Debug> fmt::Debug for Iter<'_, T> {
1302 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1303 fmt.debug_set().entries(self.clone()).finish()
1304 }
1305}
1306
1307impl<'a, T> Iter<'a, T> {
1308 fn new(it: IterInner<'a, T>, n: usize) -> Self {
1309 Self {
1310 iter: it,
1311 repeat: None,
1312 left: n,
1313 }
1314 }
1315}
1316
1317impl<'a, T> Iterator for Iter<'a, T> {
1318 type Item = &'a T;
1319 fn next(&mut self) -> Option<Self::Item> {
1320 if let Some((t, ref mut n)) = self.repeat {
1321 if *n == 0 {
1322 self.repeat = None;
1323 } else {
1324 *n -= 1;
1325 self.left -= 1;
1326 return Some(t);
1327 }
1328 }
1329
1330 let (next, n) = self.iter.next()?;
1331 if *n > 1 {
1332 self.repeat = Some((next, *n - 1));
1333 }
1334 self.left -= 1;
1335 Some(next)
1336 }
1337
1338 fn size_hint(&self) -> (usize, Option<usize>) {
1339 (self.left, Some(self.left))
1340 }
1341}
1342
1343/// An iterator over the distinct items of a `HashBag` and their occurrence counts.
1344///
1345/// This `struct` is created by [`HashBag::set_iter`].
1346/// See its documentation for more.
1347pub struct SetIter<'a, T>(IterInner<'a, T>);
1348
1349impl<'a, T> std::iter::FusedIterator for SetIter<'a, T> where
1350 IterInner<'a, T>: std::iter::FusedIterator
1351{
1352}
1353
1354impl<'a, T> ExactSizeIterator for SetIter<'a, T> where IterInner<'a, T>: ExactSizeIterator {}
1355
1356impl<'a, T> Clone for SetIter<'a, T> {
1357 fn clone(&self) -> Self {
1358 SetIter(self.0.clone())
1359 }
1360}
1361
1362impl<T: fmt::Debug> fmt::Debug for SetIter<'_, T> {
1363 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1364 fmt.debug_set().entries(self.clone()).finish()
1365 }
1366}
1367
1368impl<'a, T> Iterator for SetIter<'a, T> {
1369 type Item = (&'a T, usize);
1370 fn next(&mut self) -> Option<Self::Item> {
1371 self.0.next().map(|(t, n)| (t, *n))
1372 }
1373
1374 fn size_hint(&self) -> (usize, Option<usize>) {
1375 self.0.size_hint()
1376 }
1377}
1378
1379#[cfg(feature = "amortize")]
1380type IntoIterInner<T> = griddle::hash_map::IntoIter<T, usize>;
1381#[cfg(not(feature = "amortize"))]
1382type IntoIterInner<T> = std::collections::hash_map::IntoIter<T, usize>;
1383
1384/// An owning iterator over the distinct items of a `HashBag` and their occurrence counts.
1385///
1386/// This `struct` is created by using the implementation of [`IntoIterator`] for [`HashBag`].
1387pub struct IntoIter<T>(IntoIterInner<T>);
1388
1389impl<T> std::iter::FusedIterator for IntoIter<T> where IntoIterInner<T>: std::iter::FusedIterator {}
1390
1391impl<T> ExactSizeIterator for IntoIter<T> where IntoIterInner<T>: ExactSizeIterator {}
1392
1393impl<T: fmt::Debug> fmt::Debug for IntoIter<T> {
1394 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1395 self.0.fmt(fmt)
1396 }
1397}
1398
1399impl<T> Iterator for IntoIter<T> {
1400 type Item = (T, usize);
1401 fn next(&mut self) -> Option<Self::Item> {
1402 self.0.next()
1403 }
1404
1405 fn size_hint(&self) -> (usize, Option<usize>) {
1406 self.0.size_hint()
1407 }
1408}
1409
1410#[cfg(feature = "amortize")]
1411type DrainInner<'a, T> = griddle::hash_map::Drain<'a, T, usize>;
1412#[cfg(not(feature = "amortize"))]
1413type DrainInner<'a, T> = std::collections::hash_map::Drain<'a, T, usize>;
1414
1415/// An draining iterator over the distinct items of a `HashBag` and their occurrence counts.
1416///
1417/// This `struct` is created by [`HashBag::drain`].
1418/// See its documentation for more.
1419pub struct Drain<'a, T>(DrainInner<'a, T>);
1420
1421impl<'a, T> std::iter::FusedIterator for Drain<'a, T> where
1422 DrainInner<'a, T>: std::iter::FusedIterator
1423{
1424}
1425
1426impl<'a, T> ExactSizeIterator for Drain<'a, T> where DrainInner<'a, T>: ExactSizeIterator {}
1427
1428impl<'a, T: fmt::Debug> fmt::Debug for Drain<'a, T> {
1429 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
1430 self.0.fmt(fmt)
1431 }
1432}
1433
1434impl<'a, T> Iterator for Drain<'a, T> {
1435 type Item = (T, usize);
1436 fn next(&mut self) -> Option<Self::Item> {
1437 self.0.next()
1438 }
1439
1440 fn size_hint(&self) -> (usize, Option<usize>) {
1441 self.0.size_hint()
1442 }
1443}
1444
1445#[cfg(test)]
1446mod tests {
1447 use std::collections::HashSet;
1448 use std::iter::FromIterator;
1449
1450 use super::*;
1451
1452 #[test]
1453 fn format_all_the_things() {
1454 let mut vikings: HashBag<&'static str> =
1455 ["Einar", "Olaf", "Harald"].iter().cloned().collect();
1456 println!("{:?}", vikings);
1457 println!("{:?}", vikings.iter());
1458 println!("{:?}", vikings.set_iter());
1459 println!("{:?}", vikings.clone().into_iter());
1460 println!("{:?}", vikings.drain());
1461 }
1462
1463 #[test]
1464 fn sane_iterators() {
1465 let mut vikings: HashBag<&'static str> =
1466 ["Einar", "Einar", "Harald"].iter().cloned().collect();
1467 assert_eq!(vikings.iter().count(), 3);
1468 assert_eq!(vikings.iter().size_hint(), (3, Some(3)));
1469 assert_eq!(vikings.iter().clone().count(), 3);
1470 assert_eq!(vikings.set_iter().count(), 2);
1471 assert_eq!(vikings.set_iter().clone().count(), 2);
1472 assert_eq!(vikings.set_iter().size_hint(), (2, Some(2)));
1473 let ii = vikings.clone().into_iter();
1474 assert_eq!(ii.size_hint(), (2, Some(2)));
1475 assert_eq!(ii.count(), 2);
1476 let di = vikings.drain();
1477 assert_eq!(di.size_hint(), (2, Some(2)));
1478 assert_eq!(di.count(), 2);
1479 }
1480
1481 #[test]
1482 fn test_difference_size_hint() {
1483 let bag: HashBag<_> = [3, 2, 1].iter().cloned().collect();
1484 let empty_bag = HashBag::new();
1485 let mut difference = bag.difference(&empty_bag);
1486
1487 // Since the difference has the same number of entries as the bag, we
1488 // can predict how the size_hint() will behave, because the iteration
1489 // order does not matter
1490 assert_eq!(difference.size_hint(), (0, Some(3)));
1491 difference.next().unwrap();
1492 assert_eq!(difference.size_hint(), (0, Some(2)));
1493 difference.next().unwrap();
1494 assert_eq!(difference.size_hint(), (0, Some(1)));
1495 difference.next().unwrap();
1496 assert_eq!(difference.size_hint(), (0, Some(0)));
1497 assert_eq!(difference.next(), None);
1498 assert_eq!(difference.size_hint(), (0, Some(0)));
1499 }
1500
1501 #[test]
1502 fn test_difference_from_empty() {
1503 do_test_difference(&[], &[], &[]);
1504 do_test_difference(&[], &[1], &[]);
1505 do_test_difference(&[], &[1, 1], &[]);
1506 do_test_difference(&[], &[1, 1, 2], &[]);
1507 }
1508
1509 #[test]
1510 fn test_difference_from_one() {
1511 do_test_difference(&[1], &[], &[1]);
1512 do_test_difference(&[1], &[1], &[]);
1513 do_test_difference(&[1], &[1, 1], &[]);
1514 do_test_difference(&[1], &[2], &[1]);
1515 do_test_difference(&[1], &[1, 2], &[]);
1516 do_test_difference(&[1], &[2, 2], &[1]);
1517 }
1518
1519 #[test]
1520 fn test_difference_from_duplicate_ones() {
1521 do_test_difference(&[1, 1], &[], &[1, 1]);
1522 do_test_difference(&[1, 1], &[1], &[1]);
1523 do_test_difference(&[1, 1], &[1, 1], &[]);
1524 do_test_difference(&[1, 1], &[2], &[1, 1]);
1525 do_test_difference(&[1, 1], &[1, 2], &[1]);
1526 do_test_difference(&[1, 1], &[2, 2], &[1, 1]);
1527 }
1528
1529 #[test]
1530 fn test_difference_from_one_one_two() {
1531 do_test_difference(&[1, 1, 2], &[], &[1, 1, 2]);
1532 do_test_difference(&[1, 1, 2], &[1], &[1, 2]);
1533 do_test_difference(&[1, 1, 2], &[1, 1], &[2]);
1534 do_test_difference(&[1, 1, 2], &[2], &[1, 1]);
1535 do_test_difference(&[1, 1, 2], &[1, 2], &[1]);
1536 do_test_difference(&[1, 1, 2], &[2, 2], &[1, 1]);
1537 }
1538
1539 #[test]
1540 fn test_difference_from_larger_bags() {
1541 do_test_difference(&[1, 2, 2, 3], &[3], &[1, 2, 2]);
1542 do_test_difference(&[1, 2, 2, 3], &[4], &[1, 2, 2, 3]);
1543 do_test_difference(&[2, 2, 2, 2], &[2, 2], &[2, 2]);
1544 do_test_difference(&[2, 2, 2, 2], &[], &[2, 2, 2, 2]);
1545 }
1546
1547 fn do_test_difference(
1548 self_entries: &[isize],
1549 other_entries: &[isize],
1550 expected_entries: &[isize],
1551 ) {
1552 let this = self_entries.iter().collect::<HashBag<_>>();
1553 let other = other_entries.iter().collect::<HashBag<_>>();
1554 let expected = expected_entries.iter().collect::<HashBag<_>>();
1555 let mut actual = HashBag::new();
1556 for (t, n) in this.difference(&other) {
1557 actual.insert_many(*t, n);
1558 }
1559
1560 assert_eq!(actual, expected);
1561 }
1562
1563 #[test]
1564 fn test_outer_join_order_with_disjoint_sets() {
1565 do_test_outer_join_order(&[1, 2, 3], &[4, 5, 6]);
1566 do_test_outer_join_order(&[1, 2, 2, 3], &[4, 4, 5, 6]);
1567 }
1568
1569 #[test]
1570 fn test_outer_join_order_with_overlap() {
1571 do_test_outer_join_order(&[1, 2, 3], &[2, 3, 4]);
1572 do_test_outer_join_order(&[1, 1, 2, 3], &[2, 3, 3, 3, 4]);
1573 }
1574
1575 fn do_test_outer_join_order(this: &[usize], other: &[usize]) {
1576 let this_hashbag: HashBag<usize> = this.iter().cloned().collect();
1577 let other_hashbag: HashBag<usize> = other.iter().cloned().collect();
1578
1579 // Assert that the first yielded key that's exclusive to other (i.e. self_count is 0)
1580 // comes AFTER all of the keys in self
1581 let min_other_exclusive_key_idx = this_hashbag
1582 .outer_join(&other_hashbag)
1583 .enumerate()
1584 .find(|(_, (_, self_count, _))| self_count == &0)
1585 .map(|(idx, _)| idx);
1586 // If no such element exists that means all of the keys in other
1587 // are in self so there's no thing to assert.
1588 if let Some(idx) = min_other_exclusive_key_idx {
1589 assert_eq!(idx, this_hashbag.set_len());
1590 }
1591 }
1592
1593 #[test]
1594 fn test_outer_join_with_empty_self() {
1595 do_test_outer_join(&[], &[1, 2, 2, 3], &[(&1, 0, 1), (&2, 0, 2), (&3, 0, 1)]);
1596 }
1597
1598 #[test]
1599 fn test_outer_join_with_empty_other() {
1600 do_test_outer_join(&[1, 2, 2, 3], &[], &[(&1, 1, 0), (&2, 2, 0), (&3, 1, 0)]);
1601 }
1602
1603 #[test]
1604 fn test_outer_join_with_overlap() {
1605 do_test_outer_join(
1606 &[1, 2, 2, 3, 3],
1607 &[3, 4, 5, 5],
1608 &[(&1, 1, 0), (&2, 2, 0), (&3, 2, 1), (&4, 0, 1), (&5, 0, 2)],
1609 );
1610 }
1611
1612 fn do_test_outer_join(
1613 this: &[usize],
1614 other: &[usize],
1615 expected_entries: &[(&usize, usize, usize)],
1616 ) {
1617 let this_hashbag: HashBag<_> = this.iter().cloned().collect();
1618 let other_hashbag: HashBag<_> = other.iter().cloned().collect();
1619 let expected: HashSet<_> = HashSet::from_iter(expected_entries.iter().cloned());
1620 let actual: HashSet<_> = this_hashbag.outer_join(&other_hashbag).collect();
1621 assert_eq!(expected, actual);
1622 }
1623
1624 #[test]
1625 fn test_not_in_with_empty_self() {
1626 do_test_not_in(&[], &[1, 2, 3, 3], &[]);
1627 }
1628
1629 #[test]
1630 fn test_not_in_with_empty_other() {
1631 do_test_not_in(&[1, 2, 3, 3], &[], &[1, 2, 3, 3]);
1632 }
1633
1634 #[test]
1635 fn test_not_in_with_overlap() {
1636 do_test_not_in(&[1, 2, 3, 3], &[2, 4], &[1, 3, 3]);
1637 }
1638
1639 fn do_test_not_in(this: &[usize], other: &[usize], expected_entries: &[usize]) {
1640 let this_hashbag: HashBag<_> = this.iter().cloned().collect();
1641 let other_hashbag: HashBag<_> = other.iter().cloned().collect();
1642 let expected: HashBag<_> = expected_entries.iter().cloned().collect();
1643 let actual: HashBag<_> =
1644 this_hashbag
1645 .not_in(&other_hashbag)
1646 .fold(HashBag::new(), |mut bag, (k, count)| {
1647 bag.insert_many(*k, count);
1648 bag
1649 });
1650 assert_eq!(expected, actual);
1651 }
1652
1653 #[test]
1654 fn test_signed_difference_with_empty_self() {
1655 do_test_signed_difference(&[], &[1, 2, 2, 3], &[(&1, -1), (&2, -2), (&3, -1)]);
1656 }
1657
1658 #[test]
1659 fn test_signed_difference_with_empty_other() {
1660 do_test_signed_difference(&[1, 2, 2, 3], &[], &[(&1, 1), (&2, 2), (&3, 1)]);
1661 }
1662
1663 #[test]
1664 fn test_signed_difference_with_overlap() {
1665 do_test_signed_difference(
1666 &[1, 2, 2, 3, 3],
1667 &[3, 4, 5, 5],
1668 &[(&1, 1), (&2, 2), (&3, 1), (&4, -1), (&5, -2)],
1669 );
1670 }
1671
1672 #[test]
1673 fn test_signed_difference_with_both_large() {
1674 let mut this_hashbag = HashBag::new();
1675 let mut other_hashbag = HashBag::new();
1676
1677 let large_count = std::isize::MAX as usize;
1678 this_hashbag.insert_many(1, large_count + 1000);
1679 other_hashbag.insert_many(1, large_count);
1680
1681 let expected: HashSet<_> = HashSet::from_iter([(&1, 1000)].iter().cloned());
1682 let actual: HashSet<_> = this_hashbag.signed_difference(&other_hashbag).collect();
1683 assert_eq!(expected, actual);
1684
1685 // and in reverse:
1686 let expected: HashSet<_> = HashSet::from_iter([(&1, -1000)].iter().cloned());
1687 let actual: HashSet<_> = other_hashbag.signed_difference(&this_hashbag).collect();
1688 assert_eq!(expected, actual);
1689 }
1690
1691 #[test]
1692 fn test_signed_difference_too_large_to_hold_clamp() {
1693 let mut this_hashbag = HashBag::new();
1694 let empty_hashbag = HashBag::new();
1695
1696 let large_count = std::isize::MAX as usize;
1697 this_hashbag.insert_many(1, large_count + 1000);
1698
1699 let expected: HashSet<_> = HashSet::from_iter([(&1, std::isize::MAX)].iter().cloned());
1700 let actual: HashSet<_> = this_hashbag.signed_difference(&empty_hashbag).collect();
1701 assert_eq!(expected, actual);
1702
1703 // and in reverse:
1704 let expected: HashSet<_> = HashSet::from_iter([(&1, std::isize::MIN)].iter().cloned());
1705 let actual: HashSet<_> = empty_hashbag.signed_difference(&this_hashbag).collect();
1706 assert_eq!(expected, actual);
1707 }
1708
1709 fn do_test_signed_difference(
1710 this: &[usize],
1711 other: &[usize],
1712 expected_entries: &[(&usize, isize)],
1713 ) {
1714 let this_hashbag: HashBag<_> = this.iter().cloned().collect();
1715 let other_hashbag: HashBag<_> = other.iter().cloned().collect();
1716 let expected: HashSet<_> = HashSet::from_iter(expected_entries.iter().cloned());
1717 let actual: HashSet<_> = this_hashbag.signed_difference(&other_hashbag).collect();
1718 assert_eq!(expected, actual);
1719 }
1720
1721 #[test]
1722 fn test_no_zeros_counts() {
1723 let mut hashbag = HashBag::new();
1724 hashbag.insert(100);
1725 hashbag.retain(|_, _| 0);
1726 hashbag.insert_many(1, 0);
1727 hashbag.extend(vec![(2, 0)]);
1728 assert_eq!(hashbag.len(), 0);
1729 assert_eq!(hashbag.iter().count(), 0);
1730 assert_eq!(hashbag.set_len(), 0);
1731 assert_eq!(hashbag.set_iter().count(), 0);
1732 }
1733
1734 #[test]
1735 fn remove_up_to_affects_count() {
1736 let mut bag = HashBag::new();
1737 bag.insert_many(42, 3);
1738 assert_eq!(bag.len(), 3);
1739 assert_eq!(bag.remove_up_to(&0, 1), 0);
1740 assert_eq!(bag.len(), 3);
1741 assert_eq!(bag.remove_up_to(&42, 1), 2);
1742 assert_eq!(bag.len(), 2);
1743 assert_eq!(bag.remove_up_to(&42, 10), 0);
1744 assert_eq!(bag.len(), 0);
1745 }
1746
1747 #[test]
1748 fn entry_inserts_values() {
1749 let mut bag = HashBag::new();
1750 bag.entry(42);
1751 assert_eq!(bag.contains(&42), 0);
1752 bag.entry(84).or_insert_many(3);
1753 assert_eq!(bag.contains(&84), 3);
1754 assert_eq!(bag.len(), 3);
1755 bag.entry(84).or_insert_many(2);
1756 assert_eq!(bag.len(), 3);
1757 bag.entry(84).or_insert();
1758 assert_eq!(bag.len(), 3);
1759 }
1760
1761 #[test]
1762 fn entry_affects_count() {
1763 let mut bag = HashBag::new();
1764 bag.entry(42);
1765 assert_eq!(bag.len(), 0);
1766 bag.entry(42).and_modify(|n| *n += 3);
1767 assert_eq!(bag.len(), 0);
1768 bag.entry(42).or_insert_many(3);
1769 assert_eq!(bag.len(), 3);
1770 bag.entry(42).and_modify(|n| *n += 3);
1771 assert_eq!(bag.len(), 6);
1772 bag.entry(84).or_insert();
1773 assert_eq!(bag.len(), 7);
1774 }
1775}