use super::bucket::{next_bucket, reduce};
use super::{DenseKeyIndex, EMPTY_ROW, IndexInconsistency};
use crate::storage::warp_table::IndexKey;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[must_use]
pub(in crate::storage::warp_table) enum FindOutcome {
Present {
bucket: usize,
stored_row: u32,
row: usize,
},
Absent,
}
impl DenseKeyIndex {
pub(in crate::storage::warp_table) fn find<Key: IndexKey>(
&self,
key: Key,
keys: &[Key],
) -> Result<FindOutcome, IndexInconsistency> {
let mut bucket = reduce(key.index_word(), self.buckets.len());
for _ in 0..self.buckets.len() {
let Some(stored_row) = self.buckets.get(bucket).copied() else {
return Err(IndexInconsistency::BucketUnavailable { bucket });
};
if stored_row == EMPTY_ROW {
return Ok(FindOutcome::Absent);
}
let Ok(row) = usize::try_from(stored_row) else {
return Err(IndexInconsistency::StoredRowUnrepresentable { stored_row });
};
let Some(stored_key) = keys.get(row).copied() else {
return Err(IndexInconsistency::KeyUnavailable { row });
};
if stored_key == key {
return Ok(FindOutcome::Present {
bucket,
stored_row,
row,
});
}
bucket = next_bucket(bucket, self.buckets.len());
}
Err(IndexInconsistency::ProbeLimitReached)
}
}