The Ultimate Builder Pattern Implementation Powered by Rust's Type System
Eliminate bugs at the type level and revolutionize your development experience
Traditional builder patterns can't detect missing required fields until runtime. TypeSafe Builder leverages Rust's powerful type system to verify all constraints at compile time.
// β Traditional builder - potential runtime errors
let user = UserBuilder::new()
.name("Alice")
.build()?; // Compiles even with missing required fields
// β
TypeSafe Builder - compile-time safety guarantee
let user = UserBuilder::new()
.with_name("Alice".to_string())
.with_email("[email protected]".to_string()) // Compile error if email is required
.build(); // Always guaranteed to succeed- Required Fields - Completely prevent missing required field configuration
- Optional Fields - Freely configurable fields
- Default Values - Fields with intelligent default values using any Rust expression
- Conditional Requirements - Express dynamic dependencies at the type level
- Complex Logic - Support for AND/OR/NOT operators in complex conditional expressions
- Zero Runtime Cost - All validation completed at compile time
- No Panic - Complete elimination of runtime panics
[dependencies]
typesafe_builder = "*.*.*" # Replace with the actual versionuse typesafe_builder::*;
#[derive(Builder)]
struct User {
#[builder(required)]
name: String,
#[builder(optional)]
age: Option<u32>,
#[builder(default = "String::from(\"[email protected]\")")]
email: String,
}
// Type-safe builder pattern
let user = UserBuilder::new()
.with_name("Alice".to_string())
.with_age(30)
.build(); // email will be "[email protected]"use typesafe_builder::*;
#[derive(Builder)]
struct Account {
#[builder(optional)]
email: Option<String>,
#[builder(required_if = "email")] // Required when email is set
email_verified: Option<bool>,
}
// β
Compiles successfully
let account1 = AccountBuilder::new().build();
// β
Compiles successfully
let account2 = AccountBuilder::new()
.with_email("[email protected]".to_string())
.with_email_verified(true)
.build();
// β Compile error: email_verified is not set
// let account3 = AccountBuilder::new()
// .with_email("[email protected]".to_string())
// .build();use typesafe_builder::*;
#[derive(Builder)]
struct Config {
#[builder(optional)]
debug_mode: Option<bool>,
#[builder(optional_if = "debug_mode")] // Required when debug_mode is not set
log_level: Option<String>,
}
// β
When debug_mode is not set, log_level is required
let config1 = ConfigBuilder::new()
.with_log_level("INFO".to_string())
.build();
// β
When debug_mode is set, log_level is optional
let config2 = ConfigBuilder::new()
.with_debug_mode(true)
.build();use typesafe_builder::*;
#[derive(Builder)]
struct ApiClient {
#[builder(optional)]
use_auth: Option<bool>,
#[builder(optional)]
use_https: Option<bool>,
#[builder(optional)]
api_key: Option<String>,
// Secret is required if using auth OR HTTPS
#[builder(required_if = "use_auth || use_https")]
secret: Option<String>,
// Certificate is required only when using both auth AND HTTPS
#[builder(required_if = "use_auth && use_https")]
certificate: Option<String>,
// Warning is required when using neither auth NOR HTTPS
#[builder(required_if = "!use_auth && !use_https")]
insecure_warning: Option<String>,
// Complex condition: Token required when (auth OR HTTPS) AND (no API key)
#[builder(required_if = "(use_auth || use_https) && !api_key")]
fallback_token: Option<String>,
}
// β
All dependencies satisfied (auth + HTTPS)
let client1 = ApiClientBuilder::new()
.with_use_auth(true)
.with_use_https(true)
.with_api_key("key123".to_string())
.with_secret("secret456".to_string())
.with_certificate("cert.pem".to_string())
.build();
// β
Insecure configuration with warning
let client2 = ApiClientBuilder::new()
.with_use_auth(false)
.with_use_https(false)
.with_insecure_warning("WARNING: Insecure connection!".to_string())
.build();
// β
Using fallback token when API key is not set
let client3 = ApiClientBuilder::new()
.with_use_auth(true)
.with_secret("secret".to_string())
.with_fallback_token("backup_token".to_string())
.build();use typesafe_builder::*;
#[derive(Builder)]
struct ServerConfig {
#[builder(default = "String::from(\"localhost\")")]
host: String,
#[builder(default = "8080")]
port: u16,
#[builder(default = "vec![\"GET\".to_string(), \"POST\".to_string()]")]
allowed_methods: Vec<String>,
#[builder(default = "std::collections::HashMap::new()")]
headers: std::collections::HashMap<String, String>,
#[builder(required)]
service_name: String,
#[builder(optional)]
ssl_cert: Option<String>,
}
// β
Use default values
let config1 = ServerConfigBuilder::new()
.with_service_name("my-api".to_string())
.build();
// host: "localhost", port: 8080, allowed_methods: ["GET", "POST"], headers: {}
// β
Override some defaults
let config2 = ServerConfigBuilder::new()
.with_service_name("my-api".to_string())
.with_host("0.0.0.0".to_string())
.with_port(3000)
.build();
// host: "0.0.0.0", port: 3000, allowed_methods: ["GET", "POST"], headers: {}
// β
Complex default expressions
#[derive(Builder)]
struct AppConfig {
#[builder(default = "std::env::var(\"APP_NAME\").unwrap_or_else(|_| \"default-app\".to_string())")]
app_name: String,
#[builder(default = "chrono::Utc::now()")]
created_at: chrono::DateTime<chrono::Utc>,
#[builder(default = "uuid::Uuid::new_v4()")]
instance_id: uuid::Uuid,
}Key features of default values:
- Flexible expressions: Use any valid Rust expression as default value
- No type restrictions: Works with primitives, collections, function calls, etc.
- Environment variables: Access environment variables at build time
- Function calls: Call any function or method as default value
- Standalone attribute: Cannot be combined with
required,optional, etc.
use typesafe_builder::*;
#[derive(Builder)]
struct Database {
#[builder(optional)]
use_ssl: Option<bool>,
// Warning message required when NOT using SSL
#[builder(required_if = "!use_ssl")]
warning_message: Option<String>,
}
// β
Warning configuration for non-SSL usage
let db = DatabaseBuilder::new()
.with_use_ssl(false)
.with_warning_message("Insecure connection!".to_string())
.build();use typesafe_builder::*;
#[derive(Builder)]
#[builder(name = "MyCustomBuilder")] // Customize the builder name
struct User {
#[builder(required)]
name: String,
}
// Use the customized builder name
let user = MyCustomBuilder::new()
.with_name("Alice".to_string())
.build();#[derive(Builder)]
struct User {
#[builder(required)]
name: String,
}
// β Compile error
let user = UserBuilder::new().build();
// ^^^^^
// error: no method named `build` found for struct `UserBuilder<_TypesafeBuilderEmpty>`
// method `build` is available on `UserBuilder<_TypesafeBuilderFilled>`#[derive(Builder)]
struct Config {
#[builder(optional)]
feature: Option<bool>,
#[builder(required_if = "feature")]
config: Option<String>,
}
// β Compile error
let config = ConfigBuilder::new()
.with_feature(true)
.build();
// ^^^^^
// error: no method named `build` found for struct `ConfigBuilder<_TypesafeBuilderFilled, _TypesafeBuilderEmpty>`
// method `build` is available on `ConfigBuilder<_TypesafeBuilderFilled, _TypesafeBuilderFilled>`#[derive(Builder)]
struct ApiConfig {
#[builder(required)]
base_url: String,
#[builder(optional)]
use_auth: Option<bool>,
#[builder(required_if = "use_auth")]
api_key: Option<String>,
#[builder(required_if = "use_auth")]
secret: Option<String>,
#[builder(default = "30")]
timeout_seconds: u64,
#[builder(default = "String::from(\"application/json\")")]
content_type: String,
}#[derive(Builder)]
struct DatabaseConfig {
#[builder(required)]
host: String,
#[builder(required)]
database: String,
#[builder(default = "5432")]
port: u16,
#[builder(default = "10")]
max_connections: u32,
#[builder(optional)]
use_ssl: Option<bool>,
#[builder(required_if = "use_ssl")]
ssl_cert_path: Option<String>,
#[builder(optional_if = "!use_ssl")]
allow_insecure: Option<bool>,
}We welcome contributions to TypeSafe Builder!
git clone https://github.com/tomoikey/typesafe_builder.git
cd typesafe_builder
cargo test# Run all tests
cargo test
# UI tests (compile error verification)
cargo test --package typesafe_builder_derive --test uiAmazing developers who have contributed to this project:
tomoikey π§ Creator & Maintainer |
ramsyana π§ Contributor |
Your Name Here π Next Contributor |
Want to see your name here? Contribute now and join our amazing community!
MIT License - see the LICENSE file for details.
If you find this project useful, please consider giving it a β!
Type safety is not a luxury, it's a necessity.