19 releases
Uses new Rust 2024
| 0.0.0-19 | Jan 23, 2026 |
|---|---|
| 0.0.0-18 | Jan 21, 2026 |
| 0.0.0-13 | Dec 24, 2025 |
#1282 in Rust patterns
Used in tvid
18KB
231 lines
data-classes
data-classes provides a single, ergonomic attribute macro #[data] that simplifies common boilerplate for plain data structs and enums.
The #[data] macro is the primary feature of this crate. It acts as a concise, configurable shortcut for deriving common traits, controlling ABI/layout, and generating small helper methods (like new and Default). It can also opt in to integrations such as serde, rkyv, and bytemuck behind feature flags.
Overview
- Purpose: Reduce repetitive
deriveand small impl boilerplate for simple data types. - Primary interface: the attribute macro
#[data(...)]placed on structs or enums. - Behavior: depending on attributes and crate feature flags,
#[data]will add#[repr(...)],#[derive(...)], and optionally generateimplblocks (e.g.Default,new,Display).
Key features
- Automatic derives:
Debug,Clone,PartialEq,Eq,PartialOrd,Ord,Hashare derived by default. - Layout control: add
reproptions such asraw(C),packed,transparent, or integer-backedu8/u16/...via the macro. Defaulthandling:#[data(default)]either derivesDefaultor generates a customDefaultimpl when field-level defaults are present.- Constructor generation:
#[data(new)]creates apub fn new(...) -> Selffor structs with named fields;#[data(new(default))]generatesnew()delegating toDefault. - Display helpers:
#[data(display(...))]supportsdebug,comma,semicolon, andspacevariants to quickly implementDisplay. - Deref helpers:
#[deref]/#[deref(mut)]on a field generateDeref/DerefMutto that field. - Validation helpers:
#[data(validate)]generatesvalidate(), with field checks from#[check = ...]. - Accessor helpers:
#[get],#[get(mut)],#[set],#[with], or#[access(...)]generate getters/setters and chainable builders. - Builder helpers:
#[data(builder)]generatesXxxBuilderwithwith_xxx()andbuild(). - Optional integrations (behind features):
serdesupport,rkyvsupport (with additional per-attribute options), andbytemucksupport (pod,zeroable).
Supported attributes
You can combine multiple options inside the #[data(...)] attribute. Examples of supported options include:
raw— apply#[repr(C)].packed— apply#[repr(packed)].transparent— apply#[repr(transparent)].u8,u16,u32,u64,usize,i8,i16,i32,i64,isize— use a specific integerrepr.default— derive or implementDefault(field-level defaults may produce a customDefault).copy— deriveCopy.no-ord— skip derivingPartialOrdandOrd.no-eq— skip derivingPartialEqandEq.serde— (requiresserdefeature) deriveSerializeandDeserialize.rkyv(...)— (requiresrkyvfeature) enablesrkyvderives and accepts sub-options likeno-cmpandomit-bounds.pod,zeroable— (requirebytemuckfeature) derivebytemuck::Pod/bytemuck::Zeroableand may adjustrepras needed.display(debug)— implementDisplayby formatting with{:?}.display(comma|semicolon|space)— implementDisplayby joining struct fields with,,;, or space respectively.newandnew(default)— generatenewconstructors. Field-levelnew_valueand defaults are supported for more fine-grained constructor generation.validate— generate avalidate()method (see#[check = ...]).builder— generate aXxxBuilderwithwith_xxx()andbuild().
Field-level attributes (named structs):
#[default = expr]— set a field default (used by#[data(default)]/#[default]).#[new = expr]/#[new = _]— set a field initializer fornew.#[deref]/#[deref(mut)]— select the deref target.#[check = expr]— attach a boolean check used byvalidate,set, andwith.#[get]/#[get(mut)]— generateget_xxx()andget_xxx_mut().#[set]— generateset_xxx(value).#[with]— generatewith_xxx(value) -> Self.#[access]— shorthand forget + set.#[access(get,set,with)]/#[access(get(mut))]— explicit accessor selection.#[builder(default)]— initialize builder field withDefault::default()instead ofOption.
Examples
Use only the default derives.
For example:
#[data]
pub struct Color {
r: u8,
g: u8,
b: u8,
}
Will expand to:
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Color {
r: u8,
g: u8,
b: u8,
}
Add more options to generate additional code.
For example:
#[data(new, default, serde, rkyv(cmp), pod)]
pub struct Color {
r: u8,
g: u8,
b: u8,
}
Will expand to:
#[repr(C)]
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize, serde::Serialize, serde::Deserialize, bytemuck::Pod, bytemuck::Zeroable, Copy)]
#[rkyv(derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash), compare(PartialEq, PartialOrd))]
pub struct Color {
r: u8,
g: u8,
b: u8,
}
impl Color {
pub fn new(r: u8, g: u8, b: u8) -> Self {
Self { r, g, b }
}
}
Accessor and validation helpers:
#[data(validate)]
struct User {
#[check = name.len() > 0]
name: String,
#[check = *age >= 18]
age: u8,
}
#[data]
struct Settings {
#[get]
name: String,
#[access(get(mut), set, with)]
#[check = tag.len() < 8]
tag: String,
}
Builder helper:
#[data(builder)]
struct Project {
#[builder(default)]
tags: Vec<String>,
name: String,
}
let p = Project::builder()
.with_name("demo".to_string())
.build();
Dependencies
~0.5–1.3MB
~28K SLoC