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}