LoganFlaherty/banish
A declarative framework for rule-based state machines in Rust.
7 Releases
Latest: 2mo ago
Banish v1.4.0v1.4.1Latest
๐ Changes
- Added a no_std attribute in the source code of banish to ensure compatibility with no_std environments.
- Added pattern matching in rule conditionals such as `rule ? let Some(data) = queue.pop() { ... }`.
- Refined documentation.
- Block Attributes `#![...]` added to configure the entire state machine in one place.
- Async support introduced via `#![async]`, enabling runtime-agnostic .await usage inside rule bodies.
- Runtime dispatch `#![dispatch(expr)]` added to dynamically set the starting state using an enum variant.
- BanishDispatch derive macro implemented to map PascalCase enum variants to snake_case state names automatically.
- Transition guards `=> @state if condition;` added to allow inline conditional jumps.
- + 7 more
Banish v1.3.0: Becoming a Frameworkv1.3.1
๐ฆ Block Attributes
- ```rust
- banish! {
- @fetch
- ...
- }
- ```
- ---
๐ฆ Async
- ```rust
- async fn main() {
- banish! {
- @fetch
- load? {
- let data = reqwest::get("https://example.com").await?;
- return data;
- }
- + 4 more
๐ฆ Dispatch and BanishDispatch
- ```rust
- enum PipelineState {
- Normalize,
- Validate,
- Finalize,
- }
- let entry = PipelineState::Validate;
- banish! {
- + 9 more
๐ฆ `#[banish::machine]`
- ```rust
- async fn pipeline() {
- banish! {
- @process
- step? { do_work().await; return; }
- }
- }
- ```
- + 1 more
๐ฆ Tracing
- ```
- [banish:pipeline] entering state `validate`
- [banish:pipeline] rule `check`: condition = true
- [banish:pipeline] rule `route`: condition = false
- ```
- `banish::init_trace` is available behind the `trace-logger` feature for quick setup. Pass `None` to print to stderr or `Some("path")` to write to a file.
- ---
๐ฆ Transition Guards
- ```rust
- step? {
- do_work();
- => @done if finished;
- log_progress(); // runs only when the guard is false
- }
- ```
- ---
๐ฆ Variable Declarations
- ```rust
- banish! {
- let mut total = 0; // lives for the whole machine
- @process
- let mut dirty = false; // resets on every entry to @process
- check ? condition { dirty = true; }
- flush ? dirty { write(); return; }
- }
- + 2 more
๐ Bug Fixes
- Fixed nested returns not being recognized in validation.
- ---
๐ฆ v1.3.1
- A small patch to correct a small bug where acronym enums would not convert as intended.
- ---
๐ฆ v1.4.0
- This is the most recent minor release which added tighter no_std support and pattern matching in rule condition statements.
- https://github.com/LoganFlaherty/banish/releases/tag/v1.4.0
- ---
๐ฆ What's Next
- Full documentation is in the [[Reference](https://github.com/LoganFlaherty/banish/blob/main/docs/reference.md)](https://github.com/LoganFlaherty/banish/blob/main/docs/reference.md).
Banish v1.2.3v1.2.3
โจ New
- Hey everyone sorry for the quick releases just had some immediate improvement ideas and urgent bugs to deal with.
- `max_entry = N => @state`
- `max_entry` now accepts an optional redirect target, matching the existing `max_iter = N => @state` syntax. On the (N+1)th entry the machine transitions to the named state instead of returning.
- ```rust
- @step
- work? { process(); }
- next? { => @step; }
- @done
- + 2 more
๐ Docs
- `break` and `continue` are now documented. Both work natively inside rule bodies against the generated fixed-point loop โ `break` exits the current state and lets the scheduler advance, `continue` restarts rule evaluation from the top.
- Reference and crate docs updated to reflect all of the above.
- ---
๐ฆ Also released: v1.2.1 / v1.2.2
- `trace` now emits via `[log](https://docs.rs/log)`
Banish v1.2.1v1.2.1
๐ฆ `trace` now emits via `log`
- `log` is re-exported from `banish` directly, so no additional dependency is needed. To capture output, add a backend such as `env_logger`:
- ```toml
- [dependencies]
- env_logger = "0.11.9"
- ```
- ```rust
- fn main() {
- env_logger::init();
- + 8 more
๐ฆ Upgrading from v1.2.0
- If you use `#[trace]` and were relying on stderr output, initialize a `log` backend as shown above. Everything else is unchanged.
Banish v1.2.0: Rule-Based State Machines for Rustv1.2.0
๐ฆ State Attributes
- Attributes are declared above a state and modify its runtime behavior. Multiple attributes are comma-separated.
- ```rust
- @my_state
- rule? { ... }
- ```
๐ฆ `isolate`
- ```rust
- @error_handler
- handle? { log_error(); }
- ```
๐ฆ `max_iter = N` and `max_iter = N => @state`
- Caps the fixed-point loop to `N` iterations. Without a redirect, the machine advances normally on exhaustion. With a redirect, it transitions to the named state instead.
- ```rust
- @retry
- attempt? !succeeded { try_request(); }
- ```
๐ฆ `max_entry = N`
- Limits how many times a state can be entered across the lifetime of the `banish!` block. Returns immediately on the `(N+1)`th entry without evaluating any rules.
- ```rust
- @red
- announce? { ticks = 0; println!("Red light"); }
- timer ? ticks < 3 { ticks += 1; }
- ```
๐ฆ `trace`
- Emits runtime diagnostics to stderr on state entry and rule evaluation. Intended for debugging during development.
- ```
- [banish: trace] entering state retry
- [banish: trace] rule attempt: condition = true
- ```
- ---
๐ฆ Improved Error Messages
- All macro panics have been replaced with proper `syn::Error` diagnostics. Errors now point directly at the offending token with a clear message.
- ```
- error: Unknown state `typo`
- --> src/main.rs:8:14
- |
- 8 | => @typo;
- | ^^^^^
- ```
- + 1 more
๐ What's Changed
- Added `isolate`, `max_iter`, `max_entry`, and `trace` state attributes
- `max_iter = N => @state` redirect transitions on iteration exhaustion
- Validation for isolated states with no exit, and `max_entry` on isolated states
- All internal panics replaced with span-accurate compile errors
- Expanded test suite covering attribute behavior and scheduler correctness
- Updated [[technical reference](https://github.com/LoganFlaherty/banish/blob/main/docs/README.md)](https://github.com/LoganFlaherty/banish/blob/main/docs/README.md) with full attribute documentation, error reference, and known limitations
- ---
๐ฆ Upgrading
- This release is fully backwards compatible. Existing `banish!` blocks require no changes.
Banish v1.1.5: Rule-Based State Machines for Rustv1.1.5
๐ Changes
- Added a return/transition statement compile-time error. If the final state is missing a return or transition statement, your IDE will now let you know ahead of time and mark the final state for you. If something unexpected happens you will get an unreachable code error message during runtime.
- Refactored the codebase into more functions and split like-functions in their own files to make maintaining, readability, and contributing easier.
- Added a small test suite contributors can use to quickly make sure their changes didn't break anything established.
- Improved documentation to be less redundant and hopefully more clear.
Banish v1.1.4: Rule-Based State Machines for Rustv1.1.4
๐ฆ Notes
- This release was to improve documentation and fix a parsing bug.
- When parsing conditions:
- ```rust
- found ? buffer[idx] == target {}
- ```
- Summary of recent changes since v1.0.0:
- Refactored the macro block into a closure to support proper return statements.
- Added else clauses "!?" to rules.
- + 1 more
๐ฆ Examples
- This is a small practical example of Banish.
- ```rust
- fn find_index(buffer: &[String], target: &str) -> Option<usize> {
- let mut idx = 0;
- banish! {
- @search
- // If we reached the end, give up.
- // This must be first to prevent out-of-bounds panic below.
- + 56 more
