pipecircuit 0.0.18

Correct. Robust. Fast. Portable. Pick four.
Documentation
use super::{WarpTable, WarpTableInsertWithIdOutcome, WarpTableRow};

#[derive(Debug, Eq, PartialEq)]
#[must_use]
pub enum WarpTableUpsertOutcome<Id, Row: WarpTableRow> {
    Inserted {
        id: Id,
        row: usize,
    },
    Replaced {
        id: Id,
        row: usize,
        previous: Row,
    },
    Full {
        id: Id,
        rejected: Row,
    },
    UniqueConflict {
        id: Id,
        conflict: Row::UniqueConflict,
        rejected: Row,
    },
}

impl<Row: WarpTableRow, Brand> WarpTable<Row, Brand> {
    /// Inserts an absent caller-supplied ID or replaces its existing row.
    pub fn upsert(&mut self, id: Row::Id, row: Row) -> WarpTableUpsertOutcome<Row::Id, Row> {
        match self.insert_with_id(id, row) {
            WarpTableInsertWithIdOutcome::Inserted { id, row } => {
                WarpTableUpsertOutcome::Inserted { id, row }
            }
            WarpTableInsertWithIdOutcome::AlreadyPresent {
                id,
                existing_row,
                rejected: replacement,
            } => match self.replace_at(id, existing_row, replacement) {
                Ok(previous) => WarpTableUpsertOutcome::Replaced {
                    id,
                    row: existing_row,
                    previous,
                },
                Err((conflict, rejected)) => WarpTableUpsertOutcome::UniqueConflict {
                    id,
                    conflict,
                    rejected,
                },
            },
            WarpTableInsertWithIdOutcome::Full { id, rejected } => {
                WarpTableUpsertOutcome::Full { id, rejected }
            }
            WarpTableInsertWithIdOutcome::UniqueConflict {
                id,
                conflict,
                rejected,
            } => WarpTableUpsertOutcome::UniqueConflict {
                id,
                conflict,
                rejected,
            },
        }
    }
}