use std::cell::{Cell, UnsafeCell};
use std::fmt::Debug;
use std::ops::{Deref, DerefMut};
use std::ptr::NonNull;
use crate::helper::quasi::ObserverState;
use crate::helper::{AsDeref, QuasiObserver, Unsigned};
fn recover_provenance<S: ?Sized>(raw: *const S) -> *const S {
let exposed = std::ptr::with_exposed_provenance::<u8>(raw.cast::<u8>().addr());
let mut result = raw;
unsafe { std::ptr::write((&raw mut result).cast::<*const u8>(), exposed) }
result
}
fn recover_provenance_mut<S: ?Sized>(raw: *mut S) -> *mut S {
let exposed = std::ptr::with_exposed_provenance_mut::<u8>(raw.cast::<u8>().addr());
let mut result = raw;
unsafe { std::ptr::write((&raw mut result).cast::<*mut u8>(), exposed) }
result
}
pub struct Pointer<S: ?Sized> {
inner: Cell<NonNull<S>>,
#[expect(clippy::type_complexity)]
pub(crate) states: UnsafeCell<Vec<(isize, unsafe fn(*mut u8, &S))>>,
}
impl<S: ?Sized> Pointer<S> {
pub fn new(head: impl Into<NonNull<S>>) -> Self {
let ptr = head.into();
ptr.cast::<u8>().expose_provenance();
Pointer {
inner: Cell::new(ptr),
states: UnsafeCell::new(Vec::new()),
}
}
pub const fn get(this: &Self) -> NonNull<S> {
this.inner.get()
}
pub fn set(this: &Self, head: impl Into<NonNull<S>>) {
let ptr = head.into();
ptr.cast::<u8>().expose_provenance();
this.inner.set(ptr);
}
pub unsafe fn as_ref<'ob>(this: &Self) -> &'ob S {
unsafe { &*recover_provenance(this.inner.get().as_ptr()) }
}
pub unsafe fn as_mut<'ob>(this: &Self) -> &'ob mut S {
unsafe { &mut *recover_provenance_mut(this.inner.get().as_ptr()) }
}
pub fn register_state<O, D>(this: &Self, state: &O)
where
D: Unsigned,
S: AsDeref<D>,
O: ObserverState<Target = S::Target>,
{
unsafe fn invalidate<O, D, S>(ptr: *mut u8, value: &S)
where
D: Unsigned,
S: AsDeref<D> + ?Sized,
O: ObserverState<Target = S::Target>,
{
let state = unsafe { &mut *(ptr as *mut O) };
O::invalidate(state, value.as_deref());
}
let offset = state as *const _ as isize - this as *const _ as isize;
let invalidate: unsafe fn(*mut u8, &S) = invalidate::<O, D, S>;
unsafe { &mut *this.states.get() }.push((offset, invalidate));
}
pub fn register_observer<O: QuasiObserver>(this: &Self, observer: &O) {
unsafe fn invalidate<O: QuasiObserver, S: ?Sized>(ptr: *mut u8, _: &S) {
let state = unsafe { &mut *(ptr as *mut O) };
O::invalidate(state);
}
let offset = observer as *const _ as isize - this as *const _ as isize;
let invalidate: unsafe fn(*mut u8, &S) = invalidate::<O, S>;
unsafe { &mut *this.states.get() }.push((offset, invalidate));
}
}
impl<S: ?Sized> Deref for Pointer<S> {
type Target = S;
fn deref(&self) -> &Self::Target {
unsafe { Self::as_ref(self) }
}
}
impl<S: ?Sized> DerefMut for Pointer<S> {
fn deref_mut(&mut self) -> &mut S {
unsafe { Self::as_mut(self) }
}
}
impl<S: ?Sized> Debug for Pointer<S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("Pointer").field(&self.inner.get()).finish()
}
}
impl<S: ?Sized> PartialEq for Pointer<S> {
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
}
}
impl<S: ?Sized> Eq for Pointer<S> {}