#[macro_export]
macro_rules! erase_handler {
($handler:expr) => {
$crate::router::ErasedHandler::from_closure(Box::new(move |_args: &str| {
let fut = $handler();
Box::pin(async move {
<_ as $crate::router::IntoHandlerResult>::into_handler_result(fut.await)
})
as ::std::pin::Pin<
Box<dyn ::std::future::Future<Output = ::std::result::Result<String, String>> + Send>,
>
}))
};
}
#[macro_export]
macro_rules! erase_handler_with_args {
($handler:expr, $args_ty:ty) => {
$crate::router::ErasedHandler::from_closure(Box::new(move |args_str: &str| {
let parsed: ::std::result::Result<$args_ty, _> = ::serde_json::from_str(args_str);
match parsed {
Ok(value) => {
let fut = $handler(value);
Box::pin(async move {
<_ as $crate::router::IntoHandlerResult>::into_handler_result(fut.await)
})
as ::std::pin::Pin<
Box<
dyn ::std::future::Future<
Output = ::std::result::Result<String, String>,
> + Send,
>,
>
}
Err(e) => Box::pin(async move {
Err(format!("Failed to deserialize args: {e}"))
})
as ::std::pin::Pin<
Box<
dyn ::std::future::Future<
Output = ::std::result::Result<String, String>,
> + Send,
>,
>,
}
}))
};
}
#[macro_export]
macro_rules! erase_handler_with_state {
($handler:expr, $state_ty:ty, $args_ty:ty, $states:expr) => {{
let states = $states;
let __af_type_id = ::std::any::TypeId::of::<$state_ty>();
let __af_type_name = ::std::any::type_name::<$state_ty>();
$crate::router::ErasedHandler::from_closure(Box::new(move |args_str: &str| {
let state_arc: ::std::result::Result<::std::sync::Arc<$state_ty>, String> =
$crate::router::resolve_state_erased(&states, __af_type_id, __af_type_name)
.and_then(|any| {
any.downcast::<$state_ty>().map_err(|_| {
format!("State type mismatch: expected {}", __af_type_name)
})
});
match state_arc {
Ok(s) => {
let parsed: ::std::result::Result<$args_ty, _> =
::serde_json::from_str(args_str);
match parsed {
Ok(value) => {
let fut = $handler($crate::router::State(s), value);
Box::pin(async move {
<_ as $crate::router::IntoHandlerResult>::into_handler_result(
fut.await,
)
})
as ::std::pin::Pin<
Box<
dyn ::std::future::Future<
Output = ::std::result::Result<String, String>,
> + Send,
>,
>
}
Err(e) => Box::pin(async move {
Err(format!("Failed to deserialize args: {e}"))
})
as ::std::pin::Pin<
Box<
dyn ::std::future::Future<
Output = ::std::result::Result<String, String>,
> + Send,
>,
>,
}
}
Err(msg) => {
Box::pin(async move { Err(msg) })
as ::std::pin::Pin<
Box<
dyn ::std::future::Future<
Output = ::std::result::Result<String, String>,
> + Send,
>,
>
}
}
}))
}};
}
#[macro_export]
macro_rules! erase_handler_with_state_only {
($handler:expr, $state_ty:ty, $states:expr) => {{
let states = $states;
let __af_type_id = ::std::any::TypeId::of::<$state_ty>();
let __af_type_name = ::std::any::type_name::<$state_ty>();
$crate::router::ErasedHandler::from_closure(Box::new(move |_args: &str| {
let state_arc: ::std::result::Result<::std::sync::Arc<$state_ty>, String> =
$crate::router::resolve_state_erased(&states, __af_type_id, __af_type_name)
.and_then(|any| {
any.downcast::<$state_ty>().map_err(|_| {
format!("State type mismatch: expected {}", __af_type_name)
})
});
match state_arc {
Ok(s) => {
let fut = $handler($crate::router::State(s));
Box::pin(async move {
<_ as $crate::router::IntoHandlerResult>::into_handler_result(fut.await)
})
as ::std::pin::Pin<
Box<
dyn ::std::future::Future<
Output = ::std::result::Result<String, String>,
> + Send,
>,
>
}
Err(msg) => {
Box::pin(async move { Err(msg) })
as ::std::pin::Pin<
Box<
dyn ::std::future::Future<
Output = ::std::result::Result<String, String>,
> + Send,
>,
>
}
}
}))
}};
}
#[macro_export]
macro_rules! erase_streaming_handler {
($handler:expr) => {
$crate::router::ErasedStreamHandler::from_closure(Box::new(
move |_args: &str, tx: $crate::router::StreamSender| {
let fut = $handler(tx);
Box::pin(async move {
<_ as $crate::router::IntoHandlerResult>::into_handler_result(fut.await)
})
as ::std::pin::Pin<
Box<
dyn ::std::future::Future<
Output = ::std::result::Result<String, String>,
> + Send,
>,
>
},
))
};
}
#[macro_export]
macro_rules! erase_streaming_handler_with_args {
($handler:expr, $args_ty:ty) => {
$crate::router::ErasedStreamHandler::from_closure(Box::new(
move |args_str: &str, tx: $crate::router::StreamSender| {
let parsed: ::std::result::Result<$args_ty, _> = ::serde_json::from_str(args_str);
match parsed {
Ok(value) => {
let fut = $handler(value, tx);
Box::pin(async move {
<_ as $crate::router::IntoHandlerResult>::into_handler_result(
fut.await,
)
})
as ::std::pin::Pin<
Box<
dyn ::std::future::Future<
Output = ::std::result::Result<String, String>,
> + Send,
>,
>
}
Err(e) => Box::pin(async move {
Err(format!("Failed to deserialize args: {e}"))
})
as ::std::pin::Pin<
Box<
dyn ::std::future::Future<
Output = ::std::result::Result<String, String>,
> + Send,
>,
>,
}
},
))
};
}
#[macro_export]
macro_rules! erase_streaming_handler_with_state {
($handler:expr, $state_ty:ty, $args_ty:ty, $states:expr) => {{
let states = $states;
let __af_type_id = ::std::any::TypeId::of::<$state_ty>();
let __af_type_name = ::std::any::type_name::<$state_ty>();
$crate::router::ErasedStreamHandler::from_closure(Box::new(
move |args_str: &str, tx: $crate::router::StreamSender| {
let state_arc: ::std::result::Result<::std::sync::Arc<$state_ty>, String> =
$crate::router::resolve_state_erased(&states, __af_type_id, __af_type_name)
.and_then(|any| {
any.downcast::<$state_ty>().map_err(|_| {
format!("State type mismatch: expected {}", __af_type_name)
})
});
match state_arc {
Ok(s) => {
let parsed: ::std::result::Result<$args_ty, _> =
::serde_json::from_str(args_str);
match parsed {
Ok(value) => {
let fut = $handler($crate::router::State(s), value, tx);
Box::pin(async move {
<_ as $crate::router::IntoHandlerResult>::into_handler_result(
fut.await,
)
})
as ::std::pin::Pin<
Box<
dyn ::std::future::Future<
Output = ::std::result::Result<String, String>,
> + Send,
>,
>
}
Err(e) => Box::pin(async move {
Err(format!("Failed to deserialize args: {e}"))
})
as ::std::pin::Pin<
Box<
dyn ::std::future::Future<
Output = ::std::result::Result<String, String>,
> + Send,
>,
>,
}
}
Err(msg) => {
Box::pin(async move { Err(msg) })
as ::std::pin::Pin<
Box<
dyn ::std::future::Future<
Output = ::std::result::Result<String, String>,
> + Send,
>,
>
}
}
},
))
}};
}
#[macro_export]
macro_rules! erase_streaming_handler_with_state_only {
($handler:expr, $state_ty:ty, $states:expr) => {{
let states = $states;
let __af_type_id = ::std::any::TypeId::of::<$state_ty>();
let __af_type_name = ::std::any::type_name::<$state_ty>();
$crate::router::ErasedStreamHandler::from_closure(Box::new(
move |_args: &str, tx: $crate::router::StreamSender| {
let state_arc: ::std::result::Result<::std::sync::Arc<$state_ty>, String> =
$crate::router::resolve_state_erased(&states, __af_type_id, __af_type_name)
.and_then(|any| {
any.downcast::<$state_ty>().map_err(|_| {
format!("State type mismatch: expected {}", __af_type_name)
})
});
match state_arc {
Ok(s) => {
let fut = $handler($crate::router::State(s), tx);
Box::pin(async move {
<_ as $crate::router::IntoHandlerResult>::into_handler_result(
fut.await,
)
})
as ::std::pin::Pin<
Box<
dyn ::std::future::Future<
Output = ::std::result::Result<String, String>,
> + Send,
>,
>
}
Err(msg) => {
Box::pin(async move { Err(msg) })
as ::std::pin::Pin<
Box<
dyn ::std::future::Future<
Output = ::std::result::Result<String, String>,
> + Send,
>,
>
}
}
},
))
}};
}
#[macro_export]
macro_rules! register_handlers_erased {
($router:expr, { $($entries:tt)* }) => {
#[allow(unused_variables)]
let states = $router.shared_states();
$crate::__rhe_entries!($router, states, $($entries)*);
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __rhe_entries {
($router:expr, $states:expr, ) => {};
($router:expr, $states:expr, $name:literal => stream $handler:ident (state: $sty:ty, args: $aty:ty), $($rest:tt)*) => {
$router.register_streaming_erased(
$name,
$crate::erase_streaming_handler_with_state!($handler, $sty, $aty, $states.clone()),
);
$crate::__rhe_entries!($router, $states, $($rest)*)
};
($router:expr, $states:expr, $name:literal => stream $handler:ident (state: $sty:ty), $($rest:tt)*) => {
$router.register_streaming_erased(
$name,
$crate::erase_streaming_handler_with_state_only!($handler, $sty, $states.clone()),
);
$crate::__rhe_entries!($router, $states, $($rest)*)
};
($router:expr, $states:expr, $name:literal => stream $handler:ident (args: $aty:ty), $($rest:tt)*) => {
$router.register_streaming_erased(
$name,
$crate::erase_streaming_handler_with_args!($handler, $aty),
);
$crate::__rhe_entries!($router, $states, $($rest)*)
};
($router:expr, $states:expr, $name:literal => stream $handler:ident (), $($rest:tt)*) => {
$router.register_streaming_erased(
$name,
$crate::erase_streaming_handler!($handler),
);
$crate::__rhe_entries!($router, $states, $($rest)*)
};
($router:expr, $states:expr, $name:literal => $handler:ident (state: $sty:ty, args: $aty:ty), $($rest:tt)*) => {
$router.register_erased(
$name,
$crate::erase_handler_with_state!($handler, $sty, $aty, $states.clone()),
);
$crate::__rhe_entries!($router, $states, $($rest)*)
};
($router:expr, $states:expr, $name:literal => $handler:ident (state: $sty:ty), $($rest:tt)*) => {
$router.register_erased(
$name,
$crate::erase_handler_with_state_only!($handler, $sty, $states.clone()),
);
$crate::__rhe_entries!($router, $states, $($rest)*)
};
($router:expr, $states:expr, $name:literal => $handler:ident (args: $aty:ty), $($rest:tt)*) => {
$router.register_erased(
$name,
$crate::erase_handler_with_args!($handler, $aty),
);
$crate::__rhe_entries!($router, $states, $($rest)*)
};
($router:expr, $states:expr, $name:literal => $handler:ident (), $($rest:tt)*) => {
$router.register_erased(
$name,
$crate::erase_handler!($handler),
);
$crate::__rhe_entries!($router, $states, $($rest)*)
};
}