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> {
pub fn send(value: Value) -> Self {
Self {
passable: value,
pipes: Vec::new(),
}
}
pub fn through(mut self, pipes: Vec<PipeType<Value>>) -> Self {
self.pipes = pipes.into_iter().map(|pipe| pipe.into_function()).collect();
self
}
pub fn pipe(mut self, pipe: PipeType<Value>) -> Self {
self.pipes.push(pipe.into_function());
self
}
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)
}
pub fn then_return(self) -> Value {
self.then(|value| value)
}
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)),
}
}
}