Skip to content

Commit

Permalink
optional Mermaid diagrams
Browse files Browse the repository at this point in the history
  • Loading branch information
eugene-babichenko committed May 12, 2024
1 parent 5649858 commit f97d785
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ adheres to [Semantic Versioning][semver].
* A type alias `StateMachine` for `rust_fsm::StateMachine<Impl>` is now
generated inside the said module.
* Supplying ones own enums for state, input and output in the proc-macro (#10).
* An optional possibility to generate Mermaid diagrams.

## [0.6.2] - 2024-05-11
### Changed
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,13 @@ state_machine! {
}
```

#### Diagrams

`state_machine` macro can document your state machines with diagrams. This is
controlled by the `diagram` feature, which is non-default. The diagrams are
generated in the [Mermaid][mermaid] format. This feature includes the Mermaid
script into the documentation page.

### Without DSL

The `state_machine` macro has limited capabilities (for example, a state
Expand All @@ -197,3 +204,4 @@ You can see an example of the Circuit Breaker state machine in the
[docs-link]: https://docs.rs/rust-fsm
[crate-badge]: https://img.shields.io/crates/v/rust-fsm.svg
[crate-link]: https://crates.io/crates/rust-fsm
[mermaid]: https://mermaid.js.org/
3 changes: 3 additions & 0 deletions rust-fsm-dsl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ edition = "2018"
[lib]
proc-macro = true

[features]
diagram = []

[dependencies]
proc-macro2 = "1"
syn = "2"
Expand Down
32 changes: 32 additions & 0 deletions rust-fsm-dsl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ pub fn state_machine(tokens: TokenStream) -> TokenStream {
let mut transition_cases = Vec::new();
let mut output_cases = Vec::new();

#[cfg(feature = "diagram")]
let mut mermaid_diagram = format!(
"///```mermaid\n///stateDiagram-v2\n/// [*] --> {}\n",
input.initial_state
);

states.insert(&input.initial_state);

for transition in transitions {
Expand All @@ -67,6 +73,11 @@ pub fn state_machine(tokens: TokenStream) -> TokenStream {
output,
} = transition;

#[cfg(feature = "diagram")]
mermaid_diagram.push_str(&format!(
"/// {initial_state} --> {final_state}: {input_value}"
));

transition_cases.push(quote! {
(Self::State::#initial_state, Self::Input::#input_value) => {
Some(Self::State::#final_state)
Expand All @@ -79,8 +90,14 @@ pub fn state_machine(tokens: TokenStream) -> TokenStream {
Some(Self::Output::#output_value)
}
});

#[cfg(feature = "diagram")]
mermaid_diagram.push_str(&format!(" [{output_value}]"));
}

#[cfg(feature = "diagram")]
mermaid_diagram.push('\n');

states.insert(initial_state);
states.insert(final_state);
inputs.insert(input_value);
Expand All @@ -89,6 +106,11 @@ pub fn state_machine(tokens: TokenStream) -> TokenStream {
}
}

#[cfg(feature = "diagram")]
mermaid_diagram.push_str("///```");
#[cfg(feature = "diagram")]
let mermaid_diagram: proc_macro2::TokenStream = mermaid_diagram.parse().unwrap();

let initial_state_name = &input.initial_state;

let (input_type, input_impl) = match input.input_type {
Expand Down Expand Up @@ -139,7 +161,17 @@ pub fn state_machine(tokens: TokenStream) -> TokenStream {
}
};

#[cfg(feature = "diagram")]
let diagram = quote! {
#[cfg_attr(doc, rust_fsm::aquamarine)]
#mermaid_diagram
};

#[cfg(not(feature = "diagram"))]
let diagram = quote!();

let output = quote! {
#diagram
#visibility mod #fsm_name {
#attrs
pub struct Impl;
Expand Down
2 changes: 2 additions & 0 deletions rust-fsm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ edition = "2018"
default = ["std", "dsl"]
std = []
dsl = ["rust-fsm-dsl"]
diagram = ["aquamarine", "rust-fsm-dsl/diagram"]

[dependencies]
aquamarine = { version = "*", optional = true }
rust-fsm-dsl = { path = "../rust-fsm-dsl", version = "0.6.2", optional = true }

[profile.dev]
Expand Down
3 changes: 3 additions & 0 deletions rust-fsm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ use std::error::Error;
#[cfg(feature = "dsl")]
pub use rust_fsm_dsl::state_machine;

#[cfg(feature = "diagram")]
pub use aquamarine::aquamarine;

/// This trait is designed to describe any possible deterministic finite state
/// machine/transducer. This is just a formal definition that may be
/// inconvenient to be used in practical programming, but it is used throughout
Expand Down

0 comments on commit f97d785

Please sign in to comment.