statenum
, short for "state-enum", is a procedural macro attribute that generates a trait and a struct for each variant of an enum.
Add the following dependencies to your Cargo.toml
file:
toml
[dependencies]
statenum = "1.0"
To use statenum
, add the #[statenum]
attribute to your enum definition.
By default, the generated trait will be named State
.
You can override this by providing a name as an argument to the macro.
```rust use statenum::statenum;
enum RocketStage { Grounded, Launched, // and so on... }
enum PayloadStage { Vacant, Packed, // and so on... } ```
This will generate a trait named State
and a struct for each variant of the enum.
The visibility of the enum carries through to the implementation of statenum
.
If the enum is marked as pub
, the resulting struct variants and trait will also be marked as pub
.
However, if the enum isn't public then neither will the resulting components.
```rust mod hidden { use statenum::statenum;
#[statenum]
enum RocketStage {
Grounded,
Launched,
}
pub struct Rocket<Stage: State = Grounded> {
stage: Stage,
}
}
// This would cause an error because the enum RocketStage
is marked as private.
// let grounded: hidden::Rocket
// The same applies to the trait. // trait PayloadState: hidden::State {} ```
Normally, the state pattern in Rust requires the use of multiple struct definitions. The example below demonstrates the typical method of implementing the state pattern and is taken from the book 'Rust for Rustaceans' by Jon Gjengset.
```rust use std::marker::PhantomData;
struct Grounded; struct Launched; // and so on...
pub struct Rocket
impl
impl Rocket
impl Rocket
pub fn decelerate(&mut self) {
// ...
}
} ```
Using the macro without any trait name specified will create a trait under the name of State
, like so (intentionally ignoring the PhantomData
aspect):
```rust use statenum::statenum;
enum RocketStage { Grounded, Launched, // and so on... }
pub struct Rocket
impl
impl Rocket
impl Rocket
pub fn decelerate(&mut self) {
// ...
}
} ```
Otherwise, if you would prefer to name the trait something other than State
, you can accomplish that by specifying a name:
```rust use statenum::statenum;
enum RocketStage { Grounded, Launched, // and so on... }
pub struct Rocket
impl
impl Rocket
impl Rocket
pub fn decelerate(&mut self) {
// ...
}
} ```
statenum
is distributed under the terms of the MIT license.