diff --git a/crates/app/src/main.rs b/crates/app/src/main.rs index 2534631..2caaa2f 100644 --- a/crates/app/src/main.rs +++ b/crates/app/src/main.rs @@ -56,20 +56,17 @@ fn main() { mod dev { use clap::Subcommand; - use prowocessing::experimental::trait_based::DataType; + use prowocessing::experimental::enum_based::{Pipeline, PipelineBuilder}; #[derive(Subcommand)] pub(crate) enum DevCommands { Enums { test_str: String }, - Add { num0: i32, num1: i32 }, } impl DevCommands { pub fn run(self) { match self { DevCommands::Enums { test_str } => { - use prowocessing::experimental::enum_based::PipelineBuilder; - let upr = PipelineBuilder::new() .insert(prowocessing::experimental::enum_based::Instruction::Uppercase) .build(); @@ -80,15 +77,6 @@ mod dev { println!("Upr: {}", upr.run(test_str.clone())); println!("Lwr: {}", lwr.run(test_str.clone())); } - DevCommands::Add { num0, num1 } => { - use prowocessing::experimental::trait_based::PipelineBuilder; - - let pipe = PipelineBuilder::new().add(1).stringify().build(); - println!( - "{:?}", - pipe.run(vec![num0.into(), num1.into()].into()).into_inner()[0] - ); - } } } } diff --git a/crates/prowocessing/src/experimental.rs b/crates/prowocessing/src/experimental.rs deleted file mode 100644 index fcc0d52..0000000 --- a/crates/prowocessing/src/experimental.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub mod enum_based; - -pub mod trait_based; diff --git a/crates/prowocessing/src/experimental/enum_based.rs b/crates/prowocessing/src/experimental/enum_based.rs deleted file mode 100644 index c60f4a9..0000000 --- a/crates/prowocessing/src/experimental/enum_based.rs +++ /dev/null @@ -1,64 +0,0 @@ -pub enum Instruction { - Uppercase, - Lowercase, -} - -pub struct Pipeline { - pipeline: Vec String>, -} - -impl Pipeline { - pub fn run(&self, val: String) -> String { - let mut current = val; - - for instr in &self.pipeline { - current = instr(current); - } - - current - } -} - -pub struct PipelineBuilder { - pipeline: Vec, -} - -impl PipelineBuilder { - pub fn new() -> Self { - Self { - pipeline: Vec::new(), - } - } - - #[must_use] - pub fn insert(mut self, instr: Instruction) -> Self { - self.pipeline.push(instr); - self - } - - pub fn build(&self) -> Pipeline { - fn uppercase(v: String) -> String { - str::to_uppercase(&v) - } - fn lowercase(v: String) -> String { - str::to_lowercase(&v) - } - - let mut res = Vec::new(); - - for item in &self.pipeline { - res.push(match item { - Instruction::Uppercase => uppercase, - Instruction::Lowercase => lowercase, - }); - } - - Pipeline { pipeline: res } - } -} - -impl Default for PipelineBuilder { - fn default() -> Self { - Self::new() - } -} diff --git a/crates/prowocessing/src/experimental/trait_based.rs b/crates/prowocessing/src/experimental/trait_based.rs deleted file mode 100644 index 3be8f3a..0000000 --- a/crates/prowocessing/src/experimental/trait_based.rs +++ /dev/null @@ -1,339 +0,0 @@ -use self::{ - numops::{Add, Stringify, Subtract}, - strops::{Concatenate, Lower, Upper}, -}; - -trait PipelineElement { - fn runner(&self) -> fn(&Inputs) -> Outputs; - fn signature(&self) -> ElementIo; -} - -struct ElementIo { - pub inputs: Vec, - pub outputs: Vec, -} - -// 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>, -} - -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 - } -} - -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() - } -} - -#[derive(Clone, Copy)] -pub enum Data<'a> { - String(&'a str), - Int(i32), -} -impl Data<'_> { - pub fn to_owned_data(&self) -> OwnedData { - match self { - Data::String(s) => (*s).to_owned().into(), - Data::Int(i) => (*i).into(), - } - } -} -impl<'a> From<&'a str> for Data<'a> { - fn from(value: &'a str) -> Self { - Self::String(value) - } -} -impl From for Data<'_> { - fn from(value: i32) -> Self { - Self::Int(value) - } -} -impl<'a> From<&'a OwnedData> for Data<'a> { - fn from(value: &'a OwnedData) -> Self { - match value { - OwnedData::String(s) => Data::String(s), - OwnedData::Int(i) => Data::Int(*i), - } - } -} - -#[derive(Clone, Debug)] -pub enum OwnedData { - String(String), - Int(i32), -} -impl From for OwnedData { - fn from(value: String) -> Self { - Self::String(value) - } -} -impl From for OwnedData { - fn from(value: i32) -> Self { - Self::Int(value) - } -} - -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum DataType { - String, - Int, -} - -pub struct Inputs<'a>(Vec>); -impl<'a> Inputs<'a> { - fn inner(&self) -> Vec> { - self.0.clone() - } -} -impl<'a> From>> for Inputs<'a> { - fn from(value: Vec>) -> Self { - Self(value) - } -} -impl<'a, T: Into>> From for Inputs<'a> { - fn from(value: T) -> Self { - Self(vec![value.into()]) - } -} -impl<'a> From<&'a Outputs> for Inputs<'a> { - fn from(value: &'a Outputs) -> Self { - Self(value.0.iter().map(std::convert::Into::into).collect()) - } -} - -pub struct Outputs(Vec); -impl Outputs { - pub fn into_inner(self) -> Vec { - self.0 - } -} -impl From> for Outputs { - fn from(value: Vec) -> Self { - Self(value) - } -} -impl> From for Outputs { - fn from(value: T) -> Self { - Self(vec![value.into()]) - } -} -impl From> for Outputs { - fn from(value: Inputs) -> Self { - Self( - value - .0 - .into_iter() - .map(|i: Data<'_>| Data::to_owned_data(&i)) - .collect(), - ) - } -} - -mod strops { - use super::{Data, DataType, ElementIo, Inputs, Outputs, PipelineElement}; - - pub struct Concatenate(pub String); - impl PipelineElement for Concatenate { - fn runner(&self) -> fn(&Inputs) -> Outputs { - |input| { - if let [Data::String(s0), Data::String(s1), ..] = input.inner()[..] { - format!("{s0}{s1}").into() - } else { - panic!("Invalid data passed") - } - } - } - - fn signature(&self) -> ElementIo { - ElementIo { - inputs: vec![DataType::String, DataType::String], - outputs: vec![DataType::String], - } - } - } - - pub struct Upper; - impl PipelineElement for Upper { - fn runner(&self) -> fn(&Inputs) -> Outputs { - |input| { - if let [Data::String(s), ..] = input.inner()[..] { - s.to_uppercase().into() - } else { - panic!("Invalid data passed") - } - } - } - - fn signature(&self) -> ElementIo { - ElementIo { - inputs: vec![DataType::String], - outputs: vec![DataType::String], - } - } - } - - pub struct Lower; - impl PipelineElement for Lower { - fn runner(&self) -> fn(&Inputs) -> Outputs { - |input| { - if let [Data::String(s), ..] = input.inner()[..] { - s.to_lowercase().into() - } else { - panic!("Invalid data passed") - } - } - } - - fn signature(&self) -> ElementIo { - ElementIo { - inputs: vec![DataType::String], - outputs: vec![DataType::String], - } - } - } -} - -mod numops { - use core::panic; - - use super::{Data, DataType, ElementIo, Inputs, Outputs, PipelineElement}; - - pub struct Add(pub i32); - impl PipelineElement for Add { - fn runner(&self) -> fn(&Inputs) -> Outputs { - |input| { - if let [Data::Int(i0), Data::Int(i1), ..] = input.inner()[..] { - (i0 + i1).into() - } else { - panic!("Invalid data passed") - } - } - } - - fn signature(&self) -> ElementIo { - ElementIo { - inputs: vec![DataType::Int, DataType::Int], - outputs: vec![DataType::Int], - } - } - } - - pub struct Subtract(pub i32); - impl PipelineElement for Subtract { - fn runner(&self) -> fn(&Inputs) -> Outputs { - |input| { - if let [Data::Int(i0), Data::Int(i1), ..] = input.inner()[..] { - (i0 + i1).into() - } else { - panic!("Invalid data passed") - } - } - } - - fn signature(&self) -> ElementIo { - ElementIo { - inputs: vec![DataType::Int, DataType::Int], - outputs: vec![DataType::Int], - } - } - } - - pub struct Stringify; - impl PipelineElement for Stringify { - fn runner(&self) -> fn(&Inputs) -> Outputs { - |input| { - if let [Data::Int(int), ..] = input.inner()[..] { - int.to_string().into() - } else { - panic!("Invalid data passed") - } - } - } - - fn signature(&self) -> ElementIo { - ElementIo { - inputs: vec![DataType::Int], - outputs: vec![DataType::String], - } - } - } -} diff --git a/crates/prowocessing/src/lib.rs b/crates/prowocessing/src/lib.rs index aa81057..778d544 100644 --- a/crates/prowocessing/src/lib.rs +++ b/crates/prowocessing/src/lib.rs @@ -2,15 +2,82 @@ //! //! One of the design goals for this library is, however, to be a simple, generic image processing library. //! For now, it's just indev... lets see what comes of it! -#![feature(lint_reasons)] + +use experimental::enum_based::{Instruction, PipelineBuilder}; /// just some experiments, to test whether the architecture i want is even possible (or how to do it). probably temporary. /// Gonna first try string processing... -pub mod experimental; +pub mod experimental { + pub mod enum_based { + pub enum Instruction { + Uppercase, + Lowercase, + } + + pub struct Pipeline { + pipeline: Vec String>, + } + + impl Pipeline { + pub fn run(&self, val: String) -> String { + let mut current = val; + + for instr in &self.pipeline { + current = instr(current); + } + + current + } + } + + pub struct PipelineBuilder { + pipeline: Vec, + } + + impl PipelineBuilder { + pub fn new() -> Self { + Self { + pipeline: Vec::new(), + } + } + + #[must_use] + pub fn insert(mut self, instr: Instruction) -> Self { + self.pipeline.push(instr); + self + } + + pub fn build(&self) -> Pipeline { + fn uppercase(v: String) -> String { + str::to_uppercase(&v) + } + fn lowercase(v: String) -> String { + str::to_lowercase(&v) + } + + let mut res = Vec::new(); + + for item in &self.pipeline { + res.push(match item { + Instruction::Uppercase => uppercase, + Instruction::Lowercase => lowercase, + }); + } + + Pipeline { pipeline: res } + } + } + + impl Default for PipelineBuilder { + fn default() -> Self { + Self::new() + } + } + } +} #[test] fn test_enums() { - use crate::experimental::enum_based::{Instruction, PipelineBuilder}; let builder = PipelineBuilder::new().insert(Instruction::Uppercase); let upr = builder.build(); let upr_lowr = builder.insert(Instruction::Lowercase).build();