| Crates.io | static-automata-macros |
| lib.rs | static-automata-macros |
| version | 1.0.1 |
| created_at | 2025-12-05 13:47:01.611699+00 |
| updated_at | 2025-12-08 11:06:20.975595+00 |
| description | Static regular grammar macros |
| homepage | |
| repository | https://github.com/timothee-haudebourg/static-automata |
| max_upload_size | |
| id | 1968230 |
| size | 11,531 |
This frameworks helps you define validation functions based on deterministic finite automata (DFAs) generated from ABNF grammars.
It works as follows:
mod item annotated with the #[grammar] macro specifying an
ABNF grammar (either from a file, or in the doc comments).cargo build-automata command line interface to generate the
declared module file, containing the grammar compiled into a deterministic
finite automaton. Alternatively you can call the build-automata
library directly from a build.rs script.Validate derive macro to bind them to custom types./// Automata module.
///
/// This module file is generated by the command line interface or builder
/// library. It contains an `Iri` type definition for the `IRI` production
/// of the `iri.abnf` that we exported here, with a `validate_bytes` and a
/// `validate_bytes` const function.
///
/// The attribute macro itself doesn't generate anything, but replaces this
/// item with an external module import `mod automata;`.
use static_automata::{grammar, Validate};
#[grammar(file = "iri.abnf", export("IRI"))]
mod automata {}
/// Derive the `validate_bytes` and `validate_str` methods from the
/// `automata::Iri` automaton.
#[derive(Validate)]
#[automaton(automata::Iri)]
struct Foo;
fn main() {
// Byte string validation.
assert!(Foo::validate_bytes(b"https://example.com").is_ok());
// String validation.
assert!(Foo::validate_str("https://example.com").is_ok());
// The validation functions are `const` compatible.
const _: () = {
assert!(Foo::validate_bytes(b"https://example.com").is_ok());
assert!(Foo::validate_str("https://example.com").is_ok());
};
}
Compiling a grammar requires determinizing a potentially large automaton, which is computationally very expensive.
You can install it with cargo install cargo-build-automata then use it
when you need to re-generate the autamata (e.g. when the associated grammar
changes):
cargo build-automata
Be careful, this will override the content of the modules annotated with the
#[grammar] attribute macro. If you're not sure which file will be
overriden you can run the cli with the -d/--dry-run flag:
cargo build-automata -d
It will compile the grammars, but not write anything.
The advantage of the command line interface is that it allows you to ship
the automata already compiled with your library/application. However you
might prefer to compile the automata on the user machine, using a build.rs
script. To do that you can use the build-automata library (the cli is
basically a wrapper around this library).
use build_automata::build_automata;
fn main() {
build_automata();
}
Licensed under either of
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.