Targets

Some helpers to get you started with declarative programming in Rust

Usage

This crate defines 3 macros: - capture!($ident): register the base requisite - target!($ident($args) -> $ty = $expre): define a target that builds something from prerequisites with a fixed recipe - build!($ident: $ty, $builder): build a target based on a given state

Example

Let's build a Dashboard struct, containing a welcome message for a user.

We define the base requisite as a State struct, which contains a session identifier.

In order to construct the dashboard, we need the actual message and the logged in user. These are defined as two separate, dependent targets.

```

[macro_use]

extern crate targets;

use targets::Target; use targets::Builder;

pub struct State { loggedinid: i32, messageofthe_day: String, } pub struct User { id: i32, username: String, } pub struct Dashboard { message: String, }

fn main() { // register state which is the base requisite capture!(state);

// declare a target which depends on `state`
target!(fn user(state: State) -> User = {
    User {
        id: state.logged_in_id, // you may want to get the user from a database
        username: "otto".to_string()
    }
});

// declare a target which depends on another target
target!(fn message(user: User) -> String = {
    String::from(format!("Welcome {} (user_id {})", user.username, user.id))
});

// a target can depend on as many other targets
target!(fn dashboard(message: String, state: State) -> Dashboard = {
    Dashboard {
        message: format!("{} {}", state.message_of_the_day, message),
    }
});

// Let's run our build script, set up the state:
let my_state = State {
    logged_in_id: 8,
    message_of_the_day: String::from("Good morning!")
};
let mut my_builder = Builder::new(Box::new(my_state));
// Build the dashboard:
{
    let my_dashboard = build!(dashboard: Dashboard, my_builder);
    assert_eq!("Good morning! Welcome otto (user_id 8)", my_dashboard.message);
}
// Build another target from the same initial state
// Since it has already been built as part of the dashboard, it won't rebuild anything
{
    let my_user = build!(user: User, my_builder);
    assert_eq!("otto", my_user.username);
}

// Use our dependency graph to build another item
let my_state = State {
    logged_in_id: 12,
    message_of_the_day: String::from("It's Wednesday!")
};
let mut my_builder = Builder::new(Box::new(my_state));
{
    let my_dashboard = build!(dashboard: Dashboard, my_builder);
    assert_eq!("It's Wednesday! Welcome otto (user_id 12)", my_dashboard.message);
}

} ```