Skip to content

Commit a2ad16d

Browse files
bors[bot]e00E
andauthored
Merge #166
166: Support arbitrary::Arbitrary r=cuviper a=e00E num-bigint already supports quickcheck::Arbitrary which works roughly like arbitrary::Arbitrary. arbitrary::Arbitrary used by cargo-fuzz and makes it easier to use num-bigint BigInt and BigUint in projects that want to fuzz that way. https://github.com/rust-fuzz/arbitrary https://github.com/rust-fuzz/cargo-fuzz I have included an example fuzz target but I'm not sure whether we want to merge it. ``` cargo +nightly install cargo-fuzz cargo +nightly fuzz run fuzz_target_1 ``` Co-authored-by: Valentin <[email protected]>
2 parents b3d48f4 + 6bd8c9c commit a2ad16d

File tree

5 files changed

+51
-15
lines changed

5 files changed

+51
-15
lines changed

Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ exclude = ["/bors.toml", "/ci/*", "/.github/*"]
1515
edition = "2018"
1616

1717
[package.metadata.docs.rs]
18-
features = ["std", "serde", "rand", "quickcheck"]
18+
features = ["std", "serde", "rand", "quickcheck", "arbitrary"]
1919

2020
[[bench]]
2121
name = "bigint"
@@ -60,6 +60,11 @@ optional = true
6060
version = "0.9"
6161
default-features = false
6262

63+
[dependencies.arbitrary]
64+
optional = true
65+
version = "0.4"
66+
default-features = false
67+
6368
[features]
6469
default = ["std"]
6570
std = ["num-integer/std", "num-traits/std"]

ci/test_full.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ STD_FEATURES=(serde)
3131
check_version 1.32 && STD_FEATURES+=(rand)
3232
check_version 1.34 && STD_FEATURES+=(quickcheck)
3333
check_version 1.36 && NO_STD_FEATURES=(serde rand)
34+
check_version 1.40 && STD_FEATURES+=(arbitrary)
3435
echo "Testing supported features: ${STD_FEATURES[*]}"
3536
if [ -n "${NO_STD_FEATURES[*]}" ]; then
3637
echo " no_std supported features: ${NO_STD_FEATURES[*]}"

src/bigint.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// `Add`/`Sub` ops may flip from `BigInt` to its `BigUint` magnitude
22
#![allow(clippy::suspicious_arithmetic_impl)]
33

4-
#[cfg(feature = "quickcheck")]
4+
#[cfg(any(feature = "quickcheck", feature = "arbitrary"))]
55
use crate::std_alloc::Box;
66
use crate::std_alloc::{String, Vec};
77
use core::cmp::Ordering::{self, Equal, Greater, Less};
@@ -39,9 +39,6 @@ use crate::TryFromBigIntError;
3939
use crate::IsizePromotion;
4040
use crate::UsizePromotion;
4141

42-
#[cfg(feature = "quickcheck")]
43-
use quickcheck::{Arbitrary, Gen};
44-
4542
/// A Sign is a `BigInt`'s composing element.
4643
#[derive(PartialEq, PartialOrd, Eq, Ord, Copy, Clone, Debug, Hash)]
4744
pub enum Sign {
@@ -141,8 +138,8 @@ impl Clone for BigInt {
141138
}
142139

143140
#[cfg(feature = "quickcheck")]
144-
impl Arbitrary for BigInt {
145-
fn arbitrary<G: Gen>(g: &mut G) -> Self {
141+
impl quickcheck::Arbitrary for BigInt {
142+
fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self {
146143
let positive = bool::arbitrary(g);
147144
let sign = if positive { Sign::Plus } else { Sign::Minus };
148145
Self::from_biguint(sign, BigUint::arbitrary(g))
@@ -155,6 +152,26 @@ impl Arbitrary for BigInt {
155152
}
156153
}
157154

155+
#[cfg(feature = "arbitrary")]
156+
mod abitrary_impl {
157+
use super::*;
158+
use arbitrary::{Arbitrary, Result, Unstructured};
159+
160+
impl Arbitrary for BigInt {
161+
fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> {
162+
let positive = bool::arbitrary(u)?;
163+
let sign = if positive { Sign::Plus } else { Sign::Minus };
164+
Ok(Self::from_biguint(sign, BigUint::arbitrary(u)?))
165+
}
166+
167+
fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
168+
let sign = self.sign();
169+
let unsigned_shrink = self.data.shrink();
170+
Box::new(unsigned_shrink.map(move |x| BigInt::from_biguint(sign, x)))
171+
}
172+
}
173+
}
174+
158175
impl hash::Hash for BigInt {
159176
#[inline]
160177
fn hash<H: hash::Hasher>(&self, state: &mut H) {

src/biguint.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#[cfg(feature = "quickcheck")]
1+
#[cfg(any(feature = "quickcheck", feature = "arbitrary"))]
22
use crate::std_alloc::Box;
33
use crate::std_alloc::{Cow, String, Vec};
44
use core::cmp;
@@ -45,9 +45,6 @@ use crate::ParseBigIntError;
4545
#[cfg(has_try_from)]
4646
use crate::TryFromBigIntError;
4747

48-
#[cfg(feature = "quickcheck")]
49-
use quickcheck::{Arbitrary, Gen};
50-
5148
/// A big unsigned integer type.
5249
#[derive(Debug)]
5350
pub struct BigUint {
@@ -71,8 +68,8 @@ impl Clone for BigUint {
7168
}
7269

7370
#[cfg(feature = "quickcheck")]
74-
impl Arbitrary for BigUint {
75-
fn arbitrary<G: Gen>(g: &mut G) -> Self {
71+
impl quickcheck::Arbitrary for BigUint {
72+
fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self {
7673
// Use arbitrary from Vec
7774
biguint_from_vec(Vec::<BigDigit>::arbitrary(g))
7875
}
@@ -83,6 +80,22 @@ impl Arbitrary for BigUint {
8380
}
8481
}
8582

83+
#[cfg(feature = "arbitrary")]
84+
mod abitrary_impl {
85+
use super::*;
86+
use arbitrary::{Arbitrary, Result, Unstructured};
87+
88+
impl Arbitrary for BigUint {
89+
fn arbitrary(u: &mut Unstructured<'_>) -> Result<Self> {
90+
Ok(biguint_from_vec(Vec::<BigDigit>::arbitrary(u)?))
91+
}
92+
93+
fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
94+
Box::new(self.data.shrink().map(biguint_from_vec))
95+
}
96+
}
97+
}
98+
8699
impl hash::Hash for BigUint {
87100
#[inline]
88101
fn hash<H: hash::Hasher>(&self, state: &mut H) {

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ extern crate std;
9494
#[cfg(feature = "std")]
9595
mod std_alloc {
9696
pub(crate) use std::borrow::Cow;
97-
#[cfg(feature = "quickcheck")]
97+
#[cfg(any(feature = "quickcheck", feature = "arbitrary"))]
9898
pub(crate) use std::boxed::Box;
9999
pub(crate) use std::string::String;
100100
pub(crate) use std::vec::Vec;
@@ -107,7 +107,7 @@ extern crate alloc;
107107
#[cfg(not(feature = "std"))]
108108
mod std_alloc {
109109
pub(crate) use alloc::borrow::Cow;
110-
#[cfg(feature = "quickcheck")]
110+
#[cfg(any(feature = "quickcheck", feature = "arbitrary"))]
111111
pub(crate) use alloc::boxed::Box;
112112
pub(crate) use alloc::string::String;
113113
pub(crate) use alloc::vec::Vec;

0 commit comments

Comments
 (0)