typeswitch

Crates.iotypeswitch
lib.rstypeswitch
version0.1.0
created_at2026-01-07 02:05:29.146258+00
updated_at2026-01-07 02:05:29.146258+00
descriptionA powerful, Go-inspired macro for clean and declarative runtime type switching on dyn Any trait objects.
homepage
repositoryhttps://github.com/veecore/typeswitch
max_upload_size
id2027281
size17,269
Victor (veecore)

documentation

https://docs.rs/typeswitch

README

TypeSwitch for Rust

A powerful, Go-inspired macro to perform clean, declarative runtime type switching on dyn Any trait objects.

💡 The Inspiration

In Go, the type switch is a staple of the language:

switch v := i.(type) {
case int:
    fmt.Println("Integer:", v)
case string:
    fmt.Println("String:", v)
default:
    fmt.Println("Unknown")
}

In standard Rust, downcasting dyn Any usually requires a tedious chain of if-let blocks. typeswitch brings that ergonomic Go-style syntax to Rust while respecting Rust's strict rules on ownership, mutability, and borrowing.

🚀 Features

  • Clean Syntax: No more if let Some(x) = var.downcast_ref::<Type>() boilerplate.
  • Go-Style Binding: Automatically bind the downcasted value to a variable for all branches using the as keyword.
  • Mutability Control: Easily switch between immutable (&T) and mutable (&mut T) access.
  • Owned Consumption: Move values directly out of a Box<dyn Any>.
  • Or-Patterns: Match multiple types in a single branch (e.g., i32 | i64 => ...).

🛠 Usage

1. Automatic Binding (The "Go" Way)

By using v as subject, the identifier v is automatically bound to the concrete type in every branch.

use typeswitch::typeswitch;
use std::any::Any;

let x: Box<dyn Any> = Box::new(42i32);

typeswitch!(v as x {
    i32    => println!("It's an i32: {}", v + 1),
    String => println!("It's a string: {}", v.as_str()),
    _      => println!("Unknown type"),
});

2. Mutable Switching

Prefix the subject with mut to get mutable references in your branches.

let mut x: Box<dyn Any> = Box::new(100i32);

typeswitch!(mut v as x {
    i32 => { *v += 1; },
    _   => {},
});

3. Owned Consumption

Need the actual value? Use the box keyword. This consumes the Box if the type matches.

let x: Box<dyn Any> = Box::new(String::from("Ownership!"));

typeswitch! { x {
    box s: String => println!("Consumed string: {}", s),
    _ => println!("Not a string, box is still alive here."),
}}

4. Custom Bindings and Or-Patterns

You can define specific variable names for each arm and match multiple types.

typeswitch! { x {
    i32 | i64 => println!("Some integer"),
    s: String      => println!("String: {}", s),
    _              => println!("Fallback"),
}}

📦 Installation

Add this to your Cargo.toml:

[dependencies]
typeswitch = "0.1.0"

⚖️ License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

Commit count: 5

cargo fmt