use std::convert::Infallible;
use axum::routing;
use crate::{
handler::{CodecHandlerFn, Input},
CodecHandler, IntoCodecResponse,
};
pub struct MethodRouter<S = (), E = Infallible> {
#[cfg(not(feature = "aide"))]
inner: routing::MethodRouter<S, E>,
#[cfg(feature = "aide")]
inner: aide::axum::routing::ApiMethodRouter<S, E>,
}
impl<S, E> Clone for MethodRouter<S, E> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
#[cfg(not(feature = "aide"))]
impl<S, E> From<MethodRouter<S, E>> for routing::MethodRouter<S, E> {
fn from(router: MethodRouter<S, E>) -> Self {
router.inner
}
}
#[cfg(not(feature = "aide"))]
impl<S, E> From<routing::MethodRouter<S, E>> for MethodRouter<S, E> {
fn from(router: routing::MethodRouter<S, E>) -> Self {
Self { inner: router }
}
}
#[cfg(feature = "aide")]
impl<S, E> From<routing::MethodRouter<S, E>> for MethodRouter<S, E> {
fn from(router: routing::MethodRouter<S, E>) -> Self {
Self {
inner: router.into(),
}
}
}
#[cfg(feature = "aide")]
impl<S, E> From<MethodRouter<S, E>> for routing::MethodRouter<S, E> {
fn from(router: MethodRouter<S, E>) -> Self {
router.inner.into()
}
}
#[cfg(feature = "aide")]
impl<S, E> From<aide::axum::routing::ApiMethodRouter<S, E>> for MethodRouter<S, E> {
fn from(router: aide::axum::routing::ApiMethodRouter<S, E>) -> Self {
Self { inner: router }
}
}
#[cfg(feature = "aide")]
impl<S, E> From<MethodRouter<S, E>> for aide::axum::routing::ApiMethodRouter<S, E> {
fn from(router: MethodRouter<S, E>) -> Self {
router.inner
}
}
#[cfg(not(feature = "aide"))]
macro_rules! method_router_chain_method {
($name:ident, $with:ident) => {
#[doc = concat!("Route `", stringify!($name) ,"` requests to the given handler. See [`axum::routing::MethodRouter::", stringify!($name) , "`] for more details.")]
#[must_use]
pub fn $name<T, H, I, D>(mut self, handler: H) -> Self
where
H: CodecHandler<T, I, D, S> + Clone + Send + Sync + 'static,
I: Input + Send + Sync + 'static,
D: IntoCodecResponse + Send + 'static,
S: Clone + Send + Sync + 'static,
T: Sync + 'static
{
self.inner = self.inner.$name(CodecHandlerFn::new(handler));
self
}
};
}
#[cfg(feature = "aide")]
macro_rules! method_router_chain_method {
($name:ident, $with:ident) => {
#[doc = concat!("Route `", stringify!($name) ,"` requests to the given handler. See [`axum::routing::MethodRouter::", stringify!($name) , "`] for more details.")]
#[must_use]
pub fn $name<T, H, I, D>(mut self, handler: H) -> Self
where
H: CodecHandler<T, I, D, S> + Clone + Send + Sync + 'static,
I: Input + Send + Sync + 'static,
D: IntoCodecResponse + Send + 'static,
S: Clone + Send + Sync + 'static,
T: Sync + 'static,
{
self.inner = self.inner.$name(CodecHandlerFn::<H, I, D>::new(handler));
self
}
#[doc = concat!("Route `", stringify!($name) ,"` requests to the given handler. See [`axum::routing::MethodRouter::", stringify!($name) , "`] for more details.")]
#[must_use]
pub fn $with<T, H, I, D, F>(mut self, handler: H, transform: F) -> Self
where
H: CodecHandler<T, I, D, S> + Clone + Send + Sync + 'static,
I: Input + Send + Sync + 'static,
D: IntoCodecResponse + Send + 'static,
S: Clone + Send + Sync + 'static,
T: Sync + 'static,
F: FnOnce(aide::transform::TransformOperation) -> aide::transform::TransformOperation,
{
self.inner = self.inner.$with(CodecHandlerFn::<H, I, D>::new(handler), transform);
self
}
};
}
impl<S> MethodRouter<S, Infallible>
where
S: Clone + Send + Sync + 'static,
{
method_router_chain_method!(delete, delete_with);
method_router_chain_method!(get, get_with);
method_router_chain_method!(head, head_with);
method_router_chain_method!(options, options_with);
method_router_chain_method!(patch, patch_with);
method_router_chain_method!(post, post_with);
method_router_chain_method!(put, put_with);
method_router_chain_method!(trace, trace_with);
}
#[cfg(not(feature = "aide"))]
macro_rules! method_router_top_level {
($name:ident, $with:ident) => {
#[doc = concat!("Route `", stringify!($name) ,"` requests to the given handler. See [`axum::routing::", stringify!($name) , "`] for more details.")]
pub fn $name<T, H, I, D, S>(handler: H) -> MethodRouter<S, Infallible>
where
H: CodecHandler<T, I, D, S> + Clone + Send + Sync + 'static,
I: Input + Send + Sync + 'static,
D: IntoCodecResponse + Send + 'static,
S: Clone + Send + Sync + 'static,
T: Sync + 'static
{
MethodRouter::from(routing::$name(CodecHandlerFn::new(handler)))
}
};
}
#[cfg(feature = "aide")]
macro_rules! method_router_top_level {
($name:ident, $with:ident) => {
#[doc = concat!("Route `", stringify!($name) ,"` requests to the given handler. See [`axum::routing::", stringify!($name) , "`] for more details.")]
pub fn $name<T, H, I, D, S>(handler: H) -> MethodRouter<S, Infallible>
where
H: CodecHandler<T, I, D, S> + Clone + Send + Sync + 'static,
I: Input + Send + Sync + 'static,
D: IntoCodecResponse + Send + 'static,
S: Clone + Send + Sync + 'static,
T: Sync + 'static,
{
MethodRouter::from(aide::axum::routing::$name(
CodecHandlerFn::<H, I, D>::new(handler),
))
}
#[doc = concat!("Route `", stringify!($name) ,"` requests to the given handler. See [`axum::routing::", stringify!($name) , "`] for more details.")]
#[must_use]
pub fn $with<T, H, I, D, S, F>(handler: H, transform: F) -> MethodRouter<S, Infallible>
where
H: CodecHandler<T, I, D, S> + Clone + Send + Sync + 'static,
I: Input + Send + Sync + 'static,
D: IntoCodecResponse + Send + 'static,
S: Clone + Send + Sync + 'static,
T: Sync + 'static,
F: FnOnce(aide::transform::TransformOperation) -> aide::transform::TransformOperation,
{
MethodRouter::from(aide::axum::routing::$with(CodecHandlerFn::<H, I, D>::new(handler), transform))
}
};
}
method_router_top_level!(delete, delete_with);
method_router_top_level!(get, get_with);
method_router_top_level!(head, head_with);
method_router_top_level!(options, options_with);
method_router_top_level!(patch, patch_with);
method_router_top_level!(post, post_with);
method_router_top_level!(put, put_with);
method_router_top_level!(trace, trace_with);