use {Cursor, PendingRef, Pointer, PointerData, Slice};
use std::marker::PhantomData;
use std::ops;
impl<'a, T> Slice<'a, T> {
pub fn is_empty(&self) -> bool {
self.slice.is_empty()
}
pub fn get(&'a self, pointer: &Pointer<T>) -> Option<&'a T> {
debug_assert_eq!(pointer.data.get_storage_id(), self.offset.get_storage_id());
let index = pointer.data.get_index().wrapping_sub(self.offset.get_index());
self.slice.get(index as usize)
}
pub fn get_mut(&'a mut self, pointer: &Pointer<T>) -> Option<&'a mut T> {
debug_assert_eq!(pointer.data.get_storage_id(), self.offset.get_storage_id());
let index = pointer.data.get_index().wrapping_sub(self.offset.get_index());
self.slice.get_mut(index as usize)
}
}
#[derive(Debug)]
pub struct CursorItem<'a, T: 'a> {
item: &'a mut T,
pending: &'a PendingRef,
data: PointerData,
}
impl<'a, T> ops::Deref for CursorItem<'a, T> {
type Target = T;
fn deref(&self) -> &T {
self.item
}
}
impl<'a, T> ops::DerefMut for CursorItem<'a, T> {
fn deref_mut(&mut self) -> &mut T {
self.item
}
}
impl<'a, T> CursorItem<'a, T> {
pub fn pin(&self) -> Pointer<T> {
let epoch = {
let mut pending = self.pending.lock();
pending.add_ref.push(self.data.get_index());
pending.get_epoch(self.data.get_index())
};
Pointer {
data: self.data.with_epoch(epoch),
pending: self.pending.clone(),
marker: PhantomData,
}
}
}
impl<'a, T> Cursor<'a, T> {
fn split(&mut self, index: usize) -> (Slice<T>, CursorItem<T>, Slice<T>) {
let data = PointerData::new(index, 0, self.storage_id);
let (left, item, right) = self.storage.split(data);
let item = CursorItem {
item, data,
pending: self.pending,
};
(left, item, right)
}
pub fn next(&mut self) -> Option<(Slice<T>, CursorItem<T>, Slice<T>)> {
loop {
let id = self.index;
self.index += 1;
match self.storage.meta.get(id) {
None => {
self.index = id; return None;
},
Some(&0) => (),
Some(_) => return Some(self.split(id)),
}
}
}
pub fn prev(&mut self) -> Option<(Slice<T>, CursorItem<T>, Slice<T>)> {
loop {
if self.index == 0 {
return None
}
self.index -= 1;
let id = self.index;
debug_assert!(id < self.storage.meta.len());
if *unsafe { self.storage.meta.get_unchecked(id) } != 0 {
return Some(self.split(id));
}
}
}
}