fluent_pipeline 0.1.0

A lightweight pipeline system for Rust.
Documentation
pub trait Pipe<Value: 'static> {
    fn handle(&self, value: Value) -> Value;
}

pub struct Pipeline<Value: 'static> {
    passable: Value,
    pipes: Vec<Box<dyn FnOnce(Value) -> Value>>,
}

impl<Value> Pipeline<Value> {
    /// Set the object being sent through the pipeline.
    pub fn send(value: Value) -> Self {
        Self {
            passable: value,
            pipes: Vec::new(),
        }
    }

    /// Set the array of pipes.
    pub fn through(mut self, pipes: Vec<PipeType<Value>>) -> Self {
        self.pipes = pipes.into_iter().map(|pipe| pipe.into_function()).collect();

        self
    }

    /// Push additional pipes onto the pipeline.
    pub fn pipe(mut self, pipe: PipeType<Value>) -> Self {
        self.pipes.push(pipe.into_function());

        self
    }

    /// Run the pipeline with a final destination callback.
    pub fn then<Return>(self, callable: impl Fn(Value) -> Return) -> Return {
        let passable = self
            .pipes
            .into_iter()
            .rev()
            .fold(self.passable, |passable, pipe| pipe(passable));

        callable(passable)
    }

    /// Run the pipeline and return the result.
    pub fn then_return(self) -> Value {
        self.then(|value| value)
    }

    /// Run the pipeline.
    pub fn run(self) {
        self.then(|_| ());
    }
}

pub enum PipeType<Value: 'static> {
    Pipe(Box<dyn Pipe<Value>>),
    Fn(Box<dyn FnOnce(Value) -> Value>),
}

impl<Value: 'static> PipeType<Value> {
    fn into_function(self) -> Box<dyn FnOnce(Value) -> Value> {
        match self {
            PipeType::Fn(callable) => callable,
            PipeType::Pipe(pipe) => Box::new(move |value| pipe.handle(value)),
        }
    }
}