use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::{mem, ptr};
#[inline]
unsafe fn transmute_ref<FromT, ToT>(from: &FromT) -> &ToT {
debug_assert_eq!(mem::size_of::<FromT>(), mem::size_of::<ToT>());
&*(from as *const FromT as *const ToT)
}
#[inline]
pub(crate) unsafe fn transmute_ref_mut<FromT, ToT>(from: &mut FromT) -> &mut ToT {
debug_assert_eq!(mem::size_of::<FromT>(), mem::size_of::<ToT>());
&mut *(from as *mut FromT as *mut ToT)
}
pub struct Handle<T>(
T,
PhantomData<*const ()>,
);
impl<T> AsRef<Handle<T>> for Handle<T> {
#[inline]
fn as_ref(&self) -> &Self {
self
}
}
impl<T> From<T> for Handle<T> {
fn from(t: T) -> Self {
Self::from_instance(t)
}
}
impl<T> Handle<T> {
#[inline]
#[must_use]
pub fn from_instance(t: T) -> Self {
Handle(t, PhantomData)
}
#[inline]
#[must_use]
pub fn from_ref(t: &T) -> &Self {
unsafe { transmute_ref(t) }
}
#[inline]
#[must_use]
pub fn from_ref_mut(t: &mut T) -> &mut Self {
unsafe { transmute_ref_mut(t) }
}
#[inline]
#[must_use]
pub fn from_ptr(tp: *const T) -> *const Self {
tp as _
}
#[inline]
#[must_use]
pub fn from_ptr_mut(tp: *mut T) -> *mut Self {
tp as _
}
#[inline]
#[must_use]
pub fn replace(mut self, t: &mut T) -> Self {
mem::swap(&mut self.0, t);
self
}
#[inline]
#[must_use]
pub fn into_instance(mut self) -> T {
let r = mem::replace(&mut self.0, unsafe { mem::zeroed() });
mem::forget(self);
r
}
#[inline]
#[must_use]
pub fn instance(&self) -> &T {
&self.0
}
#[inline]
#[must_use]
pub fn instance_mut(&mut self) -> &mut T {
&mut self.0
}
}
impl<T: Clone> Clone for Handle<T> {
fn clone(&self) -> Self {
Self::from_instance(self.0.clone())
}
}
impl<T: PartialEq> PartialEq for Handle<T> {
fn eq(&self, other: &Self) -> bool {
self.instance().eq(other.instance())
}
}
impl<T> Deref for Handle<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
self.instance()
}
}
impl<T> DerefMut for Handle<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.instance_mut()
}
}
#[cfg(feature = "send_sync")]
unsafe impl<T> Send for Handle<T> {}
#[cfg(feature = "send_sync")]
unsafe impl<T> Sync for Handle<T> {}
#[repr(transparent)]
pub struct RCHandle<T>(ptr::NonNull<T>);
impl<T> From<&RCHandle<T>> for RCHandle<T> {
fn from(rch: &RCHandle<T>) -> Self {
rch.clone().into()
}
}
impl<T> AsRef<RCHandle<T>> for RCHandle<T> {
fn as_ref(&self) -> &RCHandle<T> {
self
}
}
impl<T> RCHandle<T> {
#[inline]
pub fn from_ptr(ptr: *mut T) -> Option<Self> {
ptr::NonNull::new(ptr).map(Self)
}
#[inline]
pub fn from_unshared_ptr(ptr: *mut T) -> Option<Self> {
ptr::NonNull::new(ptr).map(|ptr| {
unsafe {
let _ = ptr.as_ref();
}
Self(ptr)
})
}
#[inline]
pub fn from_unshared_ptr_ref(t: &*mut T) -> &Option<Self> {
unsafe { transmute_ref(t) }
}
#[inline]
pub fn from_ref(t: &mut T) -> Self {
unsafe { Self::from_ptr(t).unwrap_unchecked() }
}
#[inline]
pub fn as_ptr(&self) -> &ptr::NonNull<T> {
&self.0
}
#[inline]
pub fn as_ref(&self) -> &T {
unsafe { self.0.as_ref() }
}
#[inline]
pub fn as_mut(&mut self) -> &mut T {
unsafe { self.0.as_mut() }
}
#[inline]
pub fn into_ptr(self) -> *mut T {
let ptr = self.0.as_ptr();
mem::forget(self);
ptr
}
}
impl<T> Clone for RCHandle<T> {
fn clone(&self) -> Self {
let ptr = self.0;
unsafe {
let _ = ptr.as_ref();
}
Self(ptr)
}
}
impl<T: PartialEq> PartialEq for RCHandle<T> {
fn eq(&self, other: &Self) -> bool {
self.as_ref().eq(other.as_ref())
}
}
impl<T> Deref for RCHandle<T> {
type Target = T;
#[inline]
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl<T> DerefMut for RCHandle<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_mut()
}
}
#[cfg(feature = "send_sync")]
unsafe impl<T> Send for RCHandle<T> {}
#[cfg(feature = "send_sync")]
unsafe impl<T> Sync for RCHandle<T> {}
#[cfg(test)]
mod tests {
use super::*;
struct Thing {
number: i32,
}
#[test]
fn test_handle() {
for num in 0..128 {
let thing = Thing { number: num };
let handle = Handle::from_instance(thing);
assert!(handle.number == num && handle.instance().number == num);
}
}
#[test]
fn test_handle_mut() {
for num in 0..128 {
let thing = Thing { number: num };
let mut handle = Handle::from_instance(thing);
assert!(
handle.number == num
&& handle.instance().number == num
&& handle.instance_mut().number == num
);
let new_num = num * 5;
handle.number = new_num;
assert!(handle.number == new_num);
}
}
#[test]
fn test_rchandle() {
for num in 0..128 {
let mut thing = Thing { number: num };
let mut rch = RCHandle::from_ptr(&mut thing).unwrap();
assert!(rch.number == num && rch.as_ref().number == num && rch.as_mut().number == num);
let new_num = num * 6;
rch.number = new_num;
assert!(rch.number == new_num);
let mut rch = RCHandle::from_ref(&mut thing);
rch.number = 11;
assert!(rch.number == 11);
}
}
}