use std::marker::PhantomData;
pub const ADDR_MASK: u64 = 0x00FF_FFFF_FFFF_FFFF;
pub const CARD_SHIFT: u32 = 56;
#[repr(transparent)]
pub struct CardinalityPointer<T> {
raw: u64,
_phantom: PhantomData<*const T>,
}
unsafe impl<T: Send> Send for CardinalityPointer<T> {}
unsafe impl<T: Sync> Sync for CardinalityPointer<T> {}
impl<T> CardinalityPointer<T> {
pub const SIGNATURE: subetha_core::AxisMask = subetha_core::AxisMask::from_axes(
&[subetha_core::Axis::ContentPrefix],
);
pub unsafe fn from_raw(target: *const T, cardinality_hint: u64) -> Self {
let addr = target as u64;
assert!(
addr & !ADDR_MASK == 0,
"address {addr:#x} has high byte set; cannot encode cardinality. \
Use from_raw_unchecked if the caller has verified the address \
envelope out of band."
);
unsafe { Self::from_raw_unchecked(target, cardinality_hint) }
}
pub unsafe fn from_raw_unchecked(target: *const T, cardinality_hint: u64) -> Self {
let addr = target as u64;
let log2_card = if cardinality_hint == 0 {
0u64
} else {
64 - (cardinality_hint - 1).leading_zeros() as u64
};
let cap = log2_card.min(255);
let raw = (cap << CARD_SHIFT) | (addr & ADDR_MASK);
Self { raw, _phantom: PhantomData }
}
#[inline]
pub fn as_raw(&self) -> *const T {
(self.raw & ADDR_MASK) as *const T
}
#[inline]
pub const fn log2_cardinality(&self) -> u8 {
(self.raw >> CARD_SHIFT) as u8
}
#[inline]
pub fn cardinality(&self) -> u64 {
let k = self.log2_cardinality();
if k >= 63 { u64::MAX } else { 1u64 << k }
}
#[inline]
pub const fn raw(&self) -> u64 { self.raw }
pub fn set_cardinality(&mut self, new_cardinality: u64) {
let log2_card = if new_cardinality == 0 {
0u64
} else {
64 - (new_cardinality - 1).leading_zeros() as u64
};
let cap = log2_card.min(255);
self.raw = (cap << CARD_SHIFT) | (self.raw & ADDR_MASK);
}
pub fn size_tier(&self) -> SizeTier {
let k = self.log2_cardinality();
match k {
0..=3 => SizeTier::Tiny, 4..=10 => SizeTier::Medium, _ => SizeTier::Large, }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SizeTier {
Tiny,
Medium,
Large,
}
impl<T> Clone for CardinalityPointer<T> {
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for CardinalityPointer<T> {}
impl<T> std::fmt::Debug for CardinalityPointer<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "CardinalityPointer {{ addr: {:#x}, log2_card: {}, card: {} }}",
self.raw & ADDR_MASK, self.log2_cardinality(), self.cardinality())
}
}
impl<T> PartialEq for CardinalityPointer<T> {
fn eq(&self, other: &Self) -> bool { self.raw == other.raw }
}
impl<T> Eq for CardinalityPointer<T> {}
impl<T> std::hash::Hash for CardinalityPointer<T> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.raw.hash(state);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn layout_is_8_bytes() {
assert_eq!(std::mem::size_of::<CardinalityPointer<u64>>(), 8);
assert_eq!(std::mem::align_of::<CardinalityPointer<u64>>(), 8);
}
#[test]
fn address_round_trips_with_masking() {
let addr: *const u64 = 0x0000_1234_5678_9ABC as *const u64;
let p = unsafe { CardinalityPointer::from_raw(addr, 100) };
assert_eq!(p.as_raw(), addr);
}
#[test]
fn cardinality_buckets_to_log2() {
let p0: CardinalityPointer<u64>
= unsafe { CardinalityPointer::from_raw(std::ptr::dangling::<u64>(), 0) };
assert_eq!(p0.log2_cardinality(), 0);
let p1: CardinalityPointer<u64>
= unsafe { CardinalityPointer::from_raw(std::ptr::dangling::<u64>(), 1) };
assert_eq!(p1.log2_cardinality(), 0);
let p2: CardinalityPointer<u64>
= unsafe { CardinalityPointer::from_raw(std::ptr::dangling::<u64>(), 2) };
assert_eq!(p2.log2_cardinality(), 1);
let p1000: CardinalityPointer<u64>
= unsafe { CardinalityPointer::from_raw(std::ptr::dangling::<u64>(), 1000) };
assert_eq!(p1000.log2_cardinality(), 10);
assert_eq!(p1000.cardinality(), 1024);
let pm: CardinalityPointer<u64>
= unsafe { CardinalityPointer::from_raw(std::ptr::dangling::<u64>(), 1_000_000) };
assert_eq!(pm.log2_cardinality(), 20);
}
#[test]
fn size_tier_branching() {
let tiny: CardinalityPointer<u64>
= unsafe { CardinalityPointer::from_raw(std::ptr::dangling::<u64>(), 5) };
let medium: CardinalityPointer<u64>
= unsafe { CardinalityPointer::from_raw(std::ptr::dangling::<u64>(), 500) };
let large: CardinalityPointer<u64>
= unsafe { CardinalityPointer::from_raw(std::ptr::dangling::<u64>(), 1_000_000) };
assert_eq!(tiny.size_tier(), SizeTier::Tiny);
assert_eq!(medium.size_tier(), SizeTier::Medium);
assert_eq!(large.size_tier(), SizeTier::Large);
}
#[test]
fn set_cardinality_preserves_address() {
let addr: *const u64 = 0x0000_DEAD_BEEF_CAFE as *const u64;
let mut p = unsafe { CardinalityPointer::from_raw(addr, 10) };
let original_addr = p.as_raw();
p.set_cardinality(10_000);
assert_eq!(p.as_raw(), original_addr,
"address must survive cardinality update");
assert_eq!(p.log2_cardinality(), 14);
}
#[test]
fn distinct_cardinalities_compare_distinct() {
let p_small: CardinalityPointer<u64>
= unsafe { CardinalityPointer::from_raw(0xFEED as *const u64, 4) };
let p_big: CardinalityPointer<u64>
= unsafe { CardinalityPointer::from_raw(0xFEED as *const u64, 1_000_000) };
assert_ne!(p_small.raw(), p_big.raw());
assert_eq!(p_small.as_raw(), p_big.as_raw());
}
#[test]
#[should_panic(expected = "has high byte set")]
fn from_raw_panics_on_out_of_envelope_address() {
let bad: *const u64 = 0xFF00_0000_0000_0000_u64 as *const u64;
let _p = unsafe { CardinalityPointer::<u64>::from_raw(bad, 100) };
}
#[test]
fn from_raw_unchecked_skips_envelope_check() {
let ok: *const u64 = 0x0000_DEAD_BEEF_CAFE_u64 as *const u64;
let p = unsafe { CardinalityPointer::<u64>::from_raw_unchecked(ok, 100) };
assert_eq!(p.as_raw(), ok);
}
#[test]
fn query_planner_branch_without_deref() {
let plans: [CardinalityPointer<u64>; 3] = [
unsafe { CardinalityPointer::from_raw(std::ptr::dangling::<u64>(), 5) },
unsafe { CardinalityPointer::from_raw(std::ptr::dangling::<u64>(), 500) },
unsafe { CardinalityPointer::from_raw(std::ptr::dangling::<u64>(), 5_000_000) },
];
let mut linear = 0;
let mut sort_merge = 0;
let mut hash_join = 0;
for p in &plans {
match p.size_tier() {
SizeTier::Tiny => linear += 1,
SizeTier::Medium => sort_merge += 1,
SizeTier::Large => hash_join += 1,
}
}
assert_eq!((linear, sort_merge, hash_join), (1, 1, 1));
}
}