|
1 | | -use super::{Bucket, IndexMap, Slice}; |
| 1 | +use super::{Bucket, HashValue, IndexMap, Slice}; |
2 | 2 | use crate::inner::{Core, ExtractCore}; |
3 | 3 |
|
4 | 4 | use alloc::vec::{self, Vec}; |
5 | 5 | use core::fmt; |
6 | 6 | use core::hash::{BuildHasher, Hash}; |
7 | 7 | use core::iter::FusedIterator; |
| 8 | +use core::mem::MaybeUninit; |
8 | 9 | use core::ops::{Index, RangeBounds}; |
9 | 10 | use core::slice; |
10 | 11 |
|
@@ -448,11 +449,42 @@ impl<K, V> Index<usize> for Keys<'_, K, V> { |
448 | 449 | /// This `struct` is created by the [`IndexMap::into_keys`] method. |
449 | 450 | /// See its documentation for more. |
450 | 451 | pub struct IntoKeys<K, V> { |
451 | | - iter: vec::IntoIter<Bucket<K, V>>, |
| 452 | + // We eagerly drop the values during construction so we can ignore them in |
| 453 | + // `Clone`, but we keep uninit values so the bucket's size and alignment |
| 454 | + // remain the same, and therefore the `Vec` conversion should be in-place. |
| 455 | + iter: vec::IntoIter<Bucket<K, MaybeUninit<V>>>, |
452 | 456 | } |
453 | 457 |
|
454 | 458 | impl<K, V> IntoKeys<K, V> { |
455 | 459 | pub(super) fn new(entries: Vec<Bucket<K, V>>) -> Self { |
| 460 | + // The original values will be dropped here. |
| 461 | + // The hash doesn't matter, but "copying" it in-place is free. |
| 462 | + let entries = entries |
| 463 | + .into_iter() |
| 464 | + .map(|Bucket { hash, key, .. }| Bucket { |
| 465 | + hash, |
| 466 | + key, |
| 467 | + value: MaybeUninit::uninit(), |
| 468 | + }) |
| 469 | + .collect::<Vec<_>>(); |
| 470 | + Self { |
| 471 | + iter: entries.into_iter(), |
| 472 | + } |
| 473 | + } |
| 474 | +} |
| 475 | + |
| 476 | +impl<K: Clone, V> Clone for IntoKeys<K, V> { |
| 477 | + fn clone(&self) -> Self { |
| 478 | + let entries = self |
| 479 | + .iter |
| 480 | + .as_slice() |
| 481 | + .iter() |
| 482 | + .map(|Bucket { key, .. }| Bucket { |
| 483 | + hash: HashValue(0), |
| 484 | + key: key.clone(), |
| 485 | + value: MaybeUninit::uninit(), |
| 486 | + }) |
| 487 | + .collect::<Vec<_>>(); |
456 | 488 | Self { |
457 | 489 | iter: entries.into_iter(), |
458 | 490 | } |
@@ -601,11 +633,42 @@ impl<K, V> Default for ValuesMut<'_, K, V> { |
601 | 633 | /// This `struct` is created by the [`IndexMap::into_values`] method. |
602 | 634 | /// See its documentation for more. |
603 | 635 | pub struct IntoValues<K, V> { |
604 | | - iter: vec::IntoIter<Bucket<K, V>>, |
| 636 | + // We eagerly drop the keys during construction so we can ignore them in |
| 637 | + // `Clone`, but we keep uninit keys so the bucket's size and alignment |
| 638 | + // remain the same, and therefore the `Vec` conversion should be in-place. |
| 639 | + iter: vec::IntoIter<Bucket<MaybeUninit<K>, V>>, |
605 | 640 | } |
606 | 641 |
|
607 | 642 | impl<K, V> IntoValues<K, V> { |
608 | 643 | pub(super) fn new(entries: Vec<Bucket<K, V>>) -> Self { |
| 644 | + // The original keys will be dropped here. |
| 645 | + // The hash doesn't matter, but "copying" it in-place is free. |
| 646 | + let entries = entries |
| 647 | + .into_iter() |
| 648 | + .map(|Bucket { hash, value, .. }| Bucket { |
| 649 | + hash, |
| 650 | + key: MaybeUninit::uninit(), |
| 651 | + value, |
| 652 | + }) |
| 653 | + .collect::<Vec<_>>(); |
| 654 | + Self { |
| 655 | + iter: entries.into_iter(), |
| 656 | + } |
| 657 | + } |
| 658 | +} |
| 659 | + |
| 660 | +impl<K, V: Clone> Clone for IntoValues<K, V> { |
| 661 | + fn clone(&self) -> Self { |
| 662 | + let entries = self |
| 663 | + .iter |
| 664 | + .as_slice() |
| 665 | + .iter() |
| 666 | + .map(|Bucket { value, .. }| Bucket { |
| 667 | + hash: HashValue(0), |
| 668 | + key: MaybeUninit::uninit(), |
| 669 | + value: value.clone(), |
| 670 | + }) |
| 671 | + .collect::<Vec<_>>(); |
609 | 672 | Self { |
610 | 673 | iter: entries.into_iter(), |
611 | 674 | } |
|
0 commit comments