use crate::ucount;
use alloc::boxed::Box;
use branches::{assume, unlikely};
use core::{
cell::Cell,
fmt,
hash::{Hash, Hasher},
marker::PhantomData,
mem::{self, forget, MaybeUninit},
ops::Deref,
pin::Pin,
ptr::NonNull,
};
#[repr(C)]
struct RcInner<T> {
data: T,
counter: Cell<ucount>,
}
pub struct Rc<T> {
ptr: NonNull<RcInner<T>>,
phantom: PhantomData<Box<RcInner<T>>>,
}
impl<T> Rc<T> {
#[inline]
pub fn new(data: T) -> Rc<T> {
Rc {
ptr: unsafe {
NonNull::new_unchecked(Box::leak(Box::new(RcInner {
data,
counter: Cell::new(1),
})))
},
phantom: PhantomData,
}
}
#[inline(always)]
fn inner(&self) -> &RcInner<T> {
unsafe { self.ptr.as_ref() }
}
#[inline]
fn inner_mut(&mut self) -> &mut RcInner<T> {
unsafe { self.ptr.as_mut() }
}
#[inline]
#[must_use]
pub fn pin(value: T) -> Pin<Rc<T>> {
unsafe { Pin::new_unchecked(Rc::new(value)) }
}
#[inline]
#[must_use]
pub fn as_ptr(&self) -> *const T {
self.ptr.as_ptr() as *const T
}
#[inline]
pub fn into_raw(this: Self) -> *const T {
let ptr = Self::as_ptr(&this);
core::mem::forget(this);
ptr
}
#[inline]
pub unsafe fn from_raw(ptr: *const T) -> Self {
Rc {
ptr: NonNull::new_unchecked(ptr as *mut RcInner<T>),
phantom: PhantomData,
}
}
#[inline]
#[must_use]
pub fn strong_count(&self) -> usize {
self.inner().counter.get() as usize
}
#[inline]
#[must_use]
pub fn ptr_eq(this: &Self, other: &Self) -> bool {
this.ptr.as_ptr() == other.ptr.as_ptr()
}
#[inline]
fn is_unique(&self) -> bool {
self.inner().counter.get() == 1
}
#[inline]
pub fn get_mut(this: &mut Self) -> Option<&mut T> {
if this.is_unique() {
Some(&mut this.inner_mut().data)
} else {
None
}
}
#[inline]
pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T {
&mut this.inner_mut().data
}
#[inline]
pub fn try_unwrap(this: Self) -> Result<T, Self> {
if this.is_unique() {
unsafe {
let inner = Box::from_raw(this.ptr.as_ptr());
core::mem::forget(this);
let val = inner.data;
Ok(val)
}
} else {
Err(this)
}
}
unsafe fn drop_slow(&mut self) {
let _ = Box::from_raw(self.ptr.as_ptr());
}
pub fn into_inner(this: Self) -> Option<T> {
Rc::try_unwrap(this).ok()
}
pub fn new_uninit() -> Rc<mem::MaybeUninit<T>> {
let inner = Box::new(RcInner {
data: MaybeUninit::uninit(),
counter: Cell::new(1),
});
Rc {
ptr: unsafe { NonNull::new_unchecked(Box::leak(inner)) },
phantom: PhantomData,
}
}
}
impl<T> Rc<MaybeUninit<T>> {
pub unsafe fn assume_init(self) -> Rc<T> {
let ptr = self.ptr.as_ptr();
forget(self);
Rc {
ptr: NonNull::new_unchecked(ptr as *mut RcInner<T>),
phantom: PhantomData,
}
}
}
impl<T: Clone> Rc<T> {
#[inline]
pub fn unwrap_or_clone(this: Self) -> T {
Rc::try_unwrap(this).unwrap_or_else(|rc| (*rc).clone())
}
fn optimized_clone(&self) -> Rc<T> {
let mut buffer: Box<MaybeUninit<RcInner<T>>> = Box::new(MaybeUninit::uninit());
let ptr = unsafe {
(&mut (*buffer.as_mut_ptr()).data as *mut T).write(T::clone(self));
(*buffer.as_mut_ptr()).counter = Cell::new(1);
NonNull::new_unchecked(Box::leak(buffer) as *mut _ as *mut RcInner<T>)
};
Rc {
ptr,
phantom: PhantomData,
}
}
#[inline]
pub fn make_mut(this: &mut Rc<T>) -> &mut T {
if !this.is_unique() {
*this = this.optimized_clone();
}
unsafe { Self::get_mut_unchecked(this) }
}
}
impl<T> Deref for Rc<T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &T {
&(self.inner().data)
}
}
impl<T> From<T> for Rc<T> {
#[inline(always)]
fn from(value: T) -> Self {
Rc::new(value)
}
}
impl<T> Clone for Rc<T> {
#[inline]
fn clone(&self) -> Self {
let counter = &self.inner().counter;
let value = counter.get();
unsafe { assume(value != 0) };
let value = value.wrapping_add(1);
if unlikely(value == 0) {
panic!("reference counter overflow");
}
counter.set(value);
Self {
ptr: self.ptr,
phantom: PhantomData,
}
}
}
impl<T> Drop for Rc<T> {
#[inline]
fn drop(&mut self) {
let counter = &self.inner().counter;
let value = counter.get();
unsafe {
assume(value != 0);
}
if value != 1 {
let value = value.wrapping_sub(1);
counter.set(value);
} else {
unsafe { self.drop_slow() };
}
}
}
impl<T: Hash> Hash for Rc<T> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}
impl<T: fmt::Display> fmt::Display for Rc<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<T: fmt::Debug> fmt::Debug for Rc<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T> fmt::Pointer for Rc<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&(&**self as *const T), f)
}
}
impl<T: Default> Default for Rc<T> {
#[inline]
fn default() -> Rc<T> {
Rc::new(Default::default())
}
}
impl<T: PartialEq> PartialEq for Rc<T> {
#[inline]
fn eq(&self, other: &Rc<T>) -> bool {
self.deref().eq(other)
}
}
impl<T: Eq> Eq for Rc<T> {}
impl<T: PartialOrd> PartialOrd for Rc<T> {
#[inline]
fn partial_cmp(&self, other: &Rc<T>) -> Option<core::cmp::Ordering> {
(**self).partial_cmp(&**other)
}
#[inline]
fn lt(&self, other: &Rc<T>) -> bool {
**self < **other
}
#[inline]
fn le(&self, other: &Rc<T>) -> bool {
**self <= **other
}
#[inline]
fn gt(&self, other: &Rc<T>) -> bool {
**self > **other
}
#[inline]
fn ge(&self, other: &Rc<T>) -> bool {
**self >= **other
}
}
impl<T: Ord> Ord for Rc<T> {
#[inline]
fn cmp(&self, other: &Rc<T>) -> core::cmp::Ordering {
(**self).cmp(&**other)
}
}
impl<T> core::borrow::Borrow<T> for Rc<T> {
#[inline(always)]
fn borrow(&self) -> &T {
self
}
}
impl<T> AsRef<T> for Rc<T> {
#[inline(always)]
fn as_ref(&self) -> &T {
self
}
}
impl<T> Unpin for Rc<T> {}