pub mod direct;
pub mod packed;
use core::fmt::Debug;
use core::hash::Hash;
use crate::storage::Capacity;
pub unsafe trait Handle: Copy + Debug + Eq + Hash + Ord {
type Index: Capacity;
const MAX_INDEX: usize;
const MAX_GENERATION: u32;
unsafe fn new(index: usize, generation: u32) -> Self;
fn into_raw_parts(self) -> (usize, u32);
}
#[cold]
#[inline(never)]
#[track_caller]
pub(crate) fn buffer_too_large_for_handle_type<H: Handle>() {
panic!(
"provided storage block cannot be fully indexed by type {} (max capacity is {})",
core::any::type_name::<H>(),
H::MAX_INDEX - 1,
);
}
#[allow(dead_code)] #[derive(Debug)]
enum DebugEntry<'a, T: Debug, H: Handle> {
Occupied {
generation: u32,
value: &'a T,
},
Vacant {
generation: u32,
next_free_slot: H::Index,
},
}
#[macro_export]
macro_rules! handle_type {
( $(#[$attrs:meta])* $v:vis $name:ident: 64 ; $($rest:tt)* ) => {
$(#[$attrs])*
#[derive(
core::marker::Copy,
core::clone::Clone,
core::fmt::Debug,
core::hash::Hash,
core::cmp::PartialEq,
core::cmp::Eq,
core::cmp::PartialOrd,
core::cmp::Ord)]
#[repr(transparent)]
$v struct $name(core::num::NonZeroU64);
impl $name {
#[allow(dead_code)]
$v const fn null() -> Self {
unsafe { $name(core::num::NonZeroU64::new_unchecked(0xFFFF_FFFF)) }
}
}
unsafe impl $crate::collections::pool::Handle for $name {
type Index = u32;
const MAX_INDEX: usize = 0xFFFF_FFFF;
const MAX_GENERATION: u32 = 0xFFFF_FFFF;
unsafe fn new(index: usize, generation: u32) -> Self {
debug_assert!(index <= Self::MAX_INDEX);
debug_assert_eq!(generation % 2, 1);
let assembled = index as u64 & 0xFFFF_FFFF | ((generation as u64) << 32);
$name(core::num::NonZeroU64::new_unchecked(assembled))
}
fn into_raw_parts(self) -> (usize, u32) {
let raw: u64 = self.0.into();
let index = (raw & 0xFFFF_FFFF) as usize;
let generation = (raw >> 32) as u32;
(index, generation)
}
}
handle_type!($($rest)*);
};
( $(#[$attrs:meta])* $v:vis $name:ident: $n:literal / 32 ; $($rest:tt)* ) => {
#[allow(unknown_lints, eq_op)]
const _: [(); 0 - !{ const ASSERT: bool = $n <= 16; ASSERT } as usize] = [];
$(#[$attrs])*
#[derive(
core::marker::Copy,
core::clone::Clone,
core::fmt::Debug,
core::hash::Hash,
core::cmp::PartialEq,
core::cmp::Eq,
core::cmp::PartialOrd,
core::cmp::Ord)]
#[repr(transparent)]
$v struct $name(core::num::NonZeroU32);
impl $name {
#[allow(dead_code)]
$v const fn null() -> Self {
unsafe { $name(core::num::NonZeroU32::new_unchecked(
<Self as $crate::collections::pool::Handle>::MAX_INDEX as u32
)) }
}
}
unsafe impl $crate::collections::pool::Handle for $name {
type Index = u16;
const MAX_INDEX: usize = !(!0 << $n);
const MAX_GENERATION: u32 = !(!0 << (32 - $n)) as u32;
unsafe fn new(index: usize, generation: u32) -> Self {
debug_assert!(index <= Self::MAX_INDEX);
debug_assert!(generation <= Self::MAX_GENERATION);
debug_assert_eq!(generation % 2, 1);
let assembled = index as u32 & (Self::MAX_INDEX as u32) | ((generation as u32) << $n);
$name(core::num::NonZeroU32::new_unchecked(assembled))
}
fn into_raw_parts(self) -> (usize, u32) {
let raw: u32 = self.0.into();
let index = (raw & (Self::MAX_INDEX as u32)) as usize;
let generation = (raw >> $n) as u32;
(index, generation)
}
}
handle_type!($($rest)*);
};
() => {}
}
handle_type! {
pub DefaultHandle: 64;
}