field_name 0.2.0

A proc-macro for exposing a struct's field names at runtime.
Documentation
# field_name

[![Latest Version](https://img.shields.io/crates/v/field_name.svg)](https://crates.io/crates/field_name)

**Stop hardcoding strings. Start using the type system.**

We've all been there. You're writing a MongoDB query, a raw SQL statement, or some custom JSON patch logic. You type `"user_name"` into your query builder. Later, you refactor your Rust struct to use `username`.

The code compiles. The tests pass (mostly). But in production, your query returns nothing because the string literal didn't update itself.

`field_name` fixes this by making your field names available as **compile-time constants**.

## The Problem

```rust
// ❌ The "Stringly Typed" Way
// If you rename `id` to `uuid` in the struct, this line acts like nothing happened.
// You won't know it's broken until runtime.
let query = doc! { "_id": "12345" };
```

## The Solution

```rust
// ✅ The "Strongly Typed" Way
// If you rename `id` to `uuid` in the struct, this won't compile.
// You catch the bug immediately.
let query = doc! { User::ID: "12345" };
```

## Installation

Add this to your `Cargo.toml`:

```toml
[dependencies]
field_name = "0.2"
```

## How to use it

### 1. For Structs (The Mongo/SQL Use Case)

Just derive `FieldNames`. It generates a public constant for every field (uppercased) and a `FIELDS` array containing all of them.

```rust
use field_name::FieldNames;

#[derive(FieldNames)]
struct User {
    // 1. Rename support: Map Rust's "id" to Mongo's "_id"
    #[field_name(rename = "_id")] 
    id: u64,

    username: String,

    // 2. Skip support: Don't generate constants for internal fields
    #[field_name(skip)] 
    password_hash: String,
}

fn main() {
    // Use the individual constants for queries
    assert_eq!(User::ID, "_id");
    assert_eq!(User::USERNAME, "username");

    // Use the list for validation or schema generation
    assert_eq!(User::FIELDS, ["_id", "username"]);
    
    // Attempting to access User::PASSWORD_HASH will fail to compile!
}
```

### 2. For Enums (The State Machine Use Case)

Derive `VariantNames` to get string representations of your variants without instantiating them.

```rust
use field_name::VariantNames;

#[derive(VariantNames)]
enum Status {
    Pending,
    
    #[variant_name(rename = "in_progress")]
    Processing,
    
    Completed,
}

fn main() {
    assert_eq!(Status::PENDING, "Pending");
    assert_eq!(Status::PROCESSING, "in_progress");
    
    // Great for logging or quick checks
    if some_api_string == Status::PROCESSING {
        println!("We are moving!");
    }
}
```

## Why not just use Serde?

Serde is amazing for serialization, but it doesn't expose the *names* of the fields as constants you can use in code. If you need to construct a dictionary, a specific SQL query, or a dynamic generic function that iterates over valid field names, Serde can't help you there. `field_name` fills that gap.

## Configuration Cheat Sheet

| Attribute | Where? | What it does |
|:---|:---|:---|
| `#[field_name(rename = "x")]` | Struct Field | Changes the constant value to "x". Useful for `_id` or `camelCase` APIs. |
| `#[field_name(skip)]` | Struct Field | Ignores this field. No constant or array entry will be generated. |
| `#[variant_name(rename = "x")]`| Enum Variant | Same as above, but for Enums. |
| `#[variant_name(skip)]` | Enum Variant | Same as above, but for Enums. |

## License

MIT. Do whatever you want with it. Happy coding!