use super::{SlotSet, StableSlot};
#[derive(Debug)]
pub enum SlotSetInsertError {
AlreadyPresent { slot: StableSlot },
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[must_use]
pub enum SlotSetInsertOutcome {
Inserted { slot: StableSlot },
}
impl SlotSet {
pub fn try_prepare_insert(
&mut self,
slot: StableSlot,
) -> Result<PreparedSlotSetInsert<'_>, SlotSetInsertError> {
let insertion = self.try_apply_insert(slot)?;
Ok(PreparedSlotSetInsert {
set: self,
insertion: Some(insertion),
slot,
})
}
pub(in crate::storage::warp_table::secondary_index) fn try_apply_insert(
&mut self,
slot: StableSlot,
) -> Result<AppliedSlotSetInsert, SlotSetInsertError> {
if !self.0.insert(slot.value()) {
return Err(SlotSetInsertError::AlreadyPresent { slot });
}
Ok(AppliedSlotSetInsert)
}
}
pub(in crate::storage::warp_table::secondary_index) struct AppliedSlotSetInsert;
impl AppliedSlotSetInsert {
pub(in crate::storage::warp_table::secondary_index) fn commit(self) {}
pub(in crate::storage::warp_table::secondary_index) fn rollback(
self,
set: &mut SlotSet,
slot: StableSlot,
) {
match set.remove(slot) {
super::SlotSetRemoveOutcome::Removed { .. }
| super::SlotSetRemoveOutcome::Absent { .. } => {}
}
}
}
pub struct PreparedSlotSetInsert<'set> {
set: &'set mut SlotSet,
insertion: Option<AppliedSlotSetInsert>,
slot: StableSlot,
}
impl PreparedSlotSetInsert<'_> {
pub const fn slot(&self) -> StableSlot {
self.slot
}
pub fn commit(mut self) -> SlotSetInsertOutcome {
if let Some(insertion) = self.insertion.take() {
insertion.commit();
}
SlotSetInsertOutcome::Inserted { slot: self.slot }
}
}
impl Drop for PreparedSlotSetInsert<'_> {
fn drop(&mut self) {
if let Some(insertion) = self.insertion.take() {
insertion.rollback(self.set, self.slot);
}
}
}