use std::{ fmt::{Debug, Display}, marker::PhantomData, ops::{Deref, DerefMut}, }; use crate::{Mappable, MappableMut}; /// A reference to a value in a generational box. pub struct GenerationalRef> { inner: R, phantom: PhantomData, #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow: GenerationalRefBorrowInfo, } impl> GenerationalRef { pub(crate) fn new( inner: R, #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow: GenerationalRefBorrowInfo, ) -> Self { Self { inner, phantom: PhantomData, #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow, } } } impl> Mappable for GenerationalRef { type Mapped = GenerationalRef>; fn map(_self: Self, f: impl FnOnce(&T) -> &U) -> Self::Mapped { GenerationalRef { inner: R::map(_self.inner, f), phantom: PhantomData, #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow: GenerationalRefBorrowInfo { borrowed_at: _self.borrow.borrowed_at, borrowed_from: _self.borrow.borrowed_from, }, } } fn try_map( _self: Self, f: impl FnOnce(&T) -> Option<&U>, ) -> Option> { let Self { inner, #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow, .. } = _self; R::try_map(inner, f).map(|inner| GenerationalRef { inner, phantom: PhantomData, #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow: GenerationalRefBorrowInfo { borrowed_at: borrow.borrowed_at, borrowed_from: borrow.borrowed_from, }, }) } } impl> Debug for GenerationalRef { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.inner.deref().fmt(f) } } impl> Display for GenerationalRef { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.inner.deref().fmt(f) } } impl> Deref for GenerationalRef { type Target = T; fn deref(&self) -> &Self::Target { self.inner.deref() } } #[cfg(any(debug_assertions, feature = "debug_borrows"))] /// Information about a borrow. pub struct GenerationalRefBorrowInfo { pub(crate) borrowed_at: &'static std::panic::Location<'static>, pub(crate) borrowed_from: &'static crate::MemoryLocationBorrowInfo, } #[cfg(any(debug_assertions, feature = "debug_borrows"))] impl Drop for GenerationalRefBorrowInfo { fn drop(&mut self) { self.borrowed_from .borrowed_at .write() .retain(|location| std::ptr::eq(*location, self.borrowed_at as *const _)); } } /// A mutable reference to a value in a generational box. pub struct GenerationalRefMut> { inner: W, phantom: PhantomData, #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow: GenerationalRefMutBorrowInfo, } impl> GenerationalRefMut { pub(crate) fn new( inner: R, #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow: GenerationalRefMutBorrowInfo, ) -> Self { Self { inner, phantom: PhantomData, #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow, } } } impl> MappableMut for GenerationalRefMut { type Mapped = GenerationalRefMut>; fn map(_self: Self, f: impl FnOnce(&mut T) -> &mut U) -> Self::Mapped { GenerationalRefMut { inner: W::map(_self.inner, f), phantom: PhantomData, #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow: _self.borrow, } } fn try_map( _self: Self, f: impl FnOnce(&mut T) -> Option<&mut U>, ) -> Option> { let Self { inner, #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow, .. } = _self; W::try_map(inner, f).map(|inner| GenerationalRefMut { inner, phantom: PhantomData, #[cfg(any(debug_assertions, feature = "debug_borrows"))] borrow, }) } } impl> Deref for GenerationalRefMut { type Target = T; fn deref(&self) -> &Self::Target { self.inner.deref() } } impl> DerefMut for GenerationalRefMut { fn deref_mut(&mut self) -> &mut Self::Target { self.inner.deref_mut() } } #[cfg(any(debug_assertions, feature = "debug_borrows"))] /// Information about a mutable borrow. pub struct GenerationalRefMutBorrowInfo { /// The location where the borrow occurred. pub(crate) borrowed_from: &'static crate::MemoryLocationBorrowInfo, } #[cfg(any(debug_assertions, feature = "debug_borrows"))] impl Drop for GenerationalRefMutBorrowInfo { fn drop(&mut self) { self.borrowed_from.borrowed_mut_at.write().take(); } }