{"id":14992285,"url":"https://github.com/eugene-babichenko/rust-fsm","last_synced_at":"2026-03-17T23:36:58.428Z","repository":{"id":41390297,"uuid":"166660853","full_name":"eugene-babichenko/rust-fsm","owner":"eugene-babichenko","description":"Finite state machine framework for Rust with readable specifications","archived":false,"fork":false,"pushed_at":"2024-06-13T19:09:29.000Z","size":235,"stargazers_count":184,"open_issues_count":1,"forks_count":22,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-01-01T22:16:26.562Z","etag":null,"topics":["dsl","fsm","proc-macro","rust","state-machine"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eugene-babichenko.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-01-20T12:51:27.000Z","updated_at":"2024-12-31T21:29:20.000Z","dependencies_parsed_at":"2024-06-13T22:00:47.605Z","dependency_job_id":null,"html_url":"https://github.com/eugene-babichenko/rust-fsm","commit_stats":{"total_commits":90,"total_committers":6,"mean_commits":15.0,"dds":0.5111111111111111,"last_synced_commit":"df92411da28bc2dafea1246d4046bc9c926bb4e9"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eugene-babichenko%2Frust-fsm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eugene-babichenko%2Frust-fsm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eugene-babichenko%2Frust-fsm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eugene-babichenko%2Frust-fsm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eugene-babichenko","download_url":"https://codeload.github.com/eugene-babichenko/rust-fsm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234200176,"owners_count":18795139,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dsl","fsm","proc-macro","rust","state-machine"],"created_at":"2024-09-24T15:00:54.376Z","updated_at":"2025-09-25T14:31:02.301Z","avatar_url":"https://github.com/eugene-babichenko.png","language":"Rust","funding_links":["https://www.buymeacoffee.com/ybabichenko"],"categories":["Finite State Machine"],"sub_categories":[],"readme":"# A framework and a DSL for building finite state machines in Rust\n\n[![Documentation][docs-badge]][docs-link]\n[![Latest Version][crate-badge]][crate-link]\n\n[![\"Buy Me A Coffee\"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/ybabichenko)\n\nThe `rust-fsm` crate provides a simple and universal framework for building\nstate machines in Rust with minimum effort.\n\nThe essential part of this crate is the\n[`StateMachineImpl`](trait.StateMachineImpl.html) trait. This trait allows a\ndeveloper to provide a strict state machine definition, e.g. specify its:\n\n- An input alphabet - a set of entities that the state machine takes as inputs\n  and performs state transitions based on them.\n- Possible states - a set of states this machine could be in.\n- An output alphabet - a set of entities that the state machine may output as\n  results of its work.\n- A transition function - a function that changes the state of the state machine\n  based on its current state and the provided input.\n- An output function - a function that outputs something from the output\n  alphabet based on the current state and the provided inputs.\n- The initial state of the machine.\n\nNote that on the implementation level such abstraction allows build any type of\nstate machines:\n\n- A classical state machine by providing only an input alphabet, a set of states\n  and a transition function.\n- A Mealy machine by providing all entities listed above.\n- A Moore machine by providing an output function that do not depend on the\n  provided inputs.\n\n## Feature flags\n\n### Default\n\n- `std` - implement features that require the `std` environment. See below.\n- `dsl` - re-export `rust-fsm-dsl` from `rust-fsm`. Recommended to leave this on\n  for the best development experience.\n\n### Non-default\n\n- `diagram` - generate Mermaid state diagrams in the doc strings. See below.\n\n## Usage in `no_std` environments\n\nThis library has the feature named `std` which is enabled by default. You may\nwant to import this library as\n`rust-fsm = { version = \"0.8\", default-features = false, features = [\"dsl\"] }`\nto use it in a `no_std` environment. This only affects error types (the `Error`\ntrait is only available in `std`).\n\nThe DSL implementation re-export is gated by the feature named `dsl` which is\nalso enabled by default.\n\n## Use\n\nInitially this library was designed to build an easy to use DSL for defining\nstate machines on top of it. Using the DSL will require to connect an additional\ncrate `rust-fsm-dsl` (this is due to limitation of the procedural macros\nsystem).\n\n### Using the DSL for defining state machines\n\nThe DSL is parsed by the `state_machine` macro. Here is a little example.\n\n```rust\nuse rust_fsm::*;\n\nstate_machine! {\n    #[derive(Debug)]\n    #[repr(C)]\n    /// A Circuit Breaker state machine.\n    circuit_breaker(Closed)\n\n    Closed(Unsuccessful) =\u003e Open [SetupTimer],\n    Open(TimerTriggered) =\u003e HalfOpen,\n    HalfOpen =\u003e {\n        Successful =\u003e Closed,\n        Unsuccessful =\u003e Open [SetupTimer]\n    }\n}\n```\n\nThis code sample:\n\n- Defines a state machine called `circuit_breaker`;\n- Derives the `Debug` trait for it. All attributes you use here (like\n  `#[repr(C)]`) will be applied to all types generated by this macro. If you\n  want to apply attributes or a docstring to the `mod` generated by this macro,\n  just put it before the macro invocation.\n- Sets the initial state of this state machine to `Closed`;\n- Defines state transitions. For example: on receiving the `Successful` input\n  when in the `HalfOpen` state, the machine must move to the `Closed` state;\n- Defines outputs. For example: on receiving `Unsuccessful` in the `Closed`\n  state, the machine must output `SetupTimer`.\n\nThis state machine can be used as follows:\n\n```rust,ignore\n// Initialize the state machine. The state is `Closed` now.\nlet mut machine = circuit_breaker::StateMachine::new();\n// Consume the `Successful` input. No state transition is performed.\nlet _ = machine.consume(\u0026circuit_breaker::Input::Successful);\n// Consume the `Unsuccesful` input. The machine is moved to the `Open`\n// state. The output is `SetupTimer`.\nlet output = machine.consume(\u0026circuit_breaker::Input::Unsuccessful).unwrap();\n// Check the output\nif let Some(circuit_breaker::Output::SetupTimer) = output {\n    // Set up the timer...\n}\n// Check the state\nif let circuit_breaker::State::Open = machine.state() {\n    // Do something...\n}\n```\n\nThe following entities are generated:\n\n- An empty structure `circuit_breaker::Impl` that implements the\n  `StateMachineImpl` trait.\n- Enums `circuit_breaker::State`, `circuit_breaker::Input` and\n  `circuit_breaker::Output` that represent the state, the input alphabet and the\n  output alphabet respectively.\n- Type alias `circuit_breaker::StateMachine` that expands to\n  `StateMachine\u003ccircuit_breaker::Impl\u003e`.\n\nNote that if there is no outputs in the specification, the output alphabet is an\nempty enum and due to technical limitations of many Rust attributes, no\nattributes (e.g. `derive`, `repr`) are applied to it.\n\nWithin the `state_machine` macro you must define at least one state transition.\n\n#### Visibility\n\nYou can specify visibility like this:\n\n```rust\nuse rust_fsm::*;\n\nstate_machine! {\n    pub CircuitBreaker(Closed)\n\n    Closed(Unsuccessful) =\u003e Open [SetupTimer],\n    Open(TimerTriggered) =\u003e HalfOpen,\n    HalfOpen =\u003e {\n        Successful =\u003e Closed,\n        Unsuccessful =\u003e Open [SetupTimer],\n    }\n}\n```\n\nThe default visibility is private.\n\n#### Custom alphabet types\n\nYou can supply your own types to use as input, output or state. All of them are\noptional: you can use only one of them or all of them at once if you want to.\nThe current limitation is that you have to supply a fully qualified type path.\n\n```rust,ignore\nuse rust_fsm::*;\n\npub enum Input {\n    Successful,\n    Unsuccessful,\n    TimerTriggered,\n}\n\npub enum State {\n    Closed,\n    HalfOpen,\n    Open,\n}\n\npub enum Output {\n    SetupTimer,\n}\n\nstate_machine! {\n    #[state_machine(input(crate::Input), state(crate::State), output(crate::Output))]\n    circuit_breaker(Closed)\n\n    Closed(Unsuccessful) =\u003e Open [SetupTimer],\n    Open(TimerTriggered) =\u003e HalfOpen,\n    HalfOpen =\u003e {\n        Successful =\u003e Closed,\n        Unsuccessful =\u003e Open [SetupTimer]\n    }\n}\n```\n\n#### Diagrams\n\n`state_machine` macro can document your state machines with diagrams. This is\ncontrolled by the `diagram` feature, which is non-default. The diagrams are\ngenerated in the [Mermaid][mermaid] format. This feature includes the Mermaid\nscript into the documentation page.\n\nTo see this in action, download the repository and run:\n\n```bash\ncargo doc -p doc-example --open\n```\n\n![image](doc-diagram-example.png)\n\n### Without DSL\n\nThe `state_machine` macro has limited capabilities (for example, a state cannot\ncarry any additional data), so in certain complex cases a user might want to\nwrite a more complex state machine by hand.\n\nAll you need to do to build a state machine is to implement the\n`StateMachineImpl` trait and use it in conjuctions with some of the provided\nwrappers (for now there is only `StateMachine`).\n\nYou can see an example of the Circuit Breaker state machine in the [project\nrepository][repo].\n\n[repo]: https://github.com/eugene-babichenko/rust-fsm\n[docs-badge]: https://docs.rs/rust-fsm/badge.svg\n[docs-link]: https://docs.rs/rust-fsm\n[crate-badge]: https://img.shields.io/crates/v/rust-fsm.svg\n[crate-link]: https://crates.io/crates/rust-fsm\n[mermaid]: https://mermaid.js.org/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feugene-babichenko%2Frust-fsm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feugene-babichenko%2Frust-fsm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feugene-babichenko%2Frust-fsm/lists"}