pipecircuit 0.0.14

Correct. Robust. Fast. Portable.
Documentation
use super::super::dense_key_index::{PrepareRemoveOutcome, PreparedRemoval};
use super::{IndexKey, UniqueIndex, UniqueIndexInconsistency};

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum UniqueIndexRemoveError<Key> {
    Absent {
        key: Key,
    },
    Inconsistent {
        key: Key,
        reason: UniqueIndexInconsistency,
    },
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[must_use]
pub enum UniqueIndexRemoveOutcome<Key> {
    Removed { key: Key, row: usize },
}

pub struct PreparedUniqueIndexRemove<'index, Key: IndexKey> {
    index: &'index mut UniqueIndex<Key>,
    removal: PreparedRemoval<Key>,
    key: Key,
}

impl<Key: IndexKey> UniqueIndex<Key> {
    pub fn try_prepare_remove(
        &mut self,
        key: Key,
    ) -> Result<PreparedUniqueIndexRemove<'_, Key>, UniqueIndexRemoveError<Key>> {
        let Some(last_row) = self.keys.len().checked_sub(1) else {
            return Err(UniqueIndexRemoveError::Absent { key });
        };
        let removal = self
            .key_index
            .prepare_remove(key, &self.keys, last_row)
            .map_err(|reason| UniqueIndexRemoveError::Inconsistent {
                key,
                reason: reason.into(),
            })?;
        let PrepareRemoveOutcome::Prepared(removal) = removal else {
            return Err(UniqueIndexRemoveError::Absent { key });
        };
        Ok(PreparedUniqueIndexRemove {
            index: self,
            removal,
            key,
        })
    }
}

impl<Key: IndexKey> PreparedUniqueIndexRemove<'_, Key> {
    pub fn commit(self) -> UniqueIndexRemoveOutcome<Key> {
        let row = self.removal.row;
        self.index
            .key_index
            .commit_remove(self.removal, &self.index.keys);
        self.index.keys.swap_remove(row);
        UniqueIndexRemoveOutcome::Removed { key: self.key, row }
    }
}