|
3 | 3 | // can't split that into multiple files.
|
4 | 4 |
|
5 | 5 | use crate::cmp::{self, Ordering};
|
| 6 | +use crate::mem::{self, MaybeUninit}; |
6 | 7 | use crate::ops::{Add, ControlFlow, Try};
|
| 8 | +use crate::ptr; |
7 | 9 |
|
8 | 10 | use super::super::TrustedRandomAccess;
|
9 | 11 | use super::super::{Chain, Cloned, Copied, Cycle, Enumerate, Filter, FilterMap, Fuse};
|
@@ -1670,6 +1672,77 @@ pub trait Iterator {
|
1670 | 1672 | FromIterator::from_iter(self)
|
1671 | 1673 | }
|
1672 | 1674 |
|
| 1675 | + /// Collects all items from the iterator into an array of a specific size. |
| 1676 | + /// |
| 1677 | + /// If the number of elements inside the iterator is exactly equal to the |
| 1678 | + /// array size, then the array is returned inside `Some`, otherwise `None` |
| 1679 | + /// is returned. |
| 1680 | + /// |
| 1681 | + /// # Examples |
| 1682 | + /// |
| 1683 | + /// ``` |
| 1684 | + /// #![feature(iter_collect_array)] |
| 1685 | + /// |
| 1686 | + /// let xs = [1, 2, 3]; |
| 1687 | + /// let iter = xs.iter().copied(); |
| 1688 | + /// let [_a, b, _c] = iter.clone().collect_array().unwrap(); |
| 1689 | + /// assert_eq!(b, 2); |
| 1690 | + /// |
| 1691 | + /// match iter.collect_array() { |
| 1692 | + /// Some([_, _]) => panic!("Didn't expect to see two only elements"), |
| 1693 | + /// None => (), |
| 1694 | + /// } |
| 1695 | + /// ``` |
| 1696 | + #[inline] |
| 1697 | + #[unstable(reason = "new API", issue = "none", feature = "iter_collect_array")] |
| 1698 | + fn collect_array<const N: usize>(self) -> Option<[Self::Item; N]> |
| 1699 | + where |
| 1700 | + Self: Sized, |
| 1701 | + { |
| 1702 | + struct Buf<T, const N: usize> { |
| 1703 | + // Safety invariant: first `len` items are initialized. |
| 1704 | + items: [MaybeUninit<T>; N], |
| 1705 | + len: usize, |
| 1706 | + } |
| 1707 | + impl<T, const N: usize> Buf<T, N> { |
| 1708 | + fn new() -> Buf<T, N> { |
| 1709 | + Buf { items: MaybeUninit::uninit_array(), len: 0 } |
| 1710 | + } |
| 1711 | + fn push(&mut self, item: T) -> Option<()> { |
| 1712 | + let slot = self.items.get_mut(self.len)?; |
| 1713 | + slot.write(item); |
| 1714 | + self.len += 1; |
| 1715 | + Some(()) |
| 1716 | + } |
| 1717 | + fn into_array(mut self) -> Option<[T; N]> { |
| 1718 | + if self.len != N { |
| 1719 | + return None; |
| 1720 | + } |
| 1721 | + self.len = 0; |
| 1722 | + let res = |
| 1723 | + // SAFETY: `len` field invariant + the guard above. |
| 1724 | + unsafe { mem::transmute_copy::<[MaybeUninit<T>; N], [T; N]>(&self.items) }; |
| 1725 | + Some(res) |
| 1726 | + } |
| 1727 | + } |
| 1728 | + |
| 1729 | + impl<T, const N: usize> Drop for Buf<T, N> { |
| 1730 | + fn drop(&mut self) { |
| 1731 | + // SAFETY: `len` field invariant. |
| 1732 | + unsafe { |
| 1733 | + let slice = MaybeUninit::slice_assume_init_mut(&mut self.items[..self.len]); |
| 1734 | + ptr::drop_in_place(slice); |
| 1735 | + } |
| 1736 | + } |
| 1737 | + } |
| 1738 | + |
| 1739 | + let mut buf: Buf<Self::Item, { N }> = Buf::new(); |
| 1740 | + for elem in self { |
| 1741 | + buf.push(elem)?; |
| 1742 | + } |
| 1743 | + buf.into_array() |
| 1744 | + } |
| 1745 | + |
1673 | 1746 | /// Consumes an iterator, creating two collections from it.
|
1674 | 1747 | ///
|
1675 | 1748 | /// The predicate passed to `partition()` can return `true`, or `false`.
|
|
0 commit comments