diff --git a/Cargo.toml b/Cargo.toml index 4bd30d99..2f63abb6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ exclude = ["/bors.toml", "/ci/*", "/.github/*"] edition = "2018" [package.metadata.docs.rs] -features = ["std", "serde", "rand", "quickcheck"] +features = ["std", "serde", "rand", "quickcheck", "arbitrary"] [[bench]] name = "bigint" @@ -60,6 +60,11 @@ optional = true version = "0.9" default-features = false +[dependencies.arbitrary] +optional = true +version = "0.4" +default-features = false + [features] default = ["std"] std = ["num-integer/std", "num-traits/std"] diff --git a/ci/test_full.sh b/ci/test_full.sh index 849858b0..3b3b472d 100755 --- a/ci/test_full.sh +++ b/ci/test_full.sh @@ -31,6 +31,7 @@ STD_FEATURES=(serde) check_version 1.32 && STD_FEATURES+=(rand) check_version 1.34 && STD_FEATURES+=(quickcheck) check_version 1.36 && NO_STD_FEATURES=(serde rand) +check_version 1.40 && STD_FEATURES+=(arbitrary) echo "Testing supported features: ${STD_FEATURES[*]}" if [ -n "${NO_STD_FEATURES[*]}" ]; then echo " no_std supported features: ${NO_STD_FEATURES[*]}" diff --git a/src/bigint.rs b/src/bigint.rs index 23885582..cdb14385 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -1,7 +1,7 @@ // `Add`/`Sub` ops may flip from `BigInt` to its `BigUint` magnitude #![allow(clippy::suspicious_arithmetic_impl)] -#[cfg(feature = "quickcheck")] +#[cfg(any(feature = "quickcheck", feature = "arbitrary"))] use crate::std_alloc::Box; use crate::std_alloc::{String, Vec}; use core::cmp::Ordering::{self, Equal, Greater, Less}; @@ -39,9 +39,6 @@ use crate::TryFromBigIntError; use crate::IsizePromotion; use crate::UsizePromotion; -#[cfg(feature = "quickcheck")] -use quickcheck::{Arbitrary, Gen}; - /// A Sign is a `BigInt`'s composing element. #[derive(PartialEq, PartialOrd, Eq, Ord, Copy, Clone, Debug, Hash)] pub enum Sign { @@ -141,8 +138,8 @@ impl Clone for BigInt { } #[cfg(feature = "quickcheck")] -impl Arbitrary for BigInt { - fn arbitrary(g: &mut G) -> Self { +impl quickcheck::Arbitrary for BigInt { + fn arbitrary(g: &mut G) -> Self { let positive = bool::arbitrary(g); let sign = if positive { Sign::Plus } else { Sign::Minus }; Self::from_biguint(sign, BigUint::arbitrary(g)) @@ -155,6 +152,26 @@ impl Arbitrary for BigInt { } } +#[cfg(feature = "arbitrary")] +mod abitrary_impl { + use super::*; + use arbitrary::{Arbitrary, Result, Unstructured}; + + impl Arbitrary for BigInt { + fn arbitrary(u: &mut Unstructured<'_>) -> Result { + let positive = bool::arbitrary(u)?; + let sign = if positive { Sign::Plus } else { Sign::Minus }; + Ok(Self::from_biguint(sign, BigUint::arbitrary(u)?)) + } + + fn shrink(&self) -> Box> { + let sign = self.sign(); + let unsigned_shrink = self.data.shrink(); + Box::new(unsigned_shrink.map(move |x| BigInt::from_biguint(sign, x))) + } + } +} + impl hash::Hash for BigInt { #[inline] fn hash(&self, state: &mut H) { diff --git a/src/biguint.rs b/src/biguint.rs index 0a582e02..073beaeb 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -1,4 +1,4 @@ -#[cfg(feature = "quickcheck")] +#[cfg(any(feature = "quickcheck", feature = "arbitrary"))] use crate::std_alloc::Box; use crate::std_alloc::{Cow, String, Vec}; use core::cmp; @@ -45,9 +45,6 @@ use crate::ParseBigIntError; #[cfg(has_try_from)] use crate::TryFromBigIntError; -#[cfg(feature = "quickcheck")] -use quickcheck::{Arbitrary, Gen}; - /// A big unsigned integer type. #[derive(Debug)] pub struct BigUint { @@ -71,8 +68,8 @@ impl Clone for BigUint { } #[cfg(feature = "quickcheck")] -impl Arbitrary for BigUint { - fn arbitrary(g: &mut G) -> Self { +impl quickcheck::Arbitrary for BigUint { + fn arbitrary(g: &mut G) -> Self { // Use arbitrary from Vec biguint_from_vec(Vec::::arbitrary(g)) } @@ -83,6 +80,22 @@ impl Arbitrary for BigUint { } } +#[cfg(feature = "arbitrary")] +mod abitrary_impl { + use super::*; + use arbitrary::{Arbitrary, Result, Unstructured}; + + impl Arbitrary for BigUint { + fn arbitrary(u: &mut Unstructured<'_>) -> Result { + Ok(biguint_from_vec(Vec::::arbitrary(u)?)) + } + + fn shrink(&self) -> Box> { + Box::new(self.data.shrink().map(biguint_from_vec)) + } + } +} + impl hash::Hash for BigUint { #[inline] fn hash(&self, state: &mut H) { diff --git a/src/lib.rs b/src/lib.rs index 30c5abec..5e8a30ed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,7 +94,7 @@ extern crate std; #[cfg(feature = "std")] mod std_alloc { pub(crate) use std::borrow::Cow; - #[cfg(feature = "quickcheck")] + #[cfg(any(feature = "quickcheck", feature = "arbitrary"))] pub(crate) use std::boxed::Box; pub(crate) use std::string::String; pub(crate) use std::vec::Vec; @@ -107,7 +107,7 @@ extern crate alloc; #[cfg(not(feature = "std"))] mod std_alloc { pub(crate) use alloc::borrow::Cow; - #[cfg(feature = "quickcheck")] + #[cfg(any(feature = "quickcheck", feature = "arbitrary"))] pub(crate) use alloc::boxed::Box; pub(crate) use alloc::string::String; pub(crate) use alloc::vec::Vec;