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),
},
}
}
}