pipecircuit 0.0.25

Correct. Robust. Fast. Portable. Pick four.
Documentation
#![cfg(feature = "secondary-indexes")]

use core::num::NonZeroU32;
use pipecircuit::storage::query_workspace::{QueryChunk, QueryWorkspace, required_query_chunks};
use pipecircuit::storage::warp_table::{Capacity, WarpTable, WarpTableInsertOutcome, WarpTableRow};

#[global_allocator]
static ALLOCATOR: dhat::Alloc = dhat::Alloc;

#[derive(WarpTableRow)]
struct Row {
    #[index(range)]
    value: u32,
    #[index(secondary)]
    group: u8,
}

#[test]
fn mixed_composition_allocates_nothing_after_reservation() -> Result<(), &'static str> {
    {
        let _profiler = dhat::Profiler::builder().testing().build();
        let calibration = core::hint::black_box(vec![0_u8; 17]);
        assert_eq!(dhat::HeapStats::get().total_blocks, 1);
        assert_eq!(dhat::HeapStats::get().total_bytes, 17);
        drop(calibration);
    }
    for capacity in [65, 4097, 65537, 100000] {
        let mut table =
            WarpTable::<Row>::try_new(Capacity::new(NonZeroU32::new(capacity).ok_or("capacity")?))
                .map_err(|_| "table")?;
        for value in 0..capacity {
            assert!(matches!(
                table.insert(Row {
                    value,
                    group: (value % 3) as u8
                }),
                WarpTableInsertOutcome::Inserted { .. }
            ));
        }
        let mut chunks = core::iter::repeat_with(|| QueryChunk::EMPTY)
            .take(required_query_chunks(capacity as usize).map_err(|_| "chunks")?)
            .collect::<Vec<_>>();
        let mut scratch = QueryChunk::EMPTY;
        let mut workspace =
            QueryWorkspace::new(capacity as usize, chunks.as_mut_slice(), &mut scratch)
                .map_err(|_| "workspace")?;
        let expected = (0..capacity)
            .filter(|value| {
                (((10..=20000).contains(value) && value % 3 == 1) || *value >= 40000)
                    != (value % 3 == 2)
            })
            .count();
        let _profiler = dhat::Profiler::builder().testing().build();
        for _ in 0..8 {
            let selected = table
                .query_memberships()
                .find_value_in(10..=20000)
                .map_err(|_| "range")?
                .in_workspace(workspace.membership().map_err(|_| "membership")?)
                .map_err(|_| "start")?
                .and(|q| q.find_group(1))
                .map_err(|_| "and")?
                .or(|q| q.find_value_in(40000..))
                .map_err(|_| "or")?
                .xor(|q| q.find_group(2))
                .map_err(|_| "xor")?;
            assert_eq!(selected.len() as usize, expected);
            assert_eq!(selected.rows().count(), expected);
        }
        let stats = dhat::HeapStats::get();
        assert_eq!((stats.total_blocks, stats.total_bytes), (0, 0));
    }
    Ok(())
}