orz

Crates.ioorz
lib.rsorz
version1.0.0
created_at2023-02-01 02:03:00.165089+00
updated_at2025-09-30 07:02:58.307745+00
descriptionA procedural macro for generating field information methods for structs.
homepage
repository
max_upload_size
id773170
size16,860
(MDZZDYXCMDZZDYXC)

documentation

https://docs.rs/orz

README

Orz - Rust Procedural Macro for Struct Field Information

Crates.io Documentation License: 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:

[dependencies]
orz = "0.1.0"

Quick Start

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

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.

#[name("Username")]
username: String,

#[name("Email Address")]
email: String,

#[skip]

Skips the field, excluding it from all outputs.

#[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.

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 ({:?}).

#[debug]
metadata: HashMap<String, String>,

#[debug]
options: Vec<String>,

Generated Methods

field_names() -> Vec<&'static str>

Returns display names of all fields.

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.

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.

let info = product.field_info();
// [("Product Name", "Laptop"), ("Price", "¥5999.99"), ...]

field_count() -> usize

Returns the number of fields.

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.

#[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

# 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 file for details.


Orz - Making struct field reflection in Rust effortless! 🦀

Commit count: 0

cargo fmt