aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-28 15:58:34 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-04-28 15:58:34 +0000
commit2a8f11366a1b48d32982dffe7148cc6ace71c256 (patch)
tree252a378bfaad1976f5f9ecf366574d7e62e75985
parent1471ed830db50b63ea8797270b18dda048303888 (diff)
parent5187f941e4737e1d721ac600acefe66a8f4d1a46 (diff)
downloadarbitrary-android13-frc-scheduling-release.tar.gz
Snap for 8512216 from 5187f941e4737e1d721ac600acefe66a8f4d1a46 to tm-frc-scheduling-releaset_frc_sch_330443040t_frc_sch_330443010android13-frc-scheduling-release
Change-Id: Ib75138ac10ac23413099682f2f6ae9e58c42d950
-rw-r--r--.cargo_vcs_info.json7
-rw-r--r--Android.bp13
-rw-r--r--CHANGELOG.md31
-rw-r--r--Cargo.toml19
-rw-r--r--Cargo.toml.orig4
-rw-r--r--METADATA10
-rw-r--r--cargo2android.json4
-rw-r--r--src/lib.rs2
-rw-r--r--src/unstructured.rs141
-rwxr-xr-x[-rw-r--r--]tests/derive.rs4
10 files changed, 212 insertions, 23 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json
index 2d96982..508adbd 100644
--- a/.cargo_vcs_info.json
+++ b/.cargo_vcs_info.json
@@ -1,5 +1,6 @@
{
"git": {
- "sha1": "ef27875e0311786ca5210a734c6288cb5d920614"
- }
-}
+ "sha1": "d0d238d880276fd617c38f7e4712bf40db58aad6"
+ },
+ "path_in_vcs": ""
+} \ No newline at end of file
diff --git a/Android.bp b/Android.bp
index 7d29959..83c7cf4 100644
--- a/Android.bp
+++ b/Android.bp
@@ -39,10 +39,11 @@ license {
rust_test {
name: "arbitrary_test_src_lib",
+ // has rustc warnings
host_supported: true,
crate_name: "arbitrary",
cargo_env_compat: true,
- cargo_pkg_version: "1.0.2",
+ cargo_pkg_version: "1.1.0",
srcs: ["src/lib.rs"],
test_suites: ["general-tests"],
auto_gen_config: true,
@@ -59,10 +60,11 @@ rust_test {
rust_test {
name: "arbitrary_test_tests_derive",
+ // has rustc warnings
host_supported: true,
crate_name: "arbitrary",
cargo_env_compat: true,
- cargo_pkg_version: "1.0.2",
+ cargo_pkg_version: "1.1.0",
srcs: ["tests/derive.rs"],
test_suites: ["general-tests"],
auto_gen_config: true,
@@ -82,10 +84,11 @@ rust_test {
rust_library_rlib {
name: "libarbitrary",
+ // has rustc warnings
host_supported: true,
crate_name: "arbitrary",
cargo_env_compat: true,
- cargo_pkg_version: "1.0.2",
+ cargo_pkg_version: "1.1.0",
srcs: ["src/lib.rs"],
edition: "2018",
features: [
@@ -93,4 +96,8 @@ rust_library_rlib {
"derive_arbitrary",
],
proc_macros: ["libderive_arbitrary"],
+ apex_available: [
+ "com.android.uwb",
+ ],
+ min_sdk_version: "Tiramisu",
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0484728..2a7c179 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,13 +26,42 @@ Released YYYY-MM-DD.
* TODO (or remove section if none)
+--------------------------------------------------------------------------------
+
+## 1.1.0
+
+Released 2022-02-09.
+
+### Added
+
+* Added the `Unstructured::ratio` method to generate a boolean that is `true` at
+ the given rate.
+
+* Added the `Unstructured::arbitrary_loop` method to call a function an
+ arbitrary number of times.
+
+--------------------------------------------------------------------------------
+
+## 1.0.3
+
+Released 2021-11-20.
+
+### Fixed
+
+* Fixed documentation for `Unstructured::fill_bytes`. We forgot to update this
+ way back in [#53](https://github.com/rust-fuzz/arbitrary/pull/53) when the
+ behavior changed.
+
+--------------------------------------------------------------------------------
+
## 1.0.2
Released 2021-08-25.
### Added
-* `Arbitrary` impls for `HashMap`s and `HashSet`s with custom `Hasher`s [#87](https://github.com/rust-fuzz/arbitrary/pull/87)
+* `Arbitrary` impls for `HashMap`s and `HashSet`s with custom `Hasher`s
+ [#87](https://github.com/rust-fuzz/arbitrary/pull/87)
--------------------------------------------------------------------------------
diff --git a/Cargo.toml b/Cargo.toml
index cc48402..a42a90b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,14 +12,24 @@
[package]
edition = "2018"
name = "arbitrary"
-version = "1.0.2"
-authors = ["The Rust-Fuzz Project Developers", "Nick Fitzgerald <fitzgen@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>", "Simonas Kazlauskas <arbitrary@kazlauskas.me>", "Brian L. Troutwine <brian@troutwine.us>", "Corey Farwell <coreyf@rwell.org>"]
+version = "1.1.0"
+authors = [
+ "The Rust-Fuzz Project Developers",
+ "Nick Fitzgerald <fitzgen@gmail.com>",
+ "Manish Goregaokar <manishsmail@gmail.com>",
+ "Simonas Kazlauskas <arbitrary@kazlauskas.me>",
+ "Brian L. Troutwine <brian@troutwine.us>",
+ "Corey Farwell <coreyf@rwell.org>",
+]
description = "The trait for generating structured data from unstructured data"
documentation = "https://docs.rs/arbitrary/"
readme = "README.md"
-keywords = ["arbitrary", "testing"]
+keywords = [
+ "arbitrary",
+ "testing",
+]
categories = ["development-tools::testing"]
-license = "MIT/Apache-2.0"
+license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-fuzz/arbitrary/"
[[example]]
@@ -30,6 +40,7 @@ required-features = ["derive"]
name = "derive"
path = "./tests/derive.rs"
required-features = ["derive"]
+
[dependencies.derive_arbitrary]
version = "1.0.0"
optional = true
diff --git a/Cargo.toml.orig b/Cargo.toml.orig
index 63787aa..df4e2a1 100644
--- a/Cargo.toml.orig
+++ b/Cargo.toml.orig
@@ -1,6 +1,6 @@
[package]
name = "arbitrary"
-version = "1.0.2" # Make sure this matches the derive crate version
+version = "1.1.0" # Make sure this matches the derive crate version
authors = [
"The Rust-Fuzz Project Developers",
"Nick Fitzgerald <fitzgen@gmail.com>",
@@ -14,7 +14,7 @@ edition = "2018"
keywords = ["arbitrary", "testing"]
readme = "README.md"
description = "The trait for generating structured data from unstructured data"
-license = "MIT/Apache-2.0"
+license = "MIT OR Apache-2.0"
repository = "https://github.com/rust-fuzz/arbitrary/"
documentation = "https://docs.rs/arbitrary/"
diff --git a/METADATA b/METADATA
index 05cf1ce..00cf505 100644
--- a/METADATA
+++ b/METADATA
@@ -7,13 +7,13 @@ third_party {
}
url {
type: ARCHIVE
- value: "https://static.crates.io/crates/arbitrary/arbitrary-1.0.2.crate"
+ value: "https://static.crates.io/crates/arbitrary/arbitrary-1.1.0.crate"
}
- version: "1.0.2"
+ version: "1.1.0"
license_type: NOTICE
last_upgrade_date {
- year: 2021
- month: 9
- day: 22
+ year: 2022
+ month: 3
+ day: 1
}
}
diff --git a/cargo2android.json b/cargo2android.json
index 8c95f8e..47d3147 100644
--- a/cargo2android.json
+++ b/cargo2android.json
@@ -1,8 +1,12 @@
{
+ "apex_available": [
+ "com.android.uwb"
+ ],
"dependencies": true,
"device": true,
"features": "derive",
"force-rlib": true,
+ "min_sdk_version": "Tiramisu",
"run": true,
"tests": true
} \ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index addcf4e..7b791ab 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -99,7 +99,7 @@ use std::sync::{Arc, Mutex};
/// Implementing `Arbitrary` mostly involves nested calls to other `Arbitrary`
/// arbitrary implementations for each of your `struct` or `enum`'s members. But
/// sometimes you need some amount of raw data, or you need to generate a
-/// variably-sized collection type, or you something of that sort. The
+/// variably-sized collection type, or something of that sort. The
/// [`Unstructured`][crate::Unstructured] type helps you with these tasks.
///
/// ```
diff --git a/src/unstructured.rs b/src/unstructured.rs
index 968d41a..ff3e1f3 100644
--- a/src/unstructured.rs
+++ b/src/unstructured.rs
@@ -10,6 +10,7 @@
use crate::{Arbitrary, Error, Result};
use std::marker::PhantomData;
+use std::ops::ControlFlow;
use std::{mem, ops};
/// A source of unstructured data.
@@ -382,6 +383,41 @@ impl<'a> Unstructured<'a> {
Ok(&choices[idx])
}
+ /// Generate a boolean according to the given ratio.
+ ///
+ /// # Panics
+ ///
+ /// Panics when the numerator and denominator do not meet these constraints:
+ ///
+ /// * `0 < numerator <= denominator`
+ ///
+ /// # Example
+ ///
+ /// Generate a boolean that is `true` five sevenths of the time:
+ ///
+ /// ```
+ /// # fn foo() -> arbitrary::Result<()> {
+ /// use arbitrary::Unstructured;
+ ///
+ /// # let my_data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
+ /// let mut u = Unstructured::new(&my_data);
+ ///
+ /// if u.ratio(5, 7)? {
+ /// // Take this branch 5/7 of the time.
+ /// }
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn ratio<T>(&mut self, numerator: T, denominator: T) -> Result<bool>
+ where
+ T: Int,
+ {
+ assert!(T::ZERO < numerator);
+ assert!(numerator <= denominator);
+ let x = self.int_in_range(T::ONE..=denominator)?;
+ Ok(x <= numerator)
+ }
+
/// Fill a `buffer` with bytes from the underlying raw data.
///
/// This should only be called within an `Arbitrary` implementation. This is
@@ -389,8 +425,8 @@ impl<'a> Unstructured<'a> {
/// `Arbitrary` implementations like `<Vec<u8>>::arbitrary` and
/// `String::arbitrary` over using this method directly.
///
- /// If this `Unstructured` does not have enough data to fill the whole
- /// `buffer`, an error is returned.
+ /// If this `Unstructured` does not have enough underlying data to fill the
+ /// whole `buffer`, it pads the buffer out with zeros.
///
/// # Example
///
@@ -400,8 +436,15 @@ impl<'a> Unstructured<'a> {
/// let mut u = Unstructured::new(&[1, 2, 3, 4]);
///
/// let mut buf = [0; 2];
+ ///
+ /// assert!(u.fill_buffer(&mut buf).is_ok());
+ /// assert_eq!(buf, [1, 2]);
+ ///
/// assert!(u.fill_buffer(&mut buf).is_ok());
+ /// assert_eq!(buf, [3, 4]);
+ ///
/// assert!(u.fill_buffer(&mut buf).is_ok());
+ /// assert_eq!(buf, [0, 0]);
/// ```
pub fn fill_buffer(&mut self, buffer: &mut [u8]) -> Result<()> {
let n = std::cmp::min(buffer.len(), self.data.len());
@@ -516,6 +559,100 @@ impl<'a> Unstructured<'a> {
_marker: PhantomData,
})
}
+
+ /// Call the given function an arbitrary number of times.
+ ///
+ /// The function is given this `Unstructured` so that it can continue to
+ /// generate arbitrary data and structures.
+ ///
+ /// You may optionaly specify minimum and maximum bounds on the number of
+ /// times the function is called.
+ ///
+ /// You may break out of the loop early by returning
+ /// `Ok(std::ops::ControlFlow::Break)`. To continue the loop, return
+ /// `Ok(std::ops::ControlFlow::Continue)`.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `min > max`.
+ ///
+ /// # Example
+ ///
+ /// Call a closure that generates an arbitrary type inside a context an
+ /// arbitrary number of times:
+ ///
+ /// ```
+ /// use arbitrary::{Result, Unstructured};
+ /// use std::ops::ControlFlow;
+ ///
+ /// enum Type {
+ /// /// A boolean type.
+ /// Bool,
+ ///
+ /// /// An integer type.
+ /// Int,
+ ///
+ /// /// A list of the `i`th type in this type's context.
+ /// List(usize),
+ /// }
+ ///
+ /// fn arbitrary_types_context(u: &mut Unstructured) -> Result<Vec<Type>> {
+ /// let mut context = vec![];
+ ///
+ /// u.arbitrary_loop(Some(10), Some(20), |u| {
+ /// let num_choices = if context.is_empty() {
+ /// 2
+ /// } else {
+ /// 3
+ /// };
+ /// let ty = match u.int_in_range::<u8>(1..=num_choices)? {
+ /// 1 => Type::Bool,
+ /// 2 => Type::Int,
+ /// 3 => Type::List(u.int_in_range(0..=context.len() - 1)?),
+ /// _ => unreachable!(),
+ /// };
+ /// context.push(ty);
+ /// Ok(ControlFlow::Continue(()))
+ /// })?;
+ ///
+ /// // The number of loop iterations are constrained by the min/max
+ /// // bounds that we provided.
+ /// assert!(context.len() >= 10);
+ /// assert!(context.len() <= 20);
+ ///
+ /// Ok(context)
+ /// }
+ /// ```
+ pub fn arbitrary_loop(
+ &mut self,
+ min: Option<u32>,
+ max: Option<u32>,
+ mut f: impl FnMut(&mut Self) -> Result<ControlFlow<(), ()>>,
+ ) -> Result<()> {
+ let min = min.unwrap_or(0);
+ let max = max.unwrap_or(u32::MAX);
+ assert!(min <= max);
+
+ for _ in 0..min {
+ match f(self)? {
+ ControlFlow::Continue(_) => continue,
+ ControlFlow::Break(_) => return Ok(()),
+ }
+ }
+
+ for _ in 0..(max - min) {
+ let keep_going = self.arbitrary().unwrap_or(false);
+ if !keep_going {
+ break;
+ }
+ match f(self)? {
+ ControlFlow::Continue(_) => continue,
+ ControlFlow::Break(_) => break,
+ }
+ }
+
+ Ok(())
+ }
}
/// Utility iterator produced by [`Unstructured::arbitrary_iter`]
diff --git a/tests/derive.rs b/tests/derive.rs
index 9dfbbd5..adf1188 100644..100755
--- a/tests/derive.rs
+++ b/tests/derive.rs
@@ -164,7 +164,7 @@ fn one_lifetime() {
assert_eq!("abc", lifetime.alpha);
let (lower, upper) = <OneLifetime as Arbitrary>::size_hint(0);
- assert_eq!(lower, 8);
+ assert_eq!(lower, std::mem::size_of::<usize>());
assert_eq!(upper, None);
}
@@ -183,6 +183,6 @@ fn two_lifetimes() {
assert_eq!("def", lifetime.beta);
let (lower, upper) = <TwoLifetimes as Arbitrary>::size_hint(0);
- assert_eq!(lower, 16);
+ assert_eq!(lower, std::mem::size_of::<usize>() * 2);
assert_eq!(upper, None);
}