trillium_http/transport/boxed_transport.rs
1use crate::transport::Transport;
2use futures_lite::io::{AsyncRead, AsyncWrite};
3use std::{
4 any::Any,
5 fmt::{self, Debug},
6 io::Result,
7 net::SocketAddr,
8 ops::Deref,
9};
10use trillium_macros::{AsyncRead, AsyncWrite};
11
12#[allow(missing_docs)]
13#[doc(hidden)]
14pub(crate) trait AnyTransport: Transport + Any {
15 fn as_box_any(self: Box<Self>) -> Box<dyn Any>;
16 // fn as_box_transport(self: Box<Self>) -> Box<dyn Transport>;
17 fn as_any(&self) -> &dyn Any;
18 fn as_mut_any(&mut self) -> &mut dyn Any;
19 fn as_transport(&self) -> &dyn Transport;
20}
21impl<T: Transport + Any> AnyTransport for T {
22 fn as_box_any(self: Box<Self>) -> Box<dyn Any> {
23 self
24 }
25 // fn as_box_transport(self: Box<Self>) -> Box<dyn Transport> {
26 // self
27 // }
28 fn as_any(&self) -> &dyn Any {
29 self
30 }
31 fn as_mut_any(&mut self) -> &mut dyn Any {
32 self
33 }
34 fn as_transport(&self) -> &dyn Transport {
35 self
36 }
37}
38
39/**
40# A type for dyn [`Transport`][crate::transport::Transport] trait objects
41
42`BoxedTransport` represents a `Box<dyn Transport + Any>` that supports
43downcasting to the original Transport. This is used in trillium to
44erase the generic on Conn, in order to avoid writing `Conn<TcpStream>`
45throughout an application.
46
47**Stability Note:** This may go away at some point and be
48replaced by a type alias exported from a
49`trillium_server_common::Server` crate.
50*/
51#[derive(Debug, AsyncRead, AsyncWrite)]
52pub struct BoxedTransport(Box<dyn AnyTransport>);
53
54impl Debug for Box<dyn AnyTransport> {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 f.write_str("Box<dyn Any + Transport>")
57 }
58}
59
60impl BoxedTransport {
61 /**
62 Create a new `BoxedTransport` from some Transport.
63
64 ```
65 use trillium_http::transport::BoxedTransport;
66 use trillium_testing::TestTransport;
67 // this examples uses trillium_testing::TestTransport as an
68 // easily-constructed AsyncRead+AsyncWrite.
69 let (test_transport, _) = TestTransport::new();
70
71 let boxed = BoxedTransport::new(test_transport);
72
73 let downcast: Option<Box<TestTransport>> = boxed.downcast();
74 assert!(downcast.is_some());
75
76 let boxed_again = BoxedTransport::new(*downcast.unwrap());
77 assert!(boxed_again.downcast::<async_net::TcpStream>().is_none());
78 ```
79 */
80
81 pub fn new<T: Transport + Any>(t: T) -> Self {
82 Self(Box::new(t))
83 }
84
85 /**
86 Attempt to convert the trait object into a specific transport
87 T. This will only succeed if T is the type that was originally
88 passed to [`BoxedTransport::new`], and will return None otherwise
89
90 see [`BoxedTransport::new`] for example usage
91 */
92 #[must_use = "downcasting takes the inner transport, so you should use it"]
93 pub fn downcast<T: 'static>(self) -> Option<Box<T>> {
94 self.0.as_box_any().downcast().ok()
95 }
96
97 /**
98 Attempt to get a reference to the trait object as a specific transport type T. This will only
99 succeed if T is the type that was originally passed to [`BoxedTransport::new`], and will return
100 None otherwise
101 */
102 pub fn downcast_ref<T: Transport>(&self) -> Option<&T> {
103 self.0.as_any().downcast_ref()
104 }
105
106 /**
107 Attempt to get a mutable reference to the trait object as a specific transport type T. This
108 will only succeed if T is the type that was originally passed to [`BoxedTransport::new`], and
109 will return None otherwise
110 */
111 pub fn downcast_mut<T: Transport>(&mut self) -> Option<&mut T> {
112 self.0.as_mut_any().downcast_mut()
113 }
114}
115
116impl Deref for BoxedTransport {
117 type Target = dyn Transport;
118
119 fn deref(&self) -> &Self::Target {
120 self.0.as_transport()
121 }
122}
123
124impl Transport for BoxedTransport {
125 fn set_linger(&mut self, linger: Option<std::time::Duration>) -> Result<()> {
126 self.0.set_linger(linger)
127 }
128
129 fn set_nodelay(&mut self, nodelay: bool) -> Result<()> {
130 self.0.set_nodelay(nodelay)
131 }
132
133 fn set_ip_ttl(&mut self, ttl: u32) -> Result<()> {
134 self.0.set_ip_ttl(ttl)
135 }
136
137 fn peer_addr(&self) -> Result<Option<SocketAddr>> {
138 self.0.peer_addr()
139 }
140}