#![no_std]
extern crate alloc;
use core::cmp::Ordering;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
use core::mem;
use core::ops::Deref;
use core::ptr::NonNull;
pub mod refcnt;
use refcnt::{Inner, Refcount, WeakRefcount};
#[doc(hidden)]
#[path = "runtime.rs"]
pub mod __rt;
pub use refptr_macros::refcounted;
pub unsafe trait Refcounted {
type Rc: Refcount;
unsafe fn refcount_metadata(&self) -> <Self::Rc as Refcount>::Metadata;
}
pub struct RefPtr<T: ?Sized + Refcounted> {
ptr: NonNull<Inner<T>>,
_marker: PhantomData<T>,
}
impl<T: ?Sized + Refcounted> RefPtr<T> {
pub fn new(val: &T) -> RefPtr<T> {
unsafe {
let ptr = Inner::cast(val as *const T as *mut T);
T::Rc::inc_strong(ptr);
RefPtr::from_inner(ptr)
}
}
pub unsafe fn from_raw(val: *const T) -> RefPtr<T> {
RefPtr::from_inner(Inner::cast(val as *mut T))
}
pub fn into_raw(this: Self) -> *const T {
let ptr = this.deref() as *const T;
mem::forget(this);
ptr
}
unsafe fn from_inner(ptr: *mut Inner<T>) -> RefPtr<T> {
RefPtr {
ptr: NonNull::new_unchecked(ptr),
_marker: PhantomData,
}
}
}
impl<T: ?Sized + Refcounted> Deref for RefPtr<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &(*self.ptr.as_ptr()).data }
}
}
impl<T: ?Sized + Refcounted> Clone for RefPtr<T> {
fn clone(&self) -> Self {
unsafe {
T::Rc::inc_strong(self.ptr.as_ptr());
RefPtr::from_inner(self.ptr.as_ptr())
}
}
}
impl<T: ?Sized + Refcounted> Drop for RefPtr<T> {
fn drop(&mut self) {
unsafe { T::Rc::dec_strong(self.ptr.as_ptr()) }
}
}
unsafe impl<T: ?Sized + Refcounted + Sync + Send> Send for RefPtr<T> {}
unsafe impl<T: ?Sized + Refcounted + Sync + Send> Sync for RefPtr<T> {}
pub struct WeakPtr<T: ?Sized>
where
T: Refcounted,
T::Rc: WeakRefcount,
{
ptr: NonNull<Inner<T>>,
_marker: PhantomData<T>,
}
impl<T: ?Sized> WeakPtr<T>
where
T: Refcounted,
T::Rc: WeakRefcount,
{
pub fn new(val: &T) -> WeakPtr<T> {
unsafe {
let ptr = Inner::cast(val as *const T as *mut T);
T::Rc::inc_weak(ptr);
WeakPtr::from_inner(ptr)
}
}
pub fn upgrade(&self) -> Option<RefPtr<T>> {
unsafe {
if T::Rc::upgrade(self.ptr.as_ptr()) {
Some(RefPtr::from_inner(self.ptr.as_ptr()))
} else {
None
}
}
}
pub fn strong_count(&self) -> usize {
unsafe { T::Rc::strong_count(self.ptr.as_ptr()) }
}
pub fn weak_count(&self) -> usize {
unsafe { T::Rc::weak_count(self.ptr.as_ptr()) }
}
unsafe fn from_inner(ptr: *mut Inner<T>) -> WeakPtr<T> {
WeakPtr {
ptr: NonNull::new_unchecked(ptr),
_marker: PhantomData,
}
}
}
impl<T: ?Sized> Clone for WeakPtr<T>
where
T: Refcounted,
T::Rc: WeakRefcount,
{
fn clone(&self) -> Self {
unsafe {
T::Rc::inc_weak(self.ptr.as_ptr());
WeakPtr::from_inner(self.ptr.as_ptr())
}
}
}
impl<T: ?Sized> Drop for WeakPtr<T>
where
T: Refcounted,
T::Rc: WeakRefcount,
{
fn drop(&mut self) {
unsafe { T::Rc::dec_weak(self.ptr.as_ptr()) }
}
}
impl<T: ?Sized> fmt::Debug for WeakPtr<T>
where
T: Refcounted,
T::Rc: WeakRefcount,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "(WeakPtr)")
}
}
unsafe impl<T: ?Sized> Send for WeakPtr<T>
where
T: Refcounted + Send + Sync,
T::Rc: WeakRefcount,
{
}
unsafe impl<T: ?Sized> Sync for WeakPtr<T>
where
T: Refcounted + Send + Sync,
T::Rc: WeakRefcount,
{
}
impl<T: ?Sized + Refcounted + PartialEq> PartialEq for RefPtr<T> {
fn eq(&self, other: &RefPtr<T>) -> bool {
**self == **other
}
}
impl<T: ?Sized + Refcounted + PartialOrd> PartialOrd for RefPtr<T> {
fn partial_cmp(&self, other: &RefPtr<T>) -> Option<Ordering> {
(**self).partial_cmp(&**other)
}
fn lt(&self, other: &RefPtr<T>) -> bool {
*(*self) < *(*other)
}
fn le(&self, other: &RefPtr<T>) -> bool {
*(*self) <= *(*other)
}
fn gt(&self, other: &RefPtr<T>) -> bool {
*(*self) > *(*other)
}
fn ge(&self, other: &RefPtr<T>) -> bool {
*(*self) >= *(*other)
}
}
impl<T: ?Sized + Refcounted + Ord> Ord for RefPtr<T> {
fn cmp(&self, other: &RefPtr<T>) -> Ordering {
(**self).cmp(&**other)
}
}
impl<T: ?Sized + Refcounted + Eq> Eq for RefPtr<T> {}
impl<T: ?Sized + Refcounted + fmt::Display> fmt::Display for RefPtr<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&**self, f)
}
}
impl<T: ?Sized + Refcounted + fmt::Debug> fmt::Debug for RefPtr<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&**self, f)
}
}
impl<T: ?Sized + Refcounted> fmt::Pointer for RefPtr<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Pointer::fmt(&(&**self as *const T), f)
}
}
impl<T: ?Sized + Refcounted + Hash> Hash for RefPtr<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state)
}
}
impl<T: ?Sized + Refcounted> From<&T> for RefPtr<T> {
fn from(v: &T) -> Self {
RefPtr::new(v)
}
}
#[macro_export]
macro_rules! make_refptr {
($($seg:ident $(::<$($t:ty),*>)?)::+ { $($f:tt)* }) => {
{
let value = $crate::__rt::ManuallyDrop::new($($seg $(::<$($t),*>)?)::+ {
_refcnt_marker: unsafe { $crate::__rt::PhantomRefcnt::new() },
$($f)*
});
unsafe { $crate::__rt::alloc(value) }
}
}
}