async_io_helper/
lib.rs

1mod connected;
2mod io;
3
4pub use connected::Connected;
5
6use std::pin::Pin;
7use tokio::io::{AsyncRead, AsyncWrite};
8
9pub trait Io: AsyncRead + AsyncWrite + Send + 'static {}
10pub struct ClientIo(Pin<Box<dyn Io>>);
11pub trait ConnectedIo: Io + Connected {}
12pub struct ServerIo(Pin<Box<dyn ConnectedIo>>);
13
14#[cfg(test)]
15mod tests {
16    use tokio::{
17        io::{split, AsyncReadExt, AsyncWriteExt},
18        net::{TcpListener, TcpStream},
19    };
20    use tracing::info;
21
22    use super::*;
23
24    #[tokio::test]
25    async fn test_client_and_server_io_should_work() {
26        tracing_subscriber::fmt::init();
27
28        let msg = b"Hello world\n";
29        let mut buf = [0; 12];
30        start_server("0.0.0.0:5000").await;
31        start_client("127.0.0.1:5000", msg, &mut buf).await;
32
33        assert_eq!(&buf, msg);
34    }
35
36    async fn start_server(addr: &str) {
37        let listener = TcpListener::bind(addr).await.unwrap();
38        tokio::spawn(async move {
39            let (stream, _) = listener.accept().await.unwrap();
40            let io = ServerIo::new(stream);
41            info!("server: accepted: {:?}", io.remote_addr());
42            let (mut reader, mut writer) = split(io);
43            let mut buf = [0; 12];
44            reader.read_exact(&mut buf).await.unwrap();
45            info!("server: got data: {:?}", buf);
46            writer.write_all(&buf).await.unwrap();
47            info!("server: flush the data out");
48        });
49    }
50
51    async fn start_client(addr: &str, msg: &[u8], buf: &mut [u8]) {
52        let mut stream = TcpStream::connect(addr).await.unwrap();
53        info!("client: conn established");
54
55        stream.write_all(msg).await.unwrap();
56
57        info!("client: send data");
58
59        let (mut reader, _writer) = split(stream);
60
61        reader.read_exact(buf).await.unwrap();
62
63        info!("client: read echoed data");
64    }
65}