2 unstable releases

0.2.0 Jun 16, 2024
0.1.0 Dec 30, 2023

#22 in #downcast

Download history 27/week @ 2024-07-28 21/week @ 2024-08-04 111/week @ 2024-08-11 41/week @ 2024-08-18 55/week @ 2024-08-25 61/week @ 2024-09-01 84/week @ 2024-09-08 22/week @ 2024-09-15 128/week @ 2024-09-22 76/week @ 2024-09-29 381/week @ 2024-10-06 52/week @ 2024-10-13 45/week @ 2024-10-20 106/week @ 2024-10-27 107/week @ 2024-11-03

312 downloads per month
Used in 5 crates (via enum_downcast)

MIT/Apache

16KB
301 lines

enum_downcast

GitHub MIT/Apache 2.0 Crates.io docs.rs

Safe downcasting for enums

Example

#[derive(EnumDowncast)]
enum Enum {
    Player(Player),
    Enemy(Enemy),
    Items { vec: Vec<Item> }, // derived code will be identical to if it were `Items(Vec<Items>)`
    #[enum_downcast(skip)]
    Other,
}

let container = Enum::Player(Player { name: "Ryo".to_string() });
let _player_ref: &Player = container.downcast_ref::<Player>().unwrap();
let _player_mut: &mut Player = container.downcast_mut::<Player>().unwrap();
let player: Player = container.downcast::<Player>().unwrap();

You need derive feature to use the derive macro.

You can see more examples in /examples.

My favorite one is one about custom downcast that allows interesting behavior like: https://github.com/ryo33/enum_downcast/blob/75adcbc8d24adb4e9d7b3c873e92bfff0dde7882/examples/partial_custom_impl.rs#L44-L53

Features

  • completely #![no_std]
  • no unsafe code (like std::mem::transmute)
  • no dynamic dispatch
  • #[enum_downcast(skip)] to skip some variants (especially not downcastable ones)
  • enums with type parameters (see example)
  • custom downcast implementation without derive macro (see example)
  • partial custom downcast implementation for some variants with #[enum_downcast(skip)] (see example)
  • compatible with other macros, such as serde, strum, and enum_dispatch (see example with serde and strum and example with enum_dispatch)

There is one limitation: you cannot compile a code that downcasts an enum to any type not listed in the enum definition, because of the lack of the specialization in stable Rust. You can workaround this by using nightly compiler with min_specialization feature like this example. As of specialization stabilized in the future, this limitation will be cleared, and you don't need any boilerplate code like the example.

Dependencies

~240–690KB
~16K SLoC