Lockjaw

Lockjaw is a fully static, compile-time dependency injection framework for Rust inspired by Dagger. It is also what you get when jabbed by a rusty dagger.

Features:

See user guide for more information.

Example:

```rust use lockjaw::*; use std::ops::Add;

lockjaw::prologue!("src/lib.rs");

struct GreetCounter { counter: ::std::cell::RefCell }

// Allow GreetCounter to be created in the dependency graph. These bindings are available anywhere.

[injectable]

impl GreetCounter { // Marks a method as the inject constructor. Lockjaw will call this to create the object. #[inject] pub fn new() -> Self { Self{counter : std::cell::RefCell::new(0) } }

}

impl GreetCounter{ pub fn increment(&self) -> i32 { let mut m = self.counter.borrow_mut(); *m = m.add(1); m.clone() } }

pub trait Greeter { fn greet(&self) -> String; }

struct GreeterImpl { greet_counter : crate::GreetCounter, phrase : String }

[injectable]

impl GreeterImpl { // Lockjaw will call this with other injectable objects provided. #[inject] pub fn new(greetcounter : GreetCounter, phrase : String) -> Self { Self { greetcounter, phrase } } }

impl Greeter for GreeterImpl{ fn greet(&self) -> String{ format!("{} {}", self.phrase, self.greet_counter.increment()) } }

// Declare a module so we can do special bindings. These bindings are only available if the // component installs the module, so different bindings can be used based on the situation. struct MyModule {}

[module]

impl MyModule { // When ever someone needs a Greeter, use GreeterImpl as the actual implementation #[binds] pub fn bindgreeter(impl : crate::GreeterImpl) -> Cl {}

// Called when a String is requested
#[provides]
pub fn provide_string() -> String {
    "helloworld".to_owned()
}

}

// Components stitch modules and injectables together into a dependency graph, and can create // objects in the graph. The component installs modules listed in modules

[component(modules: MyModule)]

trait MyComponent { // Allows creating a greeter with the component. The created object has the lifetime of the // component fn greeter(&self) -> Cl; }

pub fn main() { // Creates the component let component = MyComponent::new(); // Creates a greeter. let greeter = component.greeter(); asserteq!(greeter.greet(), "helloworld 1"); // Internal states of the greeter is kept. asserteq!(greeter.greet(), "helloworld 2");

// A new greeter has a new independent set of injected objects.
assert_eq!(component.greeter().greet(), "helloworld 1");

} // called after the last use of lockjaw to perform validation and code generation epilogue!(); ```

A more complicated game example can be found at https://github.com/azureblaze/lockjaw/tree/main/example_game

Comparison with Dagger

Lockjaw Aims for feature parity with Dagger and uses very similar APIs. If you have used Dagger before, lockjaw should feel familiar.

Disclaimer

This is not an officially supported Google product.

Lockjaw is currently in early development and all APIs are subjected to changes. Some feature are also implemented in a hacky way. Use at your own risk.