Coverage Report

Created: 2026-03-23 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/hyper-util-0.1.18/src/common/rewind.rs
Line
Count
Source
1
use std::{cmp, io};
2
3
use bytes::{Buf, Bytes};
4
use hyper::rt::{Read, ReadBufCursor, Write};
5
6
use std::{
7
    pin::Pin,
8
    task::{self, Poll},
9
};
10
11
/// Combine a buffer with an IO, rewinding reads to use the buffer.
12
#[derive(Debug)]
13
pub(crate) struct Rewind<T> {
14
    pub(crate) pre: Option<Bytes>,
15
    pub(crate) inner: T,
16
}
17
18
impl<T> Rewind<T> {
19
    #[cfg(all(feature = "server", any(feature = "http1", feature = "http2")))]
20
0
    pub(crate) fn new_buffered(io: T, buf: Bytes) -> Self {
21
0
        Rewind {
22
0
            pre: Some(buf),
23
0
            inner: io,
24
0
        }
25
0
    }
26
}
27
28
impl<T> Read for Rewind<T>
29
where
30
    T: Read + Unpin,
31
{
32
0
    fn poll_read(
33
0
        mut self: Pin<&mut Self>,
34
0
        cx: &mut task::Context<'_>,
35
0
        mut buf: ReadBufCursor<'_>,
36
0
    ) -> Poll<io::Result<()>> {
37
0
        if let Some(mut prefix) = self.pre.take() {
38
            // If there are no remaining bytes, let the bytes get dropped.
39
0
            if !prefix.is_empty() {
40
0
                let copy_len = cmp::min(prefix.len(), buf.remaining());
41
0
                buf.put_slice(&prefix[..copy_len]);
42
0
                prefix.advance(copy_len);
43
                // Put back what's left
44
0
                if !prefix.is_empty() {
45
0
                    self.pre = Some(prefix);
46
0
                }
47
48
0
                return Poll::Ready(Ok(()));
49
0
            }
50
0
        }
51
0
        Pin::new(&mut self.inner).poll_read(cx, buf)
52
0
    }
53
}
54
55
impl<T> Write for Rewind<T>
56
where
57
    T: Write + Unpin,
58
{
59
0
    fn poll_write(
60
0
        mut self: Pin<&mut Self>,
61
0
        cx: &mut task::Context<'_>,
62
0
        buf: &[u8],
63
0
    ) -> Poll<io::Result<usize>> {
64
0
        Pin::new(&mut self.inner).poll_write(cx, buf)
65
0
    }
66
67
0
    fn poll_write_vectored(
68
0
        mut self: Pin<&mut Self>,
69
0
        cx: &mut task::Context<'_>,
70
0
        bufs: &[io::IoSlice<'_>],
71
0
    ) -> Poll<io::Result<usize>> {
72
0
        Pin::new(&mut self.inner).poll_write_vectored(cx, bufs)
73
0
    }
74
75
0
    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
76
0
        Pin::new(&mut self.inner).poll_flush(cx)
77
0
    }
78
79
0
    fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<io::Result<()>> {
80
0
        Pin::new(&mut self.inner).poll_shutdown(cx)
81
0
    }
82
83
0
    fn is_write_vectored(&self) -> bool {
84
0
        self.inner.is_write_vectored()
85
0
    }
86
}
87
88
/*
89
#[cfg(test)]
90
mod tests {
91
    use super::Rewind;
92
    use bytes::Bytes;
93
    use tokio::io::AsyncReadExt;
94
95
    #[cfg(not(miri))]
96
    #[tokio::test]
97
    async fn partial_rewind() {
98
        let underlying = [104, 101, 108, 108, 111];
99
100
        let mock = tokio_test::io::Builder::new().read(&underlying).build();
101
102
        let mut stream = Rewind::new(mock);
103
104
        // Read off some bytes, ensure we filled o1
105
        let mut buf = [0; 2];
106
        stream.read_exact(&mut buf).await.expect("read1");
107
108
        // Rewind the stream so that it is as if we never read in the first place.
109
        stream.rewind(Bytes::copy_from_slice(&buf[..]));
110
111
        let mut buf = [0; 5];
112
        stream.read_exact(&mut buf).await.expect("read1");
113
114
        // At this point we should have read everything that was in the MockStream
115
        assert_eq!(&buf, &underlying);
116
    }
117
118
    #[cfg(not(miri))]
119
    #[tokio::test]
120
    async fn full_rewind() {
121
        let underlying = [104, 101, 108, 108, 111];
122
123
        let mock = tokio_test::io::Builder::new().read(&underlying).build();
124
125
        let mut stream = Rewind::new(mock);
126
127
        let mut buf = [0; 5];
128
        stream.read_exact(&mut buf).await.expect("read1");
129
130
        // Rewind the stream so that it is as if we never read in the first place.
131
        stream.rewind(Bytes::copy_from_slice(&buf[..]));
132
133
        let mut buf = [0; 5];
134
        stream.read_exact(&mut buf).await.expect("read1");
135
    }
136
}
137
*/