use super::super::dense_key_index::{CommitOutcome, PrepareInsertOutcome, PreparedCommit};
use super::{IndexKey, UniqueIndex, UniqueIndexInconsistency};
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum UniqueIndexInsertError<Key> {
AlreadyPresent {
key: Key,
existing_row: usize,
},
Full {
key: Key,
maximum_keys: usize,
},
Inconsistent {
key: Key,
reason: UniqueIndexInconsistency,
},
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[must_use]
pub enum UniqueIndexInsertOutcome<Key> {
Inserted { key: Key, row: usize },
}
pub struct PreparedUniqueIndexInsert<'index, Key: IndexKey> {
index: &'index mut UniqueIndex<Key>,
insertion: PreparedCommit,
key: Key,
}
impl<Key: IndexKey> UniqueIndex<Key> {
pub fn try_prepare_insert(
&mut self,
key: Key,
) -> Result<PreparedUniqueIndexInsert<'_, Key>, UniqueIndexInsertError<Key>> {
let vacancy = match self
.key_index
.prepare_insert(key, &self.keys)
.map_err(|reason| UniqueIndexInsertError::Inconsistent {
key,
reason: reason.into(),
})? {
PrepareInsertOutcome::Vacant(vacancy) => vacancy,
PrepareInsertOutcome::Present { row } => {
return Err(UniqueIndexInsertError::AlreadyPresent {
key,
existing_row: row,
});
}
};
if self.keys.len() >= self.maximum_keys {
return Err(UniqueIndexInsertError::Full {
key,
maximum_keys: self.maximum_keys,
});
}
let row = self.keys.len();
let insertion = self
.key_index
.prepare_commit(vacancy, row)
.map_err(|reason| UniqueIndexInsertError::Inconsistent {
key,
reason: reason.into(),
})?;
Ok(PreparedUniqueIndexInsert {
index: self,
insertion,
key,
})
}
}
impl<Key: IndexKey> PreparedUniqueIndexInsert<'_, Key> {
pub fn commit(self) -> UniqueIndexInsertOutcome<Key> {
let CommitOutcome::Committed { row } = self.index.key_index.commit_prepared(self.insertion);
self.index.keys.push(self.key);
UniqueIndexInsertOutcome::Inserted { key: self.key, row }
}
}