diff options
Diffstat (limited to 'macros/src/util/iterator_ext.rs')
-rw-r--r-- | macros/src/util/iterator_ext.rs | 42 |
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!( |