| Crates.io | typed_grid |
| lib.rs | typed_grid |
| version | 0.1.12 |
| created_at | 2025-05-23 22:43:41.579012+00 |
| updated_at | 2025-06-02 08:00:35.397939+00 |
| description | Macro generator for typed grid navigation |
| homepage | https://github.com/tgrospic/typed-grid-rs |
| repository | https://github.com/tgrospic/typed-grid-rs.git |
| max_upload_size | |
| id | 1686828 |
| size | 9,087 |
Strongly typed grid navigation in Rust with compile-time movement constraints.
typed_grid is a Rust procedural macro crate that generates a grid of position types (PosXxY) and enforces legal movements (left, right, up, down) at compile time using Rust’s type system. Inspired by dependently typed programming, it encodes position and movement rules in the type system itself—ensuring that only valid transitions are representable and catchable by the compiler.
This is especially useful in domains such as:
Add this to your Cargo.toml:
[dependencies]
typed_grid = "*" # or replace with latest version
Add the macro import to your crate root:
use typed_grid::*;
use typed_grid::*;
typed_grid!(2, 2); // Generates a 2x2 grid
impl Moved for i32 {
fn moved(&mut self, p: Position) {
*self += 1;
println!("MOVED: {p:?} {self}")
}
}
fn run(start: Ctx<Pos0x0, i32>) -> Ctx<Pos0x0, i32> {
start.right().up().down().left()
}
let pos = Ctx(Pos0x0, 42);
let pos = pos.right().up().down().left();
let pos = run(pos);
typed_grid!(W, H)This macro generates:
Pos0x0, Pos1x2, etc.Ctx<P, T> wrapper for combining a position and your custom stateMoveRight, MoveLeft, MoveUp, MoveDown) encoded at the type leveltyped_grid_ext!(W, H)The typed_grid_ext! macro generates movements with traits (IPosXxY<T>) allowing for more composable and generic movement logic.
# use std::fmt::Debug;
# use typed_grid::*;
#
typed_grid_ext!(2, 5);
fn moves<P: IPos0x0<T>, T: Moved + Debug>(start: P) -> impl IPos0x1<T> {
start.right().up().up().up().up().down().down().left().down()
}
Ctx<P, T>Ctx is a context object wrapping a position P and user-defined state T.
You move across the grid using:
# use typed_grid::*;
#
# typed_grid!(2, 2);
#
# let ctx = Ctx(Pos0x0, ());
#
# impl Moved for () {
# fn moved(&mut self, p: Position) {}
# }
#
ctx.right().up().down().left();
Moved TraitYou MUST implement the Moved trait (generated by macro) for your custom state type (T) to receive notifications whenever a movement occurs.
trait Moved {
fn moved(&mut self, to: Position);
}
This allows mutation or side-effects during position transitions.
Invalid moves are caught at compile time:
# use typed_grid::*;
typed_grid!(2, 2);
let pos = Ctx(Pos1x1, ());
let new_pos = pos.right(); // ❌ Compile-time error: Pos2x1 doesn't exist
Rather than relying on runtime conditionals or grid bounds checks, typed_grid ensures safety using Rust’s type system. You cannot move to an invalid position, and legal transitions are encoded via trait bounds.
To run tests:
cargo test --workspace
Examples of macro expansion and usage are available under samples/src.
To run examples:
cargo run -p samples
This crate uses cargo-release for publishing and version management.
To tag and publish a new release:
cargo release {major|minor|patch}
Contributions are welcome! Please open issues for bugs, ideas, or improvements.
Inspired by dependently typed languages, denotational design, and a love for statically enforced correctness.