#enums #randomness #macro-derive #ergonomics #generate #named-fields

macro random-constructible-derive

Provides a derive macro for the random-constructible crate which is used for creating random instances of enums with weighted probabilities

9 breaking releases

new 0.10.0 Nov 22, 2024
0.8.0 Nov 21, 2024

#15 in #named-fields

Download history 334/week @ 2024-11-14

334 downloads per month
Used in 2 crates (via rand-construct)

MIT/Apache

63KB
1K SLoC

random-constructible-derive

Crates.io Documentation

random-constructible-derive is a procedural macro crate that provides custom derive macros for the random-constructible crate. It allows you to automatically implement the RandConstruct trait for your structs and enums, enabling easy random generation of complex types with minimal boilerplate.

Features

  • Automatic Implementation: Derive RandConstruct for structs and enums without manual implementation.
  • Support for Enums: Handle enums with unit variants, named fields, and unnamed fields, including custom probabilities.
  • Support for Structs: Derive for structs with named, unnamed, or unit fields.
  • Custom Probabilities: Specify custom probabilities for enum variants and Option fields using attributes.
  • Option Field Handling: Customize the probability of Some values in Option<T> fields.

Installation

Add the following to your Cargo.toml:

[dependencies]
random-constructible = "0.6.0"
random-constructible-derive = "0.6.0"

And include it in your crate:

use random_constructible::RandConstruct;
use random_constructible_derive::RandConstruct;

Usage

Deriving for Structs

You can derive RandConstruct for your structs to enable random generation:

use random_constructible::RandConstruct;
use random_constructible_derive::RandConstruct;

#[derive(RandConstruct)]
struct MyStruct {
    a: u8,
    b: String,
    c: f64,
}

Deriving for Enums

Similarly, you can derive RandConstruct for enums:

use random_constructible::RandConstruct;
use random_constructible_derive::RandConstruct;

#[derive(RandConstruct)]
enum MyEnum {
    VariantA,
    VariantB(i32, String),
    VariantC { x: f64, y: bool },
}

Custom Probabilities for Enum Variants

You can specify custom probabilities for each variant using the #[rand_construct(p = ...)] attribute:

use random_constructible::RandConstruct;
use random_constructible_derive::RandConstruct;

#[derive(RandConstruct)]
enum MyEnum {
    #[rand_construct(p = 0.5)]
    VariantA,
    #[rand_construct(p = 0.3)]
    VariantB,
    #[rand_construct(p = 0.2)]
    VariantC,
}

Handling Option Fields

For Option<T> fields, you can specify the probability of generating a Some value using the #[rand_construct(psome = ...)] attribute:

use random_constructible::RandConstruct;
use random_constructible_derive::RandConstruct;

#[derive(RandConstruct)]
struct MyStruct {
    #[rand_construct(psome = 0.8)]
    optional_field: Option<String>,
}

If you don't specify psome, it defaults to 0.5.

Examples

Struct Example

use random_constructible::RandConstruct;
use random_constructible_derive::RandConstruct;

#[derive(RandConstruct)]
struct Config {
    pub id: u32,
    pub name: String,
    #[rand_construct(psome = 0.9)]
    pub description: Option<String>,
}

fn main() {
    let random_config = Config::random();
    println!("{:?}", random_config);
}

Enum Example with Custom Probabilities

use random_constructible::RandConstruct;
use random_constructible_derive::RandConstruct;

#[derive(Debug, RandConstruct)]
enum Status {
    #[rand_construct(p = 0.7)]
    Active,
    #[rand_construct(p = 0.2)]
    Inactive,
    #[rand_construct(p = 0.1)]
    Pending,
}

fn main() {
    let random_status = Status::random();
    println!("Random Status: {:?}", random_status);
}

Complex Enum with Fields

use random_constructible::RandConstruct;
use random_constructible_derive::RandConstruct;

#[derive(Debug, RandConstruct)]
enum Message {
    Text(String),
    Data(u8, u8, u8),
    #[rand_construct(p = 0.05)]
    Disconnect,
}

fn main() {
    let random_message = Message::random();
    println!("Random Message: {:?}", random_message);
}

How It Works

The random-constructible-derive crate provides the RandConstruct derive macro, which automatically generates implementations of the RandConstruct trait for your types. It handles different kinds of data structures:

  • Structs: Generates random values for each field, respecting any specified attributes.
  • Enums: Generates random variants based on specified probabilities, and recursively generates random values for any associated data.

Attributes

  • #[rand_construct(p = <probability>)]: Sets the probability for an enum variant. The probabilities are relative weights.
  • #[rand_construct(psome = <probability>)]: Sets the probability of Some for Option<T> fields.

Limitations

  • The derive macro requires that all fields also implement RandConstruct.
  • For generic types, ensure that the generic parameters are constrained with RandConstruct where necessary.
  • The current implementation assumes that probabilities are specified as f64 literals.

Contributing

Contributions are welcome! Please feel free to submit a pull request or open an issue for any bugs or feature requests.

License

This project is licensed under the MIT License - see the LICENSE file for details.


Note: This crate is a companion to the random-constructible crate. Ensure that you have both crates added to your dependencies to utilize the full functionality.

Dependencies

~2.5MB
~52K SLoC