1use std::borrow::Cow;
2use std::collections::HashMap;
3use std::future::Future;
4
5use crate::{IncomingRequest, Method, Response};
6
7use super::handler::HandlerResult;
8use super::options::ServiceOptions;
9use super::preview::PreviewDecision;
10
11pub(super) type RequestHandler = Box<
16 dyn Fn(
17 IncomingRequest,
18 )
19 -> std::pin::Pin<Box<dyn Future<Output = HandlerResult<PreviewDecision>> + Send>>
20 + Send
21 + Sync,
22>;
23
24pub trait RouteOutput: Send + 'static {
33 const PREVIEW_AWARE: bool;
34
35 fn into_preview_decision(self) -> HandlerResult<PreviewDecision>;
36}
37
38impl RouteOutput for HandlerResult<Response> {
39 const PREVIEW_AWARE: bool = false;
40
41 fn into_preview_decision(self) -> HandlerResult<PreviewDecision> {
42 self.map(PreviewDecision::Respond)
43 }
44}
45
46impl RouteOutput for HandlerResult<PreviewDecision> {
47 const PREVIEW_AWARE: bool = true;
48
49 fn into_preview_decision(self) -> HandlerResult<PreviewDecision> {
50 self
51 }
52}
53
54pub(super) struct HandlerEntry {
55 pub(super) handler: RequestHandler,
56 pub(super) preview_aware: bool,
57}
58
59pub(super) struct RouteEntry {
61 pub(super) handlers: HashMap<Method, HandlerEntry>,
62 pub(super) options: Option<ServiceOptions>,
63}
64
65pub(super) fn resolve_service<'a>(
71 raw: &'a str,
72 aliases: &'a HashMap<String, String>,
73 default_service: Option<&'a str>,
74) -> Cow<'a, str> {
75 let mut cur: Cow<'a, str> = if raw.is_empty() || raw == "/" {
76 default_service.map_or(Cow::Borrowed(raw), Cow::Borrowed)
77 } else {
78 Cow::Borrowed(raw)
79 };
80
81 for _ in 0..4 {
82 if let Some(next) = aliases.get(cur.as_ref()) {
83 cur = Cow::Borrowed(next.as_str());
84 } else {
85 break;
86 }
87 }
88
89 cur
90}