trillium/
boxed_handler.rs1use crate::{Conn, Handler, Info, Upgrade};
2use std::{
3 any::Any,
4 borrow::Cow,
5 fmt::{self, Debug, Formatter},
6 future::Future,
7 pin::Pin,
8};
9
10trait ObjectSafeHandler: Any + Send + Sync + 'static {
11 #[must_use]
12 fn run<'handler, 'fut>(
13 &'handler self,
14 conn: Conn,
15 ) -> Pin<Box<dyn Future<Output = Conn> + Send + 'fut>>
16 where
17 'handler: 'fut,
18 Self: 'fut;
19 #[must_use]
20 fn init<'handler, 'info, 'fut>(
21 &'handler mut self,
22 info: &'info mut Info,
23 ) -> Pin<Box<dyn Future<Output = ()> + Send + 'fut>>
24 where
25 'handler: 'fut,
26 'info: 'fut,
27 Self: 'fut;
28 #[must_use]
29 fn before_send<'handler, 'fut>(
30 &'handler self,
31 conn: Conn,
32 ) -> Pin<Box<dyn Future<Output = Conn> + Send + 'fut>>
33 where
34 'handler: 'fut,
35 Self: 'fut;
36 fn has_upgrade(&self, upgrade: &Upgrade) -> bool;
37 #[must_use]
38 fn upgrade<'handler, 'fut>(
39 &'handler self,
40 upgrade: Upgrade,
41 ) -> Pin<Box<dyn Future<Output = ()> + Send + 'fut>>
42 where
43 'handler: 'fut,
44 Self: 'fut;
45 fn name(&self) -> Cow<'static, str>;
46 fn as_box_any(self: Box<Self>) -> Box<dyn Any>;
47 fn as_any(&self) -> &dyn Any;
48 fn as_mut_any(&mut self) -> &mut dyn Any;
49}
50impl<H: Handler> ObjectSafeHandler for H {
51 fn run<'handler, 'fut>(
52 &'handler self,
53 conn: Conn,
54 ) -> Pin<Box<dyn Future<Output = Conn> + Send + 'fut>>
55 where
56 'handler: 'fut,
57 Self: 'fut,
58 {
59 Box::pin(async move { Handler::run(self, conn).await })
60 }
61
62 fn init<'handler, 'info, 'fut>(
63 &'handler mut self,
64 info: &'info mut Info,
65 ) -> Pin<Box<dyn Future<Output = ()> + Send + 'fut>>
66 where
67 'handler: 'fut,
68 'info: 'fut,
69 Self: 'fut,
70 {
71 Box::pin(async move {
72 Handler::init(self, info).await;
73 })
74 }
75
76 fn before_send<'handler, 'fut>(
77 &'handler self,
78 conn: Conn,
79 ) -> Pin<Box<dyn Future<Output = Conn> + Send + 'fut>>
80 where
81 'handler: 'fut,
82 Self: 'fut,
83 {
84 Box::pin(async move { Handler::before_send(self, conn).await })
85 }
86
87 fn has_upgrade(&self, upgrade: &Upgrade) -> bool {
88 Handler::has_upgrade(self, upgrade)
89 }
90
91 fn upgrade<'handler, 'fut>(
92 &'handler self,
93 upgrade: Upgrade,
94 ) -> Pin<Box<dyn Future<Output = ()> + Send + 'fut>>
95 where
96 'handler: 'fut,
97 Self: 'fut,
98 {
99 Box::pin(async move {
100 Handler::upgrade(self, upgrade).await;
101 })
102 }
103
104 fn name(&self) -> Cow<'static, str> {
105 Handler::name(self)
106 }
107
108 fn as_box_any(self: Box<Self>) -> Box<dyn Any> {
109 self
110 }
111
112 fn as_any(&self) -> &dyn Any {
113 self
114 }
115
116 fn as_mut_any(&mut self) -> &mut dyn Any {
117 self
118 }
119}
120
121pub struct BoxedHandler(Box<dyn ObjectSafeHandler>);
123impl Debug for BoxedHandler {
124 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
125 f.debug_tuple("BoxedHandler").field(&self.0.name()).finish()
126 }
127}
128
129impl BoxedHandler {
130 #[must_use]
132 pub fn new(handler: impl Handler) -> Self {
133 Self(Box::new(handler))
134 }
135
136 pub fn is<T: Any + 'static>(&self) -> bool {
138 self.as_any().is::<T>()
139 }
140
141 #[must_use = "downcast takes the handler, so you must use it"]
147 #[allow(clippy::missing_panics_doc)]
148 pub fn downcast<T: Any + 'static>(self) -> Result<T, Self> {
149 if self.0.as_any().is::<T>() {
150 Ok(*self.0.as_box_any().downcast().unwrap())
151 } else {
152 Err(self)
153 }
154 }
155
156 pub fn downcast_ref<T: Any + 'static>(&self) -> Option<&T> {
159 self.0.as_any().downcast_ref()
160 }
161
162 pub fn downcast_mut<T: Any + 'static>(&mut self) -> Option<&mut T> {
165 self.0.as_mut_any().downcast_mut()
166 }
167}
168
169impl Handler for BoxedHandler {
170 async fn run(&self, conn: Conn) -> Conn {
171 self.0.run(conn).await
172 }
173
174 async fn init(&mut self, info: &mut Info) {
175 self.0.init(info).await;
176 }
177
178 async fn before_send(&self, conn: Conn) -> Conn {
179 self.0.before_send(conn).await
180 }
181
182 fn has_upgrade(&self, upgrade: &Upgrade) -> bool {
183 self.0.has_upgrade(upgrade)
184 }
185
186 async fn upgrade(&self, upgrade: Upgrade) {
187 self.0.upgrade(upgrade).await;
188 }
189
190 fn name(&self) -> Cow<'static, str> {
191 self.0.name()
192 }
193}