use super::data::io::{Inputs, Outputs}; use super::element::PipelineElement; use super::ops::prelude::*; /// Builder for the pipelines that are actually run /// /// 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 { /// Create new, empty builder pub fn new() -> Self { Self { elements: Vec::new(), } } /// Insert element into pipeline 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 } /// insert string concatenattion element #[must_use] pub fn concatenate(self, sec: String) -> Self { self.insert(Concatenate(sec)) } /// insert string uppercase element #[must_use] pub fn upper(self) -> Self { self.insert(Upper) } /// insert string lowercase element #[must_use] pub fn lower(self) -> Self { self.insert(Lower) } /// insert numeric addition element #[must_use] #[allow( clippy::should_implement_trait, reason = "is not equivalent to addition" )] pub fn add(self, sec: i32) -> Self { self.insert(Add(sec)) } /// insert numeric subtraction element #[must_use] pub fn subtract(self, sec: i32) -> Self { self.insert(Subtract(sec)) } /// insert stringify element #[must_use] pub fn stringify(self) -> Self { self.insert(Stringify) } /// Build the pipeline. Doesn't check again - `insert` should verify correctness. 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() } } /// Runnable pipeline - at the core of this library pub struct Pipeline { runners: Vec Outputs>, } impl Pipeline { /// run the pipeline pub fn run(&self, inputs: Inputs) -> Outputs { let mut out: Outputs = inputs.into(); for runner in &self.runners { out = runner(&(&out).into()); } out } }