Coverage Report

Created: 2026-03-31 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-rustls-0.26.4/src/common/mod.rs
Line
Count
Source
1
use std::io::{self, BufRead as _, IoSlice, Read, Write};
2
use std::ops::{Deref, DerefMut};
3
use std::pin::Pin;
4
use std::task::{Context, Poll};
5
6
use rustls::{ConnectionCommon, SideData};
7
use tokio::io::{AsyncBufRead, AsyncRead, AsyncWrite, ReadBuf};
8
9
mod handshake;
10
pub(crate) use handshake::{IoSession, MidHandshake};
11
12
#[derive(Debug)]
13
pub(crate) enum TlsState {
14
    #[cfg(feature = "early-data")]
15
    EarlyData(usize, Vec<u8>),
16
    Stream,
17
    ReadShutdown,
18
    WriteShutdown,
19
    FullyShutdown,
20
}
21
22
impl TlsState {
23
    #[inline]
24
0
    pub(crate) fn shutdown_read(&mut self) {
25
0
        match *self {
26
0
            Self::WriteShutdown | Self::FullyShutdown => *self = Self::FullyShutdown,
27
0
            _ => *self = Self::ReadShutdown,
28
        }
29
0
    }
Unexecuted instantiation: <tokio_rustls::common::TlsState>::shutdown_read
Unexecuted instantiation: <tokio_rustls::common::TlsState>::shutdown_read
30
31
    #[inline]
32
0
    pub(crate) fn shutdown_write(&mut self) {
33
0
        match *self {
34
0
            Self::ReadShutdown | Self::FullyShutdown => *self = Self::FullyShutdown,
35
0
            _ => *self = Self::WriteShutdown,
36
        }
37
0
    }
Unexecuted instantiation: <tokio_rustls::common::TlsState>::shutdown_write
Unexecuted instantiation: <tokio_rustls::common::TlsState>::shutdown_write
38
39
    #[inline]
40
0
    pub(crate) fn writeable(&self) -> bool {
41
0
        !matches!(*self, Self::WriteShutdown | Self::FullyShutdown)
42
0
    }
Unexecuted instantiation: <tokio_rustls::common::TlsState>::writeable
Unexecuted instantiation: <tokio_rustls::common::TlsState>::writeable
43
44
    #[inline]
45
0
    pub(crate) fn readable(&self) -> bool {
46
0
        !matches!(*self, Self::ReadShutdown | Self::FullyShutdown)
47
0
    }
Unexecuted instantiation: <tokio_rustls::common::TlsState>::readable
Unexecuted instantiation: <tokio_rustls::common::TlsState>::readable
48
49
    #[inline]
50
    #[cfg(feature = "early-data")]
51
    pub(crate) fn is_early_data(&self) -> bool {
52
        matches!(self, Self::EarlyData(..))
53
    }
54
55
    #[inline]
56
    #[cfg(not(feature = "early-data"))]
57
0
    pub(crate) const fn is_early_data(&self) -> bool {
58
0
        false
59
0
    }
Unexecuted instantiation: <tokio_rustls::common::TlsState>::is_early_data
Unexecuted instantiation: <tokio_rustls::common::TlsState>::is_early_data
60
}
61
62
pub(crate) struct Stream<'a, IO, C> {
63
    pub(crate) io: &'a mut IO,
64
    pub(crate) session: &'a mut C,
65
    pub(crate) eof: bool,
66
    pub(crate) need_flush: bool,
67
}
68
69
impl<'a, IO: AsyncRead + AsyncWrite + Unpin, C, SD> Stream<'a, IO, C>
70
where
71
    C: DerefMut + Deref<Target = ConnectionCommon<SD>>,
72
    SD: SideData,
73
{
74
0
    pub(crate) fn new(io: &'a mut IO, session: &'a mut C) -> Self {
75
0
        Stream {
76
0
            io,
77
0
            session,
78
0
            // The state so far is only used to detect EOF, so either Stream
79
0
            // or EarlyData state should both be all right.
80
0
            eof: false,
81
0
            // Whether a previous flush returned pending, or a write occured without a flush.
82
0
            need_flush: false,
83
0
        }
84
0
    }
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, rustls::client::client_conn::connection::ClientConnection>>::new
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>, rustls::client::client_conn::connection::ClientConnection>>::new
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>, rustls::client::client_conn::connection::ClientConnection>>::new
Unexecuted instantiation: <tokio_rustls::common::Stream<_, _>>::new
85
86
0
    pub(crate) fn set_eof(mut self, eof: bool) -> Self {
87
0
        self.eof = eof;
88
0
        self
89
0
    }
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, rustls::client::client_conn::connection::ClientConnection>>::set_eof
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>, rustls::client::client_conn::connection::ClientConnection>>::set_eof
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>, rustls::client::client_conn::connection::ClientConnection>>::set_eof
Unexecuted instantiation: <tokio_rustls::common::Stream<_, _>>::set_eof
90
91
0
    pub(crate) fn set_need_flush(mut self, need_flush: bool) -> Self {
92
0
        self.need_flush = need_flush;
93
0
        self
94
0
    }
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, rustls::client::client_conn::connection::ClientConnection>>::set_need_flush
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>, rustls::client::client_conn::connection::ClientConnection>>::set_need_flush
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>, rustls::client::client_conn::connection::ClientConnection>>::set_need_flush
Unexecuted instantiation: <tokio_rustls::common::Stream<_, _>>::set_need_flush
95
96
0
    pub(crate) fn as_mut_pin(&mut self) -> Pin<&mut Self> {
97
0
        Pin::new(self)
98
0
    }
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, rustls::client::client_conn::connection::ClientConnection>>::as_mut_pin
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>, rustls::client::client_conn::connection::ClientConnection>>::as_mut_pin
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>, rustls::client::client_conn::connection::ClientConnection>>::as_mut_pin
Unexecuted instantiation: <tokio_rustls::common::Stream<_, _>>::as_mut_pin
99
100
0
    pub(crate) fn read_io(&mut self, cx: &mut Context) -> Poll<io::Result<usize>> {
101
0
        let mut reader = SyncReadAdapter { io: self.io, cx };
102
103
0
        let n = match self.session.read_tls(&mut reader) {
104
0
            Ok(n) => n,
105
0
            Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => return Poll::Pending,
106
0
            Err(err) => return Poll::Ready(Err(err)),
107
        };
108
109
0
        self.session.process_new_packets().map_err(|err| {
110
            // In case we have an alert to send describing this error,
111
            // try a last-gasp write -- but don't predate the primary
112
            // error.
113
0
            let _ = self.write_io(cx);
114
115
0
            io::Error::new(io::ErrorKind::InvalidData, err)
116
0
        })?;
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, rustls::client::client_conn::connection::ClientConnection>>::read_io::{closure#0}
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>, rustls::client::client_conn::connection::ClientConnection>>::read_io::{closure#0}
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>, rustls::client::client_conn::connection::ClientConnection>>::read_io::{closure#0}
Unexecuted instantiation: <tokio_rustls::common::Stream<_, _>>::read_io::{closure#0}
117
118
0
        Poll::Ready(Ok(n))
119
0
    }
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, rustls::client::client_conn::connection::ClientConnection>>::read_io
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>, rustls::client::client_conn::connection::ClientConnection>>::read_io
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>, rustls::client::client_conn::connection::ClientConnection>>::read_io
Unexecuted instantiation: <tokio_rustls::common::Stream<_, _>>::read_io
120
121
0
    pub(crate) fn write_io(&mut self, cx: &mut Context) -> Poll<io::Result<usize>> {
122
0
        let mut writer = SyncWriteAdapter { io: self.io, cx };
123
124
0
        match self.session.write_tls(&mut writer) {
125
0
            Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => Poll::Pending,
126
0
            result => Poll::Ready(result),
127
        }
128
0
    }
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, rustls::client::client_conn::connection::ClientConnection>>::write_io
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>, rustls::client::client_conn::connection::ClientConnection>>::write_io
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>, rustls::client::client_conn::connection::ClientConnection>>::write_io
Unexecuted instantiation: <tokio_rustls::common::Stream<_, _>>::write_io
129
130
0
    pub(crate) fn handshake(&mut self, cx: &mut Context) -> Poll<io::Result<(usize, usize)>> {
131
0
        let mut wrlen = 0;
132
0
        let mut rdlen = 0;
133
134
        loop {
135
0
            let mut write_would_block = false;
136
0
            let mut read_would_block = false;
137
138
0
            while self.session.wants_write() {
139
0
                match self.write_io(cx) {
140
0
                    Poll::Ready(Ok(0)) => return Poll::Ready(Err(io::ErrorKind::WriteZero.into())),
141
0
                    Poll::Ready(Ok(n)) => {
142
0
                        wrlen += n;
143
0
                        self.need_flush = true;
144
0
                    }
145
                    Poll::Pending => {
146
0
                        write_would_block = true;
147
0
                        break;
148
                    }
149
0
                    Poll::Ready(Err(err)) => return Poll::Ready(Err(err)),
150
                }
151
            }
152
153
0
            if self.need_flush {
154
0
                match Pin::new(&mut self.io).poll_flush(cx) {
155
0
                    Poll::Ready(Ok(())) => self.need_flush = false,
156
0
                    Poll::Ready(Err(err)) => return Poll::Ready(Err(err)),
157
0
                    Poll::Pending => write_would_block = true,
158
                }
159
0
            }
160
161
0
            while !self.eof && self.session.wants_read() {
162
0
                match self.read_io(cx) {
163
0
                    Poll::Ready(Ok(0)) => self.eof = true,
164
0
                    Poll::Ready(Ok(n)) => rdlen += n,
165
                    Poll::Pending => {
166
0
                        read_would_block = true;
167
0
                        break;
168
                    }
169
0
                    Poll::Ready(Err(err)) => return Poll::Ready(Err(err)),
170
                }
171
            }
172
173
0
            return match (self.eof, self.session.is_handshaking()) {
174
                (true, true) => {
175
0
                    let err = io::Error::new(io::ErrorKind::UnexpectedEof, "tls handshake eof");
176
0
                    Poll::Ready(Err(err))
177
                }
178
0
                (_, false) => Poll::Ready(Ok((rdlen, wrlen))),
179
0
                (_, true) if write_would_block || read_would_block => {
180
0
                    if rdlen != 0 || wrlen != 0 {
181
0
                        Poll::Ready(Ok((rdlen, wrlen)))
182
                    } else {
183
0
                        Poll::Pending
184
                    }
185
                }
186
0
                (..) => continue,
187
            };
188
        }
189
0
    }
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, rustls::client::client_conn::connection::ClientConnection>>::handshake
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>, rustls::client::client_conn::connection::ClientConnection>>::handshake
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>, rustls::client::client_conn::connection::ClientConnection>>::handshake
Unexecuted instantiation: <tokio_rustls::common::Stream<_, _>>::handshake
190
191
0
    pub(crate) fn poll_fill_buf(mut self, cx: &mut Context<'_>) -> Poll<io::Result<&'a [u8]>>
192
0
    where
193
0
        SD: 'a,
194
    {
195
0
        let mut io_pending = false;
196
197
        // read a packet
198
0
        while !self.eof && self.session.wants_read() {
199
0
            match self.read_io(cx) {
200
                Poll::Ready(Ok(0)) => {
201
0
                    break;
202
                }
203
0
                Poll::Ready(Ok(_)) => (),
204
                Poll::Pending => {
205
0
                    io_pending = true;
206
0
                    break;
207
                }
208
0
                Poll::Ready(Err(err)) => return Poll::Ready(Err(err)),
209
            }
210
        }
211
212
0
        match self.session.reader().into_first_chunk() {
213
0
            Ok(buf) => {
214
                // Note that this could be empty (i.e. EOF) if a `CloseNotify` has been
215
                // received and there is no more buffered data.
216
0
                Poll::Ready(Ok(buf))
217
            }
218
0
            Err(e) if e.kind() == io::ErrorKind::WouldBlock => {
219
0
                if !io_pending {
220
0
                    // If `wants_read()` is satisfied, rustls will not return `WouldBlock`.
221
0
                    // but if it does, we can try again.
222
0
                    //
223
0
                    // If the rustls state is abnormal, it may cause a cyclic wakeup.
224
0
                    // but tokio's cooperative budget will prevent infinite wakeup.
225
0
                    cx.waker().wake_by_ref();
226
0
                }
227
228
0
                Poll::Pending
229
            }
230
0
            Err(e) => Poll::Ready(Err(e)),
231
        }
232
0
    }
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, rustls::client::client_conn::connection::ClientConnection>>::poll_fill_buf
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>, rustls::client::client_conn::connection::ClientConnection>>::poll_fill_buf
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>, rustls::client::client_conn::connection::ClientConnection>>::poll_fill_buf
Unexecuted instantiation: <tokio_rustls::common::Stream<_, _>>::poll_fill_buf
233
}
234
235
impl<'a, IO: AsyncRead + AsyncWrite + Unpin, C, SD> AsyncRead for Stream<'a, IO, C>
236
where
237
    C: DerefMut + Deref<Target = ConnectionCommon<SD>>,
238
    SD: SideData + 'a,
239
{
240
0
    fn poll_read(
241
0
        mut self: Pin<&mut Self>,
242
0
        cx: &mut Context<'_>,
243
0
        buf: &mut ReadBuf<'_>,
244
0
    ) -> Poll<io::Result<()>> {
245
0
        let data = ready!(self.as_mut().poll_fill_buf(cx))?;
246
0
        let amount = buf.remaining().min(data.len());
247
0
        buf.put_slice(&data[..amount]);
248
0
        self.session.reader().consume(amount);
249
0
        Poll::Ready(Ok(()))
250
0
    }
251
}
252
253
impl<'a, IO: AsyncRead + AsyncWrite + Unpin, C, SD> AsyncBufRead for Stream<'a, IO, C>
254
where
255
    C: DerefMut + Deref<Target = ConnectionCommon<SD>>,
256
    SD: SideData + 'a,
257
{
258
0
    fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
259
0
        let this = self.get_mut();
260
0
        Stream {
261
0
            // reborrow
262
0
            io: this.io,
263
0
            session: this.session,
264
0
            ..*this
265
0
        }
266
0
        .poll_fill_buf(cx)
267
0
    }
268
269
0
    fn consume(mut self: Pin<&mut Self>, amt: usize) {
270
0
        self.session.reader().consume(amt);
271
0
    }
272
}
273
274
impl<IO: AsyncRead + AsyncWrite + Unpin, C, SD> AsyncWrite for Stream<'_, IO, C>
275
where
276
    C: DerefMut + Deref<Target = ConnectionCommon<SD>>,
277
    SD: SideData,
278
{
279
0
    fn poll_write(
280
0
        mut self: Pin<&mut Self>,
281
0
        cx: &mut Context,
282
0
        buf: &[u8],
283
0
    ) -> Poll<io::Result<usize>> {
284
0
        let mut pos = 0;
285
286
0
        while pos != buf.len() {
287
0
            let mut would_block = false;
288
289
0
            match self.session.writer().write(&buf[pos..]) {
290
0
                Ok(n) => pos += n,
291
0
                Err(err) => return Poll::Ready(Err(err)),
292
            };
293
294
0
            while self.session.wants_write() {
295
0
                match self.write_io(cx) {
296
                    Poll::Ready(Ok(0)) | Poll::Pending => {
297
0
                        would_block = true;
298
0
                        break;
299
                    }
300
0
                    Poll::Ready(Ok(_)) => (),
301
0
                    Poll::Ready(Err(err)) => return Poll::Ready(Err(err)),
302
                }
303
            }
304
305
0
            return match (pos, would_block) {
306
0
                (0, true) => Poll::Pending,
307
0
                (n, true) => Poll::Ready(Ok(n)),
308
0
                (_, false) => continue,
309
            };
310
        }
311
312
0
        Poll::Ready(Ok(pos))
313
0
    }
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, rustls::client::client_conn::connection::ClientConnection> as tokio::io::async_write::AsyncWrite>::poll_write
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>, rustls::client::client_conn::connection::ClientConnection> as tokio::io::async_write::AsyncWrite>::poll_write
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>, rustls::client::client_conn::connection::ClientConnection> as tokio::io::async_write::AsyncWrite>::poll_write
Unexecuted instantiation: <tokio_rustls::common::Stream<_, _> as tokio::io::async_write::AsyncWrite>::poll_write
314
315
0
    fn poll_write_vectored(
316
0
        mut self: Pin<&mut Self>,
317
0
        cx: &mut Context<'_>,
318
0
        bufs: &[IoSlice<'_>],
319
0
    ) -> Poll<io::Result<usize>> {
320
0
        if bufs.iter().all(|buf| buf.is_empty()) {
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, rustls::client::client_conn::connection::ClientConnection> as tokio::io::async_write::AsyncWrite>::poll_write_vectored::{closure#0}
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>, rustls::client::client_conn::connection::ClientConnection> as tokio::io::async_write::AsyncWrite>::poll_write_vectored::{closure#0}
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>, rustls::client::client_conn::connection::ClientConnection> as tokio::io::async_write::AsyncWrite>::poll_write_vectored::{closure#0}
Unexecuted instantiation: <tokio_rustls::common::Stream<_, _> as tokio::io::async_write::AsyncWrite>::poll_write_vectored::{closure#0}
321
0
            return Poll::Ready(Ok(0));
322
0
        }
323
324
        loop {
325
0
            let mut would_block = false;
326
0
            let written = self.session.writer().write_vectored(bufs)?;
327
328
0
            while self.session.wants_write() {
329
0
                match self.write_io(cx) {
330
                    Poll::Ready(Ok(0)) | Poll::Pending => {
331
0
                        would_block = true;
332
0
                        break;
333
                    }
334
0
                    Poll::Ready(Ok(_)) => (),
335
0
                    Poll::Ready(Err(err)) => return Poll::Ready(Err(err)),
336
                }
337
            }
338
339
0
            return match (written, would_block) {
340
0
                (0, true) => Poll::Pending,
341
0
                (0, false) => continue,
342
0
                (n, _) => Poll::Ready(Ok(n)),
343
            };
344
        }
345
0
    }
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, rustls::client::client_conn::connection::ClientConnection> as tokio::io::async_write::AsyncWrite>::poll_write_vectored
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>, rustls::client::client_conn::connection::ClientConnection> as tokio::io::async_write::AsyncWrite>::poll_write_vectored
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>, rustls::client::client_conn::connection::ClientConnection> as tokio::io::async_write::AsyncWrite>::poll_write_vectored
Unexecuted instantiation: <tokio_rustls::common::Stream<_, _> as tokio::io::async_write::AsyncWrite>::poll_write_vectored
346
347
    #[inline]
348
0
    fn is_write_vectored(&self) -> bool {
349
0
        true
350
0
    }
351
352
0
    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<io::Result<()>> {
353
0
        self.session.writer().flush()?;
354
0
        while self.session.wants_write() {
355
0
            if ready!(self.write_io(cx))? == 0 {
356
0
                return Poll::Ready(Err(io::ErrorKind::WriteZero.into()));
357
0
            }
358
        }
359
0
        Pin::new(&mut self.io).poll_flush(cx)
360
0
    }
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, rustls::client::client_conn::connection::ClientConnection> as tokio::io::async_write::AsyncWrite>::poll_flush
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>, rustls::client::client_conn::connection::ClientConnection> as tokio::io::async_write::AsyncWrite>::poll_flush
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>, rustls::client::client_conn::connection::ClientConnection> as tokio::io::async_write::AsyncWrite>::poll_flush
Unexecuted instantiation: <tokio_rustls::common::Stream<_, _> as tokio::io::async_write::AsyncWrite>::poll_flush
361
362
0
    fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
363
0
        while self.session.wants_write() {
364
0
            if ready!(self.write_io(cx))? == 0 {
365
0
                return Poll::Ready(Err(io::ErrorKind::WriteZero.into()));
366
0
            }
367
        }
368
369
0
        Poll::Ready(match ready!(Pin::new(&mut self.io).poll_shutdown(cx)) {
370
0
            Ok(()) => Ok(()),
371
            // When trying to shutdown, not being connected seems fine
372
0
            Err(err) if err.kind() == io::ErrorKind::NotConnected => Ok(()),
373
0
            Err(err) => Err(err),
374
        })
375
0
    }
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>, rustls::client::client_conn::connection::ClientConnection> as tokio::io::async_write::AsyncWrite>::poll_shutdown
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>, rustls::client::client_conn::connection::ClientConnection> as tokio::io::async_write::AsyncWrite>::poll_shutdown
Unexecuted instantiation: <tokio_rustls::common::Stream<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>, rustls::client::client_conn::connection::ClientConnection> as tokio::io::async_write::AsyncWrite>::poll_shutdown
Unexecuted instantiation: <tokio_rustls::common::Stream<_, _> as tokio::io::async_write::AsyncWrite>::poll_shutdown
376
}
377
378
/// An adapter that implements a [`Read`] interface for [`AsyncRead`] types and an
379
/// associated [`Context`].
380
///
381
/// Turns `Poll::Pending` into `WouldBlock`.
382
pub(crate) struct SyncReadAdapter<'a, 'b, T> {
383
    pub(crate) io: &'a mut T,
384
    pub(crate) cx: &'a mut Context<'b>,
385
}
386
387
impl<T: AsyncRead + Unpin> Read for SyncReadAdapter<'_, '_, T> {
388
    #[inline]
389
0
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
390
0
        let mut buf = ReadBuf::new(buf);
391
0
        match Pin::new(&mut self.io).poll_read(self.cx, &mut buf) {
392
0
            Poll::Ready(Ok(())) => Ok(buf.filled().len()),
393
0
            Poll::Ready(Err(err)) => Err(err),
394
0
            Poll::Pending => Err(io::ErrorKind::WouldBlock.into()),
395
        }
396
0
    }
Unexecuted instantiation: <tokio_rustls::common::SyncReadAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as std::io::Read>::read
Unexecuted instantiation: <tokio_rustls::common::SyncReadAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as std::io::Read>::read
Unexecuted instantiation: <tokio_rustls::common::SyncReadAdapter<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as std::io::Read>::read
Unexecuted instantiation: <tokio_rustls::common::SyncReadAdapter<_> as std::io::Read>::read
397
}
398
399
/// An adapter that implements a [`Write`] interface for [`AsyncWrite`] types and an
400
/// associated [`Context`].
401
///
402
/// Turns `Poll::Pending` into `WouldBlock`.
403
pub(crate) struct SyncWriteAdapter<'a, 'b, T> {
404
    pub(crate) io: &'a mut T,
405
    pub(crate) cx: &'a mut Context<'b>,
406
}
407
408
impl<T: Unpin> SyncWriteAdapter<'_, '_, T> {
409
    #[inline]
410
0
    fn poll_with<U>(
411
0
        &mut self,
412
0
        f: impl FnOnce(Pin<&mut T>, &mut Context<'_>) -> Poll<io::Result<U>>,
413
0
    ) -> io::Result<U> {
414
0
        match f(Pin::new(self.io), self.cx) {
415
0
            Poll::Ready(result) => result,
416
0
            Poll::Pending => Err(io::ErrorKind::WouldBlock.into()),
417
        }
418
0
    }
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>>::poll_with::<usize, <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as std::io::Write>::write_vectored::{closure#0}>
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>>::poll_with::<usize, <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as std::io::Write>::write::{closure#0}>
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>>::poll_with::<(), <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as std::io::Write>::flush::{closure#0}>
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>>>::poll_with::<usize, <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as std::io::Write>::write_vectored::{closure#0}>
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>>>::poll_with::<usize, <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as std::io::Write>::write::{closure#0}>
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>>>::poll_with::<(), <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as std::io::Write>::flush::{closure#0}>
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>>>::poll_with::<usize, <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as std::io::Write>::write_vectored::{closure#0}>
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>>>::poll_with::<usize, <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as std::io::Write>::write::{closure#0}>
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>>>::poll_with::<(), <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as std::io::Write>::flush::{closure#0}>
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<_>>::poll_with::<_, _>
419
}
420
421
impl<T: AsyncWrite + Unpin> Write for SyncWriteAdapter<'_, '_, T> {
422
    #[inline]
423
0
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
424
0
        self.poll_with(|io, cx| io.poll_write(cx, buf))
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as std::io::Write>::write::{closure#0}
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as std::io::Write>::write::{closure#0}
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as std::io::Write>::write::{closure#0}
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<_> as std::io::Write>::write::{closure#0}
425
0
    }
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as std::io::Write>::write
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as std::io::Write>::write
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as std::io::Write>::write
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<_> as std::io::Write>::write
426
427
    #[inline]
428
0
    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
429
0
        self.poll_with(|io, cx| io.poll_write_vectored(cx, bufs))
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as std::io::Write>::write_vectored::{closure#0}
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as std::io::Write>::write_vectored::{closure#0}
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as std::io::Write>::write_vectored::{closure#0}
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<_> as std::io::Write>::write_vectored::{closure#0}
430
0
    }
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as std::io::Write>::write_vectored
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as std::io::Write>::write_vectored
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as std::io::Write>::write_vectored
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<_> as std::io::Write>::write_vectored
431
432
0
    fn flush(&mut self) -> io::Result<()> {
433
0
        self.poll_with(|io, cx| io.poll_flush(cx))
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as std::io::Write>::flush::{closure#0}
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as std::io::Write>::flush::{closure#0}
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as std::io::Write>::flush::{closure#0}
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<_> as std::io::Write>::flush::{closure#0}
434
0
    }
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>> as std::io::Write>::flush
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_util::rt::tokio::TokioIo<tokio::net::unix::stream::UnixStream>>> as std::io::Write>::flush
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<hyper_util::rt::tokio::TokioIo<hyper_rustls::stream::MaybeHttpsStream<hyper_util::rt::tokio::TokioIo<tokio::net::tcp::stream::TcpStream>>>> as std::io::Write>::flush
Unexecuted instantiation: <tokio_rustls::common::SyncWriteAdapter<_> as std::io::Write>::flush
435
}
436
437
#[cfg(test)]
438
mod test_stream;