use crate::segment::{RecordIdentifier, SegmentIdentifier};
pub(crate) struct SegmentInterner {
indices: std::collections::HashMap<SegmentIdentifier, u32>,
identifiers: Vec<SegmentIdentifier>,
}
impl SegmentInterner {
pub(crate) fn new() -> Self {
Self {
indices: std::collections::HashMap::new(),
identifiers: vec![SegmentIdentifier {
most_significant_bits: 0,
least_significant_bits: 0,
}],
}
}
fn index_of(&mut self, segment: SegmentIdentifier) -> u32 {
if let Some(index) = self.indices.get(&segment) {
return *index;
}
let index = u32::try_from(self.identifiers.len()).expect("segments per walk fit u32");
self.identifiers.push(segment);
self.indices.insert(segment, index);
index
}
fn existing_index_of(&self, segment: SegmentIdentifier) -> Option<u32> {
self.indices.get(&segment).copied()
}
fn identifier(&self, index: u32) -> SegmentIdentifier {
self.identifiers[index as usize]
}
pub(crate) fn pack(&mut self, record: RecordIdentifier) -> u64 {
u64::from(self.index_of(record.segment)) << 32 | u64::from(record.record_number)
}
fn pack_existing(&self, record: RecordIdentifier) -> Option<u64> {
self.existing_index_of(record.segment)
.map(|index| u64::from(index) << 32 | u64::from(record.record_number))
}
pub(crate) fn unpack(&self, packed: u64) -> RecordIdentifier {
RecordIdentifier {
segment: self.identifier((packed >> 32) as u32),
record_number: packed as u32,
}
}
}
const INITIAL_TABLE_SLOTS: usize = 1024;
const _: () = assert!(INITIAL_TABLE_SLOTS.is_power_of_two());
fn slot_of(key: u64, slots: usize) -> usize {
let mixed = key.wrapping_mul(0x9E37_79B9_7F4A_7C15);
(mixed >> 32) as usize & (slots - 1)
}
pub(crate) struct PackedRecordSet {
segments: SegmentInterner,
keys: Vec<u64>,
len: usize,
}
impl PackedRecordSet {
pub(crate) fn new() -> Self {
Self {
segments: SegmentInterner::new(),
keys: vec![0; INITIAL_TABLE_SLOTS],
len: 0,
}
}
pub(crate) fn contains(&self, record: RecordIdentifier) -> bool {
let Some(key) = self.segments.pack_existing(record) else {
return false;
};
let mut slot = slot_of(key, self.keys.len());
loop {
match self.keys[slot] {
0 => return false,
found if found == key => return true,
_ => slot = (slot + 1) & (self.keys.len() - 1),
}
}
}
pub(crate) fn insert(&mut self, record: RecordIdentifier) {
if (self.len + 1) * 10 >= self.keys.len() * 7 {
self.grow();
}
let key = self.segments.pack(record);
self.place(key);
self.len += 1;
}
fn place(&mut self, key: u64) {
let mut slot = slot_of(key, self.keys.len());
while self.keys[slot] != 0 {
assert_ne!(
self.keys[slot], key,
"a record was certified twice; the probe or the caller's path \
set is broken"
);
slot = (slot + 1) & (self.keys.len() - 1);
}
self.keys[slot] = key;
}
fn grow(&mut self) {
let occupied: Vec<u64> = self.keys.iter().copied().filter(|key| *key != 0).collect();
self.keys = vec![0; self.keys.len() * 2];
for key in occupied {
self.place(key);
}
}
pub(crate) fn len(&self) -> usize {
self.len
}
#[cfg(test)]
pub(crate) fn occupied_slots(&self) -> usize {
self.keys.iter().filter(|key| **key != 0).count()
}
}
#[cfg(test)]
mod tests {
use super::PackedRecordSet;
use crate::segment::{RecordIdentifier, SegmentIdentifier};
fn record(segment_seed: u64, record_number: u32) -> RecordIdentifier {
RecordIdentifier {
segment: SegmentIdentifier {
most_significant_bits: segment_seed.wrapping_mul(0x0123_4567_89AB_CDEF),
least_significant_bits: segment_seed ^ 0xDEAD_BEEF_0BAD_F00D,
},
record_number,
}
}
#[test]
fn a_packed_set_agrees_with_an_independent_hash_set() {
let mut packed = PackedRecordSet::new();
let mut oracle: std::collections::HashSet<RecordIdentifier> =
std::collections::HashSet::new();
let mut state = 0x1234_5678_9ABC_DEF0u64;
let mut next = || {
state ^= state << 13;
state ^= state >> 7;
state ^= state << 17;
state
};
for _ in 0..200_000 {
let candidate = record(next() % 64, (next() % 4096) as u32);
assert_eq!(
packed.contains(candidate),
oracle.contains(&candidate),
"membership disagreed for {candidate}"
);
if oracle.insert(candidate) {
packed.insert(candidate);
}
assert_eq!(packed.len(), oracle.len());
}
assert_eq!(packed.occupied_slots(), oracle.len());
for known in &oracle {
assert!(
packed.contains(*known),
"{known} was inserted but is absent"
);
}
}
#[test]
fn an_unseen_segment_is_absent_without_being_interned() {
let mut packed = PackedRecordSet::new();
packed.insert(record(1, 1));
assert!(!packed.contains(record(2, 1)));
assert!(!packed.contains(record(1, 2)));
assert_eq!(packed.len(), 1);
assert_eq!(packed.occupied_slots(), 1);
}
}