Skip to content

Commit

Permalink
impl Arbitrary for IndexMap and IndexSet
Browse files Browse the repository at this point in the history
This implements both `arbitrary::Arbitrary` and `quickcheck::Arbitrary`
behind optional dependencies on their respective crates.

(cherry picked from commit 3e78c62)
  • Loading branch information
cuviper committed Nov 17, 2022
1 parent fe98ec2 commit 2251812
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 2 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,15 @@ jobs:
- rust: 1.56.0 # MSRV
features:
- rust: stable
features: serde
features: arbitrary
- rust: stable
features: quickcheck
- rust: stable
features: rayon
- rust: stable
features: rustc-rayon
- rust: stable
features: serde
- rust: stable
features: std
- rust: beta
Expand Down
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ bench = false
autocfg = "1"

[dependencies]
arbitrary = { version = "1.0", optional = true, default-features = false }
quickcheck = { version = "1.0", optional = true, default-features = false }
serde = { version = "1.0", optional = true, default-features = false }
rayon = { version = "1.4.1", optional = true }

Expand Down Expand Up @@ -57,7 +59,7 @@ no-dev-version = true
tag-name = "{{version}}"

[package.metadata.docs.rs]
features = ["serde-1", "rayon"]
features = ["arbitrary", "quickcheck", "serde-1", "rayon"]

[workspace]
members = ["test-nostd", "test-serde"]
75 changes: 75 additions & 0 deletions src/arbitrary.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#[cfg(feature = "arbitrary")]
mod impl_arbitrary {
use crate::{IndexMap, IndexSet};
use arbitrary::{Arbitrary, Result, Unstructured};
use core::hash::{BuildHasher, Hash};

impl<'a, K, V, S> Arbitrary<'a> for IndexMap<K, V, S>
where
K: Arbitrary<'a> + Hash + Eq,
V: Arbitrary<'a>,
S: BuildHasher + Default,
{
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
u.arbitrary_iter()?.collect()
}

fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self> {
u.arbitrary_take_rest_iter()?.collect()
}
}

impl<'a, T, S> Arbitrary<'a> for IndexSet<T, S>
where
T: Arbitrary<'a> + Hash + Eq,
S: BuildHasher + Default,
{
fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
u.arbitrary_iter()?.collect()
}

fn arbitrary_take_rest(u: Unstructured<'a>) -> Result<Self> {
u.arbitrary_take_rest_iter()?.collect()
}
}
}

#[cfg(feature = "quickcheck")]
mod impl_quickcheck {
use crate::{IndexMap, IndexSet};
use alloc::boxed::Box;
use alloc::vec::Vec;
use core::hash::{BuildHasher, Hash};
use quickcheck::{Arbitrary, Gen};

impl<K, V, S> Arbitrary for IndexMap<K, V, S>
where
K: Arbitrary + Hash + Eq,
V: Arbitrary,
S: BuildHasher + Default + Clone + 'static,
{
fn arbitrary(g: &mut Gen) -> Self {
Self::from_iter(Vec::arbitrary(g))
}

fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
let vec = Vec::from_iter(self.clone());
Box::new(vec.shrink().map(Self::from_iter))
}
}

impl<T, S> Arbitrary for IndexSet<T, S>
where
T: Arbitrary + Hash + Eq,
S: BuildHasher + Default + Clone + 'static,
{
fn arbitrary(g: &mut Gen) -> Self {
Self::from_iter(Vec::arbitrary(g))
}

fn shrink(&self) -> Box<dyn Iterator<Item = Self>> {
let vec = Vec::from_iter(self.clone());
Box::new(vec.shrink().map(Self::from_iter))
}
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ extern crate std;

use alloc::vec::{self, Vec};

mod arbitrary;
#[macro_use]
mod macros;
mod equivalent;
Expand Down

0 comments on commit 2251812

Please sign in to comment.