pipecircuit 0.0.18

Correct. Robust. Fast. Portable. Pick four.
Documentation
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)
    }
}