ezinit 0.1.1

Initialize structs with a generated new() function based on modifiable rules
Documentation
# EzInit


Initialize structs easily with powerful derive macros.

## How does it work?


If you derive `EzInit` on your struct, it will generate a `new()` function that initializes the struct fields based on the following rules:

### Field Initialization Modes


1. **Explicit Default Value**: `#[init(default = <expression>)]`
   - Uses the provided expression to initialize the field
   - Example: `#[init(default = 100)]`, `#[init(default = "hello".to_string())]`

2. **Default Trait**: `#[init(default)]`
   - Uses `Default::default()` for types that implement `Default`
   - Example: `#[init(default)]` on a field of type `CharacterClass` (if it derives `Default`)

3. **Random Values**: `#[init(random)]` or `#[init(random = "range")]` or `#[init(random = [items])]`
   - `#[init(random)]`: Random value using the type's standard random generation
   - `#[init(random = "1..10")]`: Random integer in range
   - `#[init(random = "0.0..1.0")]`: Random float in range
   - `#[init(random = ["A", "B", "C"])]`: Random item from list

4. **Random Enum Variant**: `#[init(enum)]`
   - Picks a random variant from an enum that derives `RandomVariant`
   - The enum must only have unit variants (no data)

5. **Option Types**: No attribute needed
   - Automatically initialized to `None`

6. **Required Fields**: No attribute
   - Becomes a required parameter in the `new()` function

### RandomVariant Derive


For enums, derive `RandomVariant` to enable random variant selection:
- Only works on enums with unit variants (no associated data)
- Can be combined with `Default` derive for flexible initialization
- Implements `Distribution<YourEnum>` for `rand::distributions::Standard`

## Installation


Not published yet, so you need to clone the repo and add it as a path dependency:

```toml
[dependencies]
ezinit = { path = "path/to/ezinit" }
```

## Usage Example


```rust
use ezinit::{EzInit, RandomVariant};

// Derive RandomVariant for random enum selection
#[derive(Debug, Clone, Copy, Default, RandomVariant)]

enum RoadCondition {
    #[default]
    Excellent,
    Good,
    Fair,
    Poor,
    Fatal,
}

#[derive(Debug, Clone, Copy, Default)]

enum RoadType {
    Highway,
    #[default]
    Street,
    Avenue,
    Hill
}

// Derive EzInit to generate the new() function
#[derive(Debug, EzInit)]

struct HighWay {
    // Required field: must be passed to new()
    pub name: String,

    // Explicit default value
    #[init(default = 2)]
    pub lanes: u32,

    // Random item from list
    #[init(random = ["Me", "Cat", "Politician"])]
    pub built_by: String,

    // Use Default::default() - always returns street
    #[init(default)]
    pub road_type: RoadType,

    // Random enum variant
    #[init(enum)]
    pub condition: RoadCondition,

    // Random integer range
    #[init(random = "60..120")]
    pub max_speed: u32,

    // Random float range
    #[init(random = "0.0..100.0")]
    pub length_km: f64,

    // Option: automatically None
    pub toll_cost: Option<f32>,
}

fn main() {
    // Only 'name' is required!
    let highway = HighWay::new("I-95".to_string());
    
    println!("Highway: {}", highway.name);
    println!("Type: {:?} (always default), Condition: {:?} (random)", 
             highway.road_type, highway.condition);
    println!("Built by: {}, Lanes: {}", highway.built_by, highway.lanes);
    println!("Max Speed: {} km/h, Length: {:.1} km", 
             highway.max_speed, highway.length_km);
}
```

### Sample Output


Running the above code produces output like this (values marked as random will differ each run):

```
Highway: I-95
Type: Street (always default), Condition: Good (random)
Built by: Cat, Lanes: 2
Max Speed: 87 km/h, Length: 42.7 km
```

Each time you run the program, the random values will change:

```
Highway: I-95
Type: Street (always default), Condition: Fatal (random)
Built by: Politician, Lanes: 2
Max Speed: 103 km/h, Length: 15.3 km
```

## Generated Code


For the above example, `EzInit` generates:

```rust
impl HighWay {
    pub fn new(name: String) -> Self {
        Self {
            name,
            lanes: 2,
            built_by: {
                use ::ezinit::export::rand::seq::SliceRandom;
                ["Me", "Cat", "Politician"]
                    .choose(&mut ::ezinit::export::rand::thread_rng())
                    .unwrap()
                    .clone()
                    .into()
            },
            road_type: Default::default(),
            condition: ::ezinit::export::rand::random(),
            max_speed: ::ezinit::export::rand::Rng::gen_range(
                &mut ::ezinit::export::rand::thread_rng(),
                60..120
            ),
            length_km: ::ezinit::export::rand::Rng::gen_range(
                &mut ::ezinit::export::rand::thread_rng(), 
                0.0..100.0
            ),
            toll_cost: None,
        }
    }
}
```

## License


MIT