Expand description
§Structural Typing for Rust
Define a struct once and use it with different field combinations, tracked at compile time.
§Installation
cargo add structural-typingIf using derives on #[structural] structs, also add:
cargo add derive-where§Quick Example
use structural_typing::{structural, presence::Present, select};
#[structural]
struct User { id: u32, name: String, email: String }
type Create = select!(user: name, email);
fn create_user(data: User<Create>) -> User {
data.id(generate_id())
}
fn update_user<F: user::Fields<id = Present>>(data: User<F>) {
if let Some(name) = data.get_name() {
update_in_db(data.id, name);
}
}§Core Concepts
- Field States:
Present,Optional,Absent - Builder API:
.field(value)infers presence from type - Type Selection:
select!macro or type aliases - Bounded Impls: Require specific fields via trait bounds
- Merge and Extract: Combine partial structs or extract field subsets
For serde integration and other details, see the structural macro documentation.
See the examples directory for comprehensive usage.
§Constraints
- Named structs only (not tuple structs or enums)
- No generic parameters
- At least one field required
Modules§
- access
- Runtime field access trait for checking presence and getting values. Runtime field access for structural types.
- extract
- Traits for splitting structs into selected fields and remainder. Extract selected fields from structs, returning the selected fields and remainder.
- presence
- Type-level presence markers and traits for field state tracking. Type-level markers for field presence states.
Macros§
- select
- Construct a
FieldSetby selecting fields from a module.
Attribute Macros§
- structural
- Generates type-safe structural typing support for a struct.