# DieOnce and Die
Although [`Prng`] can only generate pseudorandom `u64`s, the `u64`s can be used for constructing
more complex values. The traits [`DieOnce`] and [`Die`] represent [`Prng`]-based generators for
values of any type.
An implementor of [`DieOnce`] is a generator that can be used a single time
(similar to [`FnOnce`]).
```rust
use dicetest::prelude::*;
let xx = "xx".to_string();
let yy = "yy".to_string();
// This generator implements `DieOnce`.
// It chooses one of the `String`s without cloning them.
let xx_or_yy_die = dice::one_of_once().two(xx, yy);
```
An implementor of [`Die`] is a generator that can be used an infinite number of
times (similar to [`Fn`]).
```rust
use dicetest::prelude::*;
let xx = "xx".to_string();
let yy = "yy".to_string();
// This generator implements `Die`.
// It chooses one of the `String`s by cloning them.
let xx_or_yy_die = dice::one_of().two(xx, yy);
// This generator uses `xx_or_yy_die` to generate three `String`s at once.
let three_xx_or_yy_die = dice::array::<_, _, 3>(xx_or_yy_die);
```
Generators can be easily implemented and composed:
```rust
use dicetest::prelude::*;
// A classic die that generates a number between 1 and 6 with uniform distribution.
let classic_die = dice::one_of().six::<u8>(1, 2, 3, 4, 5, 6);
// A loaded die that generates the number 6 more frequently.
let loaded_die =
dice::weighted_one_of().six::<u8>((1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (2, 6));
// This die generates the result of the function.
let foo_die = dice::just("foo".to_string());
// This die generates an arbitrary byte.
let byte_die = dice::u8(..);
// This die generates a non-zero byte.
let non_zero_byte_die = dice::u8(1..);
// This die generates a `Vec` that contains an arbitrary number of arbitrary bytes.
let bytes_die = dice::vec(dice::u8(..), ..);
// This die generates a `Vec` that contains up to 10 arbitrary bytes.
let up_to_ten_bytes_die = dice::vec(dice::u8(..), ..=10);
// This die generates an arbitrary wrapped byte.
struct WrappedByte(u8);
let wrapped_byte_die = dice::u8(..).map(WrappedByte);
// This die generates a permutation of `(0..=n)` for an arbitrary `n`.
dice::shuffled_vec(vec)
});
```
The struct [`Fate`] is necessary for using [`DieOnce`] or [`Die`]. It contains two parameters:
- [`Prng`]: Provides the pseudorandom `u64`s that the implementor of [`DieOnce`] or [`Die`] can use
for constructing more complex values. The implementor should only use this as its source of
randomness.
- [`Limit`]: The upper limit for the length of dynamic data structures generated by the
implementor of [`DieOnce`] or [`Die`]. The implementor is allowed to freely interpret or even
ignore this value.
```rust
use dicetest::prelude::*;
use dicetest::{Limit, Prng};
// Provides the randomness for the generator and will be mutated when used.
let mut prng = Prng::from_seed(0x5EED.into());
// Limits the length of dynamic data structures. The generator has only read access.
let limit = Limit(5);
// Contains all parameters necessary for using `DieOnce` or `Die`.
let mut fate = Fate::new(&mut prng, limit);
// Generator for a `Vec` with an arbitrary length.
let vec_die = dice::vec(dice::u8(..), ..);
// Generates a `Vec`. Although `vec_die` can generate a `Vec` with an arbitrary length,
// the length of the actual `Vec` is limited by `limit`.
let vec = fate.roll(vec_die);
assert!(vec.len() <= 5);
println!("{:?}", vec);
// Output: [252, 231, 153, 0]
```
[`DieOnce`]: https://docs.rs/dicetest/latest/dicetest/trait.DieOnce.html
[`Die`]: https://docs.rs/dicetest/latest/dicetest/trait.Die.html
[`Fate`]: https://docs.rs/dicetest/latest/dicetest/struct.Fate.html
[`FnOnce`]: https://doc.rust-lang.org/std/ops/trait.FnOnce.html
[`Fn`]: https://doc.rust-lang.org/std/ops/trait.Fn.html
[`Limit`]: https://docs.rs/dicetest/latest/dicetest/struct.Limit.html
[`Prng`]: https://docs.rs/dicetest/latest/dicetest/struct.Prng.html