| Crates.io | holda |
| lib.rs | holda |
| version | 0.1.0 |
| created_at | 2025-04-18 22:59:53.893018+00 |
| updated_at | 2025-04-18 22:59:53.893018+00 |
| description | Convenience macros for creating domain objects with serde support. |
| homepage | |
| repository | https://github.com/TeamDman/holda.git |
| max_upload_size | |
| id | 1640048 |
| size | 48,851 |
Holda is a Rust library that provides convenience macros for creating domain objects, especially those that wrap existing types, with built-in support for serde serialization and deserialization. It simplifies the process of creating value types with common trait implementations, reducing boilerplate and improving code readability.
StringHolda and Holda derive macros automatically implement common traits like From, AsRef, Deref, Display, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, and Clone.serde Support: Easily enable serde serialization and deserialization for your wrapper types with the serde feature.#[holda(...)] attribute.StringHolda macro is optimized for creating wrappers around String types, providing FromStr implementations.Add holda to your Cargo.toml:
[dependencies]
holda = "0.1.0"
StringHolda MacroThe StringHolda macro is designed for structs that hold a String. It automatically implements traits and provides FromStr implementation.
use holda::StringHolda;
#[derive(StringHolda)]
struct UserName {
inner: String,
}
fn main() {
let name = "bruh";
let user_name: UserName = name.parse().unwrap();
assert_eq!(*user_name, name);
let user_name = UserName::from(name);
assert_eq!(*user_name, name);
}
With the serde feature enabled, you can serialize and deserialize the UserName struct:
use holda::StringHolda;
use serde::Deserialize;
use serde::Serialize;
#[derive(StringHolda, Serialize, Deserialize, Debug, PartialEq)]
struct UserName {
inner: String,
}
fn main() {
let data = r#"
{
"inner": "Bruh"
}
"#;
let user_name: UserName = serde_json::from_str(data).unwrap();
println!("{:?}", user_name);
assert_eq!(*user_name, "Bruh");
}
Holda MacroThe Holda macro is more generic and can be used with any type. It requires specifying the field name as inner.
use holda::Holda;
use uuid::Uuid;
#[derive(Holda)]
struct MyUuidWrapper {
inner: Uuid,
}
fn main() {
let uuid = Uuid::new_v4();
let wrapper = MyUuidWrapper::new(uuid);
assert_eq!(*wrapper, uuid);
}
You can skip trait implementations using the #[holda(...)] attribute:
use holda::Holda;
#[derive(Holda)]
#[holda(NoDisplay, NoEq, NoOrd, NoHash)]
struct MyUnitWrapper {
inner: (),
}
fn main() {
let wrapper = MyUnitWrapper::new(());
assert_eq!(*wrapper, ());
}
serde FeatureTo enable serde support, add the serde feature to your Cargo.toml:
[dependencies]
holda = { version = "0.1.0", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] } # required
serde_json = "1.0" # required for testing
Now, the generated code will include serde::Serialize and serde::Deserialize implementations for your wrapper types.
You can use the #[holda(...)] attribute to skip specific trait implementations. The following options are available:
NoDisplay: Skips implementing Display.NoEq: Skips implementing PartialEq and Eq.NoOrd: Skips implementing PartialOrd and Ord.NoHash: Skips implementing Hash.NoClone: Skips implementing Clone.
NoSerde: Skips implementing Serialize and Deserialize.This project is licensed under the MPL-2.0 License. See the LICENSE file for details.