Skip to content

Commit bc403d9

Browse files
committed
clean up tracked struct IDs to handle overflow
1 parent 8b6cc9f commit bc403d9

File tree

4 files changed

+156
-104
lines changed

4 files changed

+156
-104
lines changed

src/id.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ impl Id {
3939
#[doc(hidden)]
4040
#[track_caller]
4141
#[inline]
42-
pub const unsafe fn from_data(v: u32) -> Self {
42+
pub const unsafe fn from_index(v: u32) -> Self {
4343
debug_assert!(v < Self::MAX_U32);
4444

4545
Id {
@@ -66,13 +66,24 @@ impl Id {
6666
}
6767
}
6868

69+
/// Returns a new `Id` with same index, but the generation incremented by one.
70+
///
71+
/// Returns `None` if the generation would overflow, i.e. the current generation
72+
/// is `u32::MAX`.
73+
#[inline]
74+
pub fn next_generation(self) -> Option<Id> {
75+
self.generation()
76+
.checked_add(1)
77+
.map(|generation| self.with_generation(generation))
78+
}
79+
6980
/// Mark the `Id` with a generation.
7081
///
7182
/// This `Id` will refer to the same page and slot in the database,
7283
/// but will differ from other identifiers of the slot based on the
7384
/// provided generation.
7485
#[inline]
75-
pub fn with_generation(self, generation: u32) -> Id {
86+
pub const fn with_generation(self, generation: u32) -> Id {
7687
let mut value = self.value.get();
7788

7889
value &= 0xFFFFFFFF;
@@ -84,9 +95,9 @@ impl Id {
8495
}
8596
}
8697

87-
/// Return the data portion of this `Id`.
98+
/// Return the index portion of this `Id`.
8899
#[inline]
89-
pub const fn data(self) -> u32 {
100+
pub const fn index(self) -> u32 {
90101
// Truncate the high-order bits.
91102
(self.value.get() as u32) - 1
92103
}
@@ -108,9 +119,9 @@ impl Id {
108119
impl Debug for Id {
109120
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110121
if self.generation() == 0 {
111-
write!(f, "Id({:x})", self.data())
122+
write!(f, "Id({:x})", self.index())
112123
} else {
113-
write!(f, "Id({:x}g{:x})", self.data(), self.generation())
124+
write!(f, "Id({:x}g{:x})", self.index(), self.generation())
114125
}
115126
}
116127
}

src/key.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,19 @@ impl DatabaseKeyIndex {
2222
#[inline]
2323
pub(crate) fn new(ingredient_index: IngredientIndex, key_index: Id) -> Self {
2424
Self {
25-
key_index: key_index.data(),
25+
key_index: key_index.index(),
2626
key_generation: key_index.generation(),
2727
ingredient_index,
2828
}
2929
}
3030

31-
pub fn ingredient_index(self) -> IngredientIndex {
31+
pub const fn ingredient_index(self) -> IngredientIndex {
3232
self.ingredient_index
3333
}
3434

35-
pub fn key_index(self) -> Id {
35+
pub const fn key_index(self) -> Id {
3636
// SAFETY: `self.key_index` was returned by `Id::data`.
37-
unsafe { Id::from_data(self.key_index) }.with_generation(self.key_generation)
37+
unsafe { Id::from_index(self.key_index) }.with_generation(self.key_generation)
3838
}
3939

4040
pub(crate) fn maybe_changed_after(

src/table.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -400,13 +400,13 @@ fn make_id(page: PageIndex, slot: SlotIndex) -> Id {
400400
let page = page.0 as u32;
401401
let slot = slot.0 as u32;
402402
// SAFETY: `slot` is guaranteed to be small enough that the resulting Id won't be bigger than `Id::MAX_U32`
403-
unsafe { Id::from_data((page << PAGE_LEN_BITS) | slot) }
403+
unsafe { Id::from_index((page << PAGE_LEN_BITS) | slot) }
404404
}
405405

406406
#[inline]
407407
fn split_id(id: Id) -> (PageIndex, SlotIndex) {
408-
let data = id.data() as usize;
409-
let slot = data & PAGE_LEN_MASK;
410-
let page = data >> PAGE_LEN_BITS;
408+
let index = id.index() as usize;
409+
let slot = index & PAGE_LEN_MASK;
410+
let page = index >> PAGE_LEN_BITS;
411411
(PageIndex::new(page), SlotIndex::new(slot))
412412
}

0 commit comments

Comments
 (0)