# field_name
[](https://github.com/h01-team/field_name/actions)
[](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.1"
```
## 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
| `#[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!