#[derive(FieldType)]
{
// Attributes available to this derive:
#[stem_type]
#[ste_type]
#[stem_type_derive]
#[ste_type_derive]
#[stem_type_attr]
#[ste_type_attr]
}
Expand description
Generates {StructName}FieldType, an enum whose variants wrap struct field values.
For enum variants without values use FieldName instead.
Each non-skipped field becomes a variant VariantName(FieldType) where the variant name is
the field name in PascalCase. The variants are ordered by field declaration order.
No derives are added by default. Add derives with #[stem_type_derive(...)].
§Attributes
| Attribute | Target | Description |
|---|---|---|
#[stem_type(skip)] | field | Exclude this field from the generated enum. |
#[stem_type(nested)] | field | Flatten the nested struct’s FieldType variants into this enum. |
#[stem_type_derive(...)] | struct | Derives for the generated enum. None are added by default. |
#[stem_type_attr(...)] | struct | Extra attributes applied verbatim to the generated enum. |
All stem_type* attributes have short aliases: ste_type, ste_type_derive, ste_type_attr.
§Generated items
For a struct Foo with N non-skipped fields, this macro generates:
enum FooFieldType { Field1(T1), Field2(T2), ... }
impl From<Foo> for [FooFieldType; N] { ... }§Example
use struct_to_enum::FieldType;
#[derive(Clone)]
#[derive(FieldType)]
#[stem_type_derive(Debug, PartialEq, Clone)]
struct Config {
width: u32,
height: u32,
#[stem_type(skip)]
name: String,
}
// Generated: enum ConfigFieldType { Width(u32), Height(u32) }
let cfg = Config { width: 1920, height: 1080, name: "hd".into() };
let fields: [ConfigFieldType; 2] = cfg.into();
assert_eq!(fields[0], ConfigFieldType::Width(1920));
assert_eq!(fields[1], ConfigFieldType::Height(1080));§Flattening nested structs
Mark a field with #[stem_type(nested)] to inline the variants of a nested struct
(which must also derive FieldType) directly into the parent enum. Nesting can be
arbitrarily deep.
use struct_to_enum::FieldType;
#[derive(FieldType)]
#[stem_type_derive(Debug, PartialEq)]
struct Color {
r: u8,
g: u8,
b: u8,
}
#[derive(FieldType)]
#[stem_type_derive(Debug, PartialEq)]
struct Pixel {
x: i32,
y: i32,
#[stem_type(nested)]
color: Color,
}
// PixelFieldType has variants: X(i32), Y(i32), R(u8), G(u8), B(u8)
let p = Pixel { x: 10, y: 20, color: Color { r: 255, g: 128, b: 0 } };
let fields: [PixelFieldType; 5] = p.into();
assert_eq!(fields[0], PixelFieldType::X(10));
assert_eq!(fields[2], PixelFieldType::R(255));
}§Generics
Generic structs are supported. The generated enum carries the same type parameters:
use struct_to_enum::FieldType;
#[derive(FieldType)]
#[stem_type_derive(Debug, PartialEq)]
struct Pair<A, B> {
first: A,
second: B,
}
// Generated: enum PairFieldType<A, B> { First(A), Second(B) }
let fields: [PairFieldType<i32, &str>; 2] = Pair { first: 42_i32, second: "hi" }.into();
assert_eq!(fields[0], PairFieldType::First(42));§Combining with other derives
Use #[stem_type_derive] and #[stem_type_attr] to pass anything to the generated enum.
This works with crates like strum:
use struct_to_enum::FieldType;
use strum::VariantNames;
#[derive(FieldType)]
#[stem_type_derive(Debug, strum_macros::VariantNames)]
#[stem_type_attr(strum(serialize_all = "SCREAMING-KEBAB-CASE"))]
struct Request {
user_id: u64,
payload: Vec<u8>,
}
assert_eq!(RequestFieldType::VARIANTS, ["USER-ID", "PAYLOAD"]);