#![no_std]
#![forbid(unsafe_code)]
use core::cell::Cell as StdCell;
use core::cmp::Ordering;
use core::fmt;
use core::ops::{Deref, DerefMut};
#[cfg(test)]
mod tests;
#[derive(Default)]
pub struct Cell<T>(StdCell<T>);
impl<T> Cell<T> {
pub fn new(value: T) -> Self {
Self(StdCell::new(value))
}
}
impl<T> Deref for Cell<T> {
type Target = StdCell<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for Cell<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T> From<T> for Cell<T> {
fn from(value: T) -> Self {
Self::new(value)
}
}
impl<T> From<StdCell<T>> for Cell<T> {
fn from(cell: StdCell<T>) -> Self {
Self(cell)
}
}
impl<T> From<Cell<T>> for StdCell<T> {
fn from(cell: Cell<T>) -> Self {
cell.0
}
}
impl<T: Copy> Cell<T> {
pub fn get(&self) -> T {
self.0.get()
}
pub fn with<F, R>(&self, f: F) -> R
where
F: FnOnce(&T) -> R,
{
f(&self.get())
}
pub fn with_mut<F, R>(&self, f: F) -> R
where
F: FnOnce(&mut T) -> R,
{
let mut value = self.get();
let result = f(&mut value);
self.set(value);
result
}
}
mod sealed {
pub trait Sealed {}
}
pub trait CellExt<T>: sealed::Sealed {
fn get(&self) -> T
where
T: Clone + Default;
fn with<F, R>(&self, f: F) -> R
where
T: Default,
F: FnOnce(&T) -> R;
fn with_mut<F, R>(&self, f: F) -> R
where
T: Default,
F: FnOnce(&mut T) -> R;
}
impl<T> sealed::Sealed for Cell<T> {}
impl<T> CellExt<T> for Cell<T> {
fn get(&self) -> T
where
T: Clone + Default,
{
self.with(T::clone)
}
fn with<F, R>(&self, f: F) -> R
where
T: Default,
F: FnOnce(&T) -> R,
{
let value = self.take();
let result = f(&value);
self.set(value);
result
}
fn with_mut<F, R>(&self, f: F) -> R
where
T: Default,
F: FnOnce(&mut T) -> R,
{
let mut value = self.take();
let result = f(&mut value);
self.set(value);
result
}
}
impl<T: Copy> Clone for Cell<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
impl<T: fmt::Debug + Copy> fmt::Debug for Cell<T> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(fmt)
}
}
impl<T: Ord + Copy> Ord for Cell<T> {
fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp(other)
}
}
impl<T: PartialOrd + Copy> PartialOrd for Cell<T> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.0.partial_cmp(other)
}
}
impl<T: PartialEq + Copy> PartialEq for Cell<T> {
fn eq(&self, other: &Self) -> bool {
self.0.eq(other)
}
}
impl<T: Eq + Copy> Eq for Cell<T> {}