field_names
is a Rust crate to expose a field or variant names from source code as strings at runtime.
Consider a simple struct such as this one.
#[derive(FieldNames)]
struct Example {
hello: String,
world: String,
#[field_names(skip)]
ignore_me: bool,
}
field_names
will emit the following:
#[automatically_derived]
impl Example {
const FIELDS: [&'static str; 2] = [
"hello",
"world",
];
}
Enums are the same:
#[derive(VariantNames)]
enum Example {
Hello(String),
#[variant_names(skip)]
Secret(String),
World,
}
field_names
will emit the following:
#[automatically_derived]
impl Example {
const VARIANTS: [&'static str; 2] = [
"Hello",
"World",
];
}
This crate was originally created for a case where a set of rules were being read at runtime which referenced fields of structs elsewhere in the code base.
The referenced struct exposed a method which had a match
statement to go from strings to its fields, but there was not a way to ensure the arms of that match statement stayed in sync with the struct definition.
With this crate, a unit test could be created to ensure that every field on the struct - except those deliberately omitted - was handled by the method.
This crate can also be used to enforce relationships among structs and enums at unit-test time that cannot be expressed at compile-time.
See tests/keep_in_sync
for an example and explanation of that scenario.
Using field_names
is an implementation convenience; it shouldn't force you to change your crate's public API.
You can add your own inherent method, e.g. fields() -> &[&'static str]
, or define a trait that matches your use-case and reference FIELDS
in the trait implementation.
This currently isn't supported, using newtype variants and separate structs per variant is currently the recommended approach.
You can use the from_variants
crate to auto-generate conversions from those structs into the enum.