#![allow(dead_code)]
use domainstack_derive::ToSchema;
use domainstack_schema::OpenApiBuilder;
#[derive(ToSchema)]
#[schema(description = "User registration request")]
struct UserRegistration {
#[validate(email)]
#[validate(max_len = 255)]
#[schema(description = "Valid email address", example = "alice@example.com")]
email: String,
#[validate(alphanumeric)]
#[validate(min_len = 3)]
#[validate(max_len = 20)]
#[schema(description = "Unique username", example = "alice123")]
username: String,
#[validate(range(min = 18, max = 120))]
#[schema(description = "User's age")]
age: u8,
#[validate(min_len = 1)]
#[validate(max_len = 100)]
#[schema(description = "Optional display name", example = "Alice Smith")]
display_name: Option<String>,
}
#[derive(ToSchema)]
#[schema(description = "Physical mailing address")]
struct Address {
#[validate(min_len = 1)]
#[validate(max_len = 200)]
#[schema(description = "Street address", example = "123 Main St")]
street: String,
#[validate(min_len = 1)]
#[validate(max_len = 100)]
#[schema(description = "City name", example = "San Francisco")]
city: String,
#[validate(alphanumeric)]
#[validate(min_len = 5)]
#[validate(max_len = 10)]
#[schema(description = "Postal code", example = "94102")]
postal_code: String,
#[validate(min_len = 2)]
#[validate(max_len = 2)]
#[schema(description = "Two-letter country code", example = "US")]
country: String,
}
#[derive(ToSchema)]
#[schema(description = "Complete user profile")]
struct UserProfile {
#[validate(email)]
#[validate(max_len = 255)]
email: String,
#[validate(nested)]
#[schema(description = "User's primary address")]
address: Address,
#[validate(nested)]
#[schema(description = "Optional billing address")]
billing_address: Option<Address>,
}
#[derive(ToSchema)]
struct Tag {
#[validate(alphanumeric)]
#[validate(min_len = 1)]
#[validate(max_len = 50)]
#[schema(description = "Tag name", example = "rust")]
name: String,
#[validate(min_len = 0)]
#[validate(max_len = 200)]
#[schema(description = "Tag description")]
description: String,
}
#[derive(ToSchema)]
#[schema(description = "Blog post with tags")]
struct BlogPost {
#[validate(min_len = 1)]
#[validate(max_len = 200)]
#[schema(description = "Post title", example = "Getting Started with Rust")]
title: String,
#[validate(min_len = 1)]
#[validate(max_len = 10000)]
#[schema(description = "Post content")]
content: String,
#[validate(each_nested)]
#[validate(min_items = 1)]
#[validate(max_items = 10)]
#[schema(description = "Post tags")]
tags: Vec<Tag>,
}
#[derive(ToSchema)]
#[schema(description = "Product in the catalog")]
struct Product {
#[validate(alphanumeric)]
#[validate(min_len = 3)]
#[validate(max_len = 20)]
#[schema(description = "Unique product SKU", example = "WIDGET123")]
sku: String,
#[validate(min_len = 1)]
#[validate(max_len = 200)]
#[schema(description = "Product name", example = "Acme Widget")]
name: String,
#[validate(min_len = 0)]
#[validate(max_len = 2000)]
#[schema(description = "Product description")]
description: String,
#[validate(range(min = 1, max = 1000000))]
#[schema(description = "Price in cents", example = 1999)]
price: i32,
#[validate(range(min = 0, max = 100000))]
#[schema(description = "Available quantity")]
stock: u32,
}
#[derive(ToSchema)]
struct CartItem {
#[validate(nested)]
product: Product,
#[validate(range(min = 1, max = 100))]
#[schema(description = "Quantity to purchase")]
quantity: u8,
}
#[derive(ToSchema)]
#[schema(description = "User's shopping cart")]
struct ShoppingCart {
#[validate(each_nested)]
#[validate(min_items = 1)]
#[validate(max_items = 50)]
#[schema(description = "Items in cart")]
items: Vec<CartItem>,
#[validate(alphanumeric)]
#[validate(min_len = 4)]
#[validate(max_len = 20)]
#[schema(description = "Optional promo code", example = "SAVE10")]
promo_code: Option<String>,
}
#[derive(ToSchema)]
#[schema(description = "API authentication credentials")]
struct ApiCredentials {
#[validate(alphanumeric)]
#[validate(min_len = 32)]
#[validate(max_len = 64)]
#[schema(description = "API key (alphanumeric)", example = "abc123xyz789")]
api_key: String,
#[validate(ascii)]
#[validate(min_len = 32)]
#[validate(max_len = 128)]
#[schema(description = "API secret (ASCII)", example = "secret_value_here")]
api_secret: String,
#[validate(url)]
#[schema(
description = "Service endpoint URL",
example = "https://api.example.com"
)]
service_url: String,
}
#[derive(ToSchema)]
#[schema(description = "Article with collections")]
struct Article {
#[validate(min_len = 1)]
#[validate(max_len = 200)]
#[schema(description = "Article title", example = "Rust Best Practices")]
title: String,
#[validate(min_items = 1)]
#[validate(max_items = 5)]
#[schema(description = "Author email addresses")]
author_emails: Vec<String>,
#[schema(description = "Content tags", example = r#"["rust", "validation"]"#)]
tags: Vec<String>,
#[schema(description = "Related article links")]
related_links: Vec<String>,
#[schema(description = "SEO keywords")]
keywords: Vec<String>,
#[schema(description = "User ratings (1-5 stars)")]
ratings: Vec<u8>,
#[schema(description = "Daily view counts")]
daily_views: Vec<u32>,
}
fn main() {
let spec = OpenApiBuilder::new("Auto-Derive Example API", "1.0.0")
.description("Demonstrating automatic schema derivation from validation rules")
.register::<UserRegistration>()
.register::<Address>()
.register::<UserProfile>()
.register::<Tag>()
.register::<BlogPost>()
.register::<Product>()
.register::<CartItem>()
.register::<ShoppingCart>()
.register::<ApiCredentials>()
.register::<Article>()
.build();
match spec.to_json() {
Ok(json) => {
println!("OpenAPI Specification:");
println!("{}", json);
println!("\n======================");
println!("Key Features Demonstrated:");
println!("======================\n");
println!("[ok] Email validation → format: 'email'");
println!("[ok] URL validation → format: 'uri'");
println!("[ok] min_len/max_len → minLength/maxLength");
println!("[ok] range(min, max) → minimum/maximum");
println!("[ok] alphanumeric → pattern: '^[a-zA-Z0-9]*$'");
println!("[ok] ascii → pattern: '^[\\x00-\\x7F]*$'");
println!("[ok] min_items/max_items → minItems/maxItems");
println!("[ok] Optional<T> → excluded from required array");
println!("[ok] Nested types → $ref to component schema");
println!("[ok] Vec<T> with each_nested → array with $ref items");
println!("[ok] Vec<T> with each(rule) → array items with validation constraints");
println!("[ok] #[schema(...)] → descriptions and examples");
println!("\n======================");
println!("Registered Schemas:");
println!("======================\n");
println!("- UserRegistration: Basic validation (email, range, length)");
println!("- Address: String validation (length, patterns)");
println!("- UserProfile: Nested types (required and optional)");
println!("- Tag: Simple nested type");
println!("- BlogPost: Collections with nested items");
println!("- Product: E-commerce entity with price/stock");
println!("- CartItem: Nested product reference");
println!("- ShoppingCart: Complex collection with constraints");
println!("- ApiCredentials: Pattern validation (alphanumeric, ascii, url)");
println!("- Article: Collection item validation with each(rule)");
}
Err(e) => eprintln!("Error generating JSON: {}", e),
}
}