use std::{
cell::{Cell, UnsafeCell},
marker::PhantomData,
ops::{Deref, DerefMut},
ptr::NonNull,
};
type BorrowFlag = isize;
const UNUSED: BorrowFlag = 0;
#[inline(always)]
fn is_reading(x: BorrowFlag) -> bool { x > UNUSED }
#[inline(always)]
fn is_writing(x: BorrowFlag) -> bool { x < UNUSED }
pub(crate) struct StateCell<W: ?Sized> {
borrow_flag: Cell<BorrowFlag>,
#[cfg(debug_assertions)]
borrowed_at: Cell<Option<&'static std::panic::Location<'static>>>,
data: UnsafeCell<W>,
}
impl<W> StateCell<W> {
pub(crate) fn new(data: W) -> Self {
StateCell {
borrow_flag: Cell::new(UNUSED),
#[cfg(debug_assertions)]
borrowed_at: Cell::new(None),
data: UnsafeCell::new(data),
}
}
#[track_caller]
pub(crate) fn read(&self) -> ReadRef<'_, W> {
let borrow = &self.borrow_flag;
let b = borrow.get().wrapping_add(1);
borrow.set(b);
#[cfg(debug_assertions)]
{
if b == 1 {
self
.borrowed_at
.set(Some(std::panic::Location::caller()));
}
}
if !is_reading(b) {
#[cfg(debug_assertions)]
panic!("Already mutably borrowed: {:?}", self.borrowed_at.get().unwrap());
#[cfg(not(debug_assertions))]
panic!("Already mutably borrowed");
}
let inner = InnerPart::Ref(unsafe { NonNull::new_unchecked(self.data.get()) });
ReadRef { inner, borrow: BorrowRef { borrow }, origin_store: <_>::default() }
}
pub(crate) fn write(&self) -> ValueMutRef<'_, W> {
if !self.is_unused() {
#[cfg(debug_assertions)]
panic!("Already borrowed at: {:?}", self.borrowed_at.get().unwrap());
#[cfg(not(debug_assertions))]
panic!("Already borrowed");
}
#[cfg(debug_assertions)]
{
self
.borrowed_at
.set(Some(std::panic::Location::caller()));
}
let borrow = &self.borrow_flag;
borrow.set(UNUSED - 1);
let v_ref = BorrowRefMut { borrow };
let inner = InnerPart::Ref(unsafe { NonNull::new_unchecked(self.data.get()) });
ValueMutRef { inner, borrow: v_ref, origin_store: <_>::default() }
}
pub(crate) fn is_unused(&self) -> bool { self.borrow_flag.get() == UNUSED }
pub(super) fn into_inner(self) -> W { self.data.into_inner() }
}
pub struct PartRef<'a, T: ?Sized> {
pub(crate) inner: InnerPart<T>,
_phantom: PhantomData<&'a T>,
}
pub struct PartMut<'a, T: ?Sized> {
pub(crate) inner: InnerPart<T>,
_phantom: PhantomData<&'a mut T>,
}
pub(crate) enum InnerPart<T: ?Sized> {
Ref(NonNull<T>),
Owned(Box<T>),
}
impl<'a, T: ?Sized> PartRef<'a, T> {
pub fn new(v: &T) -> Self {
Self { inner: InnerPart::Ref(NonNull::from(v)), _phantom: PhantomData }
}
}
impl<'a, T> PartRef<'a, T> {
pub fn from_value(value: T) -> Self {
Self { inner: InnerPart::Owned(Box::new(value)), _phantom: PhantomData }
}
}
impl<'a, T: ?Sized> PartMut<'a, T> {
pub fn new(v: &mut T) -> Self {
Self { inner: InnerPart::Ref(NonNull::from(v)), _phantom: PhantomData }
}
}
impl<'a, T> PartMut<'a, T> {
pub fn from_ptr(pointer: T) -> Self {
Self { inner: InnerPart::Owned(Box::new(pointer)), _phantom: PhantomData }
}
}
pub struct ReadRef<'a, T: ?Sized> {
pub(crate) inner: InnerPart<T>,
pub(crate) borrow: BorrowRef<'a>,
pub(crate) origin_store: OriginPartStore<'a>,
}
pub(crate) struct ValueMutRef<'a, T: ?Sized> {
pub(crate) inner: InnerPart<T>,
pub(crate) borrow: BorrowRefMut<'a>,
pub(crate) origin_store: OriginPartStore<'a>,
}
#[derive(Clone)]
pub(crate) struct BorrowRefMut<'b> {
borrow: &'b Cell<BorrowFlag>,
}
pub(crate) struct BorrowRef<'b> {
borrow: &'b Cell<BorrowFlag>,
}
#[derive(Default)]
pub(crate) struct OriginPartStore<'a>(Option<Box<dyn FnOnce() + 'a>>);
impl<'a> OriginPartStore<'a> {
pub(crate) fn add<T: ?Sized + 'a>(&mut self, origin: InnerPart<T>) {
let InnerPart::Owned(data) = origin else { return };
if let Some(free) = self.0.take() {
self.0 = Some(Box::new(move || {
free();
drop(data);
}));
} else {
self.0 = Some(Box::new(move || drop(data)));
}
}
}
impl<T: ?Sized> Deref for InnerPart<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
match self {
InnerPart::Ref(ptr) => unsafe { ptr.as_ref() },
InnerPart::Owned(data) => data,
}
}
}
impl<'a> Drop for OriginPartStore<'a> {
#[inline]
fn drop(&mut self) {
if let Some(free) = self.0.take() {
free();
}
}
}
impl<T: ?Sized> DerefMut for InnerPart<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
InnerPart::Ref(ptr) => unsafe { ptr.as_mut() },
InnerPart::Owned(data) => data,
}
}
}
impl Drop for BorrowRefMut<'_> {
#[inline]
fn drop(&mut self) {
let borrow = self.borrow.get();
debug_assert!(is_writing(borrow));
self.borrow.set(borrow + 1);
}
}
impl Drop for BorrowRef<'_> {
#[inline]
fn drop(&mut self) {
let borrow = self.borrow.get();
debug_assert!(is_reading(borrow));
self.borrow.set(borrow - 1);
}
}
impl<'a, V: ?Sized + 'a> ReadRef<'a, V> {
pub fn map<U: ?Sized>(r: ReadRef<'a, V>, f: impl FnOnce(&V) -> PartRef<U>) -> ReadRef<'a, U> {
let Self { inner, borrow, origin_store: mut orig_store } = r;
let part = f(&inner).inner;
orig_store.add(inner);
ReadRef { inner: part, borrow, origin_store: orig_store }
}
pub fn filter_map<U: ?Sized, M>(
orig: ReadRef<'a, V>, part_map: M,
) -> std::result::Result<ReadRef<'a, U>, Self>
where
M: Fn(&V) -> Option<PartRef<U>>,
{
match part_map(&orig.inner).map(|v| v.inner) {
Some(part) => {
let Self { inner, borrow, origin_store: mut orig_store } = orig;
orig_store.add(inner);
Ok(ReadRef { inner: part, borrow, origin_store: orig_store })
}
None => Err(orig),
}
}
pub(crate) fn mut_as_ref_map<U: ?Sized>(
orig: ReadRef<'a, V>, f: impl FnOnce(&mut V) -> PartMut<U>,
) -> ReadRef<'a, U> {
let ReadRef { mut inner, borrow, origin_store: mut orig_store } = orig;
let value = f(&mut inner).inner;
orig_store.add(inner);
ReadRef { inner: value, borrow, origin_store: orig_store }
}
}
impl<'a, V: ?Sized + 'a> ValueMutRef<'a, V> {
pub(crate) fn map<U: ?Sized>(self, f: impl FnOnce(&mut V) -> PartMut<U>) -> ValueMutRef<'a, U> {
let ValueMutRef { mut inner, origin_store: mut orig_store, borrow } = self;
let value = f(&mut inner).inner;
orig_store.add(inner);
ValueMutRef { inner: value, origin_store: orig_store, borrow }
}
}
impl<'a, T: ?Sized> Deref for ReadRef<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target { &self.inner }
}
impl<'a, T: ?Sized> Deref for ValueMutRef<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target { &self.inner }
}
impl<'a, T: ?Sized> DerefMut for ValueMutRef<'a, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target { &mut self.inner }
}
use std::fmt::*;
use super::{QueryRef, WriteRef};
impl<T: ?Sized + Debug> Debug for ReadRef<'_, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result { Debug::fmt(&**self, f) }
}
impl<T: ?Sized + Debug> Debug for WriteRef<'_, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result { Debug::fmt(&**self, f) }
}
impl<T: ?Sized + Debug> Debug for QueryRef<'_, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result { Debug::fmt(&**self, f) }
}
impl<'a, T: ?Sized> From<PartMut<'a, T>> for PartRef<'a, T> {
fn from(part: PartMut<T>) -> Self { Self { inner: part.inner, _phantom: PhantomData } }
}
impl<'a, T> From<&'a T> for PartRef<'a, T> {
fn from(part: &'a T) -> Self { PartRef::new(part) }
}
impl<'a, T> From<&'a mut T> for PartMut<'a, T> {
fn from(part: &'a mut T) -> Self { PartMut::new(part) }
}