Skip to main content

kevy_client_async/
rt_tokio.rs

1//! Tokio runtime adapter — implements [`crate::transport::AsyncRead`]
2//! / [`crate::transport::AsyncWrite`] on top of `tokio::net::TcpStream`.
3//!
4//! Activated by the `tokio` Cargo feature. See the crate-level docs
5//! for the dep-rule exemption rationale.
6//!
7//! Why an adapter at all: tokio's own `AsyncRead` uses a `ReadBuf`
8//! (initialised-byte tracking, useful for IO_uring); our trait uses a
9//! plain `&mut [u8]`. The adapter is a 3-line shim — no buffering, no
10//! extra allocation, no syscall.
11
12use core::pin::Pin;
13use core::task::{Context, Poll};
14use std::io;
15
16use tokio::io::{AsyncRead as TokioAsyncRead, AsyncWrite as TokioAsyncWrite, ReadBuf};
17use tokio::net::TcpStream;
18
19use crate::transport::{AsyncRead, AsyncWrite};
20
21impl AsyncRead for TcpStream {
22    fn poll_read(
23        self: Pin<&mut Self>,
24        cx: &mut Context<'_>,
25        buf: &mut [u8],
26    ) -> Poll<io::Result<usize>> {
27        let mut rb = ReadBuf::new(buf);
28        match <Self as TokioAsyncRead>::poll_read(self, cx, &mut rb) {
29            Poll::Ready(Ok(())) => Poll::Ready(Ok(rb.filled().len())),
30            Poll::Ready(Err(e)) => Poll::Ready(Err(e)),
31            Poll::Pending => Poll::Pending,
32        }
33    }
34}
35
36impl AsyncWrite for TcpStream {
37    fn poll_write(
38        self: Pin<&mut Self>,
39        cx: &mut Context<'_>,
40        buf: &[u8],
41    ) -> Poll<io::Result<usize>> {
42        <Self as TokioAsyncWrite>::poll_write(self, cx, buf)
43    }
44
45    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
46        <Self as TokioAsyncWrite>::poll_flush(self, cx)
47    }
48
49    fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
50        // tokio's equivalent is `poll_shutdown`.
51        <Self as TokioAsyncWrite>::poll_shutdown(self, cx)
52    }
53}
54
55/// Connect a tokio `TcpStream` to `host:port`, enabling
56/// `TCP_NODELAY` (best-effort), and return it ready to feed into
57/// [`crate::AsyncRespCodec::new`].
58pub async fn connect(host: &str, port: u16) -> io::Result<TcpStream> {
59    let stream = TcpStream::connect((host, port)).await?;
60    stream.set_nodelay(true).ok();
61    Ok(stream)
62}