use core::fmt;
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::ops::Deref;
use core::ptr;
use super::{Arc, ArcBorrow};
#[derive(Eq)]
#[repr(transparent)]
pub struct OffsetArc<T> {
pub(crate) ptr: ptr::NonNull<T>,
pub(crate) phantom: PhantomData<T>,
}
unsafe impl<T: Sync + Send> Send for OffsetArc<T> {}
unsafe impl<T: Sync + Send> Sync for OffsetArc<T> {}
impl<T> Deref for OffsetArc<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr.as_ptr() }
}
}
impl<T> Clone for OffsetArc<T> {
#[inline]
fn clone(&self) -> Self {
Arc::into_raw_offset(self.clone_arc())
}
}
impl<T> Drop for OffsetArc<T> {
fn drop(&mut self) {
let _ = Arc::from_raw_offset(OffsetArc {
ptr: self.ptr,
phantom: PhantomData,
});
}
}
impl<T: fmt::Debug> fmt::Debug for OffsetArc<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T: PartialEq> PartialEq for OffsetArc<T> {
fn eq(&self, other: &OffsetArc<T>) -> bool {
*(*self) == *(*other)
}
#[allow(clippy::partialeq_ne_impl)]
fn ne(&self, other: &OffsetArc<T>) -> bool {
*(*self) != *(*other)
}
}
impl<T> OffsetArc<T> {
#[inline]
pub fn with_arc<F, U>(&self, f: F) -> U
where
F: FnOnce(&Arc<T>) -> U,
{
let transient = unsafe { ManuallyDrop::new(Arc::from_raw(self.ptr.as_ptr())) };
f(&transient)
}
#[inline]
pub fn make_mut(&mut self) -> &mut T
where
T: Clone,
{
unsafe {
let this = ptr::read(self);
let mut arc = Arc::from_raw_offset(this);
let ret = Arc::make_mut(&mut arc) as *mut _;
ptr::write(self, Arc::into_raw_offset(arc));
&mut *ret
}
}
#[inline]
pub fn clone_arc(&self) -> Arc<T> {
OffsetArc::with_arc(self, |a| a.clone())
}
#[inline]
pub fn borrow_arc(&self) -> ArcBorrow<'_, T> {
ArcBorrow(&**self)
}
}