Revision control
Copy as Markdown
Other Tools
//! `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<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::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) {↩
if mem::needs_drop::<T>() {↩
// 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.↩
↩
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<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↩
}↩
}↩
↩
fn fold<B, F>(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<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()↩
}↩
↩
#[inline]↩
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↩
}↩
}↩
↩
fn rfold<B, F>(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<T, N> ExactSizeIterator for GenericArrayIter<T, N>↩
where↩
N: ArrayLength<T>,↩
{↩
fn len(&self) -> usize {↩
self.index_back - self.index↩
}↩
}↩
↩
impl<T, N> FusedIterator for GenericArrayIter<T, N> where N: ArrayLength<T> {}↩
↩
// TODO: Implement `TrustedLen` when stabilized↩