Lines
0 %
Functions
Branches
100 %
use supp_macro::command;
#[derive(Debug)]
pub enum CmdError {
Args(String),
}
impl std::fmt::Display for CmdError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
CmdError::Args(msg) => write!(f, "Argument error: {}", msg),
impl std::error::Error for CmdError {}
pub enum CmdResult {
Success(String),
Value(i64),
// Define commands using the progressive types approach
command! {
CreateUser {
#[required]
username: String,
email: String,
#[optional]
is_admin: bool,
} => {
let admin_status = is_admin.unwrap_or(false);
Ok(Some(CmdResult::Success(format!(
"Created user {} with email {} (admin: {})",
username, email, admin_status
))))
GetVersion {
Ok(Some(CmdResult::Success("v1.0.0".to_string())))
Calculate {
a: i64,
b: i64,
Ok(Some(CmdResult::Value(a + b)))
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("š Progressive Types Command Demo");
println!("===================================");
// ā SIMPLE INTERFACE - No Args types visible to users!
println!("\n1. Simple command with no arguments:");
let result = GetVersion::new().run().await?;
println!(" Result: {:?}", result);
println!("\n2. Command with required arguments (compile-time validated):");
let result = Calculate::new()
.a(10) // ā i64 type enforced at compile time
.b(20) // ā i64 type enforced at compile time
.run() // ā Only available when all required fields set
.await?;
println!("\n3. Command with mixed required and optional arguments:");
let result = CreateUser::new()
.username("alice".to_string()) // ā Required
.email("alice@example.com".to_string()) // ā Required
.is_admin(true) // ā Optional
.run()
println!("\n4. Same command with minimal arguments (optional fields omitted):");
.username("bob".to_string()) // ā Required
.email("bob@example.com".to_string()) // ā Required
// is_admin omitted - will be None/false
println!("\nā Features demonstrated:");
println!(" - Zero Args type naming (users never see *Args structs)");
println!(" - Compile-time type validation (wrong types = compile error)");
println!(" - Compile-time required field validation (missing fields = compile error)");
println!(" - Zero runtime checks (direct field access, no unwrap())");
println!(" - Clean, intuitive interface (Command::new().field().run())");
// Uncomment these to see compile-time errors:
// ā This would NOT compile - missing required field:
// let result = CreateUser::new()
// .username("incomplete".to_string())
// .run() // ERROR: no method named `run` found
// .await?;
// ā This would NOT compile - wrong type:
// let result = Calculate::new()
// .a("not_a_number") // ERROR: expected `i64`, found `&str`
// .b(20)
// .run()
// ā This would NOT compile - method doesn't exist:
// let result = GetVersion::new()
// .invalid_method("test") // ERROR: no method named `invalid_method`
Ok(())