use crate::*;
use core::fmt::Debug;
#[must_use = "dropping a `LoanedMut` panics; use `loaned::drop!` instead"]
#[repr(transparent)]
pub struct LoanedMut<'t, T> {
pub(crate) inner: RawLoaned<T>,
pub(crate) _contravariant: PhantomData<fn(&'t ())>,
}
impl<'t, T> LoanedMut<'t, T> {
#[inline]
pub fn loan(value: T) -> (&'t mut T::Target, Self)
where
T: Loanable<'t> + DerefMut,
{
let mut inner = RawLoaned::new(value);
let borrow = unsafe { &mut *(&mut **inner.as_mut() as *mut _) };
(borrow, unsafe { LoanedMut::from_raw(inner) })
}
#[inline(always)]
pub fn new(value: T) -> Self {
unsafe { LoanedMut::from_raw(RawLoaned::new(value)) }
}
#[inline(always)]
pub fn place(self, place: &'t mut impl Place<'t, T>) {
Place::place(self, place)
}
#[inline(always)]
pub(crate) fn into_raw(self) -> RawLoaned<T> {
unsafe { ptr::read(&ManuallyDrop::new(self).inner) }
}
#[inline(always)]
pub(crate) unsafe fn from_raw(inner: RawLoaned<T>) -> Self {
LoanedMut {
inner,
_contravariant: PhantomData,
}
}
}
impl<'t, T> From<Loaned<'t, T>> for LoanedMut<'t, T> {
#[inline(always)]
fn from(value: Loaned<'t, T>) -> Self {
unsafe { LoanedMut::from_raw(value.into_raw()) }
}
}
impl<'t, T> Drop for LoanedMut<'t, T> {
#[cold]
fn drop(&mut self) {
#[cfg(feature = "std")]
if mem::needs_drop::<T>() && !std::thread::panicking() {
panic!(
"memory leak: cannot drop `{Self}`
if leaking is desired, use `ManuallyDrop<{Self}>` or `mem::forget`
otherwise, use `drop!(loaned)` to drop the inner value",
Self = core::any::type_name::<Self>()
)
}
}
}
impl<'t, T> Debug for LoanedMut<'t, T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "LoanedMut(..)")
}
}
impl<'t, T: Default> Default for LoanedMut<'t, T> {
fn default() -> Self {
LoanedMut::new(Default::default())
}
}
impl<'t, T> From<T> for LoanedMut<'t, T> {
fn from(value: T) -> Self {
LoanedMut::new(value)
}
}
impl<'t, T> LoanedMut<'t, T> {
pub fn merge(value: T, f: impl for<'i> FnOnce(&'i mut T, &'i MergeMut<'t, 'i>)) -> Self {
unsafe {
let mut inner = RawLoaned::new(value);
f(inner.as_mut(), &MergeMut(PhantomData));
LoanedMut::from_raw(inner)
}
}
}
#[doc(hidden)]
pub struct MergeMut<'t, 'i>(PhantomData<(&'t mut &'t (), &'i mut &'i ())>);
impl<'t, 'i> MergeMut<'t, 'i> {
pub fn place<T>(&'i self, loaned: LoanedMut<'t, T>, place: &'i mut impl Place<'i, T>) {
Place::place(unsafe { LoanedMut::from_raw(loaned.into_raw()) }, place)
}
}
impl<'t, T> LoanedMut<'t, T> {
pub fn loan_with<L>(
value: T,
f: impl for<'i> FnOnce(&'i mut T, &'i LoanWithMut<'t, 'i>) -> L,
) -> (L, Self) {
unsafe {
let mut inner = RawLoaned::new(value);
let loans = f(inner.as_mut(), &LoanWithMut(PhantomData));
(loans, LoanedMut::from_raw(inner))
}
}
}
#[doc(hidden)]
pub struct LoanWithMut<'t, 'i>(PhantomData<(&'t mut &'t (), &'i mut &'i ())>);
impl<'t, 'i> LoanWithMut<'t, 'i> {
pub fn loan_mut<T: Loanable<'i> + DerefMut>(&'i self, value: &'i mut T) -> &'t mut T::Target {
unsafe { &mut *(&mut **value as *mut _) }
}
pub fn loan<T: Loanable<'i>>(&'i self, value: &'i T) -> &'t T::Target {
unsafe { &*(&**value as *const _) }
}
}