Skip to content

Commit d6113f3

Browse files
committed
refactor(btree): name encoded-size constants for separator and overflow records
Give the sizing math a name tied to the layout it mirrors: the separator record overhead and slot-directory entry size internal nodes use to decide whether a key fits, and the overflow-reference encoded size leaf values use for the same purpose. Previously these were repeated as bare arithmetic in both the preflight check and the encoder, free to drift apart silently.
1 parent 716a417 commit d6113f3

2 files changed

Lines changed: 28 additions & 9 deletions

File tree

src/btree/internal.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,24 @@ pub struct Internal {
2323
pub entries: Vec<InternalEntry>,
2424
}
2525

26+
/// Fixed bytes an internal record costs beyond its key: the `key_len` `u16`
27+
/// and the `right_child` `u64`.
28+
///
29+
/// Named so the sizing used to decide whether a separator fits stays tied to
30+
/// the layout [`Internal::encode`] actually writes.
31+
pub(crate) const SEPARATOR_RECORD_OVERHEAD: usize = 2 + 8;
32+
33+
/// Bytes one slot-directory entry costs.
34+
pub(crate) const SLOT_DIRECTORY_ENTRY_SIZE: usize = 2;
35+
2636
/// Encoded byte cost of one internal separator plus its slot-directory entry.
2737
pub(crate) fn separator_entry_size(key_len: usize) -> Result<usize> {
2838
if key_len > u16::MAX as usize {
2939
return Err(PagedbError::PayloadTooLarge);
3040
}
31-
2usize
32-
.checked_add(key_len)
33-
.and_then(|size| size.checked_add(8))
34-
.and_then(|size| size.checked_add(2))
41+
key_len
42+
.checked_add(SEPARATOR_RECORD_OVERHEAD)
43+
.and_then(|size| size.checked_add(SLOT_DIRECTORY_ENTRY_SIZE))
3544
.ok_or(PagedbError::PayloadTooLarge)
3645
}
3746

@@ -68,8 +77,12 @@ impl Internal {
6877
let cap = body.len();
6978
let prefix_len = 0usize;
7079
let slot_count = self.entries.len();
71-
let record_bytes: usize = self.entries.iter().map(|e| 2 + e.key.len() + 8).sum();
72-
let slot_dir_bytes = slot_count * 2;
80+
let record_bytes: usize = self
81+
.entries
82+
.iter()
83+
.map(|e| e.key.len() + SEPARATOR_RECORD_OVERHEAD)
84+
.sum();
85+
let slot_dir_bytes = slot_count * SLOT_DIRECTORY_ENTRY_SIZE;
7386
if HEADER_LEN + prefix_len + slot_dir_bytes + record_bytes > cap {
7487
return Err(PagedbError::PayloadTooLarge);
7588
}
@@ -88,7 +101,7 @@ impl Internal {
88101
}
89102
let mut tail = cap;
90103
for (i, e) in self.entries.iter().enumerate() {
91-
let rec_size = 2 + e.key.len() + 8;
104+
let rec_size = e.key.len() + SEPARATOR_RECORD_OVERHEAD;
92105
tail -= rec_size;
93106
let off = tail;
94107
write_u16_le(

src/btree/leaf.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,21 @@ pub enum LeafValue {
1717
Overflow { total_len: u64, root_page_id: u64 },
1818
}
1919

20+
/// Bytes an overflow reference occupies in an encoded record body: the
21+
/// sentinel `u16`, then `total_len` and `root_page_id` as `u64`s.
22+
///
23+
/// Named so the preflight that decides whether a record can fit and the encoder
24+
/// that lays it out cannot drift apart.
25+
pub(crate) const OVERFLOW_REF_ENCODED_SIZE: usize = 2 + 8 + 8;
26+
2027
impl LeafValue {
2128
/// Number of bytes this value occupies in the encoded record body (after
2229
/// the key suffix): 2-byte `value_len` field plus the payload.
2330
#[must_use]
2431
pub fn encoded_size(&self) -> usize {
2532
match self {
2633
Self::Inline(v) => 2 + v.len(),
27-
// sentinel u16 + total_len u64 + root_page_id u64
28-
Self::Overflow { .. } => 2 + 8 + 8,
34+
Self::Overflow { .. } => OVERFLOW_REF_ENCODED_SIZE,
2935
}
3036
}
3137
}

0 commit comments

Comments
 (0)