Skip to content

Pipeline

Larastvel's Pipeline provides a way to send a value through a series of pipes (stages), where each pipe can inspect or transform the value before passing it to the next stage. This is useful for data transformation pipelines, middleware-like processing chains, and multi-step workflows.

Basic Usage

rust
use larastvel_core::{Pipeline, pipe_fn};

let result = Pipeline::send(1)
    .through(vec![
        pipe_fn(|value: i32, next| async move {
            next.call(value + 1).await
        }),
        pipe_fn(|value: i32, next| async move {
            next.call(value * 2).await
        }),
    ])
    .then(|val| async move { val })
    .await;

assert_eq!(result, 4); // ((1 + 1) * 2)

Using Struct Pipes

For reusable pipe logic, implement the Pipe trait:

rust
use larastvel_core::pipeline::into_pipe_fn;
use larastvel_core::{Next, Pipe, Pipeline};
use async_trait::async_trait;

struct AddPipe(i32);

#[async_trait]
impl Pipe<i32> for AddPipe {
    async fn handle(&self, value: i32, next: Next<i32>) -> i32 {
        next.call(value + self.0).await
    }
}

let result = Pipeline::send(10)
    .through(vec![into_pipe_fn(AddPipe(5))])
    .then(|val| async move { val })
    .await;

assert_eq!(result, 15);

Short-Circuiting

A pipe can return a value without calling next, which short-circuits the pipeline:

rust
let result = Pipeline::send("hello")
    .through(vec![
        pipe_fn(|_: &'static str, _next| async move { "intercepted" }),
    ])
    .then(|val| async move { val })
    .await;

assert_eq!(result, "intercepted");

The Pipe Trait

rust
#[async_trait]
pub trait Pipe<T: Send + 'static>: Send + Sync {
    async fn handle(&self, value: T, next: Next<T>) -> T;
}

Use into_pipe_fn(MyStruct) to convert a Pipe implementation into a closure for the pipeline.

Released under the MIT License.