use crate::DynList;
use crate::ptr;
use crate::types::ListType;
use crate::types::ListTypeRev;
pub struct Cursor<'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,
}
impl<'a, T, Typ> Cursor<'a, T, Typ>
where
T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
Typ: ListType<T>,
{
pub fn current(&mut self) -> &mut T {
let (p, _) = unsafe {
self.list
.typ
.read_entry(self.list.data.as_ptr(), self.offset, self.index)
};
unsafe { &mut *p }
}
pub fn move_next(&mut self) -> bool {
debug_assert!(self.offset <= self.list.end);
debug_assert!(self.index <= self.list.typ.num_items());
let (_, size) = unsafe {
self.list
.typ
.read_entry(self.list.data.as_ptr(), self.offset, self.index)
};
if self.offset + size >= self.list.end {
debug_assert_eq!(self.offset + size, self.list.end);
return false;
}
self.offset += size;
self.index += 1;
true
}
pub fn drop_after(self) {
let mut offset = self.offset;
let mut index = self.index;
while offset < self.list.end {
let (p, size) = unsafe {
self.list
.typ
.read_entry(self.list.data.as_ptr(), offset, index)
};
unsafe {
core::ptr::drop_in_place(p);
}
offset += size;
index += 1;
}
debug_assert_eq!(offset, self.list.end);
self.list.end = self.offset;
self.list.typ.drop_entries(self.index..);
}
}
impl<'a, T, Typ> Cursor<'a, T, Typ>
where
T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
Typ: ListTypeRev<T>,
{
pub fn move_prev(&mut self) -> bool {
if self.offset == 0 {
return false;
}
debug_assert!(self.index > 0);
let size = unsafe {
self.list
.typ
.prev_entry_size(self.list.data.as_ptr(), self.offset, self.index)
};
debug_assert!(self.offset >= size);
self.offset -= size;
self.index -= 1;
true
}
}