aboutsummaryrefslogtreecommitdiff
path: root/macros/src/util/iterator_ext.rs
diff options
context:
space:
mode:
Diffstat (limited to 'macros/src/util/iterator_ext.rs')
-rw-r--r--macros/src/util/iterator_ext.rs42
1 files changed, 30 insertions, 12 deletions
diff --git a/macros/src/util/iterator_ext.rs b/macros/src/util/iterator_ext.rs
index 5001068..17482ae 100644
--- a/macros/src/util/iterator_ext.rs
+++ b/macros/src/util/iterator_ext.rs
@@ -1,26 +1,39 @@
-use std::collections::HashMap;
+use std::collections::HashSet;
use std::hash::Hash;
+/// [`Iterator`] extension trait.
pub trait IteratorExt<Item>
+where
+ Item: Eq + Hash,
{
- fn find_duplicate(&mut self) -> Option<Item>;
+ /// Finds the first occurance of a duplicate item.
+ ///
+ /// This function is short-circuiting. So it will immedietly return `Some` when
+ /// it comes across a item it has already seen.
+ ///
+ /// The returned tuple contains the first item occurance & the second item occurance.
+ /// In that specific order.
+ ///
+ /// Both items are returned in the case of the hash not being representative of the
+ /// whole item.
+ fn find_duplicate(self) -> Option<(Item, Item)>;
}
impl<Iter> IteratorExt<Iter::Item> for Iter
where
Iter: Iterator,
- Iter::Item: Eq + Hash + Clone,
+ Iter::Item: Eq + Hash,
{
- fn find_duplicate(&mut self) -> Option<Iter::Item>
+ fn find_duplicate(self) -> Option<(Iter::Item, Iter::Item)>
{
- let mut iterated_item_map = HashMap::<Iter::Item, ()>::new();
+ let mut iterated_item_map = HashSet::<Iter::Item>::new();
for item in self {
- if iterated_item_map.contains_key(&item) {
- return Some(item);
+ if let Some(equal_item) = iterated_item_map.take(&item) {
+ return Some((item, equal_item));
}
- iterated_item_map.insert(item, ());
+ iterated_item_map.insert(item);
}
None
@@ -33,7 +46,7 @@ mod tests
use super::*;
#[test]
- fn can_find_duplicate()
+ fn can_find_dupe()
{
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
struct Fruit
@@ -58,9 +71,14 @@ mod tests
]
.iter()
.find_duplicate(),
- Some(&Fruit {
- name: "Apple".to_string()
- })
+ Some((
+ &Fruit {
+ name: "Apple".to_string()
+ },
+ &Fruit {
+ name: "Apple".to_string()
+ }
+ ))
);
assert_eq!(