use core::{
borrow::{Borrow, BorrowMut},
cmp::Ordering,
fmt::{self, Debug, Display},
hash::{Hash, Hasher},
marker::PhantomData,
ops::{Deref, DerefMut, RangeBounds},
ptr::NonNull,
};
use crate::borrow::AtomicBorrowMut;
pub struct RefMut<'a, T: ?Sized> {
value: NonNull<T>,
borrow: AtomicBorrowMut<'a>,
_invariant: PhantomData<&'a mut T>,
}
unsafe impl<'b, T: ?Sized + 'b> Sync for RefMut<'b, T> where for<'a> &'a mut T: Sync {}
unsafe impl<'b, T: ?Sized + 'b> Send for RefMut<'b, T> where for<'a> &'a mut T: Send {}
impl<'a, T> Deref for RefMut<'a, T>
where
T: ?Sized,
{
type Target = T;
#[inline(always)]
fn deref(&self) -> &T {
unsafe { self.value.as_ref() }
}
}
impl<'a, T> DerefMut for RefMut<'a, T>
where
T: ?Sized,
{
#[inline(always)]
fn deref_mut(&mut self) -> &mut T {
unsafe { self.value.as_mut() }
}
}
impl<'a, T> Debug for RefMut<'a, T>
where
T: Debug,
{
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
<T as Debug>::fmt(self, f)
}
}
impl<'a, T> Display for RefMut<'a, T>
where
T: Display + ?Sized,
{
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
<T as Display>::fmt(self, f)
}
}
impl<'a, T, U> PartialEq<U> for RefMut<'a, T>
where
T: PartialEq<U> + ?Sized,
{
#[inline(always)]
fn eq(&self, other: &U) -> bool {
<T as PartialEq<U>>::eq(self, other)
}
}
impl<'a, T, U> PartialOrd<U> for RefMut<'a, T>
where
T: PartialOrd<U> + ?Sized,
{
#[inline(always)]
fn partial_cmp(&self, other: &U) -> Option<Ordering> {
<T as PartialOrd<U>>::partial_cmp(self, other)
}
}
impl<'a, T> Hash for RefMut<'a, T>
where
T: Hash + ?Sized,
{
#[inline(always)]
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
<T as Hash>::hash(self, state)
}
}
impl<'a, T> Borrow<T> for RefMut<'a, T>
where
T: ?Sized,
{
#[inline(always)]
fn borrow(&self) -> &T {
self
}
}
impl<'a, T> BorrowMut<T> for RefMut<'a, T>
where
T: ?Sized,
{
#[inline(always)]
fn borrow_mut(&mut self) -> &mut T {
self
}
}
impl<'a, T, U> AsRef<U> for RefMut<'a, T>
where
T: AsRef<U> + ?Sized,
{
#[inline(always)]
fn as_ref(&self) -> &U {
<T as AsRef<U>>::as_ref(self)
}
}
impl<'a, T, U> AsMut<U> for RefMut<'a, T>
where
T: AsMut<U> + ?Sized,
{
#[inline(always)]
fn as_mut(&mut self) -> &mut U {
<T as AsMut<U>>::as_mut(self)
}
}
impl<'a, T> RefMut<'a, T>
where
T: ?Sized,
{
#[inline]
pub fn new(r: &'a mut T) -> Self {
RefMut {
value: NonNull::from(r),
borrow: AtomicBorrowMut::dummy(),
_invariant: PhantomData,
}
}
#[inline]
pub fn with_borrow(r: &'a mut T, borrow: AtomicBorrowMut<'a>) -> Self {
RefMut {
value: NonNull::from(r),
borrow,
_invariant: PhantomData,
}
}
#[inline]
pub fn into_split(r: RefMut<'a, T>) -> (NonNull<T>, AtomicBorrowMut<'a>) {
(r.value, r.borrow)
}
#[inline]
pub fn map<F, U>(mut r: RefMut<'a, T>, f: F) -> RefMut<'a, U>
where
F: FnOnce(&mut T) -> &mut U,
U: ?Sized,
{
RefMut {
value: NonNull::from(f(&mut *r)),
borrow: r.borrow,
_invariant: PhantomData,
}
}
pub fn filter_map<U: ?Sized, F>(r: RefMut<'a, T>, f: F) -> Result<RefMut<'a, U>, Self>
where
F: FnOnce(&mut T) -> Option<&mut U>,
{
let RefMut { value, borrow, .. } = r;
let _ptr = value.as_ptr();
match f(unsafe { &mut *_ptr }) {
Some(value) => Ok(RefMut {
value: NonNull::from(value),
borrow,
_invariant: PhantomData,
}),
None => {
Err(RefMut {
value,
borrow,
_invariant: PhantomData,
})
}
}
}
pub fn map_split<U, V, F>(mut r: RefMut<'a, T>, f: F) -> (RefMut<'a, U>, RefMut<'a, V>)
where
U: ?Sized,
V: ?Sized,
F: FnOnce(&mut T) -> (&mut U, &mut V),
{
let borrow_u = r.borrow.clone();
let borrow_v = r.borrow;
let (u, v) = f(unsafe { r.value.as_mut() });
(
RefMut {
value: NonNull::from(u),
borrow: borrow_u,
_invariant: PhantomData,
},
RefMut {
value: NonNull::from(v),
borrow: borrow_v,
_invariant: PhantomData,
},
)
}
pub fn leak(mut r: RefMut<'a, T>) -> &'a mut T {
core::mem::forget(r.borrow);
unsafe { r.value.as_mut() }
}
#[inline]
pub fn as_mut<U>(mut r: RefMut<'a, T>) -> RefMut<'a, U>
where
U: ?Sized,
T: AsMut<U>,
{
RefMut {
value: NonNull::from(<T as AsMut<U>>::as_mut(&mut *r)),
borrow: r.borrow,
_invariant: PhantomData,
}
}
#[inline]
pub fn as_deref_mut(mut r: RefMut<'a, T>) -> RefMut<'a, T::Target>
where
T: DerefMut,
{
RefMut {
value: NonNull::from(<T as DerefMut>::deref_mut(&mut *r)),
borrow: r.borrow,
_invariant: PhantomData,
}
}
}
impl<'a, T> RefMut<'a, Option<T>> {
#[inline]
pub fn transpose(mut r: RefMut<'a, Option<T>>) -> Option<RefMut<'a, T>> {
Some(RefMut {
value: r.as_mut().map(NonNull::from)?,
borrow: r.borrow,
_invariant: PhantomData,
})
}
}
impl<'a, T> RefMut<'a, [T]> {
#[inline]
pub fn slice<R>(mut r: RefMut<'a, [T]>, range: R) -> RefMut<'a, [T]>
where
R: RangeBounds<usize>,
{
let bounds = (range.start_bound().cloned(), range.end_bound().cloned());
let slice = &mut *r;
let slice = &mut slice[bounds];
RefMut {
value: NonNull::from(slice),
borrow: r.borrow,
_invariant: PhantomData,
}
}
}