|
40 | 40 | //! ``` |
41 | 41 |
|
42 | 42 | use std::borrow::Borrow; |
43 | | -use std::collections::hash_map::Iter; |
| 43 | +use std::collections::hash_map; |
44 | 44 | use std::collections::HashMap; |
45 | 45 | use std::fmt::{self, Debug}; |
46 | 46 | use std::hash::Hash; |
@@ -221,10 +221,13 @@ impl<K1: Eq + Hash + Clone, K2: Eq + Hash + Clone, V> MultiMap<K1, K2, V> { |
221 | 221 | result |
222 | 222 | } |
223 | 223 |
|
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 |
225 | 226 | /// 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 | + } |
228 | 231 | } |
229 | 232 | } |
230 | 233 |
|
@@ -258,6 +261,94 @@ where |
258 | 261 | } |
259 | 262 | } |
260 | 263 |
|
| 264 | +/// An iterator over the entries of a `MultiMap` like in a `HashMap` but with |
| 265 | +/// values of the form (K2, V) instead of V. |
| 266 | +/// |
| 267 | +/// |
| 268 | +/// This `struct` is created by the [`iter`] method on [`MultiMap`]. See its |
| 269 | +/// documentation for more. |
| 270 | +/// |
| 271 | +#[derive(Clone, Debug)] |
| 272 | +pub struct Iter<'a, K1: 'a, K2: 'a, V: 'a> { |
| 273 | + base: hash_map::Iter<'a, K1, (K2, V)>, |
| 274 | +} |
| 275 | + |
| 276 | +/// An owning iterator over the entries of a `MultiMap`. |
| 277 | +/// |
| 278 | +/// This `struct` is created by the [`into_iter`] method on [`MultiMap`] |
| 279 | +/// (provided by the `IntoIterator` trait). See its documentation for more. |
| 280 | +/// |
| 281 | +pub struct IntoIter<K1, K2, V> { |
| 282 | + base: hash_map::IntoIter<K1, (K2, V)>, |
| 283 | +} |
| 284 | +// TODO: `HashMap` also implements this, do we need this as well? |
| 285 | +// impl<K, V> IntoIter<K, V> { |
| 286 | +// /// Returns a iterator of references over the remaining items. |
| 287 | +// #[inline] |
| 288 | +// pub(super) fn iter(&self) -> Iter<'_, K, V> { |
| 289 | +// Iter { base: self.base.rustc_iter() } |
| 290 | +// } |
| 291 | +// } |
| 292 | + |
| 293 | +impl<K1, K2, V> IntoIterator for MultiMap<K1, K2, V> |
| 294 | +where |
| 295 | + K1: Eq + Hash + Debug, |
| 296 | + K2: Eq + Hash + Debug, |
| 297 | + V: Debug, |
| 298 | +{ |
| 299 | + type Item = (K1, (K2, V)); |
| 300 | + type IntoIter = IntoIter<K1, K2, V>; |
| 301 | + |
| 302 | + /// Creates a consuming iterator, that is, one that moves each key-value |
| 303 | + /// pair out of the map in arbitrary order. The map cannot be used after |
| 304 | + /// calling this. |
| 305 | + /// |
| 306 | + fn into_iter(self) -> IntoIter<K1, K2, V> { |
| 307 | + IntoIter { |
| 308 | + base: self.value_map.into_iter(), |
| 309 | + } |
| 310 | + } |
| 311 | +} |
| 312 | + |
| 313 | +impl<'a, K1, K2, V> IntoIterator for &'a MultiMap<K1, K2, V> |
| 314 | +where |
| 315 | + K1: Eq + Hash + Debug + Clone, |
| 316 | + K2: Eq + Hash + Debug + Clone, |
| 317 | + V: Debug, |
| 318 | +{ |
| 319 | + type Item = (&'a K1, &'a (K2, V)); |
| 320 | + type IntoIter = Iter<'a, K1, K2, V>; |
| 321 | + |
| 322 | + fn into_iter(self) -> Iter<'a, K1, K2, V> { |
| 323 | + self.iter() |
| 324 | + } |
| 325 | +} |
| 326 | + |
| 327 | +impl<'a, K1, K2, V> Iterator for Iter<'a, K1, K2, V> { |
| 328 | + type Item = (&'a K1, &'a (K2, V)); |
| 329 | + |
| 330 | + fn next(&mut self) -> Option<(&'a K1, &'a (K2, V))> { |
| 331 | + self.base.next() |
| 332 | + } |
| 333 | + #[inline] |
| 334 | + fn size_hint(&self) -> (usize, Option<usize>) { |
| 335 | + self.base.size_hint() |
| 336 | + } |
| 337 | +} |
| 338 | + |
| 339 | +impl<K1, K2, V> Iterator for IntoIter<K1, K2, V> { |
| 340 | + type Item = (K1, (K2, V)); |
| 341 | + |
| 342 | + #[inline] |
| 343 | + fn next(&mut self) -> Option<(K1, (K2, V))> { |
| 344 | + self.base.next() |
| 345 | + } |
| 346 | + #[inline] |
| 347 | + fn size_hint(&self) -> (usize, Option<usize>) { |
| 348 | + self.base.size_hint() |
| 349 | + } |
| 350 | +} |
| 351 | + |
261 | 352 | #[macro_export] |
262 | 353 | /// Create a `MultiMap` from a list of key-value tuples |
263 | 354 | /// |
@@ -345,6 +436,48 @@ mod test { |
345 | 436 | assert!(map.get_alt(&"Three") == None); |
346 | 437 | assert!(map.get(&3) == None); |
347 | 438 | } |
| 439 | + #[derive(Debug, Eq, Ord, PartialEq, PartialOrd)] |
| 440 | + struct MultiCount<'a>(i32, &'a str, &'a str); |
| 441 | + #[derive(Debug, Eq, Ord, PartialEq, PartialOrd)] |
| 442 | + struct MultiCountOwned(i32, String, String); |
| 443 | + |
| 444 | + #[test] |
| 445 | + fn into_iter_test() { |
| 446 | + use MultiMap; |
| 447 | + let mut map = MultiMap::new(); |
| 448 | + |
| 449 | + map.insert(1, "One", String::from("Eins")); |
| 450 | + map.insert(2, "Two", String::from("Zwei")); |
| 451 | + map.insert(3, "Three", String::from("Drei")); |
| 452 | + |
| 453 | + let mut vec_borrow = Vec::new(); |
| 454 | + for (k1, (k2, v)) in &map { |
| 455 | + vec_borrow.push(MultiCount(*k1, *k2, v)); |
| 456 | + } |
| 457 | + vec_borrow.sort(); |
| 458 | + assert_eq!( |
| 459 | + vec_borrow, |
| 460 | + vec!( |
| 461 | + MultiCount(1, "One", "Eins"), |
| 462 | + MultiCount(2, "Two", "Zwei"), |
| 463 | + MultiCount(3, "Three", "Drei") |
| 464 | + ) |
| 465 | + ); |
| 466 | + |
| 467 | + let mut vec_owned = Vec::new(); |
| 468 | + for (k1, (k2, v)) in map { |
| 469 | + vec_owned.push(MultiCountOwned(k1, String::from(k2), v)); |
| 470 | + } |
| 471 | + vec_owned.sort(); |
| 472 | + assert_eq!( |
| 473 | + vec_owned, |
| 474 | + vec!( |
| 475 | + MultiCountOwned(1, String::from("One"), String::from("Eins")), |
| 476 | + MultiCountOwned(2, String::from("Two"), String::from("Zwei")), |
| 477 | + MultiCountOwned(3, String::from("Three"), String::from("Drei")) |
| 478 | + ) |
| 479 | + ) |
| 480 | + } |
348 | 481 |
|
349 | 482 | #[test] |
350 | 483 | fn macro_test() { |
|
0 commit comments