struct-to-enum
Derive macros for generating enums corresponding to the fields of structs.
Overview
struct-to-enum provides two derive macros:
FieldName— generates a unit enum where each variant represents a field nameFieldType— generates an enum where each variant wraps the type of a struct field
Both macros support generics, field skipping, nesting, and custom derives/attributes on the generated enum.
Intended use-case is to generate enums from struct fields, enabling compile-time column filter validation for queries.
Usage
FieldName
Generates a unit enum {StructName}FieldName and implements [FieldNames<N>] on the struct,
which provides a field_names() static method returning an ordered array of all variants.
use ;
// Generated:
// #[derive(Debug, PartialEq, Eq, Clone, Copy)]
// enum PointFieldName { X, Y }
let names: = field_names;
assert_eq!;
Nested flattening
Mark a field with #[stem_name(nested)] to flatten its FieldName variants into the parent enum.
The nested struct must also derive FieldName. Nesting can be arbitrarily deep.
use ;
// PersonFieldName has variants: Name, Street, City (Address's variants are inlined)
let names: = field_names;
assert_eq!;
FieldType
Generates a tuple-variant enum {StructName}FieldType and implements From<Struct> for
[FieldType; N], converting the struct into an ordered array of variants holding the field values.
use FieldType;
// Generated:
// #[derive(Debug, Clone, PartialEq)]
// enum ConfigFieldType {
// Width(u32),
// Height(u32),
// }
let cfg = Config ;
let fields: = cfg.into;
assert_eq!;
assert_eq!;
Nested flattening
Mark a field with #[stem_type(nested)] to flatten the nested struct's FieldType variants
into the parent enum. The nested struct must also derive FieldType. Nesting can be arbitrarily deep.
use FieldType;
// PixelFieldType has variants: X(i32), Y(i32), R(u8), G(u8), B(u8)
let p = Pixel ;
let fields: = p.into;
assert_eq!;
assert_eq!;
Generics
Both macros handle generic structs with lifetime and type parameters.
use FieldType;
let fields: = Pair .into;
assert_eq!;
Combining both macros
use ;
// RecordFieldName and RecordFieldType are both generated
let _names: = field_names;
Attributes
FieldName attributes
| Attribute | Location | Description |
|---|---|---|
#[stem_name_derive(...)] |
Struct | Merge additional derives onto the generated enum (defaults Debug, PartialEq, Eq, Clone, Copy are always kept) |
#[stem_name_attr(...)] |
Struct | Add extra attributes to the generated enum |
#[stem_name(skip)] |
Field | Exclude this field from the generated enum |
#[stem_name(nested)] |
Field | Flatten the field's FieldName variants into the parent enum |
FieldType attributes
| Attribute | Location | Description |
|---|---|---|
#[stem_type_derive(...)] |
Struct | Specify derives for the generated enum (none by default) |
#[stem_type_attr(...)] |
Struct | Add extra attributes to the generated enum |
#[stem_type(skip)] |
Field | Exclude this field from the generated enum |
#[stem_type(nested)] |
Field | Flatten the field's FieldType variants into the parent enum |
Attribute aliases:
stem_name/ste_nameandstem_type/ste_typeare interchangeable.
Example: using with strum
use FieldType;
use VariantNames;
assert_eq!;
Inspired by:
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option