We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
use std::{any::type_name, fmt::Debug}; pub struct Router<TPlugin: Plugin = BasePlugin> { plugin: TPlugin, } impl Router<BasePlugin> { pub fn new() -> Self { Self { plugin: BasePlugin {}, } } } impl<TPlugin: Plugin> Router<TPlugin> { pub fn plugin<T: Plugin>(self, t: T) -> Router<PluginJoiner<TPlugin, T>> { Router { plugin: PluginJoiner { a: self.plugin, b: t, }, } } pub fn query<T: 'static>(self, func: impl Fn() -> T) -> Self where <TPlugin as Plugin>::Result<T>: Debug, { println!("{}", type_name::<TPlugin>()); println!("{}", type_name::<TPlugin::Result<T>>()); println!("{:?}\n", self.plugin.map(func())); self } } pub trait Plugin { type Result<T: 'static>: 'static; fn map<T: 'static>(&self, t: T) -> Self::Result<T>; } pub struct PluginJoiner<A: Plugin, B: Plugin> { a: A, b: B, } impl<A: Plugin, B: Plugin> Plugin for PluginJoiner<A, B> { type Result<T: 'static> = B::Result<A::Result<T>>; fn map<T: 'static>(&self, t: T) -> Self::Result<T> { self.b.map(self.a.map(t)) } } pub struct BasePlugin; impl Plugin for BasePlugin { type Result<T: 'static> = T; fn map<T: 'static>(&self, t: T) -> Self::Result<T> { t } } pub struct MapPlugin; #[derive(Debug)] pub struct CustomType<T>(String, T); impl Plugin for MapPlugin { type Result<T: 'static> = CustomType<T>; fn map<T: 'static>(&self, t: T) -> Self::Result<T> { CustomType("Demo".to_string(), t) } } pub struct OverridePlugin; impl Plugin for OverridePlugin { type Result<T: 'static> = bool; fn map<T: 'static>(&self, _t: T) -> Self::Result<T> { true } } fn main() { let r = <Router>::new().query(|| "Query!".to_string()); let r = <Router>::new() .plugin(MapPlugin {}) .query(|| "Query!".to_string()); let r = <Router>::new() .plugin(MapPlugin {}) .plugin(OverridePlugin {}) .query(|| "Query!".to_string()); }
Playground
use std::{fmt::Debug, future::Future, pin::Pin}; pub trait Ret: Debug + 'static {} impl<T: Debug + 'static> Ret for T {} pub trait Fut<TRet: Ret>: Future<Output = TRet> + Send + 'static {} impl<TRet: Ret, TFut: Future<Output = TRet> + Send + 'static> Fut<TRet> for TFut {} pub trait Func<TRet: Ret, TFut: Fut<TRet>>: FnOnce() -> TFut + Send + 'static {} impl<TRet: Ret, TFut: Fut<TRet>, TFunc: FnOnce() -> TFut + Send + 'static> Func<TRet, TFut> for TFunc { } pub struct Router<TPlugin: Plugin = BasePlugin> { plugin: TPlugin, } impl Router<BasePlugin> { pub fn new() -> Self { Self { plugin: BasePlugin {}, } } } impl<TPlugin: Plugin> Router<TPlugin> { pub fn plugin<T: Plugin>(self, t: T) -> Router<PluginJoiner<TPlugin, T>> { Router { plugin: PluginJoiner { a: self.plugin, b: t, }, } } pub async fn query<TRet: Ret, TFut: Fut<TRet>>(&self, func: impl Func<TRet, TFut>) { let y = self.plugin.map(func); println!("\nBUILT\n"); println!("{:?}\n", y().await); } } pub trait Plugin { type Ret<TRet: Ret>: Ret; type Fut<TRet: Ret, TFut: Fut<TRet>>: Fut<Self::Ret<TRet>>; type Result<TRet: Ret, TFut: Fut<TRet>, T: Func<TRet, TFut>>: Func< Self::Ret<TRet>, Self::Fut<TRet, TFut>, >; fn map<TRet: Ret, TFut: Fut<TRet>, T: Func<TRet, TFut>>( &self, t: T, ) -> Self::Result<TRet, TFut, T>; } pub struct PluginJoiner<A: Plugin, B: Plugin> { a: A, b: B, } impl<A: Plugin, B: Plugin> Plugin for PluginJoiner<A, B> { type Ret<TRet: Ret> = A::Ret<B::Ret<TRet>>; type Fut<TRet: Ret, TFut: Fut<TRet>> = A::Fut<B::Ret<TRet>, B::Fut<TRet, TFut>>; type Result<TRet: Ret, TFut: Fut<TRet>, T: Func<TRet, TFut>> = A::Result<B::Ret<TRet>, B::Fut<TRet, TFut>, B::Result<TRet, TFut, T>>; fn map<TRet: Ret, TFut: Fut<TRet>, T: Func<TRet, TFut>>( &self, t: T, ) -> Self::Result<TRet, TFut, T> { self.a.map(self.b.map(t)) } } pub struct BasePlugin; impl Plugin for BasePlugin { type Ret<TRet: Ret> = TRet; type Fut<TRet: Ret, TFut: Fut<TRet>> = TFut; type Result<TRet: Ret, TFut: Fut<TRet>, T: Func<TRet, TFut>> = T; fn map<TRet: Ret, TFut: Fut<TRet>, T: Func<TRet, TFut>>( &self, t: T, ) -> Self::Result<TRet, TFut, T> { println!("BUILD BASE"); t } } pub struct MapPlugin(String); impl Plugin for MapPlugin { type Ret<TRet: Ret> = TRet; type Fut<TRet: Ret, TFut: Fut<TRet>> = Pin<Box<dyn Fut<Self::Ret<TRet>>>>; type Result<TRet: Ret, TFut: Fut<TRet>, T: Func<TRet, TFut>> = Box<dyn Func<Self::Ret<TRet>, Self::Fut<TRet, TFut>>>; fn map<TRet: Ret, TFut: Fut<TRet>, T: Func<TRet, TFut>>( &self, t: T, ) -> Self::Result<TRet, TFut, T> { let id = self.0.clone(); println!("BUILD {}", id); Box::new(move || { Box::pin(async move { println!("MAP {} - BEFORE", id); let data = t().await; println!("MAP {} - AFTER", id); data }) }) } } #[tokio::main] async fn main() { let r = <Router>::new() .plugin(MapPlugin("A".into())) .plugin(MapPlugin("B".into())) .query(|| async move { println!("QUERY"); "Query!".to_string() }) .await; // let r = <Router>::new() // .plugin(MapPlugin {}) // .query(|| "Query!".to_string()); // let r = <Router>::new() // .plugin(MapPlugin {}) // .plugin(OverridePlugin {}) // .query(|| "Query!".to_string()); }
The text was updated successfully, but these errors were encountered:
Final version of this merged in #153
Sorry, something went wrong.
No branches or pull requests
Original GAT's demo
Playground
Upgraded GAT's demo (Closures + Futures + Return Type)
The text was updated successfully, but these errors were encountered: