use super::dense_key_index::FindOutcome;
use super::inconsistency::invariant_violation;
use super::{WarpTable, WarpTableInconsistency, WarpTableRow, WarpTableRowGetOutcome};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[must_use]
pub enum WarpTableGetOutcome<Id, Row> {
Present { row: Row },
Absent { id: Id },
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[must_use]
pub enum WarpTableGetAtOutcome<Row> {
Present { dense_row: usize, row: Row },
Absent { dense_row: usize },
}
impl<Row: WarpTableRow, Brand> WarpTable<Row, Brand> {
pub fn get(&self, id: Row::Id) -> WarpTableGetOutcome<Row::Id, Row::Ref<'_>> {
let ids = &self.ids;
if ids.len() != self.len {
invariant_violation(WarpTableInconsistency::IdColumnLengthMismatch {
ids: ids.len(),
rows: self.len,
});
}
let found = self
.primary_index
.find(id, ids)
.unwrap_or_else(|reason| invariant_violation(WarpTableInconsistency::from(reason)));
let row = match found {
FindOutcome::Present { row, .. } => row,
FindOutcome::Absent => return WarpTableGetOutcome::Absent { id },
};
let stored_id = ids
.get(row)
.unwrap_or_else(|| invariant_violation(WarpTableInconsistency::IdUnavailable { row }));
let WarpTableRowGetOutcome::Present { row } = Row::get(stored_id, &self.columns, row)
.unwrap_or_else(|reason| invariant_violation(WarpTableInconsistency::from(reason)));
WarpTableGetOutcome::Present { row }
}
pub fn get_at(&self, dense_row: usize) -> WarpTableGetAtOutcome<Row::Ref<'_>> {
let ids = &self.ids;
if ids.len() != self.len {
invariant_violation(WarpTableInconsistency::IdColumnLengthMismatch {
ids: ids.len(),
rows: self.len,
});
}
if dense_row >= self.len {
return WarpTableGetAtOutcome::Absent { dense_row };
}
let id = ids.get(dense_row).unwrap_or_else(|| {
invariant_violation(WarpTableInconsistency::IdUnavailable { row: dense_row })
});
let WarpTableRowGetOutcome::Present { row } = Row::get(id, &self.columns, dense_row)
.unwrap_or_else(|reason| invariant_violation(WarpTableInconsistency::from(reason)));
WarpTableGetAtOutcome::Present { dense_row, row }
}
}