struct-to-enum 1.1.2

Derive macros to generate enums from struct fields - compile-time safe field selection and dispatch
Documentation
#![no_std]

#[cfg(feature = "derive")]
pub use struct_to_enum_macros::*;

/// Implemented by structs that have a `FieldName` enum generated by the [`FieldName`] derive macro.
///
/// `N` is the number of non-skipped fields + nested fields, resolved at compile time. Deriving `FieldName` on a
/// struct `Foo` with `N` non-skipped fields generates:
///
/// ```ignore
/// impl FieldNames<N> for Foo {
///     type FieldName = FooFieldName;
///     fn field_names() -> [FooFieldName; N] { ... }
/// }
/// ```
///
/// Call [`field_names`](FieldNames::field_names) to get an ordered array of all field-name
/// variants without needing a struct instance.
/// Ordered by field declaration order.
///
/// # Example
///
/// ```rust
/// use struct_to_enum::{FieldName, FieldNames};
///
/// #[derive(FieldName)]
/// struct Point {
///     x: f32,
///     y: f32,
/// }
///
/// let names: [PointFieldName; 2] = Point::field_names();
/// assert_eq!(names, [PointFieldName::X, PointFieldName::Y]);
/// ```
pub trait FieldNames<const N: usize> {
    type FieldName;

    // can't use const generics in trait bounds yet (requires nightly)
    // #![feature(generic_const_exprs)]
    // const N: usize;

    /// Returns all field-name enum variants in field declaration order.
    ///
    /// NOTE: This method will be made `const` once `const_trait_impl` is stabilised.
    /// Tracking issue: <https://github.com/rust-lang/rust/issues/67792>
    fn field_names() -> [Self::FieldName; N];
}

#[cfg(test)]
mod tests {
    use crate::FieldNames;

    #[derive(Debug, PartialEq, Clone, Copy)]
    pub struct Test {
        pub a: i32,
        pub b: i32,
    }

    #[derive(Debug, PartialEq, Clone, Copy)]
    pub enum TestFieldName {
        A,
        B,
    }

    impl FieldNames<2> for Test {
        type FieldName = TestFieldName;
        fn field_names() -> [Self::FieldName; 2] {
            [TestFieldName::A, TestFieldName::B]
        }
    }

    #[test]
    pub fn test_field_names() {
        let _test = Test { a: 0, b: 0 };
        let _a: TestFieldName = <Test as FieldNames<2>>::FieldName::A;
        assert_eq!(Test::field_names(), [TestFieldName::A, TestFieldName::B]);
    }
}