use crate::DynList;
use crate::ptr;
use crate::types::ListType;
use crate::types::ListTypeRev;
pub struct Iter<'a, T, Typ>
where
T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
Typ: ListType<T>,
{
pub(crate) list: &'a DynList<T, Typ>,
pub(crate) offset: usize,
pub(crate) index: usize,
pub(crate) rev_offset: usize,
pub(crate) rev_index: usize,
}
impl<'a, T, Typ> Iterator for Iter<'a, T, Typ>
where
T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
Typ: ListType<T>,
{
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.offset >= self.rev_offset {
debug_assert_eq!(self.offset, self.rev_offset);
debug_assert_eq!(self.index, self.rev_index);
return None;
}
let (p, size) = unsafe {
self.list
.typ
.read_entry(self.list.data.as_ptr(), self.offset, self.index)
};
self.offset += size;
self.index += 1;
Some(unsafe { &*p })
}
fn size_hint(&self) -> (usize, Option<usize>) {
let n = self.rev_index - self.index;
(n, Some(n))
}
}
impl<'a, T, Typ> DoubleEndedIterator for Iter<'a, T, Typ>
where
T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
Typ: ListTypeRev<T>,
{
fn next_back(&mut self) -> Option<Self::Item> {
if self.offset >= self.rev_offset {
debug_assert_eq!(self.offset, self.rev_offset);
debug_assert_eq!(self.index, self.rev_index);
return None;
}
let size = unsafe {
self.list
.typ
.prev_entry_size(self.list.data.as_ptr(), self.rev_offset, self.rev_index)
};
debug_assert!(
self.rev_offset >= size,
"SOUNDNESS BUG: prev_entry_size returned too big of a size. rev_offset = {} but prev_entry_size returned {}",
self.rev_offset,
size
);
self.rev_offset -= size;
self.rev_index -= 1;
let (p, s) = unsafe {
self.list
.typ
.read_entry(self.list.data.as_ptr(), self.rev_offset, self.rev_index)
};
debug_assert_eq!(s, size);
Some(unsafe { &*p })
}
}
impl<'a, T, Typ> ExactSizeIterator for Iter<'a, T, Typ>
where
T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
Typ: ListType<T>,
{
}
impl<'a, T, Typ> Clone for Iter<'a, T, Typ>
where
T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
Typ: ListType<T>,
{
fn clone(&self) -> Self {
Self {
list: self.list,
offset: self.offset,
index: self.index,
rev_index: self.index,
rev_offset: self.rev_offset,
}
}
}