use crate::*;
#[cfg(feature = "alloc")]
use core::cell::{Ref, RefMut};
#[cfg(feature = "std")]
use std::sync::{MutexGuard, RwLockReadGuard, RwLockWriteGuard};
#[non_exhaustive]
pub enum Borrow<'a, T: ?Sized> {
Ptr(*const T, PhantomData<&'a ()>),
#[cfg(feature = "alloc")]
RefCellRef(Ref<'a, T>),
#[cfg(feature = "std")]
RwLockReadGuard(RwLockReadGuard<'a, T>),
#[cfg(feature = "std")]
MutexGuard(MutexGuard<'a, T>),
}
impl<T: ?Sized> Deref for Borrow<'_, T> {
type Target = T;
fn deref(&self) -> &T {
match self {
Self::Ptr(ptr, _) => unsafe { &**ptr },
#[cfg(feature = "alloc")]
Self::RefCellRef(ref_cell_ref) => ref_cell_ref,
#[cfg(feature = "std")]
Self::RwLockReadGuard(rw_lock_read_guard) => rw_lock_read_guard,
#[cfg(feature = "std")]
Self::MutexGuard(mutex_guard) => mutex_guard,
}
}
}
#[non_exhaustive]
pub enum BorrowMut<'a, T: ?Sized> {
Ptr(*mut T, PhantomData<&'a ()>),
#[cfg(feature = "alloc")]
RefCellRefMut(RefMut<'a, T>),
#[cfg(feature = "std")]
RwLockWriteGuard(RwLockWriteGuard<'a, T>),
#[cfg(feature = "std")]
MutexGuard(MutexGuard<'a, T>),
}
impl<T: ?Sized> Deref for BorrowMut<'_, T> {
type Target = T;
fn deref(&self) -> &T {
match self {
Self::Ptr(ptr, _) => unsafe { &**ptr },
#[cfg(feature = "alloc")]
Self::RefCellRefMut(ref_cell_ref_mut) => ref_cell_ref_mut,
#[cfg(feature = "std")]
Self::RwLockWriteGuard(rw_lock_write_guard) => rw_lock_write_guard,
#[cfg(feature = "std")]
Self::MutexGuard(mutex_guard) => mutex_guard,
}
}
}
impl<T: ?Sized> DerefMut for BorrowMut<'_, T> {
fn deref_mut(&mut self) -> &mut T {
match self {
Self::Ptr(ptr, _) => unsafe { &mut **ptr },
#[cfg(feature = "alloc")]
Self::RefCellRefMut(ref_cell_ref_mut) => ref_cell_ref_mut,
#[cfg(feature = "std")]
Self::RwLockWriteGuard(rw_lock_write_guard) => rw_lock_write_guard,
#[cfg(feature = "std")]
Self::MutexGuard(mutex_guard) => mutex_guard,
}
}
}
#[non_exhaustive]
pub enum ReferenceUnsafe<T: ?Sized> {
Ptr(*mut T),
#[cfg(feature = "alloc")]
RcRefCell(Rc<RefCell<T>>),
#[cfg(feature = "std")]
PtrRwLock(*const RwLock<T>),
#[cfg(feature = "std")]
PtrMutex(*const Mutex<T>),
#[cfg(feature = "std")]
ArcRwLock(Arc<RwLock<T>>),
#[cfg(feature = "std")]
ArcMutex(Arc<Mutex<T>>),
}
impl<T: ?Sized> ReferenceUnsafe<T> {
pub const unsafe fn from_ptr(ptr: *mut T) -> Self {
Self::Ptr(ptr)
}
#[cfg(feature = "alloc")]
pub const fn from_rc_ref_cell(rc_ref_cell: Rc<RefCell<T>>) -> Self {
Self::RcRefCell(rc_ref_cell)
}
#[cfg(feature = "std")]
pub const unsafe fn from_ptr_rw_lock(ptr_rw_lock: *const RwLock<T>) -> Self {
Self::PtrRwLock(ptr_rw_lock)
}
#[cfg(feature = "std")]
pub const unsafe fn from_ptr_mutex(ptr_mutex: *const Mutex<T>) -> Self {
Self::PtrMutex(ptr_mutex)
}
#[cfg(feature = "std")]
pub const fn from_arc_rw_lock(arc_rw_lock: Arc<RwLock<T>>) -> Self {
Self::ArcRwLock(arc_rw_lock)
}
#[cfg(feature = "std")]
pub const fn from_arc_mutex(arc_mutex: Arc<Mutex<T>>) -> Self {
Self::ArcMutex(arc_mutex)
}
pub unsafe fn borrow(&self) -> Borrow<'_, T> {
match self {
Self::Ptr(ptr) => Borrow::Ptr(*ptr, PhantomData),
#[cfg(feature = "alloc")]
Self::RcRefCell(rc_ref_cell) => Borrow::RefCellRef(rc_ref_cell.borrow()),
#[cfg(feature = "std")]
Self::PtrRwLock(ptr_rw_lock) => unsafe {
Borrow::RwLockReadGuard(
(**ptr_rw_lock)
.read()
.expect("RRTK Reference borrow failed to get RwLock read lock"),
)
},
#[cfg(feature = "std")]
Self::PtrMutex(ptr_mutex) => unsafe {
Borrow::MutexGuard(
(**ptr_mutex)
.lock()
.expect("RRTK Reference borrow failed to get Mutex lock"),
)
},
#[cfg(feature = "std")]
Self::ArcRwLock(arc_rw_lock) => Borrow::RwLockReadGuard(
arc_rw_lock
.read()
.expect("RRTK Reference borrow failed to get RwLock read lock"),
),
#[cfg(feature = "std")]
Self::ArcMutex(arc_mutex) => Borrow::MutexGuard(
arc_mutex
.lock()
.expect("RRTK Reference borrow failed to get Mutex lock"),
),
}
}
pub unsafe fn borrow_mut(&self) -> BorrowMut<'_, T> {
match self {
Self::Ptr(ptr) => BorrowMut::Ptr(*ptr, PhantomData),
#[cfg(feature = "alloc")]
Self::RcRefCell(rc_ref_cell) => BorrowMut::RefCellRefMut(rc_ref_cell.borrow_mut()),
#[cfg(feature = "std")]
Self::PtrRwLock(ptr_rw_lock) => unsafe {
BorrowMut::RwLockWriteGuard(
(**ptr_rw_lock)
.write()
.expect("RRTK Reference mutable borrow failed to get RwLock write lock"),
)
},
#[cfg(feature = "std")]
Self::PtrMutex(ptr_mutex) => unsafe {
BorrowMut::MutexGuard(
(**ptr_mutex)
.lock()
.expect("RRTK Reference mutable borrow failed to get Mutex lock"),
)
},
#[cfg(feature = "std")]
Self::ArcRwLock(arc_rw_lock) => BorrowMut::RwLockWriteGuard(
arc_rw_lock
.write()
.expect("RRTK Reference mutable borrow failed to get RwLock write lock"),
),
#[cfg(feature = "std")]
Self::ArcMutex(arc_mutex) => BorrowMut::MutexGuard(
arc_mutex
.lock()
.expect("RRTK Reference mutable borrow failed to get Mutex lock"),
),
}
}
}
impl<T: ?Sized> Clone for ReferenceUnsafe<T> {
fn clone(&self) -> Self {
match self {
Self::Ptr(ptr) => Self::Ptr(*ptr),
#[cfg(feature = "alloc")]
Self::RcRefCell(rc_ref_cell) => Self::RcRefCell(Rc::clone(&rc_ref_cell)),
#[cfg(feature = "std")]
Self::PtrRwLock(ptr_rw_lock) => Self::PtrRwLock(*ptr_rw_lock),
#[cfg(feature = "std")]
Self::PtrMutex(ptr_mutex) => Self::PtrMutex(*ptr_mutex),
#[cfg(feature = "std")]
Self::ArcRwLock(arc_rw_lock) => Self::ArcRwLock(Arc::clone(&arc_rw_lock)),
#[cfg(feature = "std")]
Self::ArcMutex(arc_mutex) => Self::ArcMutex(Arc::clone(&arc_mutex)),
}
}
}
impl<T: ?Sized> From<Reference<T>> for ReferenceUnsafe<T> {
fn from(was: Reference<T>) -> Self {
was.into_inner()
}
}
#[repr(transparent)]
pub struct Reference<T: ?Sized>(ReferenceUnsafe<T>);
impl<T: ?Sized> Reference<T> {
pub const unsafe fn from_ptr(ptr: *mut T) -> Self {
Self(ReferenceUnsafe::from_ptr(ptr))
}
#[cfg(feature = "alloc")]
pub const fn from_rc_ref_cell(rc_ref_cell: Rc<RefCell<T>>) -> Self {
Self(ReferenceUnsafe::from_rc_ref_cell(rc_ref_cell))
}
#[cfg(feature = "std")]
pub const unsafe fn from_ptr_rw_lock(ptr_rw_lock: *const RwLock<T>) -> Self {
Self(ReferenceUnsafe::from_ptr_rw_lock(ptr_rw_lock))
}
#[cfg(feature = "std")]
pub const unsafe fn from_ptr_mutex(ptr_mutex: *const Mutex<T>) -> Self {
Self(ReferenceUnsafe::from_ptr_mutex(ptr_mutex))
}
#[cfg(feature = "std")]
pub const fn from_arc_rw_lock(arc_rw_lock: Arc<RwLock<T>>) -> Self {
Self(ReferenceUnsafe::from_arc_rw_lock(arc_rw_lock))
}
#[cfg(feature = "std")]
pub const fn from_arc_mutex(arc_mutex: Arc<Mutex<T>>) -> Self {
Self(ReferenceUnsafe::from_arc_mutex(arc_mutex))
}
pub fn into_inner(self) -> ReferenceUnsafe<T> {
self.0
}
pub fn borrow(&self) -> Borrow<'_, T> {
unsafe { self.0.borrow() }
}
pub fn borrow_mut(&self) -> BorrowMut<'_, T> {
unsafe { self.0.borrow_mut() }
}
}
impl<T: ?Sized> Clone for Reference<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
#[macro_export]
macro_rules! to_dyn {
($trait_:path, $was:expr) => {{
#[cfg(feature = "alloc")]
extern crate alloc;
#[allow(unreachable_patterns)]
match $was.into_inner() {
reference::ReferenceUnsafe::Ptr(ptr) => unsafe {
Reference::from_ptr(ptr as *mut dyn $trait_)
},
#[cfg(feature = "alloc")]
reference::ReferenceUnsafe::RcRefCell(rc_ref_cell) => Reference::from_rc_ref_cell(
rc_ref_cell as alloc::rc::Rc<core::cell::RefCell<dyn $trait_>>,
),
#[cfg(feature = "std")]
reference::ReferenceUnsafe::PtrRwLock(ptr_rw_lock) => unsafe {
Reference::from_ptr_rw_lock(ptr_rw_lock as *const std::sync::RwLock<dyn $trait_>)
},
_ => unimplemented!(),
}
}};
}
pub use to_dyn;
#[cfg(feature = "alloc")]
pub fn rc_ref_cell_reference<T>(was: T) -> Reference<T> {
Reference::from_rc_ref_cell(Rc::new(RefCell::new(was)))
}
#[macro_export]
macro_rules! static_reference {
($type_: ty, $was: expr) => {{
static mut WAS: $type_ = $was;
unsafe { Reference::from_ptr(core::ptr::addr_of_mut!(WAS)) }
}};
}
pub use static_reference;
#[cfg(feature = "std")]
#[macro_export]
macro_rules! static_rw_lock_reference {
($type_: ty, $was: expr) => {{
static WAS: std::sync::RwLock<$type_> = std::sync::RwLock::new($was);
unsafe { Reference::from_ptr_rw_lock(core::ptr::addr_of!(WAS)) }
}};
}
#[cfg(feature = "std")]
pub use static_rw_lock_reference;
#[cfg(feature = "std")]
#[macro_export]
macro_rules! static_mutex_reference {
($type_: ty, $was: expr) => {{
static WAS: std::sync::Mutex<$type_> = std::sync::Mutex::new($was);
unsafe { Reference::from_ptr_mutex(core::ptr::addr_of!(WAS)) }
}};
}
#[cfg(feature = "std")]
pub fn arc_rw_lock_reference<T>(was: T) -> Reference<T> {
Reference::from_arc_rw_lock(Arc::new(RwLock::new(was)))
}
#[cfg(feature = "std")]
pub use static_mutex_reference;
#[cfg(feature = "std")]
pub fn arc_mutex_reference<T>(was: T) -> Reference<T> {
Reference::from_arc_mutex(Arc::new(Mutex::new(was)))
}