Crates.io | fieldwork |
lib.rs | fieldwork |
version | 0.4.6 |
created_at | 2025-05-15 23:27:08.174598+00 |
updated_at | 2025-07-10 21:58:45.183701+00 |
description | derivable accessors for struct fields |
homepage | |
repository | https://github.com/jbr/fieldwork |
max_upload_size | |
id | 1675791 |
size | 268,560 |
fieldwork
is a procedural macro crate designed to automate the generation of field accessor
methods for named structs. By leveraging Rust's powerful macro system, fieldwork
reduces
boilerplate code, enhances code readability, and ensures consistency. Just as importantly,
fieldwork
intends to be fully customizable and expressive for common access patterns.
Manually writing getters and setters for struct fields is repetitive, and adds to maintenance
burden. fieldwork
addresses this by providing a procedural macro that automatically generates
these methods based on your struct definitions. The intent of this crate, and distinguishing
feature, is to be as customizable and expressive as writing your own getters and setters. The crate
succeeds if you are able to emit exactly the code that you would have manually written, but far more
concisely.
use std::path::PathBuf;
#[derive(fieldwork::Fieldwork, Default)]
#[fieldwork(get, set, with, without, get_mut, take, into, rename_predicates)]
struct ServerConfig {
/// server hostname
host: String,
/// server port
#[field(into = false)]
port: u16,
/// path to SSL certificate file
ssl_cert: Option<PathBuf>,
/// path to log directory
log_dir: Option<PathBuf>,
/// whether TLS is required
tls_required: bool,
/// whether verbose logging is enabled
verbose: bool,
#[field = false]
_runtime_data: (),
}
// Usage examples:
let mut config = ServerConfig::default()
.with_host("LocalHost") // accepts &str via Into<String>
.with_port(8080)
.with_log_dir("/var/log") // accepts &str, wraps in Some() automatically
.with_tls_required() // sets to true
.without_verbose(); // sets to false
config.host_mut().make_ascii_lowercase();
// Getters use idiomatic naming
assert_eq!(config.host(), "localhost");
assert_eq!(config.port(), 8080);
assert_eq!(config.log_dir().unwrap(), PathBuf::from("/var/log"));
assert!(config.is_tls_required()); // boolean getters use is_ prefix because of `rename_predicates`
assert!(!config.is_verbose());
// Chainable setters return &mut Self
config
.set_ssl_cert(PathBuf::from("/etc/ssl/cert.pem"))
.set_port(9090)
.set_verbose(true);
let cert = config.take_ssl_cert_mut();
assert_eq!(cert, Some(PathBuf::from("/etc/ssl/cert.pem")));
// Without methods provide convenient clearing
config = config.without_log_dir(); // Sets log_dir to None
assert!(config.log_dir().is_none());
The compile time cost of using a proc macro crate is always worth considering. All efforts have been made to keep this crate as lightweight as possible and featureful enough to be worth the tradeoff.
This crate has a full suite of macro-expansion tests in tests/expand. These tests are also used for test coverage.
View the docs for main on github at docs.md, or on github pages in rustdoc format. The most recent release can always be viewed at docs.rs.
This crate uses #![deny(unsafe_code)]
.