From 1fd40c2fe9c82172a3b5a39f26bdf371053388d6 Mon Sep 17 00:00:00 2001 From: Maximilian Ammann Date: Fri, 27 May 2022 11:22:25 +0200 Subject: [PATCH] Add pipeline draft --- maplibre/src/io/mod.rs | 1 + maplibre/src/io/pipeline.rs | 183 ++++++++++++++++++++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 maplibre/src/io/pipeline.rs diff --git a/maplibre/src/io/mod.rs b/maplibre/src/io/mod.rs index d0836514..7310a9a1 100644 --- a/maplibre/src/io/mod.rs +++ b/maplibre/src/io/mod.rs @@ -14,6 +14,7 @@ pub mod source_client; pub mod static_tile_fetcher; pub mod geometry_index; +pub mod pipeline; pub mod shared_thread_state; pub mod tile_cache; pub mod tile_request_state; diff --git a/maplibre/src/io/pipeline.rs b/maplibre/src/io/pipeline.rs new file mode 100644 index 00000000..d812d119 --- /dev/null +++ b/maplibre/src/io/pipeline.rs @@ -0,0 +1,183 @@ +use std::marker::PhantomData; +use std::process::Output; + +pub trait Processable { + type Input; + type Output; + + fn process(&self, input: Self::Input) -> Self::Output; +} + +pub struct PipelineStep +where + P: Processable, + N: Processable, +{ + func: P, + next: N, +} + +impl Processable for PipelineStep +where + P: Processable, + N: Processable, +{ + type Input = P::Input; + type Output = N::Output; + + fn process(&self, input: Self::Input) -> Self::Output { + let output = self.func.process(input); + self.next.process(output) + } +} + +#[derive(Default)] +pub struct EndStep { + phantom: PhantomData, +} + +impl Processable for EndStep { + type Input = I; + type Output = I; + + fn process(&self, input: Self::Input) -> Self::Output { + input + } +} + +impl Processable for &fn(I) -> O { + type Input = I; + type Output = O; + + fn process(&self, input: Self::Input) -> Self::Output { + (self)(input) + } +} + +impl Processable for fn(I) -> O { + type Input = I; + type Output = O; + + fn process(&self, input: Self::Input) -> Self::Output { + (self)(input) + } +} + +pub struct FnProcessable { + func: &'static fn(I) -> O, +} + +impl Processable for FnProcessable { + type Input = I; + type Output = O; + + fn process(&self, input: Self::Input) -> Self::Output { + (self.func)(input) + } +} + +pub struct ClosureProcessable +where + F: Fn(I) -> O, +{ + func: F, + phantom_i: PhantomData, + phantom_o: PhantomData, +} + +impl Processable for ClosureProcessable +where + F: Fn(I) -> O, +{ + type Input = I; + type Output = O; + + fn process(&self, input: Self::Input) -> Self::Output { + (self.func)(input) + } +} + +pub struct Closure2Processable { + func: fn(I) -> O, +} + +impl Processable for Closure2Processable { + type Input = I; + type Output = O; + + fn process(&self, input: Self::Input) -> Self::Output { + (self.func)(input) + } +} + +impl Processable for dyn Fn(I) -> O { + type Input = I; + type Output = O; + + fn process(&self, input: Self::Input) -> Self::Output { + (self)(input) + } +} + +#[cfg(test)] +mod tests { + use crate::io::pipeline::{ + Closure2Processable, ClosureProcessable, EndStep, FnProcessable, PipelineStep, Processable, + }; + + fn add_one(input: u32) -> u8 { + input as u8 + 1 + } + + fn add_two(input: u8) -> u32 { + input as u32 + 2 + } + + #[test] + fn test() { + let output: u32 = PipelineStep { + func: FnProcessable { + func: &(add_two as fn(u8) -> u32), + }, + next: EndStep::default(), + } + .process(5u8); + + assert_eq!(output, 7); + + let output = PipelineStep { + func: &(add_one as fn(u32) -> u8), + next: PipelineStep { + func: &(add_two as fn(u8) -> u32), + next: EndStep::default(), + }, + } + .process(5); + + assert_eq!(output, 8); + + let output: u32 = PipelineStep { + func: ClosureProcessable { + func: |input: u8| -> u32 { + return input as u32 + 2; + }, + phantom_i: Default::default(), + phantom_o: Default::default(), + }, + next: EndStep::default(), + } + .process(5u8); + + assert_eq!(output, 7); + + let output: u32 = PipelineStep { + func: Closure2Processable { + func: |input: u8| -> u32 { input as u32 + 2 }, + }, + next: EndStep::default(), + } + .process(5u8); + + assert_eq!(output, 7); + } +}