//! Support for the [`proptest`](https://crates.io/crates/proptest) crate. #![cfg(feature = "proptest")] #![cfg_attr(has_doc_cfg, doc(cfg(feature = "proptest")))] use crate::{nlimbs, Bits, Uint}; use proptest::{ arbitrary::Arbitrary, collection::{vec, VecStrategy}, num::u64::Any, strategy::{BoxedStrategy, Strategy}, }; impl Arbitrary for Uint { // FEATURE: Would be nice to have a value range as parameter // and/or a choice between uniform and 'exponential' distribution. type Parameters = (); type Strategy = BoxedStrategy; fn arbitrary_with(_: Self::Parameters) -> BoxedStrategy { // OPT: Copy [`UniformArrayStrategy`] to avoid heap allocations let limbs: VecStrategy = vec(u64::arbitrary(), nlimbs(BITS)); limbs .prop_map(|mut limbs| { if Self::LIMBS > 0 { limbs[Self::LIMBS - 1] &= Self::MASK; } Self::from_limbs_slice(&limbs) }) .boxed() } } impl Arbitrary for Bits { type Parameters = as Arbitrary>::Parameters; type Strategy = BoxedStrategy; fn arbitrary_with(args: Self::Parameters) -> Self::Strategy { Uint::::arbitrary_with(args) .prop_map(Self::from) .boxed() } } #[cfg(test)] mod tests { use super::*; use crate::const_for; use proptest::proptest; #[test] fn test_arbitrary() { const_for!(BITS in SIZES { const LIMBS: usize = nlimbs(BITS); proptest!(|(n: Uint::)| { let _ = n; }); }); } }