pipecircuit 0.0.18

Correct. Robust. Fast. Portable. Pick four.
Documentation
use super::rows::SelectionRows;
use super::rows::StableSlotResolver;
use crate::storage::warp_table::secondary_index::SlotSet;
use crate::storage::warp_table::{WarpTable, WarpTableRow};

pub(super) enum SelectionMembership<'table> {
    Empty,
    Borrowed(&'table SlotSet),
    Owned(SlotSet),
}

#[must_use]
pub struct Selection<'table, Row: WarpTableRow, Brand = Row> {
    pub(super) table: &'table WarpTable<Row, Brand>,
    pub(super) membership: SelectionMembership<'table>,
}

impl<'table, Row: WarpTableRow, Brand> Selection<'table, Row, Brand> {
    pub(super) const fn empty(table: &'table WarpTable<Row, Brand>) -> Self {
        Self {
            table,
            membership: SelectionMembership::Empty,
        }
    }

    pub(super) const fn borrowed(
        table: &'table WarpTable<Row, Brand>,
        slots: &'table SlotSet,
    ) -> Self {
        Self {
            table,
            membership: SelectionMembership::Borrowed(slots),
        }
    }

    pub(super) const fn owned(table: &'table WarpTable<Row, Brand>, slots: SlotSet) -> Self {
        Self {
            table,
            membership: SelectionMembership::Owned(slots),
        }
    }

    pub fn len(&self) -> u64 {
        match &self.membership {
            SelectionMembership::Empty => 0,
            SelectionMembership::Borrowed(slots) => slots.len(),
            SelectionMembership::Owned(slots) => slots.len(),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub(crate) fn belongs_to(&self, table: &WarpTable<Row, Brand>) -> bool {
        core::ptr::eq(self.table, table)
    }

    /// Iterates stable primary identities without projecting or cloning rows.
    pub fn ids(self) -> impl Iterator<Item = Row::Id> + 'table
    where
        Row::Indexes: super::rows::StableSlotResolver,
    {
        let slots = super::rows::SelectionSlotIter::from(self.membership);
        let table = self.table;
        slots.map(move |slot| {
            let super::super::secondary_index::StableSlotResolveOutcome::Resolved {
                dense_row, ..
            } = match table.__indexes().resolve_stable_slot(slot) {
                Ok(resolution) => resolution,
                Err(reason) => super::super::inconsistency::invariant_violation(reason),
            };
            match table.ids().get(dense_row) {
                Some(id) => *id,
                None => {
                    super::super::inconsistency::invariant_violation("selected identity missing")
                }
            }
        })
    }

    pub fn rows(self) -> SelectionRows<'table, Row, Brand>
    where
        Row::Indexes: super::rows::StableSlotResolver,
    {
        SelectionRows::new(self.table, self.membership)
    }
}