pipecircuit 0.0.6

Correct. Robust. Fast. Portable.
Documentation
use alloc::collections::TryReserveError;
use core::marker::PhantomData;

use super::blocks::storage_dimensions;
use super::{RangeIndex, RangeIndexKey};

#[derive(Debug)]
pub enum RangeIndexCreationError {
    InvalidBitWidth { bits: u32 },
    CapacityOverflow { maximum_rows: usize, bits: u32 },
    StorageUnavailable { source: TryReserveError },
}

impl<Key: RangeIndexKey> RangeIndex<Key> {
    pub fn try_new(maximum_rows: usize) -> Result<Self, RangeIndexCreationError> {
        if !(1..=u64::BITS).contains(&Key::BITS) {
            return Err(RangeIndexCreationError::InvalidBitWidth { bits: Key::BITS });
        }
        let Some((_, storage_words)) = storage_dimensions(maximum_rows, Key::BITS) else {
            return Err(RangeIndexCreationError::CapacityOverflow {
                maximum_rows,
                bits: Key::BITS,
            });
        };
        let mut blocks = alloc::vec::Vec::new();
        blocks
            .try_reserve_exact(storage_words)
            .map_err(|source| RangeIndexCreationError::StorageUnavailable { source })?;
        blocks.resize(storage_words, 0);
        Ok(Self {
            maximum_rows,
            member_count: 0,
            blocks,
            key: PhantomData,
        })
    }
}