typeway_server/
handler_for.rs1use std::marker::PhantomData;
8
9use typeway_core::{Endpoint, ExtractPath, HttpMethod, PathSpec};
10
11use crate::handler::{into_boxed_handler, BoxedHandler, Handler};
12use crate::router::Router;
13
14pub struct BoundHandler<E> {
19 method: http::Method,
20 pattern: String,
21 match_fn: crate::router::MatchFn,
22 handler: BoxedHandler,
23 _endpoint: PhantomData<E>,
24}
25
26impl<E> BoundHandler<E> {
27 pub fn new(
29 method: http::Method,
30 pattern: String,
31 match_fn: crate::router::MatchFn,
32 handler: BoxedHandler,
33 ) -> Self {
34 BoundHandler {
35 method,
36 pattern,
37 match_fn,
38 handler,
39 _endpoint: PhantomData,
40 }
41 }
42
43 pub(crate) fn register_into(self, router: &mut Router) {
45 router.add_route(self.method, self.pattern, self.match_fn, self.handler);
46 }
47}
48
49pub fn bind<E, H, Args>(handler: H) -> BoundHandler<E>
62where
63 E: BindableEndpoint,
64 H: Handler<Args>,
65 Args: 'static,
66{
67 let method = E::method();
68 let pattern = E::pattern();
69 let match_fn = E::match_fn();
70
71 BoundHandler {
72 method,
73 pattern,
74 match_fn,
75 handler: into_boxed_handler(handler),
76 _endpoint: PhantomData,
77 }
78}
79
80#[macro_export]
93macro_rules! bind {
94 ($handler:expr) => {
95 $crate::bind::<_, _, _>($handler)
96 };
97}
98
99pub trait BindableEndpoint {
101 fn method() -> http::Method;
102 fn pattern() -> String;
103 fn match_fn() -> crate::router::MatchFn;
104}
105
106impl<M, P, Req, Res, Q, Err> BindableEndpoint for Endpoint<M, P, Req, Res, Q, Err>
107where
108 M: HttpMethod,
109 P: PathSpec + ExtractPath + Send + 'static,
110 P::Captures: Send,
111{
112 fn method() -> http::Method {
113 M::METHOD
114 }
115
116 fn pattern() -> String {
117 P::pattern()
118 }
119
120 fn match_fn() -> crate::router::MatchFn {
121 Box::new(|segments| P::extract(segments).is_some())
122 }
123}