use core::borrow::Borrow;
use core::hash::{Hash, Hasher};
use core::mem::ManuallyDrop;
use core::ops::Deref;
use core::ptr;
use core::sync::atomic;
use core::{cmp::Ordering, marker::PhantomData};
use core::{fmt, mem};
use super::{Arc, ArcInner, ArcRef, OffsetArc};
#[repr(transparent)]
pub struct ArcBorrow<'a, T: ?Sized + 'a> {
pub(crate) p: ptr::NonNull<ArcInner<T>>,
pub(crate) phantom: PhantomData<&'a T>,
}
impl<'a, T> Copy for ArcBorrow<'a, T> {}
impl<'a, T> Clone for ArcBorrow<'a, T> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<'a, T> ArcBorrow<'a, T> {
#[inline]
pub fn clone_arc(this: Self) -> Arc<T> {
let arc = unsafe { Arc::from_raw_inner(this.p) };
mem::forget(arc.clone());
arc
}
#[inline]
pub fn ptr_eq(this: Self, other: Self) -> bool {
this.p == other.p
}
#[inline]
pub fn get(&self) -> &'a T {
&self.inner().data
}
#[inline]
pub fn as_arc(this: &Self) -> &Arc<T> {
unsafe { &*(this as *const _ as *const Arc<T>) }
}
#[inline]
pub fn as_arc_ref(this: &'a ArcBorrow<'a, T>) -> &'a ArcRef<'a, T> {
unsafe { &*(this as *const _ as *const ArcRef<'a, T>) }
}
#[inline]
pub fn into_raw(this: Self) -> *const T {
let arc = Self::as_arc(&this);
Arc::as_ptr(arc)
}
#[inline]
pub(super) fn inner(&self) -> &'a ArcInner<T> {
unsafe { &*self.p.as_ptr() }
}
#[inline]
pub fn count(this: Self) -> usize {
ArcBorrow::load_count(this, atomic::Ordering::Acquire)
}
#[inline]
pub fn load_count(this: Self, order: atomic::Ordering) -> usize {
this.inner().count.load(order)
}
}
impl<'a, T> Deref for ArcBorrow<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
self.get()
}
}
#[repr(transparent)]
pub struct OffsetArcBorrow<'a, T: ?Sized + 'a> {
pub(crate) p: ptr::NonNull<T>,
pub(crate) phantom: PhantomData<&'a T>,
}
impl<'a, T> Copy for OffsetArcBorrow<'a, T> {}
impl<'a, T> Clone for OffsetArcBorrow<'a, T> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<'a, T> OffsetArcBorrow<'a, T> {
#[inline]
pub fn clone_arc(this: Self) -> Arc<T> {
let arc = unsafe { Arc::from_raw(this.p.as_ptr()) };
mem::forget(arc.clone());
arc
}
#[inline]
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
this.p == other.p
}
#[inline]
pub fn with_arc<F, U>(&self, f: F) -> U
where
F: FnOnce(&Arc<T>) -> U,
T: 'static,
{
let transient = unsafe { ManuallyDrop::new(Arc::from_raw(self.p.as_ptr())) };
f(&transient)
}
#[inline]
pub fn as_arc(&self) -> &OffsetArc<T> {
unsafe { &*(self as *const _ as *const OffsetArc<T>) }
}
#[inline]
pub fn get(&self) -> &'a T {
unsafe { &*self.p.as_ptr() }
}
}
impl<'a, T> Deref for OffsetArcBorrow<'a, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
self.get()
}
}
impl<'a, 'b, T, U: PartialEq<T>> PartialEq<ArcBorrow<'a, T>> for ArcBorrow<'b, U> {
#[inline]
fn eq(&self, other: &ArcBorrow<'a, T>) -> bool {
*(*self) == *(*other)
}
#[allow(clippy::partialeq_ne_impl)]
#[inline]
fn ne(&self, other: &ArcBorrow<'a, T>) -> bool {
*(*self) != *(*other)
}
}
impl<'a, 'b, T, U: PartialOrd<T>> PartialOrd<ArcBorrow<'a, T>> for ArcBorrow<'b, U> {
#[inline]
fn partial_cmp(&self, other: &ArcBorrow<'a, T>) -> Option<Ordering> {
(**self).partial_cmp(&**other)
}
#[inline]
fn lt(&self, other: &ArcBorrow<'a, T>) -> bool {
*(*self) < *(*other)
}
#[inline]
fn le(&self, other: &ArcBorrow<'a, T>) -> bool {
*(*self) <= *(*other)
}
#[inline]
fn gt(&self, other: &ArcBorrow<'a, T>) -> bool {
*(*self) > *(*other)
}
#[inline]
fn ge(&self, other: &ArcBorrow<'a, T>) -> bool {
*(*self) >= *(*other)
}
}
impl<'a, T: Ord> Ord for ArcBorrow<'a, T> {
#[inline]
fn cmp(&self, other: &ArcBorrow<'a, T>) -> Ordering {
(**self).cmp(&**other)
}
}
impl<'a, T: Eq> Eq for ArcBorrow<'a, T> {}
impl<'a, T: fmt::Display> fmt::Display for ArcBorrow<'a, T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<'a, T: fmt::Debug> fmt::Debug for ArcBorrow<'a, T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T: Hash> Hash for ArcBorrow<'_, T> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state)
}
}
impl<T> Borrow<T> for ArcBorrow<'_, T> {
#[inline]
fn borrow(&self) -> &T {
&**self
}
}
impl<T> AsRef<T> for ArcBorrow<'_, T> {
#[inline]
fn as_ref(&self) -> &T {
&**self
}
}
impl<'a, 'b, T, U: PartialEq<T>> PartialEq<OffsetArcBorrow<'a, T>> for OffsetArcBorrow<'b, U> {
#[inline]
fn eq(&self, other: &OffsetArcBorrow<'a, T>) -> bool {
*(*self) == *(*other)
}
#[allow(clippy::partialeq_ne_impl)]
#[inline]
fn ne(&self, other: &OffsetArcBorrow<'a, T>) -> bool {
*(*self) != *(*other)
}
}
impl<'a, 'b, T, U: PartialOrd<T>> PartialOrd<OffsetArcBorrow<'a, T>> for OffsetArcBorrow<'b, U> {
#[inline]
fn partial_cmp(&self, other: &OffsetArcBorrow<'a, T>) -> Option<Ordering> {
(**self).partial_cmp(&**other)
}
#[inline]
fn lt(&self, other: &OffsetArcBorrow<'a, T>) -> bool {
*(*self) < *(*other)
}
#[inline]
fn le(&self, other: &OffsetArcBorrow<'a, T>) -> bool {
*(*self) <= *(*other)
}
#[inline]
fn gt(&self, other: &OffsetArcBorrow<'a, T>) -> bool {
*(*self) > *(*other)
}
#[inline]
fn ge(&self, other: &OffsetArcBorrow<'a, T>) -> bool {
*(*self) >= *(*other)
}
}
impl<'a, T: Ord> Ord for OffsetArcBorrow<'a, T> {
#[inline]
fn cmp(&self, other: &OffsetArcBorrow<'a, T>) -> Ordering {
(**self).cmp(&**other)
}
}
impl<'a, T: Eq> Eq for OffsetArcBorrow<'a, T> {}
impl<'a, T: fmt::Display> fmt::Display for OffsetArcBorrow<'a, T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<'a, T: fmt::Debug> fmt::Debug for OffsetArcBorrow<'a, T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T: Hash> Hash for OffsetArcBorrow<'_, T> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state)
}
}
impl<T> Borrow<T> for OffsetArcBorrow<'_, T> {
#[inline]
fn borrow(&self) -> &T {
&**self
}
}
impl<T> AsRef<T> for OffsetArcBorrow<'_, T> {
#[inline]
fn as_ref(&self) -> &T {
&**self
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn borrow_count() {
let mut borrows = Vec::with_capacity(100);
let x = Arc::new(76);
let y = Arc::borrow_arc(&x);
assert_eq!(Arc::count(&x), 1);
assert_eq!(ArcBorrow::count(y), 1);
for i in 0..100 {
borrows.push(x.clone());
assert_eq!(Arc::count(&x), i + 2);
assert_eq!(ArcBorrow::count(y), i + 2);
}
}
}