flat_bit_set 0.1.0

有序、稀疏、节省空间的 bitset,适用于小数据量
Documentation
use crate::*;
use core::{fmt::Debug, marker::PhantomData};
use prop::{collection::vec, strategy::ValueTree};
use proptest::prelude::*;
use rand::{distributions::Standard, prelude::*};

struct ChunkValueTree<C> {
    cur: C,
    prev: Option<C>,
}

#[derive(Clone, Debug)]
struct ChunkStrategy<C>(PhantomData<C>);

impl<C> Strategy for ChunkStrategy<C>
where
    C: Chunk + Debug,
    Standard: Distribution<C>,
{
    type Tree = ChunkValueTree<C>;

    type Value = C;

    fn new_tree(
        &self,
        runner: &mut prop::test_runner::TestRunner,
    ) -> prop::strategy::NewTree<Self> {
        Ok(ChunkValueTree {
            cur: runner.rng().gen(),
            prev: None,
        })
    }
}

impl<C: Chunk + Debug> ValueTree for ChunkValueTree<C> {
    type Value = C;

    fn current(&self) -> Self::Value {
        self.cur
    }

    fn simplify(&mut self) -> bool {
        let ok = self.cur.count_ones() > 1;
        if ok {
            self.prev = Some(self.cur);
            self.cur.remove_lowest_bit();
        }
        ok
    }

    fn complicate(&mut self) -> bool {
        self.prev.take().is_some_and(|prev| {
            self.cur = prev;
            true
        })
    }
}

impl<K, C> Arbitrary for FlatBitSet<K, C>
where
    K: Key + Debug + Arbitrary,
    C: Chunk + Debug,
    Standard: Distribution<C>,
{
    type Parameters = prop::sample::SizeRange;

    fn arbitrary_with(size: Self::Parameters) -> Self::Strategy {
        let ele = (
            any::<K>().prop_map(|k| k.split::<C>().0),
            ChunkStrategy::<C>(PhantomData),
        );
        let st = vec(ele, size).prop_map(|mut vec| {
            vec.sort_unstable_by_key(|&(k, _)| k);
            vec.dedup_by_key(|&mut (k, _)| k);
            for (_, c) in &vec {
                debug_assert!(c.count_ones() != 0);
            }
            Self(vec)
        });
        st.boxed()
    }

    type Strategy = BoxedStrategy<Self>;
}