diff --git a/src/duplicates_impl.rs b/src/duplicates_impl.rs index 853f97490..c947bea6c 100644 --- a/src/duplicates_impl.rs +++ b/src/duplicates_impl.rs @@ -19,13 +19,34 @@ mod private { pub(crate) meta: Meta, } - impl fmt::Debug for DuplicatesBy + impl fmt::Debug for DuplicatesBy where I: Iterator + fmt::Debug, V: fmt::Debug + Hash + Eq, S: BuildHasher, { - debug_fmt_fields!(DuplicatesBy, iter, meta.used); + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Duplicates") + .field("iter", &self.iter) + .field("seen", &self.meta.seen) + .field("pending", &self.meta.pending) + .finish() + } + } + + impl fmt::Debug for DuplicatesBy, S> + where + I: Iterator + fmt::Debug, + V: fmt::Debug + Hash + Eq, + S: BuildHasher, + { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("DuplicatesBy") + .field("iter", &self.iter) + .field("seen", &self.meta.seen) + .field("pending", &self.meta.pending) + .finish_non_exhaustive() + } } impl DuplicatesBy { @@ -33,7 +54,7 @@ mod private { Self { iter, meta: Meta { - used: HashMap::with_hasher(hash_builder), + seen: HashMap::with_hasher(hash_builder), pending: 0, key_method, }, @@ -43,7 +64,7 @@ mod private { #[derive(Clone)] pub struct Meta { - used: HashMap, + seen: HashMap, pending: usize, key_method: F, } @@ -61,9 +82,9 @@ mod private { F: KeyMethod, { let kv = self.key_method.make(item); - match self.used.get_mut(kv.key_ref()) { + match self.seen.get_mut(kv.key_ref()) { None => { - self.used.insert(kv.key(), false); + self.seen.insert(kv.key(), false); self.pending += 1; None } diff --git a/src/unique_impl.rs b/src/unique_impl.rs index 49c0055b7..215dff22e 100644 --- a/src/unique_impl.rs +++ b/src/unique_impl.rs @@ -19,17 +19,31 @@ where // Use a Hashmap for the Entry API in order to prevent hashing twice. // This can maybe be replaced with a HashSet once `get_or_insert_with` // or a proper Entry API for Hashset is stable and meets this msrv - used: HashMap, + seen: HashMap, f: F, } +/// Formats the keys of a `HashMap` used as a set, hiding the `()` values. +struct KeySet<'a, V, S>(&'a HashMap); + +impl fmt::Debug for KeySet<'_, V, S> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_set().entries(self.0.keys()).finish() + } +} + impl fmt::Debug for UniqueBy where I: Iterator + fmt::Debug, V: fmt::Debug + Hash + Eq, S: BuildHasher, { - debug_fmt_fields!(UniqueBy, iter, used); + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("UniqueBy") + .field("iter", &self.iter) + .field("seen", &KeySet(&self.seen)) + .finish_non_exhaustive() + } } /// Create a new `UniqueBy` iterator. @@ -42,22 +56,22 @@ where { UniqueBy { iter, - used: HashMap::with_hasher(hash_builder), + seen: HashMap::with_hasher(hash_builder), f, } } -// count the number of new unique keys in iterable (`used` is the set already seen) -fn count_new_keys(mut used: HashMap, iterable: I) -> usize +// count the number of new unique keys in iterable (`seen` is the set already seen) +fn count_new_keys(mut seen: HashMap, iterable: I) -> usize where I: IntoIterator, K: Hash + Eq, S: BuildHasher, { let iter = iterable.into_iter(); - let current_used = used.len(); - used.extend(iter.map(|key| (key, ()))); - used.len() - current_used + let current_seen = seen.len(); + seen.extend(iter.map(|key| (key, ()))); + seen.len() - current_seen } impl Iterator for UniqueBy @@ -70,19 +84,19 @@ where type Item = I::Item; fn next(&mut self) -> Option { - let Self { iter, used, f } = self; - iter.find(|v| used.insert(f(v), ()).is_none()) + let Self { iter, seen, f } = self; + iter.find(|v| seen.insert(f(v), ()).is_none()) } #[inline] fn size_hint(&self) -> (usize, Option) { let (low, hi) = self.iter.size_hint(); - (usize::from(low > 0 && self.used.is_empty()), hi) + (usize::from(low > 0 && self.seen.is_empty()), hi) } fn count(self) -> usize { let mut key_f = self.f; - count_new_keys(self.used, self.iter.map(move |elt| key_f(&elt))) + count_new_keys(self.seen, self.iter.map(move |elt| key_f(&elt))) } } @@ -94,8 +108,8 @@ where S: BuildHasher, { fn next_back(&mut self) -> Option { - let Self { iter, used, f } = self; - iter.rfind(|v| used.insert(f(v), ()).is_none()) + let Self { iter, seen, f } = self; + iter.rfind(|v| seen.insert(f(v), ()).is_none()) } } @@ -117,9 +131,9 @@ where type Item = I::Item; fn next(&mut self) -> Option { - let UniqueBy { iter, used, .. } = &mut self.iter; + let UniqueBy { iter, seen, .. } = &mut self.iter; iter.find_map(|v| { - if let Entry::Vacant(entry) = used.entry(v) { + if let Entry::Vacant(entry) = seen.entry(v) { let elt = entry.key().clone(); entry.insert(()); return Some(elt); @@ -131,11 +145,11 @@ where #[inline] fn size_hint(&self) -> (usize, Option) { let (low, hi) = self.iter.iter.size_hint(); - (usize::from(low > 0 && self.iter.used.is_empty()), hi) + (usize::from(low > 0 && self.iter.seen.is_empty()), hi) } fn count(self) -> usize { - count_new_keys(self.iter.used, self.iter.iter) + count_new_keys(self.iter.seen, self.iter.iter) } } @@ -146,9 +160,9 @@ where S: BuildHasher, { fn next_back(&mut self) -> Option { - let UniqueBy { iter, used, .. } = &mut self.iter; + let UniqueBy { iter, seen, .. } = &mut self.iter; iter.rev().find_map(|v| { - if let Entry::Vacant(entry) = used.entry(v) { + if let Entry::Vacant(entry) = seen.entry(v) { let elt = entry.key().clone(); entry.insert(()); return Some(elt); @@ -186,7 +200,12 @@ where I::Item: Hash + Eq + fmt::Debug + Clone, S: BuildHasher, { - debug_fmt_fields!(Unique, iter); + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("Unique") + .field("iter", &self.iter.iter) + .field("seen", &KeySet(&self.iter.seen)) + .finish() + } } pub fn unique_with_hasher(iter: I, hash_builder: S) -> Unique @@ -198,7 +217,7 @@ where Unique { iter: UniqueBy { iter, - used: HashMap::with_hasher(hash_builder), + seen: HashMap::with_hasher(hash_builder), f: (), }, }