#![allow(dead_code)] use std::fmt; use std::num::NonZeroU8; use sptr::Strict; const SIGN_MASK: u64 = 0x7FFF_FFFF_FFFF_FFFF; const QUIET_NAN: u64 = 0x7FF8_0000_0000_0000; const NEG_QUIET_NAN: u64 = 0xFFF8_0000_0000_0000; pub(crate) trait ArrayExt { type Elem; fn truncate_to(self) -> [Self::Elem; M]; } impl ArrayExt for [T; N] { type Elem = T; fn truncate_to(self) -> [Self::Elem; M] { let copy_len = usize::min(N, M); let mut out = [T::default(); M]; out[0..copy_len].copy_from_slice(&self[0..copy_len]); out } } pub(crate) trait RawStore: Sized { fn to_val(self, value: &mut Value); fn from_val(value: &Value) -> Self; } impl RawStore for [u8; 6] { #[inline] fn to_val(self, value: &mut Value) { value.set_data(self); } #[inline] fn from_val(value: &Value) -> Self { *value.data() } } impl RawStore for bool { #[inline] fn to_val(self, value: &mut Value) { value.set_data([u8::from(self)].truncate_to()); } #[inline] fn from_val(value: &Value) -> Self { value.data()[0] == 1 } } macro_rules! int_store { ($ty:ty) => { impl RawStore for $ty { #[inline] fn to_val(self, value: &mut Value) { let bytes = self.to_ne_bytes(); value.set_data(bytes.truncate_to()); } #[inline] fn from_val(value: &Value) -> Self { <$ty>::from_ne_bytes(value.data().truncate_to()) } } }; } int_store!(u8); int_store!(u16); int_store!(u32); int_store!(i8); int_store!(i16); int_store!(i32); fn store_ptr(value: &mut Value, ptr: P) { #[cfg(target_pointer_width = "64")] { assert!( ptr.addr() <= 0x0000_FFFF_FFFF_FFFF, "Pointer too large to store in NaN box" ); let val = (unsafe { value.whole_mut() } as *mut [u8; 8]).cast::

(); let ptr = Strict::map_addr(ptr, |addr| { addr | (usize::from(value.header().into_raw()) << 48) }); unsafe { val.write(ptr) }; } #[cfg(target_pointer_width = "32")] { let _ = (value, ptr); unimplemented!("32-bit pointer storage not supported"); } } fn load_ptr(value: &Value) -> P { #[cfg(target_pointer_width = "64")] { let val = (unsafe { value.whole() } as *const [u8; 8]).cast::

(); let ptr = unsafe { val.read() }; Strict::map_addr(ptr, |addr| addr & 0x0000_FFFF_FFFF_FFFF) } #[cfg(target_pointer_width = "32")] { let _ = value; unimplemented!("32-bit pointer storage not supported"); } } impl RawStore for *const T { fn to_val(self, value: &mut Value) { store_ptr::<*const T>(value, self); } fn from_val(value: &Value) -> Self { load_ptr::<*const T>(value) } } impl RawStore for *mut T { fn to_val(self, value: &mut Value) { store_ptr::<*mut T>(value, self); } fn from_val(value: &Value) -> Self { load_ptr::<*mut T>(value) } } #[derive(Copy, Clone, PartialEq, Eq)] enum TagVal { _P1, _P2, _P3, _P4, _P5, _P6, _P7, _N1, _N2, _N3, _N4, _N5, _N6, _N7, } #[derive(Copy, Clone, PartialEq, Eq)] pub(crate) struct RawTag(TagVal); impl RawTag { pub(crate) const P1: RawTag = RawTag(TagVal::_P1); pub(crate) const P2: RawTag = RawTag(TagVal::_P2); pub(crate) const P3: RawTag = RawTag(TagVal::_P3); pub(crate) const P4: RawTag = RawTag(TagVal::_P4); pub(crate) const P5: RawTag = RawTag(TagVal::_P5); pub(crate) const P6: RawTag = RawTag(TagVal::_P6); pub(crate) const P7: RawTag = RawTag(TagVal::_P7); pub(crate) const N1: RawTag = RawTag(TagVal::_N1); pub(crate) const N2: RawTag = RawTag(TagVal::_N2); pub(crate) const N3: RawTag = RawTag(TagVal::_N3); pub(crate) const N4: RawTag = RawTag(TagVal::_N4); pub(crate) const N5: RawTag = RawTag(TagVal::_N5); pub(crate) const N6: RawTag = RawTag(TagVal::_N6); pub(crate) const N7: RawTag = RawTag(TagVal::_N7); #[inline] #[must_use] pub(crate) fn new(neg: bool, val: NonZeroU8) -> RawTag { unsafe { Self::new_unchecked(neg, val.get() & 0x07) } } #[inline] #[must_use] pub(crate) fn new_checked(neg: bool, val: u8) -> Option { Some(RawTag(match (neg, val) { (false, 1) => TagVal::_P1, (false, 2) => TagVal::_P2, (false, 3) => TagVal::_P3, (false, 4) => TagVal::_P4, (false, 5) => TagVal::_P5, (false, 6) => TagVal::_P6, (false, 7) => TagVal::_P7, (true, 1) => TagVal::_N1, (true, 2) => TagVal::_N2, (true, 3) => TagVal::_N3, (true, 4) => TagVal::_N4, (true, 5) => TagVal::_N5, (true, 6) => TagVal::_N6, (true, 7) => TagVal::_N7, _ => return None, })) } /// # Safety /// /// `val` must be in the range `1..8` #[inline] #[must_use] pub(crate) const unsafe fn new_unchecked(neg: bool, val: u8) -> RawTag { RawTag(match (neg, val) { (false, 1) => TagVal::_P1, (false, 2) => TagVal::_P2, (false, 3) => TagVal::_P3, (false, 4) => TagVal::_P4, (false, 5) => TagVal::_P5, (false, 6) => TagVal::_P6, (false, 7) => TagVal::_P7, (true, 1) => TagVal::_N1, (true, 2) => TagVal::_N2, (true, 3) => TagVal::_N3, (true, 4) => TagVal::_N4, (true, 5) => TagVal::_N5, (true, 6) => TagVal::_N6, (true, 7) => TagVal::_N7, _ => unsafe { core::hint::unreachable_unchecked() }, }) } #[inline] #[must_use] pub(crate) fn is_neg(self) -> bool { matches!(self.0, |TagVal::_N1| TagVal::_N2 | TagVal::_N3 | TagVal::_N4 | TagVal::_N5 | TagVal::_N6 | TagVal::_N7) } #[inline] #[must_use] pub(crate) fn val(self) -> NonZeroU8 { match self.0 { TagVal::_P1 | TagVal::_N1 => NonZeroU8::MIN, TagVal::_P2 | TagVal::_N2 => NonZeroU8::MIN.saturating_add(1), TagVal::_P3 | TagVal::_N3 => NonZeroU8::MIN.saturating_add(2), TagVal::_P4 | TagVal::_N4 => NonZeroU8::MIN.saturating_add(3), TagVal::_P5 | TagVal::_N5 => NonZeroU8::MIN.saturating_add(4), TagVal::_P6 | TagVal::_N6 => NonZeroU8::MIN.saturating_add(5), TagVal::_P7 | TagVal::_N7 => NonZeroU8::MIN.saturating_add(6), } } #[inline] #[must_use] pub(crate) const fn neg_val(self) -> (bool, u8) { match self.0 { TagVal::_P1 => (false, 1), TagVal::_P2 => (false, 2), TagVal::_P3 => (false, 3), TagVal::_P4 => (false, 4), TagVal::_P5 => (false, 5), TagVal::_P6 => (false, 6), TagVal::_P7 => (false, 7), TagVal::_N1 => (true, 1), TagVal::_N2 => (true, 2), TagVal::_N3 => (true, 3), TagVal::_N4 => (true, 4), TagVal::_N5 => (true, 5), TagVal::_N6 => (true, 6), TagVal::_N7 => (true, 7), } } } impl fmt::Debug for RawTag { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RawTag") .field("neg", &self.is_neg()) .field("val", &self.val()) .finish() } } #[derive(Copy, Clone, Debug, PartialEq)] #[repr(transparent)] struct Header(u16); impl Header { #[inline] fn new(tag: RawTag) -> Header { let (neg, val) = tag.neg_val(); Header(0x7FF8 | (u16::from(neg) << 15) | u16::from(val)) } #[inline] const fn tag(self) -> RawTag { unsafe { RawTag::new_unchecked(self.get_sign(), self.get_tag()) } } #[inline] const fn get_sign(self) -> bool { self.0 & 0x8000 != 0 } #[inline] const fn get_tag(self) -> u8 { (self.0 & 0x0007) as u8 } #[inline] fn into_raw(self) -> u16 { self.0 } } #[derive(Copy, Clone, Debug, PartialEq)] #[repr(C, align(8))] pub(crate) struct Value { #[cfg(target_endian = "big")] header: Header, data: [u8; 6], #[cfg(target_endian = "little")] header: Header, } impl Value { #[inline] pub(crate) fn new(tag: RawTag, data: [u8; 6]) -> Value { Value { header: Header::new(tag), data, } } #[inline] pub(crate) fn empty(tag: RawTag) -> Value { Value::new(tag, [0; 6]) } pub(crate) fn store(tag: RawTag, val: T) -> Value { let mut v = Value::new(tag, [0; 6]); T::to_val(val, &mut v); v } pub(crate) fn load(self) -> T { T::from_val(&self) } #[inline] #[must_use] pub(crate) const fn tag(&self) -> RawTag { self.header.tag() } #[inline] fn header(&self) -> &Header { &self.header } #[inline] pub(crate) fn set_data(&mut self, val: [u8; 6]) { self.data = val; } #[inline] #[must_use] pub(crate) fn data(&self) -> &[u8; 6] { &self.data } #[inline] #[must_use] pub(crate) fn data_mut(&mut self) -> &mut [u8; 6] { &mut self.data } #[inline] #[must_use] unsafe fn whole(&self) -> &[u8; 8] { let ptr = (self as *const Value).cast::<[u8; 8]>(); unsafe { &*ptr } } #[inline] #[must_use] unsafe fn whole_mut(&mut self) -> &mut [u8; 8] { let ptr = (self as *mut Value).cast::<[u8; 8]>(); unsafe { &mut *ptr } } } #[repr(C)] #[derive(Copy, Clone)] pub(crate) union RawBox { float: f64, value: Value, bits: u64, #[cfg(target_pointer_width = "64")] ptr: *const (), #[cfg(target_pointer_width = "32")] ptr: (u32, *const ()), } impl RawBox { #[inline] #[must_use] pub(crate) fn from_float(val: f64) -> RawBox { match (val.is_nan(), val.is_sign_positive()) { (true, true) => RawBox { float: f64::from_bits(QUIET_NAN), }, (true, false) => RawBox { float: f64::from_bits(NEG_QUIET_NAN), }, (false, _) => RawBox { float: val }, } } #[inline] #[must_use] pub(crate) fn from_value(value: Value) -> RawBox { RawBox { value } } #[inline] #[must_use] pub(crate) const fn tag(&self) -> Option { if self.is_value() { Some(unsafe { self.value.tag() }) } else { None } } #[inline] #[must_use] pub(crate) fn is_float(&self) -> bool { (unsafe { !self.float.is_nan() } || unsafe { self.bits & SIGN_MASK == QUIET_NAN }) } #[inline] #[must_use] pub(crate) const fn is_value(&self) -> bool { (unsafe { self.float.is_nan() } && unsafe { self.bits & SIGN_MASK != QUIET_NAN }) } #[inline] #[must_use] pub(crate) fn float(&self) -> Option<&f64> { if self.is_float() { Some(unsafe { &self.float }) } else { None } } #[inline] #[must_use] pub(crate) fn value(&self) -> Option<&Value> { if self.is_value() { Some(unsafe { &self.value }) } else { None } } #[inline] pub(crate) fn into_float_unchecked(self) -> f64 { unsafe { self.float } } #[inline] #[must_use] pub(crate) fn to_bits(self) -> u64 { unsafe { self.bits } } } impl fmt::Debug for RawBox { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.float() { Some(val) => f.debug_tuple("RawBox::Float").field(val).finish(), None => { let val = self.value().expect("RawBox is neither float nor value"); f.debug_struct("RawBox::Data") .field("tag", &val.tag()) .field("data", val.data()) .finish() } } } }