mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2025-06-26 22:56:37 +02:00
79 lines
2.2 KiB
Rust
79 lines
2.2 KiB
Rust
use axum::{
|
|
Router,
|
|
extract::FromRequestParts,
|
|
response::IntoResponse,
|
|
routing::{MethodFilter, on},
|
|
};
|
|
use conduwuit::Result;
|
|
use futures::{Future, TryFutureExt};
|
|
use http::Method;
|
|
use ruma::api::IncomingRequest;
|
|
|
|
use super::{Ruma, RumaResponse, State};
|
|
|
|
pub(in super::super) trait RumaHandler<T> {
|
|
fn add_route(&'static self, router: Router<State>, path: &str) -> Router<State>;
|
|
fn add_routes(&'static self, router: Router<State>) -> Router<State>;
|
|
}
|
|
|
|
pub(in super::super) trait RouterExt {
|
|
fn ruma_route<H, T>(self, handler: &'static H) -> Self
|
|
where
|
|
H: RumaHandler<T>;
|
|
}
|
|
|
|
impl RouterExt for Router<State> {
|
|
fn ruma_route<H, T>(self, handler: &'static H) -> Self
|
|
where
|
|
H: RumaHandler<T>,
|
|
{
|
|
handler.add_routes(self)
|
|
}
|
|
}
|
|
|
|
macro_rules! ruma_handler {
|
|
( $($tx:ident),* $(,)? ) => {
|
|
#[allow(non_snake_case)]
|
|
impl<Err, Req, Fut, Fun, $($tx,)*> RumaHandler<($($tx,)* Ruma<Req>,)> for Fun
|
|
where
|
|
Fun: Fn($($tx,)* Ruma<Req>,) -> Fut + Send + Sync + 'static,
|
|
Fut: Future<Output = Result<Req::OutgoingResponse, Err>> + Send,
|
|
Req: IncomingRequest + Send + Sync + 'static,
|
|
Err: IntoResponse + Send,
|
|
<Req as IncomingRequest>::OutgoingResponse: Send,
|
|
$( $tx: FromRequestParts<State> + Send + Sync + 'static, )*
|
|
{
|
|
fn add_routes(&'static self, router: Router<State>) -> Router<State> {
|
|
Req::METADATA
|
|
.history
|
|
.all_paths()
|
|
.fold(router, |router, path| self.add_route(router, path))
|
|
}
|
|
|
|
fn add_route(&'static self, router: Router<State>, path: &str) -> Router<State> {
|
|
let action = |$($tx,)* req| self($($tx,)* req).map_ok(RumaResponse);
|
|
let method = method_to_filter(&Req::METADATA.method);
|
|
router.route(path, on(method, action))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ruma_handler!();
|
|
ruma_handler!(T1);
|
|
ruma_handler!(T1, T2);
|
|
ruma_handler!(T1, T2, T3);
|
|
ruma_handler!(T1, T2, T3, T4);
|
|
|
|
const fn method_to_filter(method: &Method) -> MethodFilter {
|
|
match *method {
|
|
| Method::DELETE => MethodFilter::DELETE,
|
|
| Method::GET => MethodFilter::GET,
|
|
| Method::HEAD => MethodFilter::HEAD,
|
|
| Method::OPTIONS => MethodFilter::OPTIONS,
|
|
| Method::PATCH => MethodFilter::PATCH,
|
|
| Method::POST => MethodFilter::POST,
|
|
| Method::PUT => MethodFilter::PUT,
|
|
| Method::TRACE => MethodFilter::TRACE,
|
|
| _ => panic!("Unsupported HTTP method"),
|
|
}
|
|
}
|