From 9e3c08db40b8916968b9f30096c7be3f00ce9647 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 21 Apr 2024 13:44:51 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- third_party/rust/generic-array/src/iter.rs | 251 +++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 third_party/rust/generic-array/src/iter.rs (limited to 'third_party/rust/generic-array/src/iter.rs') diff --git a/third_party/rust/generic-array/src/iter.rs b/third_party/rust/generic-array/src/iter.rs new file mode 100644 index 0000000000..784ffa9068 --- /dev/null +++ b/third_party/rust/generic-array/src/iter.rs @@ -0,0 +1,251 @@ +//! `GenericArray` iterator implementation. + +use super::{ArrayLength, GenericArray}; +use core::iter::FusedIterator; +use core::mem::ManuallyDrop; +use core::{cmp, fmt, mem, ptr}; + +/// An iterator that moves out of a `GenericArray` +pub struct GenericArrayIter> { + // Invariants: index <= index_back <= N + // Only values in array[index..index_back] are alive at any given time. + // Values from array[..index] and array[index_back..] are already moved/dropped. + array: ManuallyDrop>, + index: usize, + index_back: usize, +} + +#[cfg(test)] +mod test { + use super::*; + + fn send(_iter: I) {} + + #[test] + fn test_send_iter() { + send(GenericArray::from([1, 2, 3, 4]).into_iter()); + } +} + +impl GenericArrayIter +where + N: ArrayLength, +{ + /// Returns the remaining items of this iterator as a slice + #[inline] + pub fn as_slice(&self) -> &[T] { + &self.array.as_slice()[self.index..self.index_back] + } + + /// Returns the remaining items of this iterator as a mutable slice + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [T] { + &mut self.array.as_mut_slice()[self.index..self.index_back] + } +} + +impl IntoIterator for GenericArray +where + N: ArrayLength, +{ + type Item = T; + type IntoIter = GenericArrayIter; + + fn into_iter(self) -> Self::IntoIter { + GenericArrayIter { + array: ManuallyDrop::new(self), + index: 0, + index_back: N::USIZE, + } + } +} + +// Based on work in rust-lang/rust#49000 +impl fmt::Debug for GenericArrayIter +where + N: ArrayLength, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("GenericArrayIter") + .field(&self.as_slice()) + .finish() + } +} + +impl Drop for GenericArrayIter +where + N: ArrayLength, +{ + #[inline] + fn drop(&mut self) { + if mem::needs_drop::() { + // Drop values that are still alive. + for p in self.as_mut_slice() { + unsafe { + ptr::drop_in_place(p); + } + } + } + } +} + +// Based on work in rust-lang/rust#49000 +impl Clone for GenericArrayIter +where + N: ArrayLength, +{ + fn clone(&self) -> Self { + // This places all cloned elements at the start of the new array iterator, + // not at their original indices. + + let mut array = unsafe { ptr::read(&self.array) }; + let mut index_back = 0; + + for (dst, src) in array.as_mut_slice().into_iter().zip(self.as_slice()) { + unsafe { ptr::write(dst, src.clone()) }; + index_back += 1; + } + + GenericArrayIter { + array, + index: 0, + index_back, + } + } +} + +impl Iterator for GenericArrayIter +where + N: ArrayLength, +{ + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + if self.index < self.index_back { + let p = unsafe { Some(ptr::read(self.array.get_unchecked(self.index))) }; + + self.index += 1; + + p + } else { + None + } + } + + fn fold(mut self, init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let ret = unsafe { + let GenericArrayIter { + ref array, + ref mut index, + index_back, + } = self; + + let remaining = &array[*index..index_back]; + + remaining.iter().fold(init, |acc, src| { + let value = ptr::read(src); + + *index += 1; + + f(acc, value) + }) + }; + + // ensure the drop happens here after iteration + drop(self); + + ret + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.len(); + (len, Some(len)) + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + fn nth(&mut self, n: usize) -> Option { + // First consume values prior to the nth. + let ndrop = cmp::min(n, self.len()); + + for p in &mut self.array[self.index..self.index + ndrop] { + self.index += 1; + + unsafe { + ptr::drop_in_place(p); + } + } + + self.next() + } + + #[inline] + fn last(mut self) -> Option { + // Note, everything else will correctly drop first as `self` leaves scope. + self.next_back() + } +} + +impl DoubleEndedIterator for GenericArrayIter +where + N: ArrayLength, +{ + fn next_back(&mut self) -> Option { + if self.index < self.index_back { + self.index_back -= 1; + + unsafe { Some(ptr::read(self.array.get_unchecked(self.index_back))) } + } else { + None + } + } + + fn rfold(mut self, init: B, mut f: F) -> B + where + F: FnMut(B, Self::Item) -> B, + { + let ret = unsafe { + let GenericArrayIter { + ref array, + index, + ref mut index_back, + } = self; + + let remaining = &array[index..*index_back]; + + remaining.iter().rfold(init, |acc, src| { + let value = ptr::read(src); + + *index_back -= 1; + + f(acc, value) + }) + }; + + // ensure the drop happens here after iteration + drop(self); + + ret + } +} + +impl ExactSizeIterator for GenericArrayIter +where + N: ArrayLength, +{ + fn len(&self) -> usize { + self.index_back - self.index + } +} + +impl FusedIterator for GenericArrayIter where N: ArrayLength {} + +// TODO: Implement `TrustedLen` when stabilized -- cgit v1.2.3