Skip to content

Commit f98dbf5

Browse files
authored
Merge pull request #6 from hmuendel/intoIter
Implement intoIter for MultiMap and &MultiMap
2 parents 4041f3a + 73b407b commit f98dbf5

File tree

1 file changed

+136
-4
lines changed

1 file changed

+136
-4
lines changed

src/lib.rs

Lines changed: 136 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
//! ```
4141
4242
use std::borrow::Borrow;
43-
use std::collections::hash_map::Iter;
43+
use std::collections::hash_map;
4444
use std::collections::HashMap;
4545
use std::fmt::{self, Debug};
4646
use std::hash::Hash;
@@ -221,10 +221,13 @@ impl<K1: Eq + Hash + Clone, K2: Eq + Hash + Clone, V> MultiMap<K1, K2, V> {
221221
result
222222
}
223223

224-
/// Iterate through all the values in the MultiMap. Note that the values
224+
/// Iterate through all the values in the MultiMap in random order.
225+
/// Note that the values
225226
/// are `(K2, V)` tuples, not `V`, as you would get with a HashMap.
226-
pub fn iter(&self) -> Iter<K1, (K2, V)> {
227-
self.value_map.iter()
227+
pub fn iter(&self) -> Iter<'_, K1, K2, V> {
228+
Iter {
229+
base: self.value_map.iter(),
230+
}
228231
}
229232
}
230233

@@ -246,6 +249,93 @@ impl<K1: Eq + Hash + Debug, K2: Eq + Hash + Debug, V: Debug> fmt::Debug for Mult
246249
}
247250
}
248251

252+
/// An iterator over the entries of a `MultiMap` like in a `HashMap` but with
253+
/// values of the form (K2, V) instead of V.
254+
///
255+
///
256+
/// This `struct` is created by the [`iter`] method on [`MultiMap`]. See its
257+
/// documentation for more.
258+
///
259+
#[derive(Clone, Debug)]
260+
pub struct Iter<'a, K1: 'a, K2: 'a, V: 'a> {
261+
base: hash_map::Iter<'a, K1, (K2, V)>,
262+
}
263+
264+
/// An owning iterator over the entries of a `MultiMap`.
265+
///
266+
/// This `struct` is created by the [`into_iter`] method on [`MultiMap`]
267+
/// (provided by the `IntoIterator` trait). See its documentation for more.
268+
///
269+
pub struct IntoIter<K1, K2, V> {
270+
base: hash_map::IntoIter<K1, (K2, V)>,
271+
}
272+
// TODO: `HashMap` also implements this, do we need this as well?
273+
// impl<K, V> IntoIter<K, V> {
274+
// /// Returns a iterator of references over the remaining items.
275+
// #[inline]
276+
// pub(super) fn iter(&self) -> Iter<'_, K, V> {
277+
// Iter { base: self.base.rustc_iter() }
278+
// }
279+
// }
280+
281+
impl<K1, K2, V> IntoIterator for MultiMap<K1, K2, V>
282+
where
283+
K1: Eq + Hash + Debug,
284+
K2: Eq + Hash + Debug,
285+
V: Debug,
286+
{
287+
type Item = (K1, (K2, V));
288+
type IntoIter = IntoIter<K1, K2, V>;
289+
290+
/// Creates a consuming iterator, that is, one that moves each key-value
291+
/// pair out of the map in arbitrary order. The map cannot be used after
292+
/// calling this.
293+
///
294+
fn into_iter(self) -> IntoIter<K1, K2, V> {
295+
IntoIter {
296+
base: self.value_map.into_iter(),
297+
}
298+
}
299+
}
300+
301+
impl<'a, K1, K2, V> IntoIterator for &'a MultiMap<K1, K2, V>
302+
where
303+
K1: Eq + Hash + Debug + Clone,
304+
K2: Eq + Hash + Debug + Clone,
305+
V: Debug,
306+
{
307+
type Item = (&'a K1, &'a (K2, V));
308+
type IntoIter = Iter<'a, K1, K2, V>;
309+
310+
fn into_iter(self) -> Iter<'a, K1, K2, V> {
311+
self.iter()
312+
}
313+
}
314+
315+
impl<'a, K1, K2, V> Iterator for Iter<'a, K1, K2, V> {
316+
type Item = (&'a K1, &'a (K2, V));
317+
318+
fn next(&mut self) -> Option<(&'a K1, &'a (K2, V))> {
319+
self.base.next()
320+
}
321+
#[inline]
322+
fn size_hint(&self) -> (usize, Option<usize>) {
323+
self.base.size_hint()
324+
}
325+
}
326+
327+
impl<K1, K2, V> Iterator for IntoIter<K1, K2, V> {
328+
type Item = (K1, (K2, V));
329+
330+
#[inline]
331+
fn next(&mut self) -> Option<(K1, (K2, V))> {
332+
self.base.next()
333+
}
334+
#[inline]
335+
fn size_hint(&self) -> (usize, Option<usize>) {
336+
self.base.size_hint()
337+
}
338+
}
249339
#[macro_export]
250340
/// Create a `MultiMap` from a list of key-value tuples
251341
///
@@ -333,6 +423,48 @@ mod test {
333423
assert!(map.get_alt(&"Three") == None);
334424
assert!(map.get(&3) == None);
335425
}
426+
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
427+
struct MultiCount<'a>(i32, &'a str, &'a str);
428+
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
429+
struct MultiCountOwned(i32, String, String);
430+
431+
#[test]
432+
fn into_iter_test() {
433+
use MultiMap;
434+
let mut map = MultiMap::new();
435+
436+
map.insert(1, "One", String::from("Eins"));
437+
map.insert(2, "Two", String::from("Zwei"));
438+
map.insert(3, "Three", String::from("Drei"));
439+
440+
let mut vec_borrow = Vec::new();
441+
for (k1, (k2, v)) in &map {
442+
vec_borrow.push(MultiCount(*k1, *k2, v));
443+
}
444+
vec_borrow.sort();
445+
assert_eq!(
446+
vec_borrow,
447+
vec!(
448+
MultiCount(1, "One", "Eins"),
449+
MultiCount(2, "Two", "Zwei"),
450+
MultiCount(3, "Three", "Drei")
451+
)
452+
);
453+
454+
let mut vec_owned = Vec::new();
455+
for (k1, (k2, v)) in map {
456+
vec_owned.push(MultiCountOwned(k1, String::from(k2), v));
457+
}
458+
vec_owned.sort();
459+
assert_eq!(
460+
vec_owned,
461+
vec!(
462+
MultiCountOwned(1, String::from("One"), String::from("Eins")),
463+
MultiCountOwned(2, String::from("Two"), String::from("Zwei")),
464+
MultiCountOwned(3, String::from("Three"), String::from("Drei"))
465+
)
466+
)
467+
}
336468

337469
#[test]
338470
fn macro_test() {

0 commit comments

Comments
 (0)