pipeline-dsl 0.4.0

Static #[pipeline]/#[stage] DSL over the pipeline-core value layer.
Documentation

pipeline-dsl

The static front-end of the pipeline family: write ordinary functions, annotate them, and let the #[pipeline] macro derive a dependency DAG and a deterministically ordered compute().

Functions + names ⇒ DAG ⇒ deterministic compute. Edges are inferred from name-based parameter binding and mutability (&T reads, &mut T writes); the macro enforces single-writer, detects missing producers, topologically sorts, and emits crisp compile-time errors.

Setup

Two dependencies — the macros (this crate) and the value layer (pipeline-core, imported as pipeline):

[dependencies]
pipeline-core = "0.3"   # the value layer, used as `pipeline::...`
pipeline-dsl  = "0.3"   # the #[pipeline] / #[stage] macros

Quick start

use pipeline_dsl::{pipeline, stage};

#[derive(Default)]
struct Db { count: i32 }
#[derive(Default)]
struct Cache { total: i32 }

#[pipeline(name = "App", context = "db, cache")]
mod app {
    use super::*;

    #[stage]
    pub fn tick(db: &mut Db) { db.count += 1; }

    #[stage]
    pub fn sum(cache: &mut Cache, db: &Db) {
        cache.total += db.count; // reads db (after tick), writes cache
    }
}

fn main() -> Result<(), pipeline::Error> {
    let mut app = App::new();
    let (mut db, mut cache) = (Db::default(), Cache::default());
    app.compute(&mut db, &mut cache)?; // stages run in dependency order
    Ok(())
}

Runtime value types (Vector, Value, Buckets, Reset) come from pipeline (the pipeline-core crate). Code generated by #[pipeline] references pipeline::… paths, so a crate using the macro must depend on pipeline-core directly.

Attribute summary

  • #[pipeline(name="…", args="…", context="…", external="…", error="…", controlflow_break="…")] — declares the pipeline container; args/context/external describe inputs.
  • #[stage] — marks a function as a stage. Parameter attributes: #[rename = "field"], #[skip_reset], #[unused].

See the repository for the full guide (binding rules, multiple contexts, generics, diagrams, diagnostics).

Safety

This front-end is fully checked at compile time and uses no unsafe — mis-wiring (a missing producer, two writers, a cycle) is a compile error. The dynamic pipeline-graph front-end trades those compile-time guarantees for runtime flexibility, validating wiring at build() and using a small encapsulated unsafe core. If a fixed graph fits your problem, this crate gives you the stronger guarantees.

Related crates

Part of the pipeline family — a shared value layer with two front-ends:

Crate What it is
pipeline-core the value layer (Value/Vector/Buckets + Reset), imported as pipeline
pipeline-dsl static front-end: derive the graph at compile time with #[pipeline]/#[stage]
pipeline-graph dynamic front-end: wire the graph at runtime (Graph, Input/Output)

Need the graph wired at runtime (stages/implementations chosen dynamically)? See pipeline-graph.

License

MIT OR Apache-2.0.