enum-path 0.1.0

Derive FromStr and Display impls for enums that follow a hierarchical path-like serialization scheme
Documentation
//! Property tests verifying Display/FromStr round-trip behavior of the
//! `EnumPath` derive.

use enum_path::EnumPath;
use proptest::prelude::*;

#[derive(EnumPath, Clone, Debug, PartialEq, Eq)]
#[enum_path(FromStr, Display, rename_all = "snake_case")]
enum Inner
{
    First,
    Second,
    ThirdSomething,
}

#[derive(EnumPath, Clone, Debug, PartialEq, Eq)]
#[enum_path(FromStr, Display, rename_all = "snake_case")]
enum WithPayload
{
    Unit,
    Wrapper(String),
    Nested(Inner),
}

#[derive(EnumPath, Clone, Debug, PartialEq, Eq)]
#[enum_path(FromStr, Display, delimiter = "/")]
enum Slashed
{
    Unit,
    Sub(Inner),
}

fn arb_inner() -> impl Strategy<Value = Inner>
{
    prop_oneof![
        Just(Inner::First),
        Just(Inner::Second),
        Just(Inner::ThirdSomething),
    ]
}

fn arb_with_payload() -> impl Strategy<Value = WithPayload>
{
    prop_oneof![
        Just(WithPayload::Unit),
        // Payload may not contain the delimiter, since the parser splits
        // on the first occurrence and any subsequent text is treated as
        // the inner `String`. Restrict to printable ASCII minus `.`.
        "[A-Za-z0-9_ -]*".prop_map(WithPayload::Wrapper),
        arb_inner().prop_map(WithPayload::Nested),
    ]
}

fn arb_slashed() -> impl Strategy<Value = Slashed>
{
    prop_oneof![Just(Slashed::Unit), arb_inner().prop_map(Slashed::Sub),]
}

proptest! {
    #[test]
    fn round_trip_inner(value in arb_inner())
    {
        let s = value.to_string();
        let parsed: Inner = s.parse().unwrap();
        prop_assert_eq!(parsed, value);
    }

    #[test]
    fn round_trip_with_payload(value in arb_with_payload())
    {
        let s = value.to_string();
        let parsed: WithPayload = s.parse().unwrap();
        prop_assert_eq!(parsed, value);
    }

    #[test]
    fn round_trip_slashed(value in arb_slashed())
    {
        let s = value.to_string();
        let parsed: Slashed = s.parse().unwrap();
        prop_assert_eq!(parsed, value);
    }
}