pipecircuit 0.0.24

Correct. Robust. Fast. Portable. Pick four.
Documentation
use super::rows::resolve;
use crate::storage::warp_table::secondary_index::{
    RangeWorkspaceMembership, StableSlot, StableSlotResolver,
};
use crate::storage::warp_table::{RangeIndexBounds, WarpTable, WarpTableRow};

#[must_use]
pub struct RangeSelection<'table, 'workspace, Row: WarpTableRow, Brand, Key> {
    table: &'table WarpTable<Row, Brand>,
    bounds: RangeIndexBounds<Key>,
    words: &'workspace [u64],
    len: u64,
}

impl<'table, 'workspace, Row: WarpTableRow, Brand, Key>
    RangeSelection<'table, 'workspace, Row, Brand, Key>
{
    pub fn bounds(&self) -> &RangeIndexBounds<Key> {
        &self.bounds
    }

    pub fn len(&self) -> u64 {
        self.len
    }

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

    pub fn rows(self) -> impl Iterator<Item = Row::Ref<'table>> + 'workspace
    where
        'table: 'workspace,
        Row::Indexes: StableSlotResolver,
    {
        (0..=u32::MAX)
            .step_by(u64::BITS as usize)
            .zip(self.words)
            .flat_map(|(base, word)| word_slots(base, *word))
            .map(move |slot| resolve(self.table, slot))
    }
}

#[allow(
    clippy::arithmetic_side_effects,
    reason = "bases are multiples of 64 within u32; each bit is below 64 and subtraction follows a nonzero check"
)]
fn word_slots(base: u32, mut word: u64) -> impl Iterator<Item = StableSlot> {
    core::iter::from_fn(move || {
        if word == 0 {
            return None;
        }
        let bit = word.trailing_zeros();
        word &= word - 1;
        Some(StableSlot::new(base + bit))
    })
}

#[doc(hidden)]
pub fn bind_range_workspace_lookup<'table, 'workspace, Row: WarpTableRow, Brand, Key>(
    table: &'table WarpTable<Row, Brand>,
    membership: RangeWorkspaceMembership<'workspace, Key>,
) -> RangeSelection<'table, 'workspace, Row, Brand, Key> {
    let (bounds, words, len) = membership.into_parts();
    RangeSelection {
        table,
        bounds,
        words,
        len,
    }
}