#![cfg_attr(not(any(doc, test)), no_std)]
#![deny(
clippy::multiple_unsafe_ops_per_block,
clippy::undocumented_unsafe_blocks,
unsafe_op_in_unsafe_fn
)]
use {
core::{cell::UnsafeCell, marker::PhantomData, mem},
type_factory::Unique,
};
#[cfg(any(doctest, test))]
mod tests;
pub use type_factory;
#[repr(transparent)]
pub struct Cell<T, B>
where
T: ?Sized,
B: Unique,
{
marker: PhantomData<fn() -> B>,
inner: UnsafeCell<T>,
}
impl<T, B> Cell<T, B>
where
B: Unique,
{
pub const fn new(value: T) -> Self {
Self {
marker: PhantomData,
inner: UnsafeCell::new(value),
}
}
pub fn into_inner(self) -> T {
self.inner.into_inner()
}
pub fn take(&self, token: &mut B) -> T
where
T: Default,
{
mem::take(self.borrow_mut(token))
}
pub const fn replace(&self, value: T, token: &mut B) -> T {
mem::replace(self.borrow_mut(token), value)
}
}
impl<T, B> Cell<T, B>
where
T: ?Sized,
B: Unique,
{
pub const fn from_mut(value: &mut T) -> &mut Self {
unsafe { &mut *(value as *mut T as *mut Self) }
}
pub const fn get_mut(&mut self) -> &mut T {
self.inner.get_mut()
}
pub const fn as_ptr(&self) -> *mut T {
self.inner.get()
}
pub const fn borrow<'a>(&'a self, #[allow(unused_variables)] token: &'a B) -> &'a T {
unsafe { &*self.inner.get() }
}
pub const fn borrow_mut<'a>(
&'a self,
#[allow(unused_variables)] token: &'a mut B,
) -> &'a mut T {
unsafe { &mut *self.inner.get() }
}
}
impl<T, B> AsMut<T> for Cell<T, B>
where
T: ?Sized,
B: Unique,
{
fn as_mut(&mut self) -> &mut T {
self.get_mut()
}
}
impl<T, B> Default for Cell<T, B>
where
T: Default,
B: Unique,
{
fn default() -> Self {
Self::new(T::default())
}
}
impl<T, B> From<T> for Cell<T, B>
where
B: Unique,
{
fn from(value: T) -> Self {
Self::new(value)
}
}
unsafe impl<T, B> Send for Cell<T, B>
where
T: ?Sized + Send,
B: Unique,
{
}
unsafe impl<T, B> Sync for Cell<T, B>
where
T: ?Sized + Send + Sync,
B: Unique,
{
}