WorkTablesIndex 0.0.5

A two-level BTree with fast iteration and indexing operations
Documentation
#[cfg(feature = "multimap")]
use {
    crate::core::multipair::{OrdMultiPair, RandomMultiPair},
    crate::core::pair::Pair,
};

/// Unique event identifier.
///
/// For any two events `event1` and `event2`, if `event1` should be applied before
/// `event2`, then `event1.id()` should be less than `event2.id()`.
#[derive(Copy, Clone, Debug, Default, Ord, PartialOrd, Eq, PartialEq)]
pub struct Id(u64);

impl Id {
    pub fn inner(&self) -> u64 {
        self.0
    }

    pub fn is_next_for(&self, other: Id) -> bool {
        self.0 == other.0 + 1
    }
}

impl From<u64> for Id {
    fn from(value: u64) -> Self {
        Self(value)
    }
}

impl From<Id> for u64 {
    fn from(id: Id) -> Self {
        id.0
    }
}

#[derive(Debug, Clone)]
pub enum ChangeEvent<T> {
    /// Describes value insert event.
    InsertAt {
        event_id: Id,
        /// Max value that is used to identify node to remove value in.
        max_value: T,
        /// Value that is inserted itself.
        value: T,
        /// Index of a place in array to insert a value in.
        index: usize,
    },
    /// Describes value remove event.
    RemoveAt {
        event_id: Id,
        /// Max value that is used to identify node to remove value from.
        max_value: T,
        /// Value that is removed itself.
        value: T,
        /// Index of a place in array to remove a value from.
        index: usize,
    },
    /// Describes node creation event.
    CreateNode {
        event_id: Id,
        /// Initial max value.
        max_value: T,
    },
    /// Describes node removal event.
    RemoveNode {
        event_id: Id,
        /// Max value that is used to identify removed node.
        max_value: T,
    },
    /// Describes node split event.
    SplitNode {
        event_id: Id,
        /// Max value that is used to identify node to split.
        max_value: T,
        /// Index of a value that will be last value in first split part.
        split_index: usize,
    },
}

impl<T> ChangeEvent<T> {
    pub fn id(&self) -> Id {
        match self {
            ChangeEvent::InsertAt { event_id, .. } => *event_id,
            ChangeEvent::RemoveAt { event_id, .. } => *event_id,
            ChangeEvent::CreateNode { event_id, .. } => *event_id,
            ChangeEvent::RemoveNode { event_id, .. } => *event_id,
            ChangeEvent::SplitNode { event_id, .. } => *event_id,
        }
    }
}

/// A [`ChangeEvent`] that has not yet been assigned an event [`Id`].
///
/// This type is used to defer event [`Id`] allocation until after an operation
/// successfully commits, ensuring no gaps in event [`Id`]a.
#[derive(Debug, Clone)]
pub enum ChangeEventUnassigned<T> {
    /// Unassigned [`ChangeEvent::InsertAt`].
    InsertAt { max_value: T, value: T, index: usize },
    /// Unassigned [`ChangeEvent::RemoveAt`].
    RemoveAt { max_value: T, value: T, index: usize },
    /// Unassigned [`ChangeEvent::CreateNode`].
    CreateNode { max_value: T },
    /// Unassigned [`ChangeEvent::RemoveNode`].
    RemoveNode { max_value: T },
    /// Unassigned [`ChangeEvent::SplitNode`].
    SplitNode { max_value: T, split_index: usize },
}

impl<T> ChangeEventUnassigned<T> {
    /// Assign an event [`Id`] to this unassigned event, converting it to a [`ChangeEvent`].
    pub fn assign_id(self, event_id: Id) -> ChangeEvent<T> {
        match self {
            Self::InsertAt {
                max_value,
                value,
                index,
            } => ChangeEvent::InsertAt {
                event_id,
                max_value,
                value,
                index,
            },
            Self::RemoveAt {
                max_value,
                value,
                index,
            } => ChangeEvent::RemoveAt {
                event_id,
                max_value,
                value,
                index,
            },
            Self::CreateNode { max_value } => ChangeEvent::CreateNode { event_id, max_value },
            Self::RemoveNode { max_value } => ChangeEvent::RemoveNode { event_id, max_value },
            Self::SplitNode { max_value, split_index } => ChangeEvent::SplitNode {
                event_id,
                max_value,
                split_index,
            },
        }
    }
}

#[cfg(feature = "multimap")]
fn multipair_change_event_into_pair<K, V, M>(ev: ChangeEvent<M>) -> ChangeEvent<Pair<K, V>>
where
    M: Into<Pair<K, V>>,
{
    match ev {
        ChangeEvent::InsertAt {
            event_id,
            max_value,
            value,
            index,
        } => ChangeEvent::InsertAt {
            event_id,
            max_value: max_value.into(),
            value: value.into(),
            index,
        },
        ChangeEvent::RemoveAt {
            event_id,
            max_value,
            value,
            index,
        } => ChangeEvent::RemoveAt {
            event_id,
            max_value: max_value.into(),
            value: value.into(),
            index,
        },
        ChangeEvent::CreateNode { event_id, max_value } => ChangeEvent::CreateNode {
            event_id,
            max_value: max_value.into(),
        },
        ChangeEvent::RemoveNode { event_id, max_value } => ChangeEvent::RemoveNode {
            event_id,
            max_value: max_value.into(),
        },
        ChangeEvent::SplitNode {
            event_id,
            max_value,
            split_index,
        } => ChangeEvent::SplitNode {
            event_id,
            max_value: max_value.into(),
            split_index,
        },
    }
}

#[cfg(feature = "multimap")]
impl<K, V> From<ChangeEvent<RandomMultiPair<K, V>>> for ChangeEvent<Pair<K, V>> {
    fn from(ev: ChangeEvent<RandomMultiPair<K, V>>) -> Self {
        multipair_change_event_into_pair(ev)
    }
}

#[cfg(feature = "multimap")]
impl<K, V> From<ChangeEvent<OrdMultiPair<K, V>>> for ChangeEvent<Pair<K, V>> {
    fn from(ev: ChangeEvent<OrdMultiPair<K, V>>) -> Self {
        multipair_change_event_into_pair(ev)
    }
}