diff options
Diffstat (limited to 'vendor/generic-array-0.12.4/src/iter.rs')
-rw-r--r-- | vendor/generic-array-0.12.4/src/iter.rs | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/vendor/generic-array-0.12.4/src/iter.rs b/vendor/generic-array-0.12.4/src/iter.rs new file mode 100644 index 000000000..a2d67fc67 --- /dev/null +++ b/vendor/generic-array-0.12.4/src/iter.rs @@ -0,0 +1,190 @@ +//! `GenericArray` iterator implementation. + +use super::{ArrayLength, GenericArray}; +use core::{cmp, ptr, fmt, mem}; +use core::mem::ManuallyDrop; + +/// An iterator that moves out of a `GenericArray` +pub struct GenericArrayIter<T, N: ArrayLength<T>> { + // 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<GenericArray<T, N>>, + index: usize, + index_back: usize, +} + +#[cfg(test)] +mod test { + use super::*; + + fn send<I: Send>(_iter: I) {} + + #[test] + fn test_send_iter() { + send(GenericArray::from([1, 2, 3, 4]).into_iter()); + } +} + +impl<T, N> GenericArrayIter<T, N> +where + N: ArrayLength<T>, +{ + /// 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<T, N> IntoIterator for GenericArray<T, N> +where + N: ArrayLength<T>, +{ + type Item = T; + type IntoIter = GenericArrayIter<T, N>; + + fn into_iter(self) -> Self::IntoIter { + GenericArrayIter { + array: ManuallyDrop::new(self), + index: 0, + index_back: N::to_usize(), + } + } +} + +// Based on work in rust-lang/rust#49000 +impl<T: fmt::Debug, N> fmt::Debug for GenericArrayIter<T, N> +where + N: ArrayLength<T>, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("GenericArrayIter") + .field(&self.as_slice()) + .finish() + } +} + +impl<T, N> Drop for GenericArrayIter<T, N> +where + N: ArrayLength<T>, +{ + #[inline] + fn drop(&mut self) { + // 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<T: Clone, N> Clone for GenericArrayIter<T, N> +where + N: ArrayLength<T>, +{ + fn clone(&self) -> Self { + // This places all cloned elements at the start of the new array iterator, + // not at their original indices. + unsafe { + let mut iter = GenericArrayIter { + array: ManuallyDrop::new(mem::uninitialized()), + index: 0, + index_back: 0, + }; + + for (dst, src) in iter.array.iter_mut().zip(self.as_slice()) { + ptr::write(dst, src.clone()); + + iter.index_back += 1; + } + + iter + } + } +} + +impl<T, N> Iterator for GenericArrayIter<T, N> +where + N: ArrayLength<T>, +{ + type Item = T; + + #[inline] + fn next(&mut self) -> Option<T> { + if self.index < self.index_back { + let p = unsafe { Some(ptr::read(self.array.get_unchecked(self.index))) }; + + self.index += 1; + + p + } else { + None + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option<usize>) { + let len = self.len(); + (len, Some(len)) + } + + #[inline] + fn count(self) -> usize { + self.len() + } + + fn nth(&mut self, n: usize) -> Option<T> { + // 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() + } + + fn last(mut self) -> Option<T> { + // Note, everything else will correctly drop first as `self` leaves scope. + self.next_back() + } +} + +impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N> +where + N: ArrayLength<T>, +{ + fn next_back(&mut self) -> Option<T> { + if self.index < self.index_back { + self.index_back -= 1; + + unsafe { Some(ptr::read(self.array.get_unchecked(self.index_back))) } + } else { + None + } + } +} + +impl<T, N> ExactSizeIterator for GenericArrayIter<T, N> +where + N: ArrayLength<T>, +{ + fn len(&self) -> usize { + self.index_back - self.index + } +} + +// TODO: Implement `FusedIterator` and `TrustedLen` when stabilized
\ No newline at end of file |