use super::UnsafeCell;
#[derive(Debug)]
pub struct Cell<T> {
cell: UnsafeCell<T>,
}
impl<T> Cell<T> {
#[track_caller]
pub fn new(v: T) -> Self {
Self {
cell: UnsafeCell::new(v),
}
}
#[track_caller]
pub fn set(&self, val: T) {
let old = self.replace(val);
drop(old);
}
#[track_caller]
pub fn swap(&self, other: &Self) {
if core::ptr::eq(self, other) {
return;
}
self.cell.with_mut(|my_ptr| {
other.cell.with_mut(|their_ptr| unsafe {
core::ptr::swap(my_ptr, their_ptr);
})
})
}
#[track_caller]
pub fn replace(&self, val: T) -> T {
self.cell
.with_mut(|ptr| unsafe { core::mem::replace(&mut *ptr, val) })
}
#[track_caller]
pub fn get(&self) -> T
where
T: Copy,
{
self.cell.with(|ptr| unsafe { *ptr })
}
#[track_caller]
pub fn take(&self) -> T
where
T: Default,
{
self.replace(T::default())
}
#[track_caller]
pub fn into_inner(self) -> T {
self.cell.into_inner()
}
}
impl<T: Default> Default for Cell<T> {
#[track_caller]
fn default() -> Cell<T> {
Cell::new(T::default())
}
}
impl<T: Copy> Clone for Cell<T> {
#[track_caller]
fn clone(&self) -> Cell<T> {
Cell::new(self.get())
}
}
impl<T> From<T> for Cell<T> {
#[track_caller]
fn from(src: T) -> Cell<T> {
Cell::new(src)
}
}
impl<T: PartialEq + Copy> PartialEq for Cell<T> {
fn eq(&self, other: &Self) -> bool {
self.get() == other.get()
}
}
impl<T: Eq + Copy> Eq for Cell<T> {}
impl<T: PartialOrd + Copy> PartialOrd for Cell<T> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.get().partial_cmp(&other.get())
}
}
impl<T: Ord + Copy> Ord for Cell<T> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.get().cmp(&other.get())
}
}