pipecircuit 0.0.2

Correct. Robust. Fast. Portable.
Documentation
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 WarpTableUpdateOutcome<Key, Output> {
    Updated {
        key: Key,
        row: usize,
        output: Output,
    },
    Absent {
        key: Key,
    },
}

impl<Row: WarpTableRow, Brand> WarpTable<Row, Brand> {
    pub fn update<Output>(
        &mut self,
        key: Row::Key,
        update: impl FnOnce(Row::Mut<'_>) -> Output,
    ) -> WarpTableUpdateOutcome<Row::Key, Output> {
        if self.primary_keys.len() != self.len {
            invariant_violation(WarpTableInconsistency::PrimaryKeyColumnLengthMismatch {
                keys: self.primary_keys.len(),
                rows: self.len,
            });
        }
        let row = match self.primary_index.find(key, &self.primary_keys) {
            Ok(FindOutcome::Present { row, .. }) => row,
            Ok(FindOutcome::Absent) => return WarpTableUpdateOutcome::Absent { key },
            Err(reason) => invariant_violation(WarpTableInconsistency::from(reason)),
        };
        let output = self.update_at(row, update);
        WarpTableUpdateOutcome::Updated { key, row, output }
    }

    pub(super) fn update_at<Output>(
        &mut self,
        row: usize,
        update: impl FnOnce(Row::Mut<'_>) -> Output,
    ) -> Output {
        let stored_key = self.primary_keys.get(row).unwrap_or_else(|| {
            invariant_violation(WarpTableInconsistency::PrimaryKeyUnavailable { row })
        });
        let WarpTableRowGetOutcome::Present { row: mutable } =
            Row::get_mut(stored_key, &mut self.columns, &mut self.indexes, row)
                .unwrap_or_else(|reason| invariant_violation(WarpTableInconsistency::from(reason)));
        update(mutable)
    }
}