# Orz - Rust Procedural Macro for Struct Field Information
[](https://crates.io/crates/orz)
[](https://docs.rs/orz)
[](https://opensource.org/licenses/MIT)
A powerful and practical Rust procedural macro for automatically generating field information methods for structs. The name "Orz" expresses admiration while hinting at the library's powerful capabilities.
## Features
- 🔤 **Custom field display names** - Define custom names for struct fields
- 🚫 **Skip specified fields** - Exclude certain fields from output
- 🔧 **Custom formatting functions** - Apply custom logic to format field values
- 🐛 **Debug trait formatting** - Format values using Debug trait when needed
- 📊 **Field information & statistics** - Get comprehensive field metadata
## Installation
Add this to your `Cargo.toml`:
```toml
[dependencies]
orz = "0.1.0"
```
## Quick Start
```rust
use orz::Orz;
#[derive(Orz)]
struct User {
#[name("Username")]
username: String,
#[name("Age")]
age: u32,
#[skip]
password_hash: String,
}
let user = User {
username: "alice".to_string(),
age: 30,
password_hash: "hashed".to_string(),
};
println!("Field names: {:?}", User::field_names());
// Output: ["Username", "Age"]
println!("Field values: {:?}", user.field_values());
// Output: ["alice", "30"]
```
## Complete Example
```rust
use orz::Orz;
// Custom formatting functions
fn format_count(n: &i32) -> String {
format!("{} items", n)
}
fn format_price(p: &f64) -> String {
format!("¥{:.2}", p)
}
#[derive(Orz, Debug)]
struct Product {
#[name("Product Name")]
name: String,
#[name("Price")]
#[to_string_with("format_price")]
price: f64,
#[name("Stock Quantity")]
#[to_string_with("format_count")]
stock: i32,
#[skip]
secret_info: String,
// No name attribute, uses field name "description"
description: String,
#[name("Debug Info")]
#[debug]
debug_data: Vec<String>,
}
fn main() {
let product = Product {
name: "Laptop".to_string(),
price: 5999.99,
stock: 100,
secret_info: "Confidential".to_string(),
description: "High-performance gaming laptop".to_string(),
debug_data: vec!["data1".to_string(), "data2".to_string()],
};
// Get field names
println!("Field names: {:?}", Product::field_names());
// Output: ["Product Name", "Price", "Stock Quantity", "description", "Debug Info"]
// Get field values
println!("Field values: {:?}", product.field_values());
// Output: ["Laptop", "¥5999.99", "100 items", "High-performance gaming laptop", "[\"data1\", \"data2\"]"]
// Get field count
println!("Field count: {}", Product::field_count());
// Output: 5
// Get detailed field information
for (name, value) in product.field_info() {
println!("{}: {}", name, value);
}
// Output:
// Product Name: Laptop
// Price: ¥5999.99
// Stock Quantity: 100 items
// description: High-performance gaming laptop
// Debug Info: ["data1", "data2"]
}
```
## Attribute Reference
### `#[name("Display Name")]`
Sets the display name for a field. If not set, the field identifier is used by default.
```rust
#[name("Username")]
username: String,
#[name("Email Address")]
email: String,
```
### `#[skip]`
Skips the field, excluding it from all outputs.
```rust
#[skip]
password_hash: String,
#[skip]
internal_id: u64,
```
### `#[to_string_with("function_name")]`
Uses a custom function to format the field value. Function signature should be `fn(&T) -> String`.
```rust
fn format_date(d: &chrono::NaiveDate) -> String {
d.format("%Y-%m-%d").to_string()
}
#[to_string_with("format_date")]
created_at: chrono::NaiveDate,
```
### `#[debug]`
Formats the field value using the Debug trait (`{:?}`).
```rust
#[debug]
metadata: HashMap<String, String>,
#[debug]
options: Vec<String>,
```
## Generated Methods
### `field_names() -> Vec<&'static str>`
Returns display names of all fields.
```rust
let names = Product::field_names();
// ["Product Name", "Price", "Stock Quantity", "description", "Debug Info"]
```
### `field_values(&self) -> Vec<String>`
Returns string representations of all field values.
```rust
let values = product.field_values();
// ["Laptop", "¥5999.99", "100 items", "High-performance gaming laptop", "[\"data1\", \"data2\"]"]
```
### `field_info(&self) -> Vec<(&'static str, String)>`
Returns a mapping of field names to field values.
```rust
let info = product.field_info();
// [("Product Name", "Laptop"), ("Price", "¥5999.99"), ...]
```
### `field_count() -> usize`
Returns the number of fields.
```rust
let count = Product::field_count();
// 5
```
### `field_values_ref(&self) -> Vec<&str>` (Conditionally Generated)
Automatically generated when all field types implement `AsRef<str>` (like `&str`, `String`), returning references to field values.
```rust
#[derive(Orz)]
struct Log<'a> {
level: &'a str,
message: &'a str,
}
let log = Log { level: "INFO", message: "Hello" };
let refs = log.field_values_ref();
// ["INFO", "Hello"]
```
## Priority Rules
Field value formatting priority (highest to lowest):
1. `#[to_string_with("function_name")]` - Custom function
2. `#[debug]` - Debug trait formatting
3. Default `to_string()` - Display trait formatting
## Why "Orz"?
Orz is often used online to express admiration or kneeling in respect. The library name reflects its powerful capabilities:
- **O** - Object field information
- **R** - Rapid retrieval
- **Z** - Zero boilerplate code
Using the Orz procedural macro, you'll be impressed by its convenience!
## Notes
- Only supports named field structs
- Does not support enums or unions
- Field display names support Unicode characters
- Custom formatting functions must be visible in the current scope
- Only supports `#[name("value")]` and `#[to_string_with("function_name")]` formats
## Running Examples
```bash
# Run example
cargo run --example demo
# Run tests
cargo test
```
## Contributing
Contributions are welcome! Please feel free to submit pull requests or open issues for any bugs or feature requests.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
---
<div align="center">
**Orz** - Making struct field reflection in Rust effortless! 🦀
</div>