1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use crate::{
SAMPLES,
generate::Generate,
shrink::{Shrink, Shrinkers},
state::{self, Modes, Sizes, State},
};
use core::iter;
/// Configures the sampling process.
///
/// This struct is created by the [`Sample::sampler`] method and provides a
/// builder-like interface for configuring how values are sampled.
#[derive(Debug, Clone)]
pub struct Sampler<G: ?Sized> {
/// The seed for the random number generator.
///
/// Using the same seed will cause the sampler to produce the same sequence
/// of random values. It defaults to a random value.
pub seed: u64,
/// The range of sizes (`0.0..=1.0`) that will be gradually traversed while
/// generating values.
///
/// Defaults to `0.0..=1.0`.
pub sizes: Sizes,
/// The number of samples to generate.
///
/// Defaults to `SAMPLES`.
pub count: usize,
/// The generator that will provide the samples.
pub generator: G,
}
/// An iterator that yields random values from a generator.
///
/// This struct is created by the [`Sample::samples`] method.
#[derive(Debug, Clone)]
pub struct Samples<G: ?Sized>(Shrinkers<G>);
/// An extension trait, implemented for all [`Generate`] types, that provides
/// methods for sampling random values.
pub trait Sample: Generate {
/// Creates a [`Sampler`] for this generator.
///
/// The `Sampler` can be used to configure and control the sampling process.
fn sampler(self) -> Sampler<Self>
where
Self: Sized,
{
Sampler::new(self, state::seed())
}
/// Creates an iterator that generates `count` random values.
///
/// The generated values will have progressively larger sizes. For more
/// control over the sampling process, see [`Sample::sampler`].
fn samples(self, count: usize) -> Samples<Self>
where
Self: Sized,
{
let mut sampler = self.sampler();
sampler.count = count;
sampler.samples()
}
/// Generates a single random value of a specific `size`.
///
/// The `size` should be between `0.0` and `1.0`. For more control over the
/// sampling process, see [`Sample::sampler`].
fn sample(&self, size: f64) -> Self::Item {
self.sampler().sample(size)
}
}
impl<G: Generate + ?Sized> Sample for G {}
impl<G> Sampler<G> {
pub(crate) const fn new(generator: G, seed: u64) -> Self {
Self {
generator,
seed,
sizes: Sizes::DEFAULT,
count: SAMPLES,
}
}
}
impl<G: Generate + ?Sized> Sampler<G> {
pub fn sample(&self, size: f64) -> G::Item {
let mut state = State::random(0, 1, size.into(), self.seed);
self.generator.generate(&mut state).item()
}
}
impl<G: Generate> Sampler<G> {
pub fn samples(self) -> Samples<G> {
let cardinality = self.generator.cardinality();
Samples::new(
self.generator,
Modes::with(self.count, self.sizes, self.seed, cardinality, Some(false)),
)
}
}
impl<G: Generate> Samples<G> {
pub(crate) fn new(generator: G, modes: Modes) -> Self {
Self(Shrinkers::new(generator, modes))
}
}
impl<G: Generate> Iterator for Samples<G> {
type Item = G::Item;
fn next(&mut self) -> Option<Self::Item> {
Some(self.0.next()?.item())
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
fn count(self) -> usize {
self.0.count()
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
Some(self.0.nth(n)?.item())
}
fn last(self) -> Option<Self::Item> {
Some(self.0.last()?.item())
}
}
impl<G: Generate> DoubleEndedIterator for Samples<G> {
fn next_back(&mut self) -> Option<Self::Item> {
Some(self.0.next_back()?.item())
}
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
Some(self.0.nth_back(n)?.item())
}
}
impl<G: Generate> ExactSizeIterator for Samples<G> {
fn len(&self) -> usize {
self.0.len()
}
}
impl<G: Generate> iter::FusedIterator for Samples<G> {}