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