#![no_std]
use core::cell::Cell;
use core::fmt::{Debug, Display, Formatter, Octal};
use core::hash::{Hash, Hasher};
use core::ptr::NonNull;
#[repr(transparent)]
pub struct CellOptionRef<T: ?Sized> {
ptr: Cell<Option<NonNull<T>>>,
}
impl<T: ?Sized> CellOptionRef<T> {
pub const fn new() -> Self {
Self {
ptr: Cell::new(None),
}
}
pub fn get_ptr(&self) -> Option<NonNull<T>> {
self.ptr.get()
}
pub fn read<F: FnOnce(Option<&T>) -> R, R>(&self, f: F) -> R {
f(unsafe { self.get_ptr().map(|r| r.as_ref()) })
}
pub fn with<F: FnOnce() -> R, R>(&self, r: Option<&T>, f: F) -> R {
struct Guard<'s, T: ?Sized> {
this: &'s CellOptionRef<T>,
ptr: Option<NonNull<T>>,
}
impl<'s, T: ?Sized> Drop for Guard<'s, T> {
fn drop(&mut self) {
self.this.ptr.set(self.ptr);
}
}
let _guard = Guard {
this: &self,
ptr: self.ptr.replace(r.map(NonNull::from)),
};
f()
}
}
impl<T: ?Sized> Default for CellOptionRef<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Debug + ?Sized> Debug for CellOptionRef<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
self.read(|s| Debug::fmt(&s, f))
}
}
impl<T: PartialEq + ?Sized> PartialEq for CellOptionRef<T> {
fn eq(&self, other: &Self) -> bool {
self.read(|s| other.read(|r| PartialEq::eq(&s, &r)))
}
fn ne(&self, other: &Self) -> bool {
self.read(|s| other.read(|r| PartialEq::ne(&s, &r)))
}
}
impl<T: Eq + ?Sized> Eq for CellOptionRef<T> {}
impl<T: Hash + ?Sized> Hash for CellOptionRef<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.read(|s| Hash::hash(&s, state));
}
}