use core::{
cell::UnsafeCell,
cmp::Ordering,
fmt,
fmt::{Debug, Formatter},
mem, ptr,
};
use crate::clone::PureClone;
#[repr(transparent)]
pub struct Cell<T>
where
T: ?Sized,
{
value: UnsafeCell<T>,
}
impl<T> Cell<T> {
#[inline]
pub const fn new(value: T) -> Self {
Self {
value: UnsafeCell::new(value),
}
}
#[inline]
pub fn set(&self, value: T) {
self.replace(value);
}
#[inline]
pub fn swap(&self, other: &Self) {
if ptr::eq(self, other) {
return;
}
let src_usize = self as *const Self as usize;
let dst_usize = other as *const Self as usize;
let diff = src_usize.abs_diff(dst_usize);
if diff < size_of::<Self>() {
panic!("`Cell::swap` on overlapping non-identical `Cell`s");
}
unsafe {
ptr::swap(self.value.get(), other.value.get());
}
}
pub fn replace(&self, value: T) -> T {
mem::replace(unsafe { &mut *self.value.get() }, value)
}
pub fn into_inner(self) -> T {
self.value.into_inner()
}
#[inline]
pub fn get(&self) -> T
where
T: PureClone,
{
unsafe { (*self.value.get()).pure_clone() }
}
pub fn take(&self) -> T
where
T: Default,
{
self.replace(Default::default())
}
}
impl<T> Cell<T>
where
T: ?Sized,
{
#[inline]
pub const fn as_ptr(&self) -> *mut T {
self.value.get()
}
#[inline]
pub fn get_mut(&mut self) -> &mut T {
self.value.get_mut()
}
#[inline]
pub fn from_mut(t: &mut T) -> &Self {
unsafe { &*(t as *mut T as *const Self) }
}
}
impl<T> Cell<[T]> {
pub fn as_slice_of_cells(&self) -> &[Cell<T>] {
unsafe { &*(self as *const Self as *const [Cell<T>]) }
}
}
impl<T> Clone for Cell<T>
where
T: PureClone,
{
#[inline]
fn clone(&self) -> Self {
Self::new(self.get())
}
}
impl<T> Debug for Cell<T>
where
T: Debug + PureClone,
{
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_struct("Cell").field("value", &self.get()).finish()
}
}
impl<T> Default for Cell<T>
where
T: Default,
{
#[inline]
fn default() -> Self {
Self::new(Default::default())
}
}
impl<T> From<T> for Cell<T> {
fn from(t: T) -> Self {
Self::new(t)
}
}
impl<T> PartialEq for Cell<T>
where
T: PartialEq + PureClone,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.get() == other.get()
}
}
impl<T> Eq for Cell<T> where T: Eq + PureClone {}
impl<T> PartialOrd for Cell<T>
where
T: PartialOrd + PureClone,
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.get().partial_cmp(&other.get())
}
#[inline]
fn lt(&self, other: &Self) -> bool {
self.get() < other.get()
}
#[inline]
fn le(&self, other: &Self) -> bool {
self.get() <= other.get()
}
#[inline]
fn gt(&self, other: &Self) -> bool {
self.get() > other.get()
}
#[inline]
fn ge(&self, other: &Self) -> bool {
self.get() >= other.get()
}
}
impl<T> Ord for Cell<T>
where
T: Ord + PureClone,
{
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.get().cmp(&other.get())
}
}