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