#[cfg(all(native, feature = "client-router"))]
use crate::routers::client_router::ClientRouter;
#[cfg(native)]
use crate::routers::server_router::ServerRouter;
#[cfg(native)]
use std::future::Future;
#[cfg(native)]
use std::pin::Pin;
#[cfg(native)]
use std::sync::Arc;
#[cfg(native)]
pub type AsyncRouterFactoryFn = fn() -> Pin<
Box<
dyn Future<Output = Result<Arc<ServerRouter>, Box<dyn std::error::Error + Send + Sync>>>
+ Send,
>,
>;
#[cfg(native)]
#[derive(Clone)]
pub enum RouterFactory {
Sync(fn() -> Arc<ServerRouter>),
Async(AsyncRouterFactoryFn),
}
#[cfg(native)]
#[derive(Clone)]
pub struct UrlPatternsRegistration {
pub factory: RouterFactory,
#[cfg(feature = "client-router")]
pub get_client_router: Option<fn() -> Arc<ClientRouter>>,
}
#[cfg(native)]
impl UrlPatternsRegistration {
#[cfg(feature = "client-router")]
pub const fn new(
get_server_router: fn() -> Arc<ServerRouter>,
get_client_router: Option<fn() -> Arc<ClientRouter>>,
) -> Self {
Self {
factory: RouterFactory::Sync(get_server_router),
get_client_router,
}
}
#[cfg(not(feature = "client-router"))]
pub const fn new(get_server_router: fn() -> Arc<ServerRouter>) -> Self {
Self {
factory: RouterFactory::Sync(get_server_router),
}
}
#[doc(hidden)]
pub const fn __macro_new(get_server_router: fn() -> Arc<ServerRouter>) -> Self {
Self {
factory: RouterFactory::Sync(get_server_router),
#[cfg(feature = "client-router")]
get_client_router: None,
}
}
#[doc(hidden)]
pub const fn __macro_new_async(factory: AsyncRouterFactoryFn) -> Self {
Self {
factory: RouterFactory::Async(factory),
#[cfg(feature = "client-router")]
get_client_router: None,
}
}
#[cfg(feature = "client-router")]
pub const fn with_client_router(
mut self,
get_client_router: fn() -> Arc<ClientRouter>,
) -> Self {
self.get_client_router = Some(get_client_router);
self
}
pub fn server_router(&self) -> Arc<ServerRouter> {
match &self.factory {
RouterFactory::Sync(f) => f(),
RouterFactory::Async(_) => {
panic!(
"Cannot call server_router() on an async #[routes] registration. \
Use server_router_async() instead."
)
}
}
}
pub async fn server_router_async(
&self,
) -> Result<Arc<ServerRouter>, Box<dyn std::error::Error + Send + Sync>> {
match &self.factory {
RouterFactory::Sync(f) => Ok(f()),
RouterFactory::Async(f) => f().await,
}
}
#[cfg(feature = "client-router")]
pub fn client_router(&self) -> Option<Arc<ClientRouter>> {
self.get_client_router.map(|f| f())
}
}
#[cfg(native)]
inventory::collect!(UrlPatternsRegistration);
#[cfg(native)]
pub fn iter_registered_url_patterns() -> impl Iterator<Item = &'static UrlPatternsRegistration> {
inventory::iter::<UrlPatternsRegistration>()
}
#[cfg(all(
target_family = "wasm",
target_os = "unknown",
feature = "client-router"
))]
mod client_registration {
use crate::routers::client_router::ClientRouter;
use std::sync::Arc;
#[derive(Clone)]
pub struct ClientRouterRegistration {
get_client_router: fn() -> Arc<ClientRouter>,
}
impl ClientRouterRegistration {
#[doc(hidden)]
pub const fn __macro_new(get_client_router: fn() -> Arc<ClientRouter>) -> Self {
Self { get_client_router }
}
pub fn client_router(&self) -> Arc<ClientRouter> {
(self.get_client_router)()
}
}
inventory::collect!(ClientRouterRegistration);
pub fn iter_registered_client_routers()
-> impl Iterator<Item = &'static ClientRouterRegistration> {
inventory::iter::<ClientRouterRegistration>()
}
pub fn collect_client_router_from_inventory() -> Option<ClientRouter> {
let mut merged: Option<ClientRouter> = None;
for reg in iter_registered_client_routers() {
let arc = reg.client_router();
let r = Arc::try_unwrap(arc).unwrap_or_else(|a| (*a).clone());
merged = Some(match merged.take() {
None => r,
Some(acc) => acc.merge(r),
});
}
merged
}
}
#[cfg(all(
target_family = "wasm",
target_os = "unknown",
feature = "client-router"
))]
pub use client_registration::{
ClientRouterRegistration, collect_client_router_from_inventory, iter_registered_client_routers,
};