From 4dec5ef1155a36ba5a957707c7bca0b5d1ea63bb Mon Sep 17 00:00:00 2001 From: Mingun Date: Wed, 2 Jan 2019 18:05:52 +0500 Subject: [PATCH 1/4] IndexMap: Implement Clone, Debug and add documentation for structures Clone for: Keys, Values, Iter Debug for: Keys, Values, Iter, Entry Docs for: Keys, Values, Iter, Entry, ValuesMut, IterMut, IntoIter, Drain All copied from HashMap --- Cargo.toml | 4 +- src/map.rs | 171 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4e1de435..a0548389 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "indexmap" -version = "1.0.2" +version = "1.1.0" authors = [ "bluss", "Josh Stone " @@ -31,7 +31,7 @@ bench = false serde = { version = "1.0", optional = true } [dev-dependencies] -itertools = "0.7.0" +itertools = "0.7.0" # 0.8 not compiles on Rust 1.18 rand = "0.4" quickcheck = { version = "0.6", default-features = false } fnv = "1.0" diff --git a/src/map.rs b/src/map.rs index fccbde16..7932def4 100644 --- a/src/map.rs +++ b/src/map.rs @@ -580,6 +580,27 @@ impl<'a, K, V> Entry<'a, K, V> { } } +impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for Entry<'a, K, V> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Entry::Vacant(ref v) => { + f.debug_tuple("Entry") + .field(v) + .finish() + } + Entry::Occupied(ref o) => { + f.debug_tuple("Entry") + .field(o) + .finish() + } + } + } +} + +/// A view into an occupied entry in a `IndexMap`. +/// It is part of the [`Entry`] enum. +/// +/// [`Entry`]: enum.Entry.html pub struct OccupiedEntry<'a, K: 'a, V: 'a> { map: &'a mut OrderMapCore, key: K, @@ -625,7 +646,19 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> { } } +impl<'a, K: 'a + fmt::Debug, V: 'a + fmt::Debug> fmt::Debug for OccupiedEntry<'a, K, V> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_struct("OccupiedEntry") + .field("key", self.key()) + .field("value", self.get()) + .finish() + } +} +/// A view into a vacant entry in a `IndexMap`. +/// It is part of the [`Entry`] enum. +/// +/// [`Entry`]: enum.Entry.html pub struct VacantEntry<'a, K: 'a, V: 'a> { map: &'a mut OrderMapCore, key: K, @@ -657,6 +690,14 @@ impl<'a, K, V> VacantEntry<'a, K, V> { } } +impl<'a, K: 'a + fmt::Debug, V: 'a> fmt::Debug for VacantEntry<'a, K, V> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("VacantEntry") + .field(self.key()) + .finish() + } +} + impl IndexMap where K: Hash + Eq, S: BuildHasher, @@ -1455,6 +1496,13 @@ use std::slice::Iter as SliceIter; use std::slice::IterMut as SliceIterMut; use std::vec::IntoIter as VecIntoIter; +/// An iterator over the keys of a `IndexMap`. +/// +/// This `struct` is created by the [`keys`] method on [`IndexMap`]. See its +/// documentation for more. +/// +/// [`keys`]: struct.IndexMap.html#method.keys +/// [`IndexMap`]: struct.IndexMap.html pub struct Keys<'a, K: 'a, V: 'a> { pub(crate) iter: SliceIter<'a, Bucket>, } @@ -1477,6 +1525,28 @@ impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> { } } +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +impl<'a, K, V> Clone for Keys<'a, K, V> { + fn clone(&self) -> Keys<'a, K, V> { + Keys { iter: self.iter.clone() } + } +} + +impl<'a, K: fmt::Debug, V> fmt::Debug for Keys<'a, K, V> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.clone()) + .finish() + } +} + +/// An iterator over the values of a `IndexMap`. +/// +/// This `struct` is created by the [`values`] method on [`IndexMap`]. See its +/// documentation for more. +/// +/// [`values`]: struct.IndexMap.html#method.values +/// [`IndexMap`]: struct.IndexMap.html pub struct Values<'a, K: 'a, V: 'a> { iter: SliceIter<'a, Bucket>, } @@ -1499,6 +1569,28 @@ impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> { } } +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +impl<'a, K, V> Clone for Values<'a, K, V> { + fn clone(&self) -> Values<'a, K, V> { + Values { iter: self.iter.clone() } + } +} + +impl<'a, K, V: fmt::Debug> fmt::Debug for Values<'a, K, V> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.clone()) + .finish() + } +} + +/// A mutable iterator over the values of a `IndexMap`. +/// +/// This `struct` is created by the [`values_mut`] method on [`IndexMap`]. See its +/// documentation for more. +/// +/// [`values_mut`]: struct.IndexMap.html#method.values_mut +/// [`IndexMap`]: struct.IndexMap.html pub struct ValuesMut<'a, K: 'a, V: 'a> { iter: SliceIterMut<'a, Bucket>, } @@ -1521,6 +1613,13 @@ impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { } } +/// An iterator over the entries of a `IndexMap`. +/// +/// This `struct` is created by the [`iter`] method on [`IndexMap`]. See its +/// documentation for more. +/// +/// [`iter`]: struct.IndexMap.html#method.iter +/// [`IndexMap`]: struct.IndexMap.html pub struct Iter<'a, K: 'a, V: 'a> { iter: SliceIter<'a, Bucket>, } @@ -1543,6 +1642,28 @@ impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> { } } +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +impl<'a, K, V> Clone for Iter<'a, K, V> { + fn clone(&self) -> Iter<'a, K, V> { + Iter { iter: self.iter.clone() } + } +} + +impl<'a, K: fmt::Debug, V: fmt::Debug> fmt::Debug for Iter<'a, K, V> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list() + .entries(self.clone()) + .finish() + } +} + +/// A mutable iterator over the entries of a `IndexMap`. +/// +/// This `struct` is created by the [`iter_mut`] method on [`IndexMap`]. See its +/// documentation for more. +/// +/// [`iter_mut`]: struct.IndexMap.html#method.iter_mut +/// [`IndexMap`]: struct.IndexMap.html pub struct IterMut<'a, K: 'a, V: 'a> { iter: SliceIterMut<'a, Bucket>, } @@ -1565,6 +1686,13 @@ impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { } } +/// An owning iterator over the entries of a `IndexMap`. +/// +/// This `struct` is created by the [`into_iter`] method on [`IndexMap`] +/// (provided by the `IntoIterator` trait). See its documentation for more. +/// +/// [`into_iter`]: struct.IndexMap.html#method.into_iter +/// [`IndexMap`]: struct.IndexMap.html pub struct IntoIter { pub(crate) iter: VecIntoIter>, } @@ -1587,6 +1715,13 @@ impl ExactSizeIterator for IntoIter { } } +/// A draining iterator over the entries of a `IndexMap`. +/// +/// This `struct` is created by the [`drain`] method on [`IndexMap`]. See its +/// documentation for more. +/// +/// [`drain`]: struct.IndexMap.html#method.drain +/// [`IndexMap`]: struct.IndexMap.html pub struct Drain<'a, K, V> where K: 'a, V: 'a { pub(crate) iter: ::std::vec::Drain<'a, Bucket> } @@ -2047,4 +2182,40 @@ mod tests { assert_eq!(&mut TestEnum::DefaultValue, map.entry(2).or_default()); } + + #[test] + fn keys() { + let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; + let map: IndexMap<_, _> = vec.into_iter().collect(); + let keys: Vec<_> = map.keys().cloned().collect(); + assert_eq!(keys.len(), 3); + assert!(keys.contains(&1)); + assert!(keys.contains(&2)); + assert!(keys.contains(&3)); + } + + #[test] + fn values() { + let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')]; + let map: IndexMap<_, _> = vec.into_iter().collect(); + let values: Vec<_> = map.values().cloned().collect(); + assert_eq!(values.len(), 3); + assert!(values.contains(&'a')); + assert!(values.contains(&'b')); + assert!(values.contains(&'c')); + } + + #[test] + fn values_mut() { + let vec = vec![(1, 1), (2, 2), (3, 3)]; + let mut map: IndexMap<_, _> = vec.into_iter().collect(); + for value in map.values_mut() { + *value = (*value) * 2 + } + let values: Vec<_> = map.values().cloned().collect(); + assert_eq!(values.len(), 3); + assert!(values.contains(&2)); + assert!(values.contains(&4)); + assert!(values.contains(&6)); + } } From 52330ea1befcd3cc49cde4d4f414fca950c9320e Mon Sep 17 00:00:00 2001 From: Mingun Date: Wed, 2 Jan 2019 18:42:21 +0500 Subject: [PATCH 2/4] IndexSet: Implement Clone, Debug and add documentation for structures Clone for: Iter, Difference, Intersection, SymmetricDifference, Union Debug for: Iter, Difference, Intersection, SymmetricDifference, Union Docs for: Iter, Difference, Intersection, SymmetricDifference, Union, IntoIter, Drain All copied from HashSet --- src/set.rs | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/src/set.rs b/src/set.rs index c1ba3b6d..f0bfbe95 100644 --- a/src/set.rs +++ b/src/set.rs @@ -423,6 +423,13 @@ impl IndexSet { } +/// An owning iterator over the items of a `IndexSet`. +/// +/// This `struct` is created by the [`into_iter`] method on [`IndexSet`] +/// (provided by the `IntoIterator` trait). See its documentation for more. +/// +/// [`IndexSet`]: struct.IndexSet.html +/// [`into_iter`]: struct.IndexSet.html#method.into_iter pub struct IntoIter { iter: vec::IntoIter>, } @@ -446,6 +453,13 @@ impl ExactSizeIterator for IntoIter { } +/// An iterator over the items of a `IndexSet`. +/// +/// This `struct` is created by the [`iter`] method on [`IndexSet`]. +/// See its documentation for more. +/// +/// [`IndexSet`]: struct.IndexSet.html +/// [`iter`]: struct.IndexSet.html#method.iter pub struct Iter<'a, T: 'a> { iter: slice::Iter<'a, Bucket>, } @@ -468,6 +482,25 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> { } } +impl<'a, T> Clone for Iter<'a, T> { + fn clone(&self) -> Self { + Iter { iter: self.iter.clone() } + } +} + +impl<'a, T: fmt::Debug> fmt::Debug for Iter<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + +/// A draining iterator over the items of a `IndexSet`. +/// +/// This `struct` is created by the [`drain`] method on [`IndexSet`]. +/// See its documentation for more. +/// +/// [`IndexSet`]: struct.IndexSet.html +/// [`drain`]: struct.IndexSet.html#method.drain pub struct Drain<'a, T: 'a> { iter: vec::Drain<'a, Bucket>, } @@ -595,6 +628,13 @@ impl IndexSet } +/// A lazy iterator producing elements in the difference of `IndexSet`s. +/// +/// This `struct` is created by the [`difference`] method on [`IndexSet`]. +/// See its documentation for more. +/// +/// [`IndexSet`]: struct.IndexSet.html +/// [`difference`]: struct.IndexSet.html#method.difference pub struct Difference<'a, T: 'a, S: 'a> { iter: Iter<'a, T>, other: &'a IndexSet, @@ -634,7 +674,29 @@ impl<'a, T, S> DoubleEndedIterator for Difference<'a, T, S> } } +impl<'a, T, S> Clone for Difference<'a, T, S> { + fn clone(&self) -> Self { + Difference { iter: self.iter.clone(), ..*self } + } +} + +impl<'a, T, S> fmt::Debug for Difference<'a, T, S> + where T: fmt::Debug + Eq + Hash, + S: BuildHasher +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + +/// A lazy iterator producing elements in the intersection of `IndexSet`s. +/// +/// This `struct` is created by the [`intersection`] method on [`IndexSet`]. +/// See its documentation for more. +/// +/// [`IndexSet`]: struct.IndexSet.html +/// [`intersection`]: struct.IndexSet.html#method.intersection pub struct Intersection<'a, T: 'a, S: 'a> { iter: Iter<'a, T>, other: &'a IndexSet, @@ -674,7 +736,29 @@ impl<'a, T, S> DoubleEndedIterator for Intersection<'a, T, S> } } +impl<'a, T, S> Clone for Intersection<'a, T, S> { + fn clone(&self) -> Self { + Intersection { iter: self.iter.clone(), ..*self } + } +} + +impl<'a, T, S> fmt::Debug for Intersection<'a, T, S> + where T: fmt::Debug + Eq + Hash, + S: BuildHasher, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + +/// A lazy iterator producing elements in the symmetric difference of `IndexSet`s. +/// +/// This `struct` is created by the [`symmetric_difference`] method on +/// [`IndexSet`]. See its documentation for more. +/// +/// [`IndexSet`]: struct.IndexSet.html +/// [`symmetric_difference`]: struct.IndexSet.html#method.symmetric_difference pub struct SymmetricDifference<'a, T: 'a, S1: 'a, S2: 'a> { iter: Chain, Difference<'a, T, S1>>, } @@ -711,7 +795,30 @@ impl<'a, T, S1, S2> DoubleEndedIterator for SymmetricDifference<'a, T, S1, S2> } } +impl<'a, T, S1, S2> Clone for SymmetricDifference<'a, T, S1, S2> { + fn clone(&self) -> Self { + SymmetricDifference { iter: self.iter.clone() } + } +} +impl<'a, T, S1, S2> fmt::Debug for SymmetricDifference<'a, T, S1, S2> + where T: fmt::Debug + Eq + Hash, + S1: BuildHasher, + S2: BuildHasher, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + + +/// A lazy iterator producing elements in the union of `IndexSet`s. +/// +/// This `struct` is created by the [`union`] method on [`IndexSet`]. +/// See its documentation for more. +/// +/// [`IndexSet`]: struct.IndexSet.html +/// [`union`]: struct.IndexSet.html#method.union pub struct Union<'a, T: 'a, S: 'a> { iter: Chain, Difference<'a, T, S>>, } @@ -746,6 +853,21 @@ impl<'a, T, S> DoubleEndedIterator for Union<'a, T, S> } } +impl<'a, T, S> Clone for Union<'a, T, S> { + fn clone(&self) -> Self { + Union { iter: self.iter.clone() } + } +} + +impl<'a, T, S> fmt::Debug for Union<'a, T, S> + where T: fmt::Debug + Eq + Hash, + S: BuildHasher, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_list().entries(self.clone()).finish() + } +} + impl<'a, 'b, T, S1, S2> BitAnd<&'b IndexSet> for &'a IndexSet where T: Eq + Hash + Clone, From 6476531b5febfd9b07efe72a82e79e5035b1bebf Mon Sep 17 00:00:00 2001 From: Mingun Date: Wed, 2 Jan 2019 19:15:46 +0500 Subject: [PATCH 3/4] Add changelog entry --- README.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.rst b/README.rst index bde10609..62554265 100644 --- a/README.rst +++ b/README.rst @@ -108,6 +108,14 @@ Ideas that we already did Recent Changes ============== +- 1.1.0 + + - Implemented ``Clone`` for ``Keys``, ``Values``, ``Iter`` (for map and set), + ``Difference``, ``Intersection``, ``SymmetricDifference`` and ``Union`` + + - Implemented ``Debug`` for ``Keys``, ``Values``, ``Iter`` (for map and set), + ``Entry``, ``Difference``, ``Intersection``, ``SymmetricDifference`` and ``Union`` + - 1.0.2 - The new methods ``IndexMap::insert_full`` and ``IndexSet::insert_full`` are From 33fd850ae3cdbe26331aa8da1688df985e825b69 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 20 Feb 2019 08:59:32 -0800 Subject: [PATCH 4/4] Implement `Debug` for `map::IntoIter` and `set::IntoIter` --- README.rst | 8 ++++---- src/map.rs | 7 +++++++ src/set.rs | 7 +++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 62554265..a250092d 100644 --- a/README.rst +++ b/README.rst @@ -110,11 +110,11 @@ Recent Changes - 1.1.0 - - Implemented ``Clone`` for ``Keys``, ``Values``, ``Iter`` (for map and set), - ``Difference``, ``Intersection``, ``SymmetricDifference`` and ``Union`` + - Implemented ``Clone`` for ``map::{Iter, Keys, Values}`` and + ``set::{Difference, Intersection, Iter, SymmetricDifference, Union}`` - - Implemented ``Debug`` for ``Keys``, ``Values``, ``Iter`` (for map and set), - ``Entry``, ``Difference``, ``Intersection``, ``SymmetricDifference`` and ``Union`` + - Implemented ``Debug`` for ``map::{Entry, IntoIter, Iter, Keys, Values}`` and + ``set::{Difference, Intersection, IntoIter, Iter, SymmetricDifference, Union}`` - 1.0.2 diff --git a/src/map.rs b/src/map.rs index 7932def4..a52d3d88 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1715,6 +1715,13 @@ impl ExactSizeIterator for IntoIter { } } +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let iter = self.iter.as_slice().iter().map(Bucket::refs); + f.debug_list().entries(iter).finish() + } +} + /// A draining iterator over the entries of a `IndexMap`. /// /// This `struct` is created by the [`drain`] method on [`IndexMap`]. See its diff --git a/src/set.rs b/src/set.rs index f0bfbe95..7d1a956a 100644 --- a/src/set.rs +++ b/src/set.rs @@ -452,6 +452,13 @@ impl ExactSizeIterator for IntoIter { } } +impl fmt::Debug for IntoIter { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let iter = self.iter.as_slice().iter().map(Bucket::key_ref); + f.debug_list().entries(iter).finish() + } +} + /// An iterator over the items of a `IndexSet`. ///