reflected 0.30.0

Something like reflection
Documentation
use chrono::Utc;
use fake::{Fake, Faker, faker::internet::en::FreeEmail};
use rust_decimal::Decimal;

use crate::{Field, Reflected, Type};

pub trait RandomReflected {
    fn random() -> Self;
}

impl<T: Reflected> RandomReflected for T {
    fn random() -> Self {
        let mut new = Self::default();

        for field in Self::fields() {
            if matches!(field.tp, Type::DateTime | Type::Enum) {
                continue;
            }

            new.set_value(*field, random_val(field).as_deref());
        }

        new
    }
}

fn random_val<T>(field: &Field<T>) -> Option<String> {
    match field.tp {
        Type::Text => {
            if field.name.contains("email") {
                FreeEmail().fake::<String>().into()
            } else {
                16.fake::<String>().into()
            }
        }
        Type::Integer | Type::Float => (0..1_000).fake::<i64>().to_string().into(),
        Type::Date => Utc::now().naive_utc().to_string().into(),
        Type::Decimal => Decimal::new(i64::from((u32::MIN..u32::MAX).fake::<u32>()), (1..6).fake())
            .to_string()
            .into(),
        Type::Bool => (0..2).fake::<i32>().to_string().into(),
        Type::Optional(_) => {
            if Faker.fake::<bool>() {
                random_val(&field.non_optional())
            } else {
                None
            }
        }
        Type::Duration => (0..100).fake::<u64>().to_string().into(),
        Type::DateTime | Type::Enum => unreachable!("Failed to gen random value for: {field:?}"),
    }
}