surprise_me/
surprise.rs

1use rand::{prelude::Distribution, Rng};
2
3/// Trait to generate random instances of types.
4///
5/// # Derive macro
6///
7/// The macro has two jobs:
8/// - Create a [`SurpriseFactor`] (unless one is already specified, see recursive types)
9/// - Implement [`Surprise`] with that surprise factor
10///
11/// Types themselves can be annotated with `#[factor = "MySurpriseFactor"]` in which
12/// case the macro won't create a new type and instead use the specified name as [`SurpriseFactor`].
13///
14/// ## On structs
15///
16/// Fields can be annotated with:
17/// - `#[factor(field = ...)]` or `#[factor(field(...))]`: These attributes modify the
18/// default values for the surprise factor. `field` can be the name of any field
19/// of the type's [`SurpriseFactor`]. Note that this works recursively for inner fields.
20/// - `#[factor = "MySurpriseFactor"]`: Same as for the outer struct; specifying a factor
21/// like this will prevent the macro from creating a new type.
22///
23/// ```rust
24/// # use surprise_me::Surprise;
25/// #
26/// #[derive(Surprise)]
27/// pub(crate) struct MyStruct {
28///     // at most 5 elements
29///     #[factor(max_len = 5)]
30///     // 30% chance of being `Some` containing a value between 10 and 20
31///     #[factor(items(chance = 0.3, inner(min = 10, max = 20)))]
32///     my_field: Vec<Option<u32>>,
33/// }
34///
35/// #[derive(Surprise)]
36/// struct MyWrapper(
37///     // same defaults except the minimum length is now 2
38///     #[factor(my_field(min_len = 2))]
39///     MyStruct
40/// );
41/// ```
42///
43/// In order to use attributes recursively, it helps to understand what the
44/// generated surprise factor looks like:
45///
46/// ```rust
47/// # use surprise_me::factors::{NumberSurprise, OptionSurprise, VecSurprise};
48/// #
49/// pub(crate) struct MyStructSurprise {
50///     pub my_field: VecSurprise<Option<u32>>
51/// }
52///
53/// impl Default for MyStructSurprise {
54///     fn default() -> Self {
55///         Self {
56///             my_field: VecSurprise {
57///                 max_len: 5,
58///                 items: OptionSurprise {
59///                     chance: 0.3,
60///                     inner: NumberSurprise {
61///                         min: 10,
62///                         max: 20,
63///                     },
64///                 },
65///                 min_len: Default::default(),
66///             }
67///         }
68///     }
69/// }
70///
71/// struct MyWrapperSurprise(pub MyStructSurprise);
72///
73/// impl Default for MyWrapperSurprise {
74///     fn default() -> Self {
75///         let mut inner = MyStructSurprise::default();
76///         inner.my_field.min_len = 2;
77///
78///         Self(inner)
79///     }
80/// }
81/// ```
82///
83/// ## On enums
84///
85/// Variants can be annotated with `#[weight = number]` to specify how
86/// likely it is for one variant to be generated compared to other variants.
87/// For example, a variant with weight 2 is 50% less likely to appear than
88/// one with weight 3.
89///
90/// If no variant has a specified weight, all variants have a weight of 1.
91/// If at least one variant has a specified weight, all other variants that
92/// don't have a specified weight will have a weight of 0.
93///
94/// Fields of variants have the same attributes as fields for structs, i.e.
95/// - `#[factor(field = ...)]` or `#[factor(field(...))]`
96/// - `#[factor = "MySurpriseFactor")]`
97///
98/// ```rust
99/// # use surprise_me::Surprise;
100/// #
101/// #[derive(Surprise)]
102/// enum MyEnum {
103///     #[weight = 5]
104///     A(#[factor(max_len = 3)] Vec<u8>),
105///     #[weight = 1.5]
106///     B,
107///     // no specified weight means a weight of 0 in this case
108///     C {
109///         #[factor(chance = 0.9)]
110///         my_bool: bool,
111///         another_field: i32,
112///     }
113/// }
114/// ```
115///
116/// The surprise factor for this enums will look as follows:
117///
118/// ```rust
119/// # use surprise_me::factors::{BoolSurprise, NumberSurprise, VecSurprise};
120/// #
121/// struct MyEnumSurprise {
122///     variants_weight: Box<[f64; 3]>,
123///     A: (VecSurprise<u8>,),
124///     // no field `B` because it's a unit variant
125///     C: (BoolSurprise, NumberSurprise<i32>),
126/// }
127///
128/// impl Default for MyEnumSurprise {
129///     fn default() -> Self {
130///         Self {
131///             variants_weight: Box::new([5.0, 1.5, 0.0]),
132///             A: (
133///                 VecSurprise {
134///                     max_len: 3,
135///                     ..Default::default()
136///                 },
137///             ),
138///             C: (
139///                 BoolSurprise { chance: 0.9 },
140///                 NumberSurprise::default(),
141///             ),
142///         }
143///     }
144/// }
145/// ```
146///
147/// # Recursive types
148///
149/// In case of recursive types, a custom surprise factor is required.
150///
151/// ```rust
152/// use surprise_me::{Distribution, Rng, Surprise};
153/// use surprise_me::factors::{OptionSurprise, VecSurprise};
154///
155/// #[derive(Surprise)]
156/// // Instead of creating a new surprise factor, use the specified one.
157/// #[factor = "RecursedSurprise"]
158/// struct MyStruct {
159///     my_vec: Vec<MyStruct>,
160///     my_opt: Option<Box<MyStruct>>,
161/// }
162///
163/// struct RecursedSurprise {
164///     depth: usize,
165///     min_len: usize,
166/// }
167///
168/// // Surprise factors are required to implement `surprise_me::Distribution`
169/// impl Distribution<MyStruct> for RecursedSurprise {
170///     fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> MyStruct {
171///         // Once a certain depth is reached, don't nest any further.
172///         if self.depth == 5 {
173///             MyStruct {
174///                 my_vec: Vec::new(),
175///                 my_opt: None,
176///             }
177///         } else {
178///             // Otherwise create the inner surprise factors.
179///             // And be sure to update the depth!
180///             let vec_factor = VecSurprise {
181///                 min_len: self.min_len,
182///                 max_len: 8, // can also be hardcoded here instead of a field
183///                 items: RecursedSurprise { depth: self.depth + 1, min_len: self.min_len },
184///             };
185///
186///             let mut opt_factor = OptionSurprise::<Box<MyStruct>>::default();
187///             opt_factor.chance = 0.42;
188///             // `OptionSurprise::inner` -> `BoxSurprise::inner` -> `RecursedSurprise::depth`
189///             opt_factor.inner.inner.depth = self.depth + 1;
190///
191///             MyStruct {
192///                 my_vec: Surprise::generate_with_factor(rng, &vec_factor),
193///                 my_opt: Surprise::generate_with_factor(rng, &opt_factor),
194///             }
195///         }
196///     }
197/// }
198///
199/// impl Default for RecursedSurprise {
200///     fn default() -> Self {
201///         Self {
202///             depth: 0,
203///             min_len: 3,
204///         }
205///     }
206/// }
207/// ```
208pub trait Surprise: Sized {
209    /// Surprise factor that guides the random generation.
210    type Factor: Distribution<Self>;
211
212    /// Generate a random instance of the type by using a default surprise factor.
213    #[inline]
214    fn generate<R>(rng: &mut R) -> Self
215    where
216        R: Rng + ?Sized,
217        SurpriseFactor<Self>: Default,
218    {
219        let factor = SurpriseFactor::<Self>::default();
220
221        <Self as Surprise>::generate_with_factor(rng, &factor)
222    }
223
224    /// Generate a random instance of the type by using the given surprise factor.
225    #[inline]
226    fn generate_with_factor<R, F>(rng: &mut R, factor: &F) -> Self
227    where
228        R: Rng + ?Sized,
229        F: Distribution<Self>,
230    {
231        rng.sample(factor)
232    }
233}
234
235/// The surprise factor on which the random generation of `T` depends on.
236///
237/// For example, the surprise factor [`VecSurprise`] dictates
238/// the minimum and maximum length of a [`Vec`], as well as the surprise factor for the
239/// items themselves.
240///
241/// [`VecSurprise`]: crate::factors::VecSurprise
242pub type SurpriseFactor<T> = <T as Surprise>::Factor;