mod erased_arc;
use alloc::sync::Arc;
use core::{
clone::Clone,
cmp::{Eq, Ord, PartialEq, PartialOrd},
convert::{AsRef, From, Into},
hash::Hash,
iter::{FromIterator, IntoIterator},
marker::{Send, Sized, Sync, Unpin},
ops::Deref,
ops::FnOnce,
option::{Option, Option::Some},
ptr::NonNull,
};
use erased_arc::{TypeErasedArc, TypeErasedWeak};
pub struct Parc<T: ?Sized> {
arc: TypeErasedArc,
projected: NonNull<T>,
}
impl<T> Parc<T>
where
T: Send + Sync + 'static,
{
#[inline]
pub fn new(value: T) -> Parc<T> {
Arc::new(value).into()
}
}
impl<T: ?Sized> Parc<T> {
#[inline]
pub fn from_arc<U, F>(arc: &Arc<U>, project: F) -> Self
where
U: ?Sized + Send + Sync + 'static,
F: FnOnce(&U) -> &T,
T: 'static,
{
let projected = project(arc);
let projected = unsafe { NonNull::new_unchecked(projected as *const T as *mut T) };
Self {
arc: TypeErasedArc::new(arc.clone()),
projected,
}
}
#[inline]
pub fn try_from_arc<U, E, F>(arc: &Arc<U>, project: F) -> Result<Self, E>
where
U: ?Sized + Sync + Send + 'static,
T: 'static,
F: FnOnce(&U) -> Result<&T, E>,
{
let projected = project(arc)?;
let projected = unsafe { NonNull::new_unchecked(projected as *const T as *mut T) };
Ok(Self {
arc: TypeErasedArc::new(arc.clone()),
projected,
})
}
#[inline]
pub fn project<U, F>(&self, project: F) -> Parc<U>
where
T: Send + Sync + 'static,
U: ?Sized + 'static,
F: FnOnce(&T) -> &U,
{
let projected = project(self);
let projected = unsafe { NonNull::new_unchecked(projected as *const U as *mut U) };
Parc::<U> {
arc: self.arc.clone(),
projected,
}
}
pub fn try_project<U, E, F>(&self, project: F) -> Result<Parc<U>, E>
where
T: Send + Sync,
U: ?Sized + 'static,
F: for<'x> FnOnce(&'x T) -> Result<&'x U, E>,
{
let projected = project(self)?;
let projected = unsafe { NonNull::new_unchecked(projected as *const U as *mut U) };
Ok(Parc::<U> {
arc: self.arc.clone(),
projected,
})
}
#[must_use]
pub fn as_ptr(this: &Self) -> *const T {
NonNull::as_ptr(this.projected)
}
#[inline]
pub fn downgrade(this: &Parc<T>) -> Weak<T> {
Weak::<T> {
weak: this.arc.downgrade(),
projected: this.projected,
}
}
#[inline]
pub fn weak_count(this: &Parc<T>) -> usize {
this.arc.weak_count()
}
#[inline]
pub fn strong_count(this: &Parc<T>) -> usize {
this.arc.strong_count()
}
pub fn ptr_eq(this: &Parc<T>, other: &Parc<T>) -> bool {
core::ptr::eq(this.projected.as_ptr(), other.projected.as_ptr())
}
}
impl<T: ?Sized> AsRef<T> for Parc<T> {
#[inline]
fn as_ref(&self) -> &T {
self.deref()
}
}
impl<T: ?Sized> core::borrow::Borrow<T> for Parc<T> {
#[inline]
fn borrow(&self) -> &T {
self.deref()
}
}
impl<T: ?Sized> Clone for Parc<T> {
#[inline]
fn clone(&self) -> Self {
Self {
arc: self.arc.clone(),
projected: self.projected,
}
}
}
impl<T: ?Sized + core::fmt::Debug> core::fmt::Debug for Parc<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Parc")
.field("projected", &self.deref())
.finish()
}
}
impl<T> core::fmt::Display for Parc<T>
where
T: core::fmt::Display + ?Sized,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.deref().fmt(f)
}
}
impl<T: ?Sized> Deref for Parc<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
unsafe { self.projected.as_ref() }
}
}
#[cfg(feature = "std")]
impl<T> std::error::Error for Parc<T>
where
T: std::error::Error + ?Sized,
{
#[inline]
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.deref().source()
}
}
impl<T, F> From<F> for Parc<T>
where
T: ?Sized + Send + Sync + 'static,
F: Into<Arc<T>>,
{
#[inline]
fn from(value: F) -> Self {
Parc::from_arc(&value.into(), |x| x)
}
}
impl<T> FromIterator<T> for Parc<[T]>
where
T: Send + Sync + 'static,
{
#[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
iter.into_iter().collect::<Arc<[T]>>().into()
}
}
impl<T> Hash for Parc<T>
where
T: Hash + ?Sized,
{
#[inline]
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.deref().hash(state)
}
}
impl<T> PartialEq<Parc<T>> for Parc<T>
where
T: PartialEq<T> + ?Sized,
{
#[inline]
fn eq(&self, other: &Parc<T>) -> bool {
let this: &T = self;
let other: &T = other;
this.eq(other)
}
}
impl<T> Eq for Parc<T> where T: Eq + ?Sized {}
impl<T> Ord for Parc<T>
where
T: Ord + ?Sized,
{
#[inline]
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
let this: &T = self;
let other: &T = other;
this.cmp(other)
}
}
impl<T> PartialOrd<Parc<T>> for Parc<T>
where
T: PartialOrd<T> + ?Sized,
{
#[inline]
fn partial_cmp(&self, other: &Parc<T>) -> Option<core::cmp::Ordering> {
self.deref().partial_cmp(other)
}
}
impl<T> core::fmt::Pointer for Parc<T>
where
T: ?Sized,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Pointer::fmt(&self.projected, f)
}
}
unsafe impl<T> Send for Parc<T> where T: Sync + Send + ?Sized {}
unsafe impl<T> Sync for Parc<T> where T: Sync + Send + ?Sized {}
impl<T> Unpin for Parc<T> where T: ?Sized {}
impl<T> core::panic::UnwindSafe for Parc<T> where T: core::panic::RefUnwindSafe + ?Sized {}
pub struct Weak<T: ?Sized> {
weak: TypeErasedWeak,
projected: NonNull<T>,
}
unsafe impl<T: ?Sized + Sync + Send> Send for Weak<T> {}
unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> {}
impl<T: ?Sized> Weak<T> {
#[must_use]
pub fn as_ptr(&self) -> *const T {
NonNull::as_ptr(self.projected)
}
#[inline]
pub fn upgrade(&self) -> Option<Parc<T>> {
Some(Parc {
arc: self.weak.upgrade()?,
projected: self.projected,
})
}
#[inline]
pub fn strong_count(&self) -> usize {
self.weak.strong_count()
}
#[inline]
pub fn weak_count(&self) -> usize {
self.weak.weak_count()
}
#[inline]
pub fn ptr_eq(&self, other: &Weak<T>) -> bool {
core::ptr::eq(self.projected.as_ptr(), other.projected.as_ptr())
}
}
impl<T: ?Sized> Clone for Weak<T> {
#[inline]
fn clone(&self) -> Self {
Self {
weak: self.weak.clone(),
projected: self.projected,
}
}
}
impl<T: ?Sized> core::fmt::Debug for Weak<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "(Weak)")
}
}