pipecircuit 0.0.23

Correct. Robust. Fast. Portable. Pick four.
Documentation
use super::dense_key_index::FindOutcome;
use super::inconsistency::invariant_violation;
use super::{WarpTable, WarpTableInconsistency, WarpTableRow, WarpTableRowGetOutcome};

pub(super) fn stored_id<Id>(ids: &[Id], row: usize) -> &Id {
    ids.get(row)
        .unwrap_or_else(|| invariant_violation(WarpTableInconsistency::IdUnavailable { row }))
}

pub(super) fn validate_id_count(ids: usize, rows: usize) {
    if ids != rows {
        invariant_violation(WarpTableInconsistency::IdColumnLengthMismatch { ids, rows });
    }
}

pub(super) fn row_ref<'row, Row: WarpTableRow>(
    id: &'row Row::Id,
    columns: &'row Row::Columns,
    row: usize,
) -> Row::Ref<'row> {
    let WarpTableRowGetOutcome::Present { row } = Row::get(id, columns, row)
        .unwrap_or_else(|reason| invariant_violation(WarpTableInconsistency::from(reason)));
    row
}

#[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 },
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[must_use]
pub enum WarpTableUniqueGetOutcome<Key, Row> {
    Present { key: Key, row: Row },
    Absent { key: Key },
}

impl<Row: WarpTableRow, Brand> WarpTable<Row, Brand> {
    pub fn get(&self, id: Row::Id) -> WarpTableGetOutcome<Row::Id, Row::Ref<'_>> {
        let ids = &self.ids;
        validate_id_count(ids.len(), self.len);
        let found = self
            .primary_index
            .find(id, ids)
            .unwrap_or_else(|reason| invariant_violation(WarpTableInconsistency::from(reason)));
        let (row, stored_id) = match found {
            FindOutcome::Present { location, key } => (location.row, key),
            FindOutcome::Absent => return WarpTableGetOutcome::Absent { id },
        };
        let row = row_ref::<Row>(stored_id, &self.columns, row);
        WarpTableGetOutcome::Present { row }
    }

    /// Reads the current physical row at `dense_row`.
    ///
    /// Dense rows may relocate after removal. Persistent identity should use a
    /// ID; secondary selections resolve their opaque membership
    /// immediately before access.
    pub fn get_at(&self, dense_row: usize) -> WarpTableGetAtOutcome<Row::Ref<'_>> {
        let ids = &self.ids;
        validate_id_count(ids.len(), self.len);
        let Some(id) = ids.get(dense_row) else {
            return WarpTableGetAtOutcome::Absent { dense_row };
        };
        let row = row_ref::<Row>(id, &self.columns, dense_row);
        WarpTableGetAtOutcome::Present { dense_row, row }
    }
}