hyper/common/io/
compat.rs

1use std::pin::Pin;
2use std::task::{Context, Poll};
3
4/// This adapts from `hyper` IO traits to the ones in Tokio.
5///
6/// This is currently used by `h2`, and by hyper internal unit tests.
7#[derive(Debug)]
8pub(crate) struct Compat<T>(pub(crate) T);
9
10impl<T> Compat<T> {
11    pub(crate) fn new(io: T) -> Self {
12        Compat(io)
13    }
14
15    fn p(self: Pin<&mut Self>) -> Pin<&mut T> {
16        // SAFETY: The simplest of projections. This is just
17        // a wrapper, we don't do anything that would undo the projection.
18        unsafe { self.map_unchecked_mut(|me| &mut me.0) }
19    }
20}
21
22impl<T> tokio::io::AsyncRead for Compat<T>
23where
24    T: crate::rt::Read,
25{
26    fn poll_read(
27        self: Pin<&mut Self>,
28        cx: &mut Context<'_>,
29        tbuf: &mut tokio::io::ReadBuf<'_>,
30    ) -> Poll<Result<(), std::io::Error>> {
31        let init = tbuf.initialized().len();
32        let filled = tbuf.filled().len();
33        let (new_init, new_filled) = unsafe {
34            let mut buf = crate::rt::ReadBuf::uninit(tbuf.inner_mut());
35            buf.set_init(init);
36            buf.set_filled(filled);
37
38            match crate::rt::Read::poll_read(self.p(), cx, buf.unfilled()) {
39                Poll::Ready(Ok(())) => (buf.init_len(), buf.len()),
40                other => return other,
41            }
42        };
43
44        let n_init = new_init - init;
45        unsafe {
46            tbuf.assume_init(n_init);
47            tbuf.set_filled(new_filled);
48        }
49
50        Poll::Ready(Ok(()))
51    }
52}
53
54impl<T> tokio::io::AsyncWrite for Compat<T>
55where
56    T: crate::rt::Write,
57{
58    fn poll_write(
59        self: Pin<&mut Self>,
60        cx: &mut Context<'_>,
61        buf: &[u8],
62    ) -> Poll<Result<usize, std::io::Error>> {
63        crate::rt::Write::poll_write(self.p(), cx, buf)
64    }
65
66    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), std::io::Error>> {
67        crate::rt::Write::poll_flush(self.p(), cx)
68    }
69
70    fn poll_shutdown(
71        self: Pin<&mut Self>,
72        cx: &mut Context<'_>,
73    ) -> Poll<Result<(), std::io::Error>> {
74        crate::rt::Write::poll_shutdown(self.p(), cx)
75    }
76
77    fn is_write_vectored(&self) -> bool {
78        crate::rt::Write::is_write_vectored(&self.0)
79    }
80
81    fn poll_write_vectored(
82        self: Pin<&mut Self>,
83        cx: &mut Context<'_>,
84        bufs: &[std::io::IoSlice<'_>],
85    ) -> Poll<Result<usize, std::io::Error>> {
86        crate::rt::Write::poll_write_vectored(self.p(), cx, bufs)
87    }
88}
89
90#[cfg(test)]
91impl<T> crate::rt::Read for Compat<T>
92where
93    T: tokio::io::AsyncRead,
94{
95    fn poll_read(
96        self: Pin<&mut Self>,
97        cx: &mut Context<'_>,
98        mut buf: crate::rt::ReadBufCursor<'_>,
99    ) -> Poll<Result<(), std::io::Error>> {
100        let n = unsafe {
101            let mut tbuf = tokio::io::ReadBuf::uninit(buf.as_mut());
102            match tokio::io::AsyncRead::poll_read(self.p(), cx, &mut tbuf) {
103                Poll::Ready(Ok(())) => tbuf.filled().len(),
104                other => return other,
105            }
106        };
107
108        unsafe {
109            buf.advance(n);
110        }
111        Poll::Ready(Ok(()))
112    }
113}
114
115#[cfg(test)]
116impl<T> crate::rt::Write for Compat<T>
117where
118    T: tokio::io::AsyncWrite,
119{
120    fn poll_write(
121        self: Pin<&mut Self>,
122        cx: &mut Context<'_>,
123        buf: &[u8],
124    ) -> Poll<Result<usize, std::io::Error>> {
125        tokio::io::AsyncWrite::poll_write(self.p(), cx, buf)
126    }
127
128    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), std::io::Error>> {
129        tokio::io::AsyncWrite::poll_flush(self.p(), cx)
130    }
131
132    fn poll_shutdown(
133        self: Pin<&mut Self>,
134        cx: &mut Context<'_>,
135    ) -> Poll<Result<(), std::io::Error>> {
136        tokio::io::AsyncWrite::poll_shutdown(self.p(), cx)
137    }
138
139    fn is_write_vectored(&self) -> bool {
140        tokio::io::AsyncWrite::is_write_vectored(&self.0)
141    }
142
143    fn poll_write_vectored(
144        self: Pin<&mut Self>,
145        cx: &mut Context<'_>,
146        bufs: &[std::io::IoSlice<'_>],
147    ) -> Poll<Result<usize, std::io::Error>> {
148        tokio::io::AsyncWrite::poll_write_vectored(self.p(), cx, bufs)
149    }
150}