use crate::DynList;
use crate::ptr;
use crate::types::ListType;
use crate::types::ListTypeRev;
pub struct IterMut<'a, T, Typ>
where
T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized + 'a,
Typ: ListType<T>,
{
pub(crate) list: &'a mut 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 IterMut<'a, T, Typ>
where
T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
Typ: ListType<T>,
{
type Item = &'a mut 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 { &mut *p })
}
fn size_hint(&self) -> (usize, Option<usize>) {
let n = self.rev_index - self.index;
(n, Some(n))
}
}
impl<'a, T, Typ> DoubleEndedIterator for IterMut<'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 { &mut *p })
}
}
impl<'a, T, Typ> ExactSizeIterator for IterMut<'a, T, Typ>
where
T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
Typ: ListType<T>,
{
}
impl<'a, T, Typ> IterMut<'a, T, Typ>
where
T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
Typ: ListType<T>,
{
pub fn as_immutable<'b>(&'b self) -> crate::iters::Iter<'b, T, Typ> {
crate::iters::Iter {
list: &*self.list,
offset: self.offset,
index: self.index,
rev_offset: self.rev_offset,
rev_index: self.rev_index,
}
}
}