use core::mem;
use core::ptr;
use alloc::rc::Rc;
use alloc::sync::Arc;
pub unsafe trait RefCnt: Clone {
type Base;
fn into_ptr(me: Self) -> *mut Self::Base;
fn as_ptr(me: &Self) -> *mut Self::Base;
unsafe fn from_ptr(ptr: *const Self::Base) -> Self;
fn inc(me: &Self) -> *mut Self::Base {
Self::into_ptr(Self::clone(me))
}
unsafe fn dec(ptr: *const Self::Base) {
drop(Self::from_ptr(ptr));
}
}
unsafe impl<T> RefCnt for Arc<T> {
type Base = T;
fn into_ptr(me: Arc<T>) -> *mut T {
Arc::into_raw(me) as *mut T
}
fn as_ptr(me: &Arc<T>) -> *mut T {
let ptr = Arc::into_raw(unsafe { ptr::read(me) });
let ptr = ptr as *mut T;
mem::forget(unsafe { Arc::from_raw(ptr) });
ptr
}
unsafe fn from_ptr(ptr: *const T) -> Arc<T> {
Arc::from_raw(ptr)
}
}
unsafe impl<T> RefCnt for Rc<T> {
type Base = T;
fn into_ptr(me: Rc<T>) -> *mut T {
Rc::into_raw(me) as *mut T
}
fn as_ptr(me: &Rc<T>) -> *mut T {
let ptr = Rc::into_raw(unsafe { ptr::read(me) });
let ptr = ptr as *mut T;
mem::forget(unsafe { Rc::from_raw(ptr) });
ptr
}
unsafe fn from_ptr(ptr: *const T) -> Rc<T> {
Rc::from_raw(ptr)
}
}
unsafe impl<T: RefCnt> RefCnt for Option<T> {
type Base = T::Base;
fn into_ptr(me: Option<T>) -> *mut T::Base {
me.map(T::into_ptr).unwrap_or_else(ptr::null_mut)
}
fn as_ptr(me: &Option<T>) -> *mut T::Base {
me.as_ref().map(T::as_ptr).unwrap_or_else(ptr::null_mut)
}
unsafe fn from_ptr(ptr: *const T::Base) -> Option<T> {
if ptr.is_null() {
None
} else {
Some(T::from_ptr(ptr))
}
}
}