1use std::{marker::PhantomData, num::NonZeroU64};
2
3use crate::config::{Config, ConfigPrivate};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
16#[repr(transparent)]
17pub struct Key(NonZeroU64);
18
19impl Key {
20 pub(crate) unsafe fn new_unchecked<C: Config>(slot_id: u32, generation: Generation<C>) -> Self {
24 debug_assert!(0 < slot_id && slot_id <= C::SLOT_MASK);
25 let raw = u64::from(generation.to_u32()) << C::SLOT_BITS | u64::from(slot_id);
26 Self(NonZeroU64::new_unchecked(raw))
27 }
28
29 pub(crate) fn page_no<C: Config>(self) -> PageNo<C> {
30 let slot_id = self.slot_id::<C>();
31
32 let base = 32 - C::INITIAL_PAGE_SIZE.trailing_zeros() - 1;
62 let lz_repr = slot_id.leading_zeros();
63
64 let page_no = base.wrapping_sub(lz_repr);
67
68 PageNo::new(page_no)
69 }
70
71 pub(crate) fn slot_id<C: Config>(self) -> u32 {
72 self.0.get() as u32 & C::SLOT_MASK
73 }
74
75 pub(crate) fn generation<C: Config>(self) -> Generation<C> {
76 let gen = (self.0.get() >> C::SLOT_BITS) as u32 & C::GENERATION_MASK;
77 Generation::new(gen)
78 }
79}
80
81impl From<NonZeroU64> for Key {
82 fn from(raw: NonZeroU64) -> Self {
83 Self(raw)
84 }
85}
86
87impl From<Key> for NonZeroU64 {
88 fn from(key: Key) -> NonZeroU64 {
89 key.0
90 }
91}
92
93impl TryFrom<u64> for Key {
94 type Error = std::num::TryFromIntError;
95
96 fn try_from(raw: u64) -> Result<Self, Self::Error> {
97 NonZeroU64::try_from(raw).map(Into::into)
98 }
99}
100
101impl From<Key> for u64 {
102 fn from(key: Key) -> u64 {
103 key.0.get()
104 }
105}
106
107#[repr(transparent)]
110pub(crate) struct PageNo<C> {
111 value: u32,
112 _config: PhantomData<C>,
113}
114
115impl<C> Copy for PageNo<C> {}
116
117impl<C> Clone for PageNo<C> {
118 fn clone(&self) -> Self {
119 *self
120 }
121}
122
123impl<C: Config> PageNo<C> {
124 pub(crate) fn new(value: u32) -> Self {
125 Self {
126 value,
127 _config: PhantomData,
128 }
129 }
130
131 pub(crate) fn to_usize(self) -> usize {
132 self.value as usize
133 }
134
135 pub(crate) fn start_slot_id(self) -> u32 {
136 let shift = C::INITIAL_PAGE_SIZE.trailing_zeros() + self.value;
137 1 << shift
138 }
139
140 pub(crate) fn capacity(self) -> u32 {
141 C::INITIAL_PAGE_SIZE * 2u32.pow(self.value)
142 }
143}
144
145impl<C> PartialEq for PageNo<C> {
146 fn eq(&self, other: &Self) -> bool {
147 self.value == other.value
148 }
149}
150
151#[repr(transparent)]
154pub(crate) struct Generation<C> {
155 value: u32,
156 _config: PhantomData<C>,
157}
158
159impl<C> Copy for Generation<C> {}
160
161impl<C> Clone for Generation<C> {
162 fn clone(&self) -> Self {
163 *self
164 }
165}
166
167impl<C: Config> Generation<C> {
168 pub(crate) fn new(value: u32) -> Self {
169 Self {
170 value,
171 _config: PhantomData,
172 }
173 }
174
175 pub(crate) fn to_u32(self) -> u32 {
176 self.value
177 }
178
179 pub(crate) fn inc(self) -> Self {
180 Self {
181 value: (self.value + 1) & C::GENERATION_MASK,
182 _config: PhantomData,
183 }
184 }
185}
186
187impl<C> PartialEq for Generation<C> {
188 fn eq(&self, other: &Self) -> bool {
189 self.value == other.value
190 }
191}