Crate field_name

Crate field_name 

Source
Expand description

§field_name

A procedural macro crate that allows you to access struct field names and enum variant names as compile-time string constants.

§Motivation

When writing code that interacts with databases (like MongoDB), serialization formats (JSON), or dynamic query builders, developers often hardcode field names as strings:

// ❌ Error-prone: if the struct field changes, this string becomes invalid.
let query = doc! { "userName": "alice" };

field_name solves this by generating associated constants for your types. If you rename a field in your struct, your code will fail to compile, saving you from runtime errors.

// ✅ Type-safe: compiler ensures this field exists.
let query = doc! { User::USER_NAME: "alice" };

§Features

  • Struct Fields: Generates pub const FIELD_NAME for every field.
  • Enum Variants: Generates pub const VARIANT_NAME for every variant.
  • Renaming: Support for mapping Rust field names to wire formats (e.g., id -> _id).
  • Skipping: Exclude internal fields or variants from generation.
  • Lists: Generates a FIELDS or VARIANTS array containing all valid names.

§Usage

Add this to your Cargo.toml:

[dependencies]
field_name = "0.1"

§Deriving Struct Field Names

Use #[derive(FieldNames)] on named structs.

use field_name::FieldNames;

#[derive(FieldNames)]
struct User {
    username: String,
    email: String,

    #[field_name(rename = "_id")]
    id: u64,

    #[field_name(skip)]
    internal_cache: String,
}

fn main() {
    // Access individual field names as constants
    assert_eq!(User::USERNAME, "username");
    assert_eq!(User::EMAIL, "email");
    assert_eq!(User::ID, "_id");

    // Access all fields as a list
    assert_eq!(User::FIELDS, ["username", "email", "_id"]);

    // 'internal_cache' is skipped
    assert!(!User::FIELDS.contains(&"internal_cache"));
}

§Deriving Enum Variant Names

Use #[derive(VariantNames)] on enums.

use field_name::VariantNames;

#[derive(VariantNames)]
enum ConnectionState {
    Connected,

    #[variant_name(rename = "disconnected_by_server")]
    Disconnected,

    Error(String),
}

fn main() {
    assert_eq!(ConnectionState::CONNECTED, "Connected");
    assert_eq!(ConnectionState::DISCONNECTED, "disconnected_by_server");
    assert_eq!(ConnectionState::ERROR, "Error");

    assert_eq!(ConnectionState::VARIANTS, ["Connected", "disconnected_by_server", "Error"]);
}

§Configuration

The macros can be configured using the #[field_name(...)] (for structs) and #[variant_name(...)] (for enums) attributes.

AttributeDescription
skipExcludes the field/variant from the FIELDS/VARIANTS array and does not generate a constant.
rename = "name"Uses the provided string value instead of the Rust identifier. Useful for _id or camelCase.

Derive Macros§

FieldNames
Derives associated constants and a FIELDS array for struct fields.
VariantNames
Derives associated constants and a VARIANTS array for enum variants.