pipecircuit 0.0.23

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<'keys, Key> {
    Present {
        location: FoundLocation,
        key: &'keys Key,
    },
    Absent,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(in crate::storage::warp_table) struct FoundLocation {
    pub(in crate::storage::warp_table::dense_key_index) bucket: usize,
    pub(in crate::storage::warp_table::dense_key_index) stored_row: u32,
    pub(in crate::storage::warp_table) row: usize,
}

impl DenseKeyIndex {
    pub(in crate::storage::warp_table) fn find<'keys, Key: IndexKey>(
        &self,
        key: Key,
        keys: &'keys [Key],
    ) -> Result<FindOutcome<'keys, Key>, IndexInconsistency> {
        let mut bucket = reduce(key.index_word(), self.buckets.len());
        for _ in 0..self.buckets.len() {
            let stored_row = self
                .buckets
                .get(bucket)
                .copied()
                .ok_or(IndexInconsistency::BucketUnavailable { bucket })?;
            if stored_row == EMPTY_ROW {
                return Ok(FindOutcome::Absent);
            }
            let row = represent_stored_row(stored_row)?;
            let Some(stored_key) = keys.get(row) else {
                return Err(IndexInconsistency::KeyUnavailable { row });
            };
            if *stored_key == key {
                return Ok(FindOutcome::Present {
                    location: FoundLocation {
                        bucket,
                        stored_row,
                        row,
                    },
                    key: stored_key,
                });
            }
            bucket = next_bucket(bucket, self.buckets.len());
        }
        Err(IndexInconsistency::ProbeLimitReached)
    }
}

pub(super) fn represent_stored_row<Index: TryFrom<u32>>(
    stored_row: u32,
) -> Result<Index, IndexInconsistency> {
    Index::try_from(stored_row)
        .map_err(|_| IndexInconsistency::StoredRowUnrepresentable { stored_row })
}