use crate::{Conn, Headers, Info, Status, Upgrade};
use std::{borrow::Cow, future::Future};
pub trait Handler: Send + Sync + 'static {
fn run(&self, conn: Conn) -> impl Future<Output = Conn> + Send {
async { conn }
}
fn init(&mut self, info: &mut Info) -> impl Future<Output = ()> + Send {
let _ = info;
std::future::ready(())
}
fn before_send(&self, conn: Conn) -> impl Future<Output = Conn> + Send {
std::future::ready(conn)
}
fn has_upgrade(&self, upgrade: &Upgrade) -> bool {
let _ = upgrade;
false
}
fn upgrade(&self, upgrade: Upgrade) -> impl Future<Output = ()> + Send {
let _ = upgrade;
async { unimplemented!("if has_upgrade returns true, you must also implement upgrade") }
}
fn name(&self) -> Cow<'static, str> {
std::any::type_name::<Self>().into()
}
}
impl Handler for Status {
async fn run(&self, conn: Conn) -> Conn {
conn.with_status(*self)
}
}
impl<H: Handler> Handler for Vec<H> {
async fn run(&self, mut conn: Conn) -> Conn {
for handler in self {
log::debug!("running {}", handler.name());
conn = handler.run(conn).await;
if conn.is_halted() {
break;
}
}
conn
}
async fn init(&mut self, info: &mut Info) {
for handler in self {
handler.init(info).await;
}
}
async fn before_send(&self, mut conn: Conn) -> Conn {
for handler in self.iter().rev() {
conn = handler.before_send(conn).await;
}
conn
}
fn name(&self) -> Cow<'static, str> {
self.iter()
.map(Handler::name)
.collect::<Vec<_>>()
.join(",")
.into()
}
fn has_upgrade(&self, upgrade: &Upgrade) -> bool {
self.iter().any(|g| g.has_upgrade(upgrade))
}
async fn upgrade(&self, upgrade: Upgrade) {
if let Some(handler) = self.iter().find(|g| g.has_upgrade(&upgrade)) {
handler.upgrade(upgrade).await;
}
}
}
impl<const L: usize, H: Handler> Handler for [H; L] {
async fn run(&self, mut conn: Conn) -> Conn {
for handler in self {
log::debug!("running {}", handler.name());
conn = handler.run(conn).await;
if conn.is_halted() {
break;
}
}
conn
}
async fn init(&mut self, info: &mut Info) {
for handler in self {
handler.init(info).await;
}
}
async fn before_send(&self, mut conn: Conn) -> Conn {
for handler in self.iter().rev() {
conn = handler.before_send(conn).await;
}
conn
}
fn name(&self) -> Cow<'static, str> {
self.iter()
.map(Handler::name)
.collect::<Vec<_>>()
.join(",")
.into()
}
fn has_upgrade(&self, upgrade: &Upgrade) -> bool {
self.iter().any(|g| g.has_upgrade(upgrade))
}
async fn upgrade(&self, upgrade: Upgrade) {
if let Some(handler) = self.iter().find(|g| g.has_upgrade(&upgrade)) {
handler.upgrade(upgrade).await;
}
}
}
impl<Fun, Fut> Handler for Fun
where
Fun: Fn(Conn) -> Fut + Send + Sync + 'static,
Fut: Future<Output = Conn> + Send + 'static,
{
async fn run(&self, conn: Conn) -> Conn {
(self)(conn).await
}
}
impl Handler for &'static str {
async fn run(&self, conn: Conn) -> Conn {
conn.ok(*self)
}
fn name(&self) -> Cow<'static, str> {
format!("conn.ok({:?})", &self).into()
}
}
impl Handler for String {
async fn run(&self, conn: Conn) -> Conn {
conn.ok(self.clone())
}
fn name(&self) -> Cow<'static, str> {
format!("conn.ok({:?})", &self).into()
}
}
impl Handler for () {
async fn run(&self, conn: Conn) -> Conn {
conn
}
}
impl<H: Handler> Handler for Option<H> {
async fn run(&self, conn: Conn) -> Conn {
let handler = crate::conn_unwrap!(self, conn);
handler.run(conn).await
}
async fn init(&mut self, info: &mut Info) {
if let Some(handler) = self {
handler.init(info).await;
}
}
async fn before_send(&self, conn: Conn) -> Conn {
let handler = crate::conn_unwrap!(self, conn);
handler.before_send(conn).await
}
fn name(&self) -> Cow<'static, str> {
self.as_ref().map_or_else(|| "-".into(), Handler::name)
}
fn has_upgrade(&self, upgrade: &Upgrade) -> bool {
self.as_ref().is_some_and(|h| h.has_upgrade(upgrade))
}
async fn upgrade(&self, upgrade: Upgrade) {
if let Some(handler) = self {
handler.upgrade(upgrade).await;
}
}
}
impl Handler for Headers {
async fn run(&self, mut conn: Conn) -> Conn {
conn.response_headers_mut().append_all(self.clone());
conn
}
}
impl<T, E> Handler for Result<T, E>
where
T: Handler,
E: Handler,
{
async fn run(&self, conn: Conn) -> Conn {
match self {
Ok(t) => t.run(conn).await,
Err(e) => e.run(conn).await,
}
}
async fn init(&mut self, info: &mut Info) {
match self {
Ok(t) => t.init(info).await,
Err(e) => e.init(info).await,
}
}
async fn before_send(&self, conn: Conn) -> Conn {
match self {
Ok(t) => t.before_send(conn).await,
Err(e) => e.before_send(conn).await,
}
}
fn name(&self) -> Cow<'static, str> {
match self {
Ok(t) => format!("Ok({})", t.name()).into(),
Err(e) => format!("Err({})", e.name()).into(),
}
}
fn has_upgrade(&self, upgrade: &Upgrade) -> bool {
match self {
Ok(t) => t.has_upgrade(upgrade),
Err(e) => e.has_upgrade(upgrade),
}
}
async fn upgrade(&self, upgrade: Upgrade) {
match self {
Ok(t) => t.upgrade(upgrade).await,
Err(e) => e.upgrade(upgrade).await,
}
}
}
macro_rules! reverse_before_send {
($conn:ident, $name:ident) => (
let $conn = ($name).before_send($conn).await;
);
($conn:ident, $name:ident $($other_names:ident)+) => (
reverse_before_send!($conn, $($other_names)*);
reverse_before_send!($conn, $name);
);
}
macro_rules! impl_handler_tuple {
($($name:ident)+) => (
impl<$($name),*> Handler for ($($name,)*) where $($name: Handler),* {
#[allow(non_snake_case)]
async fn run(&self, conn: Conn) -> Conn {
let ($(ref $name,)*) = *self;
$(
log::debug!("running {}", ($name).name());
let conn = ($name).run(conn).await;
if conn.is_halted() { return conn }
)*
conn
}
#[allow(non_snake_case)]
async fn init(&mut self, info: &mut Info) {
let ($(ref mut $name,)*) = *self;
$(
log::trace!("initializing {}", ($name).name());
($name).init(info).await;
)*
}
#[allow(non_snake_case)]
async fn before_send(&self, conn: Conn) -> Conn {
let ($(ref $name,)*) = *self;
reverse_before_send!(conn, $($name)+);
conn
}
#[allow(non_snake_case)]
fn has_upgrade(&self, upgrade: &Upgrade) -> bool {
let ($(ref $name,)*) = *self;
$(if ($name).has_upgrade(upgrade) { return true })*
false
}
#[allow(non_snake_case)]
async fn upgrade(&self, upgrade: Upgrade) {
let ($(ref $name,)*) = *self;
$(if ($name).has_upgrade(&upgrade) {
return ($name).upgrade(upgrade).await;
})*
}
#[allow(non_snake_case)]
fn name(&self) -> Cow<'static, str> {
let ($(ref $name,)*) = *self;
format!(concat!("(\n", $(
concat!(" {",stringify!($name) ,":},\n")
),*, ")"), $($name = ($name).name()),*).into()
}
}
);
}
impl_handler_tuple! { A B }
impl_handler_tuple! { A B C }
impl_handler_tuple! { A B C D }
impl_handler_tuple! { A B C D E }
impl_handler_tuple! { A B C D E F }
impl_handler_tuple! { A B C D E F G }
impl_handler_tuple! { A B C D E F G H }
impl_handler_tuple! { A B C D E F G H I }
impl_handler_tuple! { A B C D E F G H I J }
impl_handler_tuple! { A B C D E F G H I J K }
impl_handler_tuple! { A B C D E F G H I J K L }
impl_handler_tuple! { A B C D E F G H I J K L M }
impl_handler_tuple! { A B C D E F G H I J K L M N }
impl_handler_tuple! { A B C D E F G H I J K L M N O }