1 unstable release

Uses new Rust 2024

new 0.1.0 May 8, 2025

#895 in Procedural macros


Used in froql

MIT/Apache

110KB
3K SLoC

image

froql

Froql is a proc_macro based DSL for dealing with graph-like state in Rust.

Target use case

Froql was designed with game jams in mind. In a game jam requirements aren't clear and time is limited. Lots of experimentation needs to happen but large scale refactoring is too costly. State is often graph-like (hard to express in Rust) and not tree-like (easy to express in Rust).

Froql allows an user to input data, define relations between data objects and then query the data back out in whatever shape is needed at the usage site.

This dynamic behavior relaxes both the requirements and the guarantees of Rust's typesystem.

froql has

  • Fast compile times
  • First class relation support
  • An ergonomic DSL for creating queries
  • Queries that double as normal rust iterators
  • Components that don't need to implement a trait (thus letting you use library types as is)

froql doesn't have

  • Systems, observers or a scheduler
  • Multithreading support
  • A codebase free of unsafe

Example

Let's name some facts that can be expressed as relations:

A tomato is a fruit. A fruit is food. Bread is food.

These truths can be expressed and evaluated in froql like this:

struct Name(&'static str);
enum IsA {}

let mut world = World::new();
// registering the IsA relationship as being transitive
world.register_relation_flags::<IsA>(TRANSITIVE);

// creating entities and relating them
let food = world.create().add(Name("Food")).entity;
let fruit = world.create().add(Name("Fruit")).relate_to::<IsA>(food).entity;
world.create().add(Name("Tomato")).relate_to::<IsA>(fruit);
world.create().add(Name("Bread")).relate_to::<IsA>(food);

// querying
for (a, b) in query!(world, Name(a), Name(b), IsA(a, b)) {
    println!("{} is a {}", a.0, b.0);
}

Output:

Fruit is a Food
Bread is a Food
Tomato is a Food
Tomato is a Fruit

To learn how this works check out the book.

You can also find more elaborate examples in the examples/ folder.

Installation

cargo add froql for the latest version on crates.io

or

cargo add cargo add --git https://github.com/kampffrosch94/froql froql for latest master.

Plans for 1.0

I am happy with the current feature set and APIs. Next up is smoothing out rough edges and improving the developer experience a bit.

Then improving performance (both runtime and compile time) which first up needs some proper benchmarks and more elaborate (fuzzy) testing.

Once I am happy with that I'll release 1.0 and then consider adding fancier queries, like branches, components as entities, aggregate functions and straight up injecting user supplied code.

Inspirations

Froql was inspired by many other projects. Click on the arrows to see what idea was taken from each.

flecs As far as I know this is the most advanced ECS out there at the moment. If you need something polyglot (it's written in C with bindings for lots of language), fancy features or state of the art performance, flecs is what I would recommend.

The backing archetypical ECS of froql and its query language were inspired by flecs. Its creator wrote a lot of helpful articles about ECS design and also gave me direct advice ❤️

Start by reading https://medium.com/@ajmmertens/building-an-ecs-storage-in-pictures-642b8bfd6e04 if you are curious.

flecs-rust The idea for EntityViews came from here.
ascent Transpiling a query language to Rust.

How ascent can interact with Rust by calling regular Rust functions is really cool. I want to explore that idea more for advanced queries.

nanoserde This is the fastest compiling proc macro crate for serialization I know. So copying from that I wrote froql's proc macro without any external dependencies.
bevy_ecs Bevy has lots of interesting ideas and I ignored most of them. Froql has a pretty different approach after all.

But how bevy reserves entity IDs safely in deferred contexts is something I copied.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

No runtime deps