1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
use crate::core::errors::ThrusterError; use paste::paste; use std::boxed::Box; use std::future::Future; use std::pin::Pin; use thruster_proc::generate_tuples; pub type NextFn<T> = Box< dyn FnOnce( T, ) -> Pin<Box<dyn Future<Output = Result<T, ThrusterError<T>>> + 'static + Sync + Send>> + 'static + Sync + Send, >; pub type MiddlewareFnPointer<T> = fn( T, NextFn<T>, ) -> Pin<Box<dyn Future<Output = Result<T, ThrusterError<T>>> + 'static + Sync + Send>>; pub trait MiddlewareFunc<T>: Fn( T, NextFn<T>, ) -> Pin<Box<dyn Future<Output = Result<T, ThrusterError<T>>> + 'static + Sync + Send>> { } impl<A, T: Sync + Send> MiddlewareFunc<T> for A where A: Fn( T, NextFn<T>, ) -> Pin<Box<dyn Future<Output = Result<T, ThrusterError<T>>> + 'static + Sync + Send>> { } pub trait IntoMiddleware<T, A> { fn middleware( self, ) -> Box< dyn Fn(T) -> Pin<Box<dyn Future<Output = Result<T, ThrusterError<T>>> + Sync + Send>> + Send + Sync, >; } pub trait CombineMiddleware<T, AFuncs, BFuncs, CFuncs> { fn combine(self, funcs: BFuncs) -> CFuncs; } macro_rules! impl_into_middleware { ($($param: ident),*) => { #[allow(unused_parens)] impl<T: 'static + Sync + Send, $($param: MiddlewareFunc<T> + 'static + Send + Sync + Copy),*> IntoMiddleware<T, ($($param,)*)> for ($($param,)*) { fn middleware(self) -> Box<dyn Fn(T) -> Pin<Box<dyn Future<Output = Result<T, ThrusterError<T>>> + Sync + Send>> + Send + Sync> { #[allow(non_snake_case)] let ($($param,)*) = self; recurse!($($param),*) } } } } macro_rules! recurse { ($head:ident, $($tail:ident),*) => { Box::new(move |i| ($head)(i, recurse!($($tail),*))) }; ($head:ident) => { Box::new(move |i| ($head)(i, Box::new(|i| Box::pin(async move { Ok(i) })))) }; } #[macro_export] macro_rules! pinbox { ($type:ty, $fn:ident) => {{ fn __internal( a: $type, b: NextFn<$type>, ) -> Pin<Box<dyn Future<Output = Result<$type, ThrusterError<$type>>> + Sync + Send>> { Box::pin($fn(a, b)) } __internal }}; } macro_rules! expand_combine { ($($param:ident),*) => { paste! { expand_combine!(@mid $($param),*); expand_combine!(@lhs $($param),*|$([<$param:lower>]),*); } }; (@mid $head:ident, $($param:ident),*) => { impl_into_middleware!($head, $($param),*); expand_combine!(@mid $($param),*); }; (@mid $head:ident) => { impl_into_middleware!($head); }; (@lhs $head:ident, $($param:ident),*|$($right:ident),*) => { paste! { expand_combine!(@rhs $head, $($param),*|$([<$right:lower>]),*); expand_combine!(@lhs $($param),*|$([<$right:lower>]),*); } }; (@lhs $head:ident|$($right:ident),*) => { paste! { expand_combine!(@rhs $head|$([<$right:lower>]),*); } }; (@rhs $($left:ident),*|$head:ident, $($param:ident),*) => { expand_combine!(@rhs $($left),*|$($param),*); }; (@rhs $($left:ident),*|$head:ident) => { }; } type M<T> = MiddlewareFnPointer<T>; expand_combine!(P, O, N, M, L, K, J, I, H, G, F, E, D, C, B, A); generate_tuples!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P);