aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Cargo.toml19
-rw-r--r--lib/src/lib.rs130
2 files changed, 149 insertions, 0 deletions
diff --git a/lib/Cargo.toml b/lib/Cargo.toml
new file mode 100644
index 0000000..8050d42
--- /dev/null
+++ b/lib/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "generate-random"
+version = "0.1.0"
+edition = "2021"
+license = "MIT OR Apache-2.0"
+authors = ["Alexander van Ratingen"]
+homepage = "https://github.com/alvra/generate-random"
+repository = "https://github.com/alvra/generate-random"
+documentation = "https://docs.rs/generate-random"
+description = "Generate random data"
+readme = "README.md"
+keywords = ["random"]
+
+[dependencies]
+rand = "0.8.5"
+generate-random-macro = { path = "../derive-macro" }
+
+[dev-dependencies]
+rand_chacha = "0.3.1"
diff --git a/lib/src/lib.rs b/lib/src/lib.rs
new file mode 100644
index 0000000..40f02e9
--- /dev/null
+++ b/lib/src/lib.rs
@@ -0,0 +1,130 @@
+//! Generate random data.
+//!
+//! # Examples
+//!
+//! ```
+//! use generate_random::GenerateRandom;
+//!
+//! #[derive(GenerateRandom)]
+//! enum MyEnum {
+//! A,
+//! C(bool),
+//! B {
+//! x: u8,
+//! },
+//! // Providing a weight allows changing the probabilities.
+//! // This variant is now twice as likely to be generated as the others.
+//! #[weight(2)]
+//! D,
+//! }
+//!
+//! let mut rng = rand::thread_rng();
+//! let my_value = MyEnum::generate_random(&mut rng);
+//! ```
+
+/// This derive macro provides an implementation
+/// of the [`trait@GenerateRandom`] trait.
+///
+/// Enum variants can be given a `weight` attribute
+/// to change how often it is generated.
+/// By default, the weight is `1`.
+/// The probability of a variants is its weight
+/// divided by the sum over all variants.
+pub use generate_random_macro::GenerateRandom;
+
+/// Enable randomly generating values of a type.
+///
+/// This trait can be implemented using the derive
+/// macro of the same name: [`macro@GenerateRandom`].
+pub trait GenerateRandom {
+ /// Create a new random value of this type.
+ fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self;
+}
+
+macro_rules! impl_generate_random {
+ ( $( $t:ty, )+ ) => {
+ $(
+ impl GenerateRandom for $t {
+ fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
+ rng.gen()
+ }
+ }
+ )+
+ }
+}
+
+impl_generate_random! {
+ bool,
+ char,
+ u8,
+ i8,
+ u16,
+ i16,
+ u32,
+ i32,
+ u64,
+ i64,
+ u128,
+ i128,
+ usize,
+ isize,
+ f32,
+ f64,
+}
+
+impl<T: GenerateRandom> GenerateRandom for Option<T> {
+ fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
+ if bool::generate_random(rng) {
+ Some(T::generate_random(rng))
+ } else {
+ None
+ }
+ }
+}
+
+macro_rules! impl_generate_random_tuple {
+ ( $t0:ident $( $t:ident )* ) => {
+ impl< $t0, $( $t, )* > GenerateRandom for ( $t0, $( $t, )* )
+ where
+ $t0: GenerateRandom,
+ $(
+ $t: GenerateRandom,
+ )*
+ {
+ fn generate_random<R: rand::Rng + ?Sized>(rng: &mut R) -> Self {
+ (
+ $t0::generate_random(rng),
+ $(
+ $t::generate_random(rng),
+ )*
+ )
+ }
+ }
+ impl_generate_random_tuple!( $( $t )* );
+ };
+ () => {
+ impl GenerateRandom for () {
+ fn generate_random<R: rand::Rng + ?Sized>(_rng: &mut R) -> Self {
+ ()
+ }
+ }
+ }
+}
+
+impl_generate_random_tuple!(A B C D E F G H I J K L);
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ fn rng() -> impl rand::Rng {
+ use rand::SeedableRng;
+ rand_chacha::ChaCha8Rng::from(rand_chacha::ChaCha8Core::from_seed([37; 32]))
+ }
+
+ #[test]
+ fn test_u8() {
+ let mut rng = rng();
+ assert_eq!(u8::generate_random(&mut rng), 55);
+ }
+}