use std::{fmt::Debug, marker::PhantomData};
pub trait Config: Sized {
const INITIAL_PAGE_SIZE: u32 = DefaultConfig::INITIAL_PAGE_SIZE;
const MAX_PAGES: u32 = DefaultConfig::MAX_PAGES;
const RESERVED_BITS: u32 = DefaultConfig::RESERVED_BITS;
#[must_use]
fn debug() -> impl Debug {
DebugConfig::<Self>(PhantomData)
}
}
#[allow(missing_debug_implementations)] pub struct DefaultConfig;
impl Config for DefaultConfig {
const INITIAL_PAGE_SIZE: u32 = 32;
const MAX_PAGES: u32 = 27;
const RESERVED_BITS: u32 = 0;
}
pub(crate) trait ConfigPrivate: Config {
const USED_BITS: u32 = 64 - Self::RESERVED_BITS;
const SLOT_BITS: u32 = Self::MAX_PAGES + Self::INITIAL_PAGE_SIZE.trailing_zeros();
const SLOT_MASK: u32 = ((1u64 << Self::SLOT_BITS) - 1) as u32;
const GENERATION_BITS: u32 = Self::USED_BITS - Self::SLOT_BITS;
const GENERATION_MASK: u32 = ((1u64 << Self::GENERATION_BITS) - 1) as u32;
const MAX_SLOTS: u64 = ((1u64 << Self::MAX_PAGES) - 1) * Self::INITIAL_PAGE_SIZE as u64;
const MAX_GENERATIONS: u64 = 1u64 << Self::GENERATION_BITS;
const ENSURE_VALID: bool = {
assert!(Self::INITIAL_PAGE_SIZE.is_power_of_two());
assert!(Self::MAX_PAGES > 0);
assert!(Self::RESERVED_BITS <= 32);
assert!(Self::SLOT_BITS <= 32);
assert!(Self::GENERATION_BITS <= 32);
true
};
}
impl<C: Config> ConfigPrivate for C {}
struct DebugConfig<C>(PhantomData<C>);
impl<C: Config> Debug for DebugConfig<C> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct(std::any::type_name::<C>())
.field("INITIAL_PAGE_SIZE", &C::INITIAL_PAGE_SIZE)
.field("MAX_PAGES", &C::MAX_PAGES)
.field("RESERVED_BITS", &C::RESERVED_BITS)
.field("USED_BITS", &C::USED_BITS)
.field("SLOT_BITS", &C::SLOT_BITS)
.field("GENERATION_BITS", &C::GENERATION_BITS)
.field("MAX_SLOTS", &C::MAX_SLOTS)
.field("MAX_GENERATIONS", &C::MAX_GENERATIONS)
.finish()
}
}
#[test]
fn test_default_config() {
assert_eq!(DefaultConfig::USED_BITS, 64);
assert_eq!(DefaultConfig::SLOT_BITS, 32);
assert_eq!(DefaultConfig::SLOT_MASK, u32::MAX);
assert_eq!(DefaultConfig::GENERATION_BITS, 32);
assert_eq!(DefaultConfig::GENERATION_MASK, u32::MAX);
assert_eq!(DefaultConfig::MAX_SLOTS, 4_294_967_264);
assert_eq!(DefaultConfig::MAX_GENERATIONS, 4_294_967_296);
}