hyper_util_wasm/client/legacy/connect/
mod.rs1use std::fmt;
66
67use ::http::Extensions;
68
69#[cfg(feature = "tokio")]
70pub use self::http::{HttpConnector, HttpInfo};
71
72#[cfg(feature = "tokio")]
73pub mod dns;
74#[cfg(feature = "tokio")]
75mod http;
76
77pub use self::sealed::Connect;
78
79pub trait Connection {
81 fn connected(&self) -> Connected;
83}
84
85#[derive(Debug)]
90pub struct Connected {
91 pub(super) alpn: Alpn,
92 pub(super) is_proxied: bool,
93 pub(super) extra: Option<Extra>,
94}
95
96pub(super) struct Extra(Box<dyn ExtraInner>);
97
98#[derive(Clone, Copy, Debug, PartialEq)]
99pub(super) enum Alpn {
100 H2,
101 None,
102}
103
104impl Connected {
105 pub fn new() -> Connected {
107 Connected {
108 alpn: Alpn::None,
109 is_proxied: false,
110 extra: None,
111 }
112 }
113
114 pub fn proxy(mut self, is_proxied: bool) -> Connected {
133 self.is_proxied = is_proxied;
134 self
135 }
136
137 pub fn is_proxied(&self) -> bool {
139 self.is_proxied
140 }
141
142 pub fn extra<T: Clone + Send + Sync + 'static>(mut self, extra: T) -> Connected {
144 if let Some(prev) = self.extra {
145 self.extra = Some(Extra(Box::new(ExtraChain(prev.0, extra))));
146 } else {
147 self.extra = Some(Extra(Box::new(ExtraEnvelope(extra))));
148 }
149 self
150 }
151
152 pub fn get_extras(&self, extensions: &mut Extensions) {
154 if let Some(extra) = &self.extra {
155 extra.set(extensions);
156 }
157 }
158
159 pub fn negotiated_h2(mut self) -> Connected {
161 self.alpn = Alpn::H2;
162 self
163 }
164
165 pub fn is_negotiated_h2(&self) -> bool {
167 self.alpn == Alpn::H2
168 }
169
170 #[cfg(feature = "http2")]
173 pub(super) fn clone(&self) -> Connected {
174 Connected {
175 alpn: self.alpn,
176 is_proxied: self.is_proxied,
177 extra: self.extra.clone(),
178 }
179 }
180}
181
182impl Extra {
185 pub(super) fn set(&self, res: &mut Extensions) {
186 self.0.set(res);
187 }
188}
189
190impl Clone for Extra {
191 fn clone(&self) -> Extra {
192 Extra(self.0.clone_box())
193 }
194}
195
196impl fmt::Debug for Extra {
197 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198 f.debug_struct("Extra").finish()
199 }
200}
201
202trait ExtraInner: Send + Sync {
203 fn clone_box(&self) -> Box<dyn ExtraInner>;
204 fn set(&self, res: &mut Extensions);
205}
206
207#[derive(Clone)]
211struct ExtraEnvelope<T>(T);
212
213impl<T> ExtraInner for ExtraEnvelope<T>
214where
215 T: Clone + Send + Sync + 'static,
216{
217 fn clone_box(&self) -> Box<dyn ExtraInner> {
218 Box::new(self.clone())
219 }
220
221 fn set(&self, res: &mut Extensions) {
222 res.insert(self.0.clone());
223 }
224}
225
226struct ExtraChain<T>(Box<dyn ExtraInner>, T);
227
228impl<T: Clone> Clone for ExtraChain<T> {
229 fn clone(&self) -> Self {
230 ExtraChain(self.0.clone_box(), self.1.clone())
231 }
232}
233
234impl<T> ExtraInner for ExtraChain<T>
235where
236 T: Clone + Send + Sync + 'static,
237{
238 fn clone_box(&self) -> Box<dyn ExtraInner> {
239 Box::new(self.clone())
240 }
241
242 fn set(&self, res: &mut Extensions) {
243 self.0.set(res);
244 res.insert(self.1.clone());
245 }
246}
247
248pub(super) mod sealed {
249 use std::error::Error as StdError;
250 use std::future::Future;
251
252 use ::http::Uri;
253 use hyper::rt::{Read, Write};
254
255 use super::Connection;
256
257 pub trait Connect: Sealed + Sized {
270 #[doc(hidden)]
271 type _Svc: ConnectSvc;
272 #[doc(hidden)]
273 fn connect(self, internal_only: Internal, dst: Uri) -> <Self::_Svc as ConnectSvc>::Future;
274 }
275
276 pub trait ConnectSvc {
277 type Connection: Read + Write + Connection + Unpin + Send + 'static;
278 type Error: Into<Box<dyn StdError + Send + Sync>>;
279 type Future: Future<Output = Result<Self::Connection, Self::Error>> + Unpin + Send + 'static;
280
281 fn connect(self, internal_only: Internal, dst: Uri) -> Self::Future;
282 }
283
284 impl<S, T> Connect for S
285 where
286 S: tower_service::Service<Uri, Response = T> + Send + 'static,
287 S::Error: Into<Box<dyn StdError + Send + Sync>>,
288 S::Future: Unpin + Send,
289 T: Read + Write + Connection + Unpin + Send + 'static,
290 {
291 type _Svc = S;
292
293 fn connect(self, _: Internal, dst: Uri) -> tower::util::Oneshot<S, Uri> {
294 tower::util::Oneshot::new(self, dst)
295 }
296 }
297
298 impl<S, T> ConnectSvc for S
299 where
300 S: tower_service::Service<Uri, Response = T> + Send + 'static,
301 S::Error: Into<Box<dyn StdError + Send + Sync>>,
302 S::Future: Unpin + Send,
303 T: Read + Write + Connection + Unpin + Send + 'static,
304 {
305 type Connection = T;
306 type Error = S::Error;
307 type Future = tower::util::Oneshot<S, Uri>;
308
309 fn connect(self, _: Internal, dst: Uri) -> Self::Future {
310 tower::util::Oneshot::new(self, dst)
311 }
312 }
313
314 impl<S, T> Sealed for S
315 where
316 S: tower_service::Service<Uri, Response = T> + Send,
317 S::Error: Into<Box<dyn StdError + Send + Sync>>,
318 S::Future: Unpin + Send,
319 T: Read + Write + Connection + Unpin + Send + 'static,
320 {
321 }
322
323 pub trait Sealed {}
324 #[allow(missing_debug_implementations)]
325 pub struct Internal;
326}
327
328#[cfg(test)]
329mod tests {
330 use super::Connected;
331
332 #[derive(Clone, Debug, PartialEq)]
333 struct Ex1(usize);
334
335 #[derive(Clone, Debug, PartialEq)]
336 struct Ex2(&'static str);
337
338 #[derive(Clone, Debug, PartialEq)]
339 struct Ex3(&'static str);
340
341 #[test]
342 fn test_connected_extra() {
343 let c1 = Connected::new().extra(Ex1(41));
344
345 let mut ex = ::http::Extensions::new();
346
347 assert_eq!(ex.get::<Ex1>(), None);
348
349 c1.extra.as_ref().expect("c1 extra").set(&mut ex);
350
351 assert_eq!(ex.get::<Ex1>(), Some(&Ex1(41)));
352 }
353
354 #[test]
355 fn test_connected_extra_chain() {
356 let c1 = Connected::new()
360 .extra(Ex1(45))
361 .extra(Ex2("zoom"))
362 .extra(Ex3("pew pew"));
363
364 let mut ex1 = ::http::Extensions::new();
365
366 assert_eq!(ex1.get::<Ex1>(), None);
367 assert_eq!(ex1.get::<Ex2>(), None);
368 assert_eq!(ex1.get::<Ex3>(), None);
369
370 c1.extra.as_ref().expect("c1 extra").set(&mut ex1);
371
372 assert_eq!(ex1.get::<Ex1>(), Some(&Ex1(45)));
373 assert_eq!(ex1.get::<Ex2>(), Some(&Ex2("zoom")));
374 assert_eq!(ex1.get::<Ex3>(), Some(&Ex3("pew pew")));
375
376 let c2 = Connected::new()
378 .extra(Ex1(33))
379 .extra(Ex2("hiccup"))
380 .extra(Ex1(99));
381
382 let mut ex2 = ::http::Extensions::new();
383
384 c2.extra.as_ref().expect("c2 extra").set(&mut ex2);
385
386 assert_eq!(ex2.get::<Ex1>(), Some(&Ex1(99)));
387 assert_eq!(ex2.get::<Ex2>(), Some(&Ex2("hiccup")));
388 }
389}