#![allow(unstable_name_collisions)]
use sptr::Strict;
use std::ptr::NonNull;
#[derive(Debug)]
pub(crate) struct Tagged<T>(NonNull<T>);
impl<T> Clone for Tagged<T> {
fn clone(&self) -> Self {
Self(self.0)
}
}
impl<T> Copy for Tagged<T> {}
impl<T> Tagged<T> {
pub(crate) const fn from_tag(tag: usize) -> Self {
debug_assert!(std::mem::align_of::<T>() >= 2);
let addr = (tag << 1) | 1;
unsafe { Self(NonNull::new_unchecked(sptr::invalid_mut(addr))) }
}
pub(crate) const unsafe fn from_ptr(ptr: *mut T) -> Self {
debug_assert!(std::mem::align_of::<T>() >= 2);
unsafe { Self(NonNull::new_unchecked(ptr)) }
}
pub(crate) const fn from_non_null(ptr: NonNull<T>) -> Self {
debug_assert!(std::mem::align_of::<T>() >= 2);
Self(ptr)
}
pub(crate) fn unwrap(self) -> UnwrappedTagged<T> {
let addr = self.0.as_ptr().addr();
if addr & 1 == 0 {
UnwrappedTagged::Ptr(self.0)
} else {
UnwrappedTagged::Tag(addr >> 1)
}
}
#[allow(unused)]
pub(crate) fn addr(self) -> usize {
self.0.as_ptr().addr()
}
#[allow(unused)]
pub(crate) fn is_tagged(self) -> bool {
self.0.as_ptr().addr() & 1 > 0
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) enum UnwrappedTagged<T> {
Ptr(NonNull<T>),
Tag(usize),
}