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}