use core::ptr::NonNull;
use super::{GhostCell, GhostToken};
pub struct GhostCursor<'a, 'brand, T> {
token: NonNull<GhostToken<'brand>>,
cell: Option<&'a GhostCell<'brand, T>>,
}
impl<'a, 'brand, T> GhostCursor<'a, 'brand, T> {
pub fn new(token: &'a mut GhostToken<'brand>, cell: Option<&'a GhostCell<'brand, T>>) -> Self {
let token = NonNull::from(token);
Self { token, cell, }
}
pub fn into_inner(self) -> Option<&'a mut T> {
let token = unsafe { as_mut(self.token) };
self.cell.map(move |cell| cell.borrow_mut(token))
}
pub fn into_parts(self) -> (&'a GhostToken<'brand>, Option<&'a GhostCell<'brand, T>>) {
(unsafe { as_ref(self.token) }, self.cell)
}
pub fn token(&self) -> &GhostToken<'brand> {
unsafe { as_ref(self.token) }
}
pub fn borrow(&self) -> Option<&T> {
let token = unsafe { as_ref(self.token) };
self.cell.map(|cell| cell.borrow(token))
}
pub fn borrow_mut(&mut self) -> Option<&mut T> {
let token = unsafe { as_mut(self.token) };
self.cell.map(move |cell| cell.borrow_mut(token))
}
pub fn move_mut<F>(&mut self, fun: F) -> Result<(), ()>
where
F: FnOnce(&'a T) -> Option<&'a GhostCell<'brand, T>>,
{
let token = unsafe { as_ref(self.token) };
let cell = self.cell.ok_or(())?;
let cell = fun(cell.borrow(token)).ok_or(())?;
self.cell = Some(cell);
Ok(())
}
pub fn move_into<U, F>(self, fun: F) -> Result<GhostCursor<'a, 'brand, U>, Self>
where
F: FnOnce(&'a T) -> Option<&'a GhostCell<'brand, U>>,
{
let result = self.move_into_impl(fun);
result.or(Err(self))
}
fn move_into_impl<U, F>(&self, fun: F) -> Result<GhostCursor<'a, 'brand, U>, ()>
where
F: FnOnce(&'a T) -> Option<&'a GhostCell<'brand, U>>,
{
let token_mut = unsafe { as_mut(self.token) };
let cell = self.cell.ok_or(())?;
let cell = fun(cell.borrow(token_mut)).ok_or(())?;
Ok(GhostCursor { token: self.token, cell: Some(cell), })
}
}
unsafe fn as_ref<'a, T>(ptr: NonNull<T>) -> &'a T {
&*ptr.as_ptr()
}
unsafe fn as_mut<'a, T>(ptr: NonNull<T>) -> &'a mut T {
&mut *ptr.as_ptr()
}