1#![cfg_attr(feature = "fail-on-warnings", deny(warnings))]
2#![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)]
3#![allow(clippy::multiple_crate_versions)]
4
5use std::{marker::PhantomData, net::SocketAddr};
6
7use ::tokio::io::{AsyncRead, AsyncWrite};
8use async_trait::async_trait;
9use thiserror::Error;
10
11#[cfg(feature = "tokio")]
12pub mod tokio;
13
14#[cfg(feature = "simulator")]
15pub mod simulator;
16
17#[derive(Debug, Error)]
18pub enum Error {
19 #[error(transparent)]
20 IO(#[from] ::std::io::Error),
21}
22
23#[async_trait]
24pub trait GenericTcpListener<T>: Send + Sync {
25 async fn accept(&self) -> Result<(T, SocketAddr), Error>;
26}
27
28pub trait GenericTcpStream<R: GenericTcpStreamReadHalf, W: GenericTcpStreamWriteHalf>:
29 AsyncRead + AsyncWrite + Send + Sync + Unpin
30{
31 fn into_split(self) -> (R, W);
32}
33pub trait GenericTcpStreamReadHalf: AsyncRead + Send + Sync + Unpin {}
34pub trait GenericTcpStreamWriteHalf: AsyncWrite + Send + Sync + Unpin {}
35
36pub struct TcpListenerWrapper<
37 R: GenericTcpStreamReadHalf,
38 W: GenericTcpStreamWriteHalf,
39 S: GenericTcpStream<R, W>,
40 T: GenericTcpListener<S>,
41>(T, PhantomData<R>, PhantomData<W>, PhantomData<S>);
42pub struct TcpStreamWrapper<
43 R: GenericTcpStreamReadHalf,
44 W: GenericTcpStreamWriteHalf,
45 T: GenericTcpStream<R, W>,
46>(T, PhantomData<R>, PhantomData<W>);
47
48#[allow(unused)]
49macro_rules! impl_http {
50 ($module:ident, $local_module:ident $(,)?) => {
51 paste::paste! {
52 pub use [< impl_ $module >]::*;
53 }
54
55 mod $local_module {
56 use std::pin::pin;
57
58 use crate::*;
59
60 paste::paste! {
61 pub type [< $module:camel TcpStreamReadHalf >] = $module::TcpStreamReadHalf;
62 type ModuleTcpStreamReadHalf = [< $module:camel TcpStreamReadHalf >];
63
64 pub type [< $module:camel TcpStreamWriteHalf >] = $module::TcpStreamWriteHalf;
65 type ModuleTcpStreamWriteHalf = [< $module:camel TcpStreamWriteHalf >];
66
67 pub type [< $module:camel TcpStream >] = TcpStreamWrapper<ModuleTcpStreamReadHalf, ModuleTcpStreamWriteHalf, $module::TcpStream>;
68 type ModuleTcpStream = [< $module:camel TcpStream >];
69
70 pub type [< $module:camel TcpListener >] = TcpListenerWrapper<ModuleTcpStreamReadHalf, ModuleTcpStreamWriteHalf, ModuleTcpStream, $module::TcpListener>;
71 type ModuleTcpListener = [< $module:camel TcpListener >];
72 }
73
74 #[async_trait]
75 impl GenericTcpListener<ModuleTcpStream> for ModuleTcpListener {
76 async fn accept(&self) -> Result<(ModuleTcpStream, SocketAddr), Error> {
77 self.0.accept().await
78 }
79 }
80
81 impl GenericTcpStream<ModuleTcpStreamReadHalf, ModuleTcpStreamWriteHalf> for ModuleTcpStream {
82 fn into_split(self) -> (ModuleTcpStreamReadHalf, ModuleTcpStreamWriteHalf) {
83 self.0.into_split()
84 }
85 }
86
87 impl AsyncRead for ModuleTcpStream {
88 fn poll_read(
89 self: std::pin::Pin<&mut Self>,
90 cx: &mut std::task::Context<'_>,
91 buf: &mut ::tokio::io::ReadBuf<'_>,
92 ) -> std::task::Poll<std::io::Result<()>> {
93 let this = self.get_mut();
94 let inner = &mut this.0;
95 let inner = pin!(inner);
96 AsyncRead::poll_read(inner, cx, buf)
97 }
98 }
99
100 impl AsyncWrite for ModuleTcpStream {
101 fn poll_write(
102 self: std::pin::Pin<&mut Self>,
103 cx: &mut std::task::Context<'_>,
104 buf: &[u8],
105 ) -> std::task::Poll<Result<usize, std::io::Error>> {
106 let this = self.get_mut();
107 let inner = &mut this.0;
108 let inner = pin!(inner);
109 AsyncWrite::poll_write(inner, cx, buf)
110 }
111
112 fn poll_flush(
113 self: std::pin::Pin<&mut Self>,
114 cx: &mut std::task::Context<'_>,
115 ) -> std::task::Poll<Result<(), std::io::Error>> {
116 let this = self.get_mut();
117 let inner = &mut this.0;
118 let inner = pin!(inner);
119 AsyncWrite::poll_flush(inner, cx)
120 }
121
122 fn poll_shutdown(
123 self: std::pin::Pin<&mut Self>,
124 cx: &mut std::task::Context<'_>,
125 ) -> std::task::Poll<Result<(), std::io::Error>> {
126 let this = self.get_mut();
127 let inner = &mut this.0;
128 let inner = pin!(inner);
129 AsyncWrite::poll_shutdown(inner, cx)
130 }
131 }
132 }
133 };
134}
135
136#[cfg(feature = "simulator")]
137impl_http!(simulator, impl_simulator);
138
139#[cfg(feature = "tokio")]
140impl_http!(tokio, impl_tokio);
141
142#[allow(unused)]
143macro_rules! impl_gen_types {
144 ($module:ident $(,)?) => {
145 paste::paste! {
146 pub type TcpListener = [< $module:camel TcpListener >];
147 pub type TcpStream = [< $module:camel TcpStream >];
148 pub type TcpStreamReadHalf = [< $module:camel TcpStreamReadHalf >];
149 pub type TcpStreamWriteHalf = [< $module:camel TcpStreamWriteHalf >];
150 }
151 };
152}
153
154#[cfg(feature = "simulator")]
155impl_gen_types!(simulator);
156
157#[cfg(all(not(feature = "simulator"), feature = "tokio"))]
158impl_gen_types!(tokio);
159
160#[allow(unused)]
161macro_rules! impl_read_inner {
162 ($type:ty $(,)?) => {
163 impl tokio::io::AsyncRead for $type {
164 fn poll_read(
165 self: std::pin::Pin<&mut Self>,
166 cx: &mut std::task::Context<'_>,
167 buf: &mut ::tokio::io::ReadBuf<'_>,
168 ) -> std::task::Poll<std::io::Result<()>> {
169 let this = self.get_mut();
170 let inner = &mut this.0;
171 let inner = std::pin::pin!(inner);
172 tokio::io::AsyncRead::poll_read(inner, cx, buf)
173 }
174 }
175 };
176}
177
178#[allow(unused)]
179macro_rules! impl_write_inner {
180 ($type:ty $(,)?) => {
181 impl tokio::io::AsyncWrite for $type {
182 fn poll_write(
183 self: std::pin::Pin<&mut Self>,
184 cx: &mut std::task::Context<'_>,
185 buf: &[u8],
186 ) -> std::task::Poll<Result<usize, std::io::Error>> {
187 let this = self.get_mut();
188 let inner = &mut this.0;
189 let inner = std::pin::pin!(inner);
190 tokio::io::AsyncWrite::poll_write(inner, cx, buf)
191 }
192
193 fn poll_flush(
194 self: std::pin::Pin<&mut Self>,
195 cx: &mut std::task::Context<'_>,
196 ) -> std::task::Poll<Result<(), std::io::Error>> {
197 let this = self.get_mut();
198 let inner = &mut this.0;
199 let inner = std::pin::pin!(inner);
200 tokio::io::AsyncWrite::poll_flush(inner, cx)
201 }
202
203 fn poll_shutdown(
204 self: std::pin::Pin<&mut Self>,
205 cx: &mut std::task::Context<'_>,
206 ) -> std::task::Poll<Result<(), std::io::Error>> {
207 let this = self.get_mut();
208 let inner = &mut this.0;
209 let inner = std::pin::pin!(inner);
210 tokio::io::AsyncWrite::poll_shutdown(inner, cx)
211 }
212 }
213 };
214}
215
216#[allow(unused)]
217pub(crate) use impl_read_inner;
218#[allow(unused)]
219pub(crate) use impl_write_inner;