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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
/*!
# The `#[derive(Mutate)]` Macro
The `#[derive(Mutate)]` macro is only available when the `derive` cargo feature
is enabled:
```toml
[dependencies]
mutatis = { version = "...", features = ["derive"] }
```
Once the `derive` feature is enabled, you can put `#[derive(Mutate)]` on top of
your `struct` and `enum` definitions. It supports unit-, tuple-, and
named-field-styles of `struct`s and `enum` variants. You cannot derive a mutator
for `union`s.
```rust
# fn foo() -> mutatis::Result<()> {
# #![cfg(feature = "derive")]
use mutatis::Mutate;
#[derive(Mutate)]
pub struct Hero {
needed: bool,
deserved: bool,
armor: Option<u32>,
}
# Ok(())
# }
# #[cfg(feature = "derive")] foo().unwrap();
```
The derive macro generates the following:
### A `HeroMutator` type
```rust
# use mutatis::DefaultMutate;
// A mutator for `Hero` values.
pub struct HeroMutator<
MutatorT0 = <bool as DefaultMutate>::DefaultMutate,
MutatorT1 = <bool as DefaultMutate>::DefaultMutate,
MutatorT2 = <Option<u32> as DefaultMutate>::DefaultMutate,
> {
# _priv: (MutatorT0, MutatorT1, MutatorT2),
// ...
}
```
The name of the generated type can be customized with the `mutator_name`
attribute. See the "Container Attributes" section below.
The generated mutator type has the same visibility (`pub`, `pub(crate)`, etc...)
as the original type.
You can customize the documentation comment for the generated mutator type with
the `#[mutatis(mutator_doc = "...")]` attribute. See the "Container Attributes"
section below.
The generated mutator has a generic type parameter for each field in the
`struct`, or each field in each variant of the `enum`. These generic type
parameters control how their associated field is mutated. The exception being
any fields marked with `#[mutatis(ignore)]`, whose associated fields are never
mutated, or any fields marked with `#[mutatis(default_mutator)]`, which will
always use the default mutator. See the "Field Attributes" section below for
more details.
Each generic type parameter defaults to the default mutator of its associated
field's type, unless the `enum`/`struct` is annotated with
`#[mutatis(default_mutate = false)]`.
### A `Mutate<Hero> for HeroMutator` implementation
```rust
# struct Hero { }
# struct HeroMutator<MutatorT0, MutatorT1, MutatorT2> { _priv: (MutatorT0, MutatorT1, MutatorT2) }
# trait Mutate<X> {}
impl<MutatorT0, MutatorT1, MutatorT2> Mutate<Hero>
for HeroMutator<MutatorT0, MutatorT1, MutatorT2>
where
MutatorT0: Mutate<bool>,
MutatorT1: Mutate<bool>,
MutatorT2: Mutate<Option<u32>>,
{
// ...
}
```
### A `HeroMutator::new` constructor
```rust,no_run
# struct HeroMutator<MutatorT0, MutatorT1, MutatorT2> { _priv: (MutatorT0, MutatorT1, MutatorT2) }
impl<MutatorT0, MutatorT1, MutatorT2> HeroMutator<MutatorT0, MutatorT1, MutatorT2> {
pub fn new(needed: MutatorT0, deserved: MutatorT1, armor: MutatorT2) -> Self {
# todo!()
// ...
}
}
```
This constructor takes a parameter for each of the mutator type's generic type
parameters.
Any mutator you pass into the constructor will be used whenever the mutator is
mutating the associated field. For example, if we always wanted
`armor.is_some()`, then we could do the following:
```rust,no_run
use mutatis::mutators as m;
# struct HeroMutator<MutatorT0, MutatorT1, MutatorT2> { _priv: (MutatorT0, MutatorT1, MutatorT2) }
# impl<MutatorT0, MutatorT1, MutatorT2> HeroMutator<MutatorT0, MutatorT1, MutatorT2> {
# pub fn new(needed: MutatorT0, deserved: MutatorT1, armor: MutatorT2) -> Self { todo!() }
# }
// Create a `HeroMutator` that mutates `Hero`s such that they always have
// some armor.
let mut mutator = HeroMutator::new(m::bool(), m::bool(), m::some(m::u32()));
```
### A `Default for HeroMutator` implementation
```rust
# struct HeroMutator<MutatorT0, MutatorT1, MutatorT2> { _priv: (MutatorT0, MutatorT1, MutatorT2) }
impl<MutatorT0, MutatorT1, MutatorT2> Default for HeroMutator<MutatorT0, MutatorT1, MutatorT2> {
fn default() -> Self {
# todo!()
// ...
}
}
```
This is omitted if the `#[mutatis(default_mutate = false)]` attribute is
present on the container. See the "Container Attributes" section below for
more details.
### A `Generate<Hero> for HeroMutator` implementation
```rust
# struct Hero { }
# struct HeroMutator<MutatorT0, MutatorT1, MutatorT2> { _priv: (MutatorT0, MutatorT1, MutatorT2) }
# trait Generate<X> {}
impl<MutatorT0, MutatorT1, MutatorT2> Generate<Hero>
for HeroMutator<MutatorT0, MutatorT1, MutatorT2>
where
MutatorT0: Generate<bool>,
MutatorT1: Generate<bool>,
MutatorT2: Generate<Option<u32>>,
{
// ...
}
```
For `struct`s, the generated `Generate` implementation calls each field
mutator's `generate` method to produce the field values.
For `enum`s, it randomly selects a variant and then calls each of that
variant's field mutators' `generate` methods to produce the payloads.
This is omitted if the `#[mutatis(generate = false)]` attribute is present on
the container. See the "Container Attributes" section below for more details.
## Container Attributes
The `#[derive(Mutate)]` macro supports the following attributes on `struct`s
and `enum`s:
### `#[mutatis(mutator_name = MyCoolName)]`
Generate a mutator type named `MyCoolName` instead of appending `Mutator` to the
input type's name.
```rust
# fn foo() -> mutatis::Result<()> {
# #![cfg(feature = "derive")]
use mutatis::{mutators as m, Mutate};
#[derive(Mutate)]
#[mutatis(mutator_name = TheMutatorForFoo)]
pub struct Foo(u32);
let mut mutator = TheMutatorForFoo::new(m::just(5));
# Ok(())
# }
# #[cfg(feature = "derive")] foo().unwrap();
```
### `#[mutatis(mutator_doc = "my documentation")]`
Generate a custom doc comment for the generated mutator type. This may be
repeated multiple times. The resulting doc comment is a concatenation of all
occurrences.
```rust
# fn foo() -> mutatis::Result<()> {
# #![cfg(feature = "derive")]
use mutatis::Mutate;
#[derive(Mutate)]
#[mutatis(mutator_doc = r###"
This is a mutator for `Foo` values.
You can use with with the `mutatis` crate and its combinators to perform
pseudo-random mutations on `Foo` values.
Etc...
"###)]
pub struct Foo(u32);
# Ok(())
# }
# #[cfg(feature = "derive")] foo().unwrap();
```
### `#[mutatis(default_mutate = false)]`
Do not implement the `DefaultMutate` trait for the generated mutator type.
This is useful if the container type contains a field whose type does not
implement `DefaultMutate`, or you want to customize the `DefaultMutate`
implementation yourself.
```rust
# fn foo() -> mutatis::Result<()> {
# #![cfg(feature = "derive")]
use mutatis::{mutators as m, DefaultMutate, Mutate};
#[derive(Default, Mutate)]
#[mutatis(default_mutate = false)]
pub struct Foo(u32);
// Implement `DefaultMutate` ourselves with a particular sub-mutator, rather
// than the default mutator for `u32`.
impl DefaultMutate for Foo {
type DefaultMutate = FooMutator<m::Just<u32>>;
}
# Ok(())
# }
# #[cfg(feature = "derive")] foo().unwrap();
```
### `#[mutatis(generate = false)]`
Do not implement the `Generate` trait for the generated mutator type.
This is useful if you want to provide your own `Generate` implementation, or
if the type contains fields whose types cannot be generated from scratch
(for example, fields with reference types that are marked `#[mutatis(ignore)]`).
```rust
# fn foo() -> mutatis::Result<()> {
# #![cfg(feature = "derive")]
use mutatis::{Context, Generate, Mutate};
#[derive(Debug, Default, Mutate)]
#[mutatis(generate = false)]
pub struct Foo(u32);
// Implement `Generate` ourselves.
impl<M> Generate<Foo> for FooMutator<M>
where
M: Mutate<u32>,
{
fn generate(&mut self, cx: &mut Context) -> mutatis::Result<Foo> {
// Never generate values with the bottom bit set, for some reason.
let x = cx.rng().gen_u32();
let mask = !1;
let masked = x & mask;
Ok(Foo(masked))
}
}
# Ok(())
# }
# #[cfg(feature = "derive")] foo().unwrap();
```
## Field Attributes
The `#[derive(Mutate)]` macro suports the following attributes on fields within
`struct`s and `enum` variants:
### `#[mutatis(ignore)]`
Do not mutate this field. Do not generate a generic type parameter on the
mutator for it, nor an argument in the mutator's constructor for it.
```rust
# fn foo() -> mutatis::Result<()> {
# #![cfg(feature = "derive")]
use mutatis::{Mutate, Session};
#[derive(Clone, Default, Mutate)]
struct MyStruct {
x: u64,
#[mutatis(ignore)]
y: u64,
}
let mut session = Session::new();
let orig = MyStruct::default();
let mut value = orig.clone();
for _ in 0..100 {
session.mutate(&mut value)?;
assert_eq!(orig.y, value.y);
}
# Ok(())
# }
# #[cfg(feature = "derive")] foo().unwrap();
```
### `#[mutatis(default_mutate)]`
Always use this field's type's `DefaultMutate` implementation to mutate this
field. Do not generate a generic type parameter or argument to the generated
mutator's constructor for mutating this field.
```rust
# fn foo() -> mutatis::Result<()> {
# #![cfg(feature = "derive")]
use mutatis::{mutators as m, Mutate, Session};
#[derive(Debug, Default, Mutate)]
struct MyStruct {
x: u64,
#[mutatis(default_mutate)]
y: u64,
}
let mut session = Session::new();
// Only an `x` mutator argument because `y` always uses the default mutator.
let mut mutator = MyStructMutator::new(m::mrange(10..=19));
let mut value = MyStruct::default();
session.mutate_with(&mut mutator, &mut value)?;
# Ok(())
# }
# #[cfg(feature = "derive")] foo().unwrap();
```
*/