🏗️ Elegant & Highly Performant Async Gemini Server Framework for the Modern Age
async framework gemini-protocol protocol gemini rust
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(route): merge async and sync mount functions !!

Fuwn 6909271f a6a61d5b

+39 -50
+2 -2
examples/windmark.rs
··· 200 200 ) 201 201 } 202 202 }); 203 - router.mount_async("/async", move |_| { 203 + router.mount("/async", move |_| { 204 204 let async_clicks = async_clicks.clone(); 205 205 206 206 async move { ··· 211 211 Response::success(*clicks) 212 212 } 213 213 }); 214 - router.mount_async("/async-nothing", |_| { 214 + router.mount("/async-nothing", |_| { 215 215 async { Response::success("This is an async route.") } 216 216 }); 217 217
+8 -10
src/handler/response/route.rs
··· 16 16 // Copyright (C) 2022-2022 Fuwn <contact@fuwn.me> 17 17 // SPDX-License-Identifier: GPL-3.0-only 18 18 19 - use std::{future::Future, pin::Pin}; 19 + use std::future::Future; 20 + 21 + use async_trait::async_trait; 20 22 21 23 use crate::{context::RouteContext, Response}; 22 24 23 25 #[allow(clippy::module_name_repetitions)] 26 + #[async_trait] 24 27 pub trait RouteResponse: Send + Sync { 25 - fn call( 26 - &mut self, 27 - context: RouteContext<'_>, 28 - ) -> Pin<Box<dyn Future<Output = Response> + Send>>; 28 + async fn call(&mut self, context: RouteContext<'_>) -> Response; 29 29 } 30 30 31 + #[async_trait] 31 32 impl<T, F> RouteResponse for T 32 33 where 33 34 T: FnMut(RouteContext<'_>) -> F + Send + Sync, 34 35 F: Future<Output = Response> + Send + 'static, 35 36 { 36 - fn call( 37 - &mut self, 38 - context: RouteContext<'_>, 39 - ) -> Pin<Box<dyn Future<Output = Response> + Send>> { 40 - Box::pin((*self)(context)) 37 + async fn call(&mut self, context: RouteContext<'_>) -> Response { 38 + (*self)(context).await 41 39 } 42 40 }
+7
src/response.rs
··· 144 144 self 145 145 } 146 146 } 147 + 148 + impl std::future::IntoFuture for Response { 149 + type IntoFuture = std::future::Ready<Self::Output>; 150 + type Output = Self; 151 + 152 + fn into_future(self) -> Self::IntoFuture { std::future::ready(self) } 153 + }
+22 -38
src/router.rs
··· 20 20 21 21 use std::{ 22 22 error::Error, 23 + future::IntoFuture, 23 24 sync::{Arc, Mutex}, 24 25 time, 25 26 }; ··· 65 66 /// response generation, panics, logging, and more. 66 67 #[derive(Clone)] 67 68 pub struct Router { 68 - routes: matchit::Router<Arc<Mutex<Box<dyn RouteResponse>>>>, 69 + routes: matchit::Router<Arc<AsyncMutex<Box<dyn RouteResponse>>>>, 69 70 error_handler: Arc<Mutex<Box<dyn ErrorResponse>>>, 70 71 private_key_file_name: String, 71 72 ca_file_name: String, ··· 133 134 134 135 /// Map routes to URL paths 135 136 /// 136 - /// # Examples 137 - /// 138 - /// ```rust 139 - /// windmark::Router::new() 140 - /// .mount("/", windmark::success!("This is the index page!")) 141 - /// .mount("/test", windmark::success!("This is a test page!")); 142 - /// ``` 143 - /// 144 - /// # Panics 145 - /// 146 - /// May panic if the route cannot be mounted. 147 - pub fn mount( 148 - &mut self, 149 - route: impl Into<String> + AsRef<str>, 150 - mut handler: impl FnMut(RouteContext<'_>) -> Response + Send + Sync + 'static, 151 - ) -> &mut Self { 152 - self.mount_async(route, move |context| { 153 - let response = handler(context); 154 - 155 - async move { response } 156 - }); 157 - 158 - self 159 - } 160 - 161 - /// Map routes to URL paths; with async support 137 + /// Supports both synchronous and asynchronous handlers 162 138 /// 163 139 /// # Examples 164 140 /// 165 141 /// ```rust 166 - /// windmark::Router::new().mount_async("/", |_| { 167 - /// async { windmark::Response::success("This is the index page!") } 168 - /// }); 142 + /// use windmark::Response; 143 + /// 144 + /// windmark::Router::new() 145 + /// .mount("/", |_| { 146 + /// async { Response::success("This is the index page!") } 147 + /// }) 148 + /// .mount("/about", |_| async { Response::success("About that...") }); 169 149 /// ``` 170 150 /// 171 151 /// # Panics 172 152 /// 173 153 /// May panic if the route cannot be mounted. 174 - pub fn mount_async<R>( 154 + pub fn mount<R>( 175 155 &mut self, 176 156 route: impl Into<String> + AsRef<str>, 177 157 mut handler: impl FnMut(RouteContext<'_>) -> R + Send + Sync + 'static, 178 158 ) -> &mut Self 179 159 where 180 - R: std::future::Future<Output = Response> + Send + 'static, 160 + R: IntoFuture<Output = Response> + Send + 'static, 161 + <R as IntoFuture>::IntoFuture: Send, 181 162 { 182 163 self 183 164 .routes 184 165 .insert( 185 166 route.into(), 186 - Arc::new(Mutex::new(Box::new(move |context: RouteContext<'_>| { 187 - Box::pin(handler(context)) 188 - }))), 167 + Arc::new(AsyncMutex::new(Box::new( 168 + move |context: RouteContext<'_>| { 169 + Box::pin(handler(context).into_future()) 170 + }, 171 + ))), 189 172 ) 190 173 .unwrap(); 191 174 ··· 419 402 )); 420 403 } 421 404 422 - let handler = (*route.value).lock().unwrap().call(RouteContext::new( 405 + let mut lock = (*route.value).lock().await; 406 + let handler = lock.call(RouteContext::new( 423 407 stream.get_ref(), 424 408 &url, 425 409 &route.params, ··· 669 653 /// use windmark::Response; 670 654 /// 671 655 /// windmark::Router::new().attach_stateless(|r| { 672 - /// r.mount_async( 656 + /// r.mount( 673 657 /// "/module", 674 658 /// Box::new(|_| Response::success("This is a module!")), 675 659 /// ); ··· 688 672 /// 689 673 /// mod windmark_example { 690 674 /// pub fn module(router: &mut windmark::Router) { 691 - /// router.mount_async( 675 + /// router.mount( 692 676 /// "/module", 693 677 /// Box::new(|_| windmark::Response::success("This is a module!")), 694 678 /// );