Crates.io | random-constructible |
lib.rs | random-constructible |
version | 0.10.0 |
source | src |
created_at | 2024-11-16 17:35:46.530681 |
updated_at | 2024-11-22 02:14:54.884392 |
description | Provides a trait for creating random instances of enums with weighted probabilities |
homepage | https://github.com/klebs6/klebs-general |
repository | https://github.com/klebs6/klebs-general |
max_upload_size | |
id | 1450512 |
size | 20,903 |
random-constructible
is a Rust crate that provides traits and macros to facilitate the random generation of primitive types and enums, with support for custom probability distributions. It simplifies the process of creating random instances of your types, especially when dealing with enums that require weighted random selection.
Add the following to your Cargo.toml
:
[dependencies]
random-constructible = "0.6.0"
and include it in your crate:
use random_constructible::*;
The crate automatically provides implementations for all primitive integer and floating-point types. You can generate random values using:
use random_constructible::RandConstruct;
let random_u32: u32 = u32::random();
let random_f64: f64 = f64::random();
To enable random generation for your enums, implement the RandConstructEnum
trait. You can do this manually or use the provided macros for convenience.
use random_constructible::{RandConstructEnum, RandConstruct};
#[derive(Default, Copy, Clone, Debug, PartialEq, Eq, Hash)]
enum MyEnum {
#[default]
VariantA,
VariantB,
VariantC,
}
impl RandConstructEnum for MyEnum {
fn all_variants() -> Vec<Self> {
vec![Self::VariantA, Self::VariantB, Self::VariantC]
}
fn default_weight(&self) -> f64 {
match self {
Self::VariantA => 1.0,
Self::VariantB => 2.0,
Self::VariantC => 3.0,
}
}
fn create_default_probability_map() -> std::sync::Arc<std::collections::HashMap<Self, f64>> {
use std::collections::HashMap;
let mut map = HashMap::new();
for variant in Self::all_variants() {
map.insert(variant, variant.default_weight());
}
std::sync::Arc::new(map)
}
}
rand_construct_env!
MacroAlternatively, you can use the rand_construct_env!
macro to define the probability map:
use random_constructible::{RandConstructEnumWithEnv, rand_construct_env};
struct DefaultProvider;
rand_construct_env!(DefaultProvider => MyEnum {
VariantA => 1.0,
VariantB => 2.0,
VariantC => 3.0,
});
Once you've implemented RandConstructEnum
for your enum, you can generate random variants:
use random_constructible::RandConstruct;
let random_variant = MyEnum::random(); // Uses default weights
let uniform_variant = MyEnum::uniform(); // Uniform probability
To sample using a custom provider:
use random_constructible::RandConstructEnumWithEnv;
let random_variant = MyEnum::sample_from_provider::<DefaultProvider, _>(&mut rand::thread_rng());
use random_constructible::{RandConstructEnum, RandConstructEnumWithEnv, rand_construct_env, RandConstruct};
use rand::Rng;
// Define your enum
#[derive(Default, Copy, Clone, Debug, PartialEq, Eq, Hash)]
enum Color {
#[default]
Red,
Green,
Blue,
}
// Implement RandConstructEnum
impl RandConstructEnum for Color {
fn all_variants() -> Vec<Self> {
vec![Self::Red, Self::Green, Self::Blue]
}
fn default_weight(&self) -> f64 {
match self {
Self::Red => 1.0,
Self::Green => 1.0,
Self::Blue => 1.0,
}
}
fn create_default_probability_map() -> std::sync::Arc<std::collections::HashMap<Self, f64>> {
use std::collections::HashMap;
let mut map = HashMap::new();
for variant in Self::all_variants() {
map.insert(variant, variant.default_weight());
}
std::sync::Arc::new(map)
}
}
// Define a custom probability provider
struct CustomColorProvider;
rand_construct_env!(CustomColorProvider => Color {
Red => 0.5,
Green => 0.3,
Blue => 0.2,
});
fn main() {
// Random variant using default weights
let random_color = Color::random();
println!("Random Color: {:?}", random_color);
// Random variant using custom probabilities
let mut rng = rand::thread_rng();
let random_color = Color::sample_from_provider::<CustomColorProvider, _>(&mut rng);
println!("Custom Random Color: {:?}", random_color);
}
The crate also provides utilities for testing the distribution of your random generation:
use random_constructible::{RandConstructEnum, RandConstruct};
use std::collections::HashMap;
fn main() {
let mut counts = HashMap::new();
for _ in 0..10000 {
let variant = Color::random();
*counts.entry(variant).or_insert(0) += 1;
}
for (variant, count) in counts {
println!("{:?}: {}", variant, count);
}
}
This project is licensed under the MIT License - see the LICENSE file for details.
Note: This README is generated based on the crate's code and is meant to help you get started with random-constructible
. For more detailed information, please refer to the documentation.