1use futures::io::{AsyncRead, AsyncWrite};
7use std::io;
8#[cfg(feature = "tokio-providers")]
9use tokio_util::compat::{Compat, TokioAsyncReadCompatExt};
10
11pub trait NetworkProvider: Clone + Send + Sync + 'static {
15 type TcpStream: AsyncRead + AsyncWrite + Unpin + Send + 'static;
17 type TcpListener: TcpListenerTrait<TcpStream = Self::TcpStream> + 'static;
19
20 fn bind(
22 &self,
23 addr: &str,
24 ) -> impl std::future::Future<Output = io::Result<Self::TcpListener>> + Send;
25
26 fn connect(
28 &self,
29 addr: &str,
30 ) -> impl std::future::Future<Output = io::Result<Self::TcpStream>> + Send;
31}
32
33pub trait TcpListenerTrait: Send + Sync + 'static {
35 type TcpStream: AsyncRead + AsyncWrite + Unpin + Send + 'static;
37
38 fn accept(
40 &self,
41 ) -> impl std::future::Future<Output = io::Result<(Self::TcpStream, String)>> + Send;
42
43 fn local_addr(&self) -> io::Result<String>;
50}
51
52#[cfg(feature = "tokio-providers")]
58#[derive(Debug, Clone, Default)]
59pub struct TokioNetworkProvider;
60
61#[cfg(feature = "tokio-providers")]
62impl TokioNetworkProvider {
63 #[must_use]
65 pub fn new() -> Self {
66 Self
67 }
68}
69
70#[cfg(feature = "tokio-providers")]
71impl NetworkProvider for TokioNetworkProvider {
72 type TcpStream = Compat<tokio::net::TcpStream>;
73 type TcpListener = TokioTcpListener;
74
75 async fn bind(&self, addr: &str) -> io::Result<Self::TcpListener> {
76 let listener = tokio::net::TcpListener::bind(addr).await?;
77 Ok(TokioTcpListener { inner: listener })
78 }
79
80 async fn connect(&self, addr: &str) -> io::Result<Self::TcpStream> {
81 Ok(tokio::net::TcpStream::connect(addr).await?.compat())
82 }
83}
84
85#[cfg(feature = "tokio-providers")]
87#[derive(Debug)]
88pub struct TokioTcpListener {
89 inner: tokio::net::TcpListener,
90}
91
92#[cfg(feature = "tokio-providers")]
93impl TcpListenerTrait for TokioTcpListener {
94 type TcpStream = Compat<tokio::net::TcpStream>;
95
96 async fn accept(&self) -> io::Result<(Self::TcpStream, String)> {
97 let (stream, addr) = self.inner.accept().await?;
98 Ok((stream.compat(), addr.to_string()))
99 }
100
101 fn local_addr(&self) -> io::Result<String> {
102 Ok(self.inner.local_addr()?.to_string())
103 }
104}