pipecircuit 0.0.25

Correct. Robust. Fast. Portable. Pick four.
Documentation
use super::super::{
    UniqueIndexLookupError, UniqueIndexLookupOutcome, WarpTable, WarpTableBacking,
    WarpTableGetAtOutcome, WarpTableRow, WarpTableUniqueGetOutcome,
    inconsistency::invariant_violation,
};

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CallerUniqueLookupError<Key> {
    DifferentTables,
    Lookup(UniqueIndexLookupError<Key>),
}

pub struct CallerUniqueLookup<'index, Indexes, Key> {
    indexes: &'index Indexes,
    lookup: Result<UniqueIndexLookupOutcome<Key>, UniqueIndexLookupError<Key>>,
}
impl<'index, Indexes, Key> CallerUniqueLookup<'index, Indexes, Key> {
    pub fn new(
        indexes: &'index Indexes,
        lookup: Result<UniqueIndexLookupOutcome<Key>, UniqueIndexLookupError<Key>>,
    ) -> Self {
        Self { indexes, lookup }
    }
}

impl<Row: WarpTableRow, Brand, Backing: WarpTableBacking<Row>> WarpTable<Row, Brand, Backing> {
    pub fn get_unique<'table, Key>(
        &'table self,
        find: impl FnOnce(&'table Backing::Indexes) -> CallerUniqueLookup<'table, Backing::Indexes, Key>,
    ) -> Result<WarpTableUniqueGetOutcome<Key, Row::Ref<'table>>, CallerUniqueLookupError<Key>>
    {
        let lookup = find(&self.indexes);
        if !core::ptr::eq(&self.indexes, lookup.indexes) {
            return Err(CallerUniqueLookupError::DifferentTables);
        }
        match lookup.lookup.map_err(CallerUniqueLookupError::Lookup)? {
            UniqueIndexLookupOutcome::Absent { key } => {
                Ok(WarpTableUniqueGetOutcome::Absent { key })
            }
            UniqueIndexLookupOutcome::Present { key, row } => match self.get_at(row) {
                WarpTableGetAtOutcome::Present { row, .. } => {
                    Ok(WarpTableUniqueGetOutcome::Present { key, row })
                }
                WarpTableGetAtOutcome::Absent { dense_row } => invariant_violation(dense_row),
            },
        }
    }
}