diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c6680623..a77373f6 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -14,8 +14,10 @@ jobs: matrix: rust: [ 1.31.0, # 2018! - 1.34.0, # quickcheck, has_try_from + 1.34.0, # has_try_from 1.36.0, # alloc, rand + 1.40.0, # arbitrary + 1.46.0, # quickcheck stable, beta, nightly diff --git a/Cargo.toml b/Cargo.toml index 6e54ee32..85ba6b14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,12 +62,12 @@ default-features = false [dependencies.quickcheck] optional = true -version = "0.9" +version = "1" default-features = false [dependencies.arbitrary] optional = true -version = "0.4" +version = "1" default-features = false [build-dependencies] diff --git a/bors.toml b/bors.toml index 1a5421b0..163c03ab 100644 --- a/bors.toml +++ b/bors.toml @@ -2,6 +2,8 @@ status = [ "Test (1.31.0)", "Test (1.34.0)", "Test (1.36.0)", + "Test (1.40.0)", + "Test (1.46.0)", "Test (stable)", "Test (beta)", "Test (nightly)", diff --git a/ci/big_quickcheck/Cargo.toml b/ci/big_quickcheck/Cargo.toml index c58f6d47..6002eedb 100644 --- a/ci/big_quickcheck/Cargo.toml +++ b/ci/big_quickcheck/Cargo.toml @@ -7,10 +7,10 @@ edition = "2018" [dependencies] num-integer = "0.1.42" num-traits = "0.2.11" -quickcheck_macros = "0.9" +quickcheck_macros = "1" [dependencies.quickcheck] -version = "0.9" +version = "1" default-features = false [dependencies.num-bigint] diff --git a/ci/big_quickcheck/src/lib.rs b/ci/big_quickcheck/src/lib.rs index 36d52877..4db72f8f 100644 --- a/ci/big_quickcheck/src/lib.rs +++ b/ci/big_quickcheck/src/lib.rs @@ -9,7 +9,7 @@ use num_bigint::{BigInt, BigUint}; use num_integer::Integer; use num_traits::{Num, One, Signed, Zero}; -use quickcheck::{QuickCheck, StdThreadGen, TestResult}; +use quickcheck::{Gen, QuickCheck, TestResult}; use quickcheck_macros::quickcheck; #[quickcheck] @@ -42,8 +42,8 @@ fn quickcheck_signed_eq_symmetric(a: BigInt, b: BigInt) -> bool { #[test] fn quickcheck_arith_primitive() { - let gen = StdThreadGen::new(usize::max_value()); - let mut qc = QuickCheck::with_gen(gen); + let gen = Gen::new(usize::max_value()); + let mut qc = QuickCheck::new().gen(gen); fn test_unsigned_add_primitive(a: usize, b: usize) -> TestResult { let actual = BigUint::from(a) + BigUint::from(b); @@ -79,11 +79,11 @@ fn quickcheck_arith_primitive() { } } - fn test_signed_sub_primitive(a: i128, b: i128) -> bool { - if b < a { - BigInt::from(a - b) == BigInt::from(a) - BigInt::from(b) - } else { - BigInt::from(b - a) == BigInt::from(b) - BigInt::from(a) + fn test_signed_sub_primitive(a: i128, b: i128) -> TestResult { + let actual = BigInt::from(a) - BigInt::from(b); + match a.checked_sub(b) { + None => TestResult::discard(), + Some(expected) => TestResult::from_bool(BigInt::from(expected) == actual), } } @@ -96,7 +96,7 @@ fn quickcheck_arith_primitive() { } fn test_signed_div_primitive(a: i128, b: i128) -> TestResult { - if b == 0 { + if b == 0 || (a == i128::MIN && b == -1) { TestResult::discard() } else { TestResult::from_bool(BigInt::from(a / b) == BigInt::from(a) / BigInt::from(b)) @@ -108,7 +108,7 @@ fn quickcheck_arith_primitive() { qc.quickcheck(test_unsigned_mul_primitive as fn(u64, u64) -> bool); qc.quickcheck(test_signed_mul_primitive as fn(i64, i64) -> bool); qc.quickcheck(test_unsigned_sub_primitive as fn(u128, u128) -> bool); - qc.quickcheck(test_signed_sub_primitive as fn(i128, i128) -> bool); + qc.quickcheck(test_signed_sub_primitive as fn(i128, i128) -> TestResult); qc.quickcheck(test_unsigned_div_primitive as fn(u128, u128) -> TestResult); qc.quickcheck(test_signed_div_primitive as fn(i128, i128) -> TestResult); } @@ -280,8 +280,8 @@ fn quickcheck_signed_conversion(a: BigInt, radix: u8) -> TestResult { #[test] fn quicktest_shift() { - let gen = StdThreadGen::new(usize::max_value()); - let mut qc = QuickCheck::with_gen(gen); + let gen = Gen::new(usize::max_value()); + let mut qc = QuickCheck::new().gen(gen); fn test_shr_unsigned(a: u64, shift: u8) -> TestResult { let shift = (shift % 64) as usize; //shift at most 64 bits @@ -317,8 +317,8 @@ fn quicktest_shift() { #[test] fn quickcheck_modpow() { - let gen = StdThreadGen::new(usize::max_value()); - let mut qc = QuickCheck::with_gen(gen); + let gen = Gen::new(usize::max_value()); + let mut qc = QuickCheck::new().gen(gen); fn simple_modpow(base: &BigInt, exponent: &BigInt, modulus: &BigInt) -> BigInt { assert!(!exponent.is_negative()); diff --git a/ci/rustup.sh b/ci/rustup.sh index ef75c700..607901c0 100755 --- a/ci/rustup.sh +++ b/ci/rustup.sh @@ -5,6 +5,6 @@ set -ex ci=$(dirname $0) -for version in 1.31.0 1.34.0 1.36.0 stable beta nightly; do +for version in 1.31.0 1.34.0 1.36.0 1.40.0 1.46.0 stable beta nightly; do rustup run "$version" "$ci/test_full.sh" done diff --git a/ci/test_full.sh b/ci/test_full.sh index c3e2785f..d84feae8 100755 --- a/ci/test_full.sh +++ b/ci/test_full.sh @@ -28,10 +28,10 @@ if ! check_version $MSRV ; then fi STD_FEATURES=(serde) -check_version 1.34 && STD_FEATURES+=(quickcheck) check_version 1.36 && STD_FEATURES+=(rand) check_version 1.36 && NO_STD_FEATURES=(serde rand) check_version 1.40 && STD_FEATURES+=(arbitrary) +check_version 1.46 && STD_FEATURES+=(quickcheck) 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 4b0e4891..891eeb46 100644 --- a/src/bigint.rs +++ b/src/bigint.rs @@ -59,7 +59,6 @@ impl Neg for Sign { } /// A big signed integer type. -#[derive(Debug)] pub struct BigInt { sign: Sign, data: BigUint, @@ -137,6 +136,12 @@ impl Default for BigInt { } } +impl fmt::Debug for BigInt { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + impl fmt::Display for BigInt { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad_integral(!self.is_negative(), "", &self.data.to_str_radix(10)) diff --git a/src/bigint/arbitrary.rs b/src/bigint/arbitrary.rs index 08e05f9e..df66050e 100644 --- a/src/bigint/arbitrary.rs +++ b/src/bigint/arbitrary.rs @@ -1,11 +1,12 @@ use super::{BigInt, Sign}; +#[cfg(feature = "quickcheck")] use crate::std_alloc::Box; use crate::BigUint; #[cfg(feature = "quickcheck")] impl quickcheck::Arbitrary for BigInt { - fn arbitrary(g: &mut G) -> Self { + fn arbitrary(g: &mut quickcheck::Gen) -> Self { let positive = bool::arbitrary(g); let sign = if positive { Sign::Plus } else { Sign::Minus }; Self::from_biguint(sign, BigUint::arbitrary(g)) @@ -19,16 +20,20 @@ impl quickcheck::Arbitrary for BigInt { } #[cfg(feature = "arbitrary")] -impl arbitrary::Arbitrary for BigInt { +impl arbitrary::Arbitrary<'_> for BigInt { fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::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))) + fn arbitrary_take_rest(mut u: arbitrary::Unstructured<'_>) -> arbitrary::Result { + let positive = bool::arbitrary(&mut u)?; + let sign = if positive { Sign::Plus } else { Sign::Minus }; + Ok(Self::from_biguint(sign, BigUint::arbitrary_take_rest(u)?)) + } + + fn size_hint(depth: usize) -> (usize, Option) { + arbitrary::size_hint::and(bool::size_hint(depth), BigUint::size_hint(depth)) } } diff --git a/src/biguint.rs b/src/biguint.rs index b790c57a..42350714 100644 --- a/src/biguint.rs +++ b/src/biguint.rs @@ -35,7 +35,6 @@ pub(crate) use self::convert::to_str_radix_reversed; pub use self::iter::{U32Digits, U64Digits}; /// A big unsigned integer type. -#[derive(Debug)] pub struct BigUint { data: Vec, } @@ -106,6 +105,12 @@ impl Default for BigUint { } } +impl fmt::Debug for BigUint { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + impl fmt::Display for BigUint { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad_integral(true, "", &self.to_str_radix(10)) diff --git a/src/biguint/arbitrary.rs b/src/biguint/arbitrary.rs index 8a2eb9e9..6fa91c0f 100644 --- a/src/biguint/arbitrary.rs +++ b/src/biguint/arbitrary.rs @@ -1,11 +1,13 @@ use super::{biguint_from_vec, BigUint}; use crate::big_digit::BigDigit; -use crate::std_alloc::{Box, Vec}; +#[cfg(feature = "quickcheck")] +use crate::std_alloc::Box; +use crate::std_alloc::Vec; #[cfg(feature = "quickcheck")] impl quickcheck::Arbitrary for BigUint { - fn arbitrary(g: &mut G) -> Self { + fn arbitrary(g: &mut quickcheck::Gen) -> Self { // Use arbitrary from Vec biguint_from_vec(Vec::::arbitrary(g)) } @@ -17,12 +19,16 @@ impl quickcheck::Arbitrary for BigUint { } #[cfg(feature = "arbitrary")] -impl arbitrary::Arbitrary for BigUint { +impl arbitrary::Arbitrary<'_> for BigUint { fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result { Ok(biguint_from_vec(Vec::::arbitrary(u)?)) } - fn shrink(&self) -> Box> { - Box::new(self.data.shrink().map(biguint_from_vec)) + fn arbitrary_take_rest(u: arbitrary::Unstructured<'_>) -> arbitrary::Result { + Ok(biguint_from_vec(Vec::::arbitrary_take_rest(u)?)) + } + + fn size_hint(depth: usize) -> (usize, Option) { + Vec::::size_hint(depth) } } diff --git a/src/lib.rs b/src/lib.rs index bfca016c..a4ab704a 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(any(feature = "quickcheck", feature = "arbitrary"))] + #[cfg(any(feature = "quickcheck"))] 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(any(feature = "quickcheck", feature = "arbitrary"))] + #[cfg(any(feature = "quickcheck"))] pub(crate) use alloc::boxed::Box; pub(crate) use alloc::string::String; pub(crate) use alloc::vec::Vec;