Skip to main content

FieldName

Derive Macro FieldName 

Source
#[derive(FieldName)]
{
    // Attributes available to this derive:
    #[stem_name]
    #[ste_name]
    #[stem_name_derive]
    #[ste_name_derive]
    #[stem_name_attr]
    #[ste_name_attr]
}
Expand description

Generates {StructName}FieldName, an enum whose variants represent struct field names. For enum variants with values use FieldType instead.

Each non-skipped field becomes a unit variant in PascalCase. The variants are ordered by field declaration order.

The generated enum derives Debug, PartialEq, Eq, Clone, and Copy by default. They can be removed by adding no_defaults to the stem_name_derive attribute. Use #[stem_name_derive(...)] to add more derives - the defaults are merged with whatever you specify, so you only need to list derives not already in the default set.

§Attributes

AttributeTargetDescription
#[stem_name(skip)]fieldExclude this field from the generated enum.
#[stem_name(nested)]fieldFlatten the nested struct’s FieldName variants into this enum.
#[stem_name_derive(...)]structMerge additional derives onto the generated enum (defaults are kept).
#[stem_name_attr(...)]structExtra attributes applied verbatim to the generated enum.

All stem_name* attributes have short aliases: ste_name, ste_name_derive, ste_name_attr.

§Generated items

For a struct Foo with N non-skipped fields, the macro generates:

enum FooFieldName { Field1, Field2, ... }

impl FieldNames<N> for Foo { ... }

§Example

use struct_to_enum::{FieldName, FieldNames};

#[derive(FieldName)]
struct User {
    id: u64,
    user_name: String,
    #[stem_name(skip)]
    internal_token: String,
}

// Generated: enum UserFieldName { Id, UserName }  (Debug, PartialEq, Eq, Clone, Copy)

let names: [UserFieldName; 2] = User::field_names();
assert_eq!(names, [UserFieldName::Id, UserFieldName::UserName]);

§Flattening nested structs

Mark a field with #[stem_name(nested)] to inline the variants of a nested struct (which must also derive FieldName) directly into the parent enum. Nesting can be arbitrarily deep.

use struct_to_enum::{FieldName, FieldNames};

#[derive(FieldName)]
pub struct Address {
    pub street: String,
    pub city: String,
}

#[derive(FieldName)]
struct Person {
    name: String,
    #[stem_name(nested)]
    address: Address,
}

// PersonFieldName: Name, Street, City  (Address's variants are inlined)

let fields: [PersonFieldName; 3] = Person::field_names();
assert_eq!(fields, [PersonFieldName::Name, PersonFieldName::Street, PersonFieldName::City]);

§Generics

Generic structs are supported. The FieldNames impl carries the same type parameters:

use struct_to_enum::{FieldName, FieldNames};

#[derive(FieldName)]
struct Pair<A, B> {
    first: A,
    second: B,
}

// Generated: enum PairFieldName { First, Second }
assert_eq!(PairFieldName::First, PairFieldName::First);

§Combining with other derives

Use #[stem_name_derive] and #[stem_name_attr] to pass anything to the generated enum. This works with crates like strum:

use struct_to_enum::FieldName;
use strum_macros::EnumString;

#[derive(FieldName)]
#[stem_name_derive(EnumString)]
#[stem_name_attr(strum(ascii_case_insensitive))]
struct Query {
    user_id: u64,
    status: String,
}

// Default derives (Debug, PartialEq, Eq, Clone, Copy) are merged with EnumString.
let variant: QueryFieldName = "userid".parse().unwrap(); // case-insensitive
assert_eq!(variant, QueryFieldName::UserId);