use alloc::boxed::Box;
use alloc::sync::Arc;
use core::marker::PhantomData;
use core::mem::ManuallyDrop;
use core::ops::{Deref, Not};
use crate::node::{TryClone, XNode};
pub unsafe trait ItemEntry {
type Ref<'a>: Deref<Target = Self>
where
Self: 'a;
fn into_raw(self) -> *const ();
unsafe fn from_raw(raw: *const ()) -> Self;
unsafe fn raw_as_ref<'a>(raw: *const ()) -> Self::Ref<'a>;
}
#[derive(PartialEq, Debug)]
pub struct ArcRef<'a, T> {
inner: ManuallyDrop<Arc<T>>,
_marker: PhantomData<&'a Arc<T>>,
}
impl<'a, T> Deref for ArcRef<'a, T> {
type Target = Arc<T>;
fn deref(&self) -> &Self::Target {
&*self.inner
}
}
unsafe impl<T> ItemEntry for Arc<T> {
type Ref<'a> = ArcRef<'a, T> where Self: 'a;
fn into_raw(self) -> *const () {
assert!((core::mem::align_of::<T>() & XEntry::<Self>::TYPE_MASK) == 0);
Arc::into_raw(self).cast()
}
unsafe fn from_raw(raw: *const ()) -> Self {
unsafe { Arc::from_raw(raw.cast()) }
}
unsafe fn raw_as_ref<'a>(raw: *const ()) -> Self::Ref<'a> {
unsafe {
ArcRef {
inner: ManuallyDrop::new(Arc::from_raw(raw.cast())),
_marker: PhantomData,
}
}
}
}
#[derive(PartialEq, Debug)]
pub struct BoxRef<'a, T> {
inner: *mut T,
_marker: PhantomData<&'a Box<T>>,
}
impl<'a, T> Deref for BoxRef<'a, T> {
type Target = Box<T>;
fn deref(&self) -> &Self::Target {
unsafe { core::mem::transmute(&self.inner) }
}
}
unsafe impl<T> ItemEntry for Box<T> {
type Ref<'a> = BoxRef<'a, T> where Self: 'a;
fn into_raw(self) -> *const () {
assert!((core::mem::align_of::<T>() & XEntry::<Self>::TYPE_MASK) == 0);
Box::into_raw(self).cast_const().cast()
}
unsafe fn from_raw(raw: *const ()) -> Self {
unsafe { Box::from_raw(raw.cast_mut().cast()) }
}
unsafe fn raw_as_ref<'a>(raw: *const ()) -> Self::Ref<'a> {
BoxRef {
inner: raw.cast_mut().cast(),
_marker: PhantomData,
}
}
}
#[derive(PartialEq, Eq, Debug)]
#[repr(transparent)]
pub(super) struct XEntry<I>
where
I: ItemEntry,
{
raw: *const (),
_marker: core::marker::PhantomData<(Arc<XNode<I>>, I)>,
}
unsafe impl<I: ItemEntry> Send for XEntry<I> where (Arc<XNode<I>>, I): Send {}
unsafe impl<I: ItemEntry> Sync for XEntry<I> where (Arc<XNode<I>>, I): Sync {}
#[derive(PartialEq, Eq, Debug)]
#[repr(usize)]
enum EntryType {
Node = 0,
Item = 2,
}
impl TryFrom<usize> for EntryType {
type Error = ();
fn try_from(val: usize) -> Result<Self, Self::Error> {
match val {
x if x == EntryType::Node as usize => Ok(EntryType::Node),
x if x == EntryType::Item as usize => Ok(EntryType::Item),
_ => Err(()),
}
}
}
impl<I: ItemEntry> XEntry<I> {
const TYPE_MASK: usize = 3;
pub const EMPTY: Self = Self {
raw: core::ptr::null(),
_marker: PhantomData,
};
unsafe fn new(ptr: *const (), ty: EntryType) -> Self {
let raw = ptr.map_addr(|addr| {
debug_assert!(addr & Self::TYPE_MASK == 0);
addr | (ty as usize)
});
Self {
raw,
_marker: PhantomData,
}
}
fn ptr(&self) -> *const () {
self.raw.map_addr(|addr| addr & !Self::TYPE_MASK)
}
fn ty(&self) -> Option<EntryType> {
self.is_null()
.not()
.then(|| (self.raw.addr() & Self::TYPE_MASK).try_into().unwrap())
}
pub fn is_null(&self) -> bool {
self.raw.is_null()
}
}
pub(super) enum NodeMaybeMut<'a, I>
where
I: ItemEntry,
{
Shared(&'a XNode<I>),
Exclusive(&'a mut XNode<I>),
}
impl<'a, I: ItemEntry> Deref for NodeMaybeMut<'a, I> {
type Target = XNode<I>;
fn deref(&self) -> &XNode<I> {
match &self {
Self::Shared(ref node) => node,
Self::Exclusive(ref node) => node,
}
}
}
impl<I: ItemEntry> XEntry<I> {
pub fn from_node(node: XNode<I>) -> Self {
let node_ptr = {
let arc_node = Arc::new(node);
Arc::into_raw(arc_node).cast()
};
unsafe { Self::new(node_ptr, EntryType::Node) }
}
pub fn is_node(&self) -> bool {
self.ty() == Some(EntryType::Node)
}
pub fn as_node_ref(&self) -> Option<&XNode<I>> {
if !self.is_node() {
return None;
}
Some(unsafe { &*self.ptr().cast() })
}
pub fn as_node_maybe_mut(&mut self) -> Option<NodeMaybeMut<'_, I>> {
match self.node_strong_count() {
0 => None,
1 => Some(NodeMaybeMut::Exclusive(unsafe {
&mut *self.ptr().cast_mut().cast()
})),
_ => Some(NodeMaybeMut::Shared(unsafe { &*self.ptr().cast() })),
}
}
pub fn as_node_mut_or_cow(&mut self) -> Option<&mut XNode<I>> {
match self.node_strong_count() {
0 => return None,
1 => return Some(unsafe { &mut *self.ptr().cast_mut().cast() }),
_ => (),
}
let node: &XNode<I> = unsafe { &*self.ptr().cast() };
let new_node = node.try_clone().unwrap();
*self = Self::from_node(new_node);
Some(unsafe { &mut *self.ptr().cast_mut().cast() })
}
fn node_strong_count(&self) -> usize {
if !self.is_node() {
return 0;
}
let node = unsafe { ManuallyDrop::new(Arc::<XNode<I>>::from_raw(self.ptr().cast())) };
Arc::strong_count(&*node)
}
}
impl<I: ItemEntry> XEntry<I> {
pub fn from_item(item: I) -> Self {
let item_ptr = I::into_raw(item);
unsafe { Self::new(item_ptr, EntryType::Item) }
}
pub fn is_item(&self) -> bool {
self.ty() == Some(EntryType::Item)
}
pub fn into_item(self) -> Option<I> {
if !self.is_item() {
return None;
}
let ptr = self.ptr();
core::mem::forget(self);
Some(unsafe { I::from_raw(ptr) })
}
pub fn as_item_ref(&self) -> Option<I::Ref<'_>> {
if !self.is_item() {
return None;
}
let ptr = self.ptr();
Some(unsafe { I::raw_as_ref(ptr) })
}
}
impl<I: ItemEntry> Drop for XEntry<I> {
fn drop(&mut self) {
match self.ty() {
None => (),
Some(EntryType::Item) => unsafe {
I::from_raw(self.ptr());
},
Some(EntryType::Node) => unsafe {
Arc::<XNode<I>>::from_raw(self.ptr().cast());
},
}
}
}
impl<I: ItemEntry + Clone> Clone for XEntry<I> {
fn clone(&self) -> Self {
match self.ty() {
None => Self::EMPTY,
Some(EntryType::Item) => {
let item_entry = unsafe { I::raw_as_ref(self.ptr()) };
Self::from_item((*item_entry).clone())
}
Some(EntryType::Node) => unsafe {
Arc::<XNode<I>>::increment_strong_count(self.ptr().cast());
Self {
raw: self.raw,
_marker: PhantomData,
}
},
}
}
}