use nodrop::NoDrop;
use std::cmp;
use std::ptr;
use super::{GenericArray, ArrayLength};
pub struct GenericArrayIter<T, N: ArrayLength<T>> {
array: NoDrop<GenericArray<T, N>>,
index: usize,
index_back: usize,
}
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: NoDrop::new(self),
index: 0,
index_back: N::to_usize(),
}
}
}
impl<T, N> Drop for GenericArrayIter<T, N> where N: ArrayLength<T> {
fn drop(&mut self) {
for p in &mut self.array[self.index..self.index_back] {
unsafe { ptr::drop_in_place(p); }
}
}
}
impl<T, N> Iterator for GenericArrayIter<T, N> where N: ArrayLength<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
if self.len() > 0 {
unsafe {
let p = self.array.get_unchecked(self.index);
self.index += 1;
Some(ptr::read(p))
}
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.len();
(len, Some(len))
}
fn count(self) -> usize {
self.len()
}
fn nth(&mut self, n: usize) -> Option<T> {
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> {
self.next_back()
}
}
impl<T, N> DoubleEndedIterator for GenericArrayIter<T, N> where N: ArrayLength<T> {
fn next_back(&mut self) -> Option<T> {
if self.len() > 0 {
self.index_back -= 1;
unsafe {
let p = self.array.get_unchecked(self.index_back);
Some(ptr::read(p))
}
} else {
None
}
}
}
impl<T, N> ExactSizeIterator for GenericArrayIter<T, N> where N: ArrayLength<T> {
fn len(&self) -> usize {
self.index_back - self.index
}
}