use super::data::io::{Inputs, Outputs}; use super::element::PipelineElement; use super::ops::prelude::*; // TODO: // - Bind additional inputs if instruction has more then one and is passd without any additional // - allow binding to pointers to other pipelines? // - allow referencing earlier data pub struct PipelineBuilder { elements: Vec>, } impl PipelineBuilder { pub fn new() -> Self { Self { elements: Vec::new(), } } fn insert(mut self, el: T) -> Self { if let Some(previous_item) = self.elements.last() { assert_eq!( previous_item.signature().outputs[0], el.signature().inputs[0] ); } self.elements.push(Box::new(el)); self } #[must_use] pub fn concatenate(self, sec: String) -> Self { self.insert(Concatenate(sec)) } #[must_use] pub fn upper(self) -> Self { self.insert(Upper) } #[must_use] pub fn lower(self) -> Self { self.insert(Lower) } #[must_use] #[allow( clippy::should_implement_trait, reason = "is not equivalent to addition" )] pub fn add(self, sec: i32) -> Self { self.insert(Add(sec)) } #[must_use] pub fn subtract(self, sec: i32) -> Self { self.insert(Subtract(sec)) } #[must_use] pub fn stringify(self) -> Self { self.insert(Stringify) } pub fn build(&self) -> Pipeline { let mut r = Vec::new(); self.elements.iter().for_each(|el| r.push(el.runner())); Pipeline { runners: r } } } impl Default for PipelineBuilder { fn default() -> Self { Self::new() } } pub struct Pipeline { runners: Vec Outputs>, } impl Pipeline { pub fn run(&self, inputs: Inputs) -> Outputs { let mut out: Outputs = inputs.into(); for runner in &self.runners { out = runner(&(&out).into()); } out } }