3 stable releases
| 1.1.1 | Jan 7, 2026 |
|---|---|
| 1.0.0 | Jan 6, 2026 |
#33 in #dto
Used in 4 crates
125KB
2.5K
SLoC
domainstack-derive
Derive macros for the domainstack full-stack validation ecosystem.
Provides two derive macros that share the same unified rich syntax:
#[derive(Validate)]- Runtime validation#[derive(ToSchema)]- OpenAPI schema generation
Usage
Add this to your Cargo.toml:
[dependencies]
domainstack = { version = "1.0", features = ["derive"] } # Includes Validate
domainstack-derive = "1.0" # Adds ToSchema derive
domainstack-schema = "1.0" # Schema builder utilities
Validation Only
use domainstack::Validate;
#[derive(Validate)]
struct User {
#[validate(email)]
#[validate(max_len = 255)]
email: String,
#[validate(range(min = 18, max = 120))]
age: u8,
#[validate(min_len = 3)]
#[validate(max_len = 50)]
name: String,
}
Validation + Schema Generation (Unified Syntax)
NEW: Write validation rules ONCE, get BOTH runtime validation AND OpenAPI schemas:
use domainstack_derive::{Validate, ToSchema};
#[derive(Validate, ToSchema)]
struct User {
#[validate(email)] // [ok] Works for both validation and schema
#[validate(max_len = 255)]
#[schema(description = "User's email", example = "alice@example.com")]
email: String,
#[validate(range(min = 18, max = 120))]
#[schema(description = "User's age")]
age: u8,
#[validate(min_len = 3)]
#[validate(max_len = 50)]
name: String,
}
// Runtime validation works
user.validate()?;
// Schema generation works
let schema = User::schema();
// → email: { type: "string", format: "email", maxLength: 255, ... }
// → age: { type: "integer", minimum: 18, maximum: 120 }
Available Attributes
Validation Rules (Unified Rich Syntax)
Both Validate and ToSchema support these validation rules:
String Rules:
#[validate(email)]- Email format#[validate(url)]- URL format#[validate(min_len = n)]- Minimum length#[validate(max_len = n)]- Maximum length#[validate(alphanumeric)]- Alphanumeric only#[validate(ascii)]- ASCII only#[validate(alpha_only)]- Letters only#[validate(numeric_string)]- Digits only#[validate(non_empty)]- Not empty#[validate(non_blank)]- Not blank (no whitespace)#[validate(matches_regex = "pattern")]- Custom regex- Plus:
contains,starts_with,ends_with,no_whitespace
Numeric Rules:
#[validate(range(min = a, max = b))]- Range validation#[validate(positive)]- Positive numbers#[validate(negative)]- Negative numbers#[validate(non_zero)]- Not zero#[validate(multiple_of = n)]- Multiple of n- Plus:
min,max,finite,equals,not_equals
Collection Rules:
#[validate(min_items = n)]- Minimum items#[validate(max_items = n)]- Maximum items#[validate(unique)]- All items unique
Composite Rules:
#[validate(nested)]- Validate nested struct#[validate(each(nested))]- Validate each item in collection (for nested types)#[validate(each(rule))]- Validate each item with any rule (for primitives)#[validate(custom = "function")]- Custom validation function
Collection Item Validation:
The each(rule) syntax allows validating each item in a collection:
#[derive(Validate)]
struct BlogPost {
// Validate each email in the list
#[validate(each(email))]
author_emails: Vec<String>,
// Validate each tag length
#[validate(each(length(min = 1, max = 50)))]
tags: Vec<String>,
// Validate each URL
#[validate(each(url))]
related_links: Vec<String>,
// Validate each item is alphanumeric
#[validate(each(alphanumeric))]
keywords: Vec<String>,
}
Error paths include array indices: tags[0], author_emails[1], etc.
Legacy Syntax (Still Supported):
#[validate(length(min = a, max = b))]- String length (prefermin_len/max_len)
Schema Hints
For ToSchema, add documentation metadata:
#[schema(description = "Field description")]
#[schema(example = "example value")]
#[schema(deprecated = true)]
#[schema(read_only = true)]
#[schema(write_only = true)]
Struct-Level Validation
#[derive(Validate)]
#[validate(
check = "self.password == self.password_confirmation",
code = "passwords_mismatch",
message = "Passwords must match"
)]
struct RegisterForm {
#[validate(min_len = 8)]
password: String,
password_confirmation: String,
}
Documentation
This is a proc macro implementation crate. For complete documentation, examples, and usage guides, see:
License
Apache 2.0
Dependencies
~130–590KB
~14K SLoC