Coverage Report

Created: 2025-10-31 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/http-body-util-0.1.3/src/util.rs
Line
Count
Source
1
use std::collections::VecDeque;
2
use std::io::IoSlice;
3
4
use bytes::{Buf, BufMut, Bytes, BytesMut};
5
6
#[derive(Debug)]
7
pub(crate) struct BufList<T> {
8
    bufs: VecDeque<T>,
9
}
10
11
impl<T: Buf> BufList<T> {
12
    #[inline]
13
0
    pub(crate) fn push(&mut self, buf: T) {
14
0
        debug_assert!(buf.has_remaining());
15
0
        self.bufs.push_back(buf);
16
0
    }
17
18
    #[inline]
19
    pub(crate) fn pop(&mut self) -> Option<T> {
20
        self.bufs.pop_front()
21
    }
22
}
23
24
impl<T: Buf> Buf for BufList<T> {
25
    #[inline]
26
0
    fn remaining(&self) -> usize {
27
0
        self.bufs.iter().map(|buf| buf.remaining()).sum()
28
0
    }
29
30
    #[inline]
31
0
    fn has_remaining(&self) -> bool {
32
0
        self.bufs.iter().any(|buf| buf.has_remaining())
33
0
    }
34
35
    #[inline]
36
0
    fn chunk(&self) -> &[u8] {
37
0
        self.bufs.front().map(Buf::chunk).unwrap_or_default()
38
0
    }
39
40
    #[inline]
41
0
    fn advance(&mut self, mut cnt: usize) {
42
0
        while cnt > 0 {
43
            {
44
0
                let front = &mut self.bufs[0];
45
0
                let rem = front.remaining();
46
0
                if rem > cnt {
47
0
                    front.advance(cnt);
48
0
                    return;
49
0
                } else {
50
0
                    front.advance(rem);
51
0
                    cnt -= rem;
52
0
                }
53
            }
54
0
            self.bufs.pop_front();
55
        }
56
0
    }
57
58
    #[inline]
59
    fn chunks_vectored<'t>(&'t self, dst: &mut [IoSlice<'t>]) -> usize {
60
        if dst.is_empty() {
61
            return 0;
62
        }
63
        let mut vecs = 0;
64
        for buf in &self.bufs {
65
            vecs += buf.chunks_vectored(&mut dst[vecs..]);
66
            if vecs == dst.len() {
67
                break;
68
            }
69
        }
70
        vecs
71
    }
72
73
    #[inline]
74
0
    fn copy_to_bytes(&mut self, len: usize) -> Bytes {
75
        // Our inner buffer may have an optimized version of copy_to_bytes, and if the whole
76
        // request can be fulfilled by the front buffer, we can take advantage.
77
0
        match self.bufs.front_mut() {
78
0
            Some(front) if front.remaining() == len => {
79
0
                let b = front.copy_to_bytes(len);
80
0
                self.bufs.pop_front();
81
0
                b
82
            }
83
0
            Some(front) if front.remaining() > len => front.copy_to_bytes(len),
84
            _ => {
85
0
                let rem = self.remaining();
86
0
                assert!(len <= rem, "`len` greater than remaining");
87
0
                let mut bm = BytesMut::with_capacity(len);
88
0
                if rem == len {
89
0
                    // .take() costs a lot more, so skip it if we don't need it
90
0
                    bm.put(self);
91
0
                } else {
92
0
                    bm.put(self.take(len));
93
0
                }
94
0
                bm.freeze()
95
            }
96
        }
97
0
    }
98
}
99
100
impl<T> Default for BufList<T> {
101
0
    fn default() -> Self {
102
0
        BufList {
103
0
            bufs: VecDeque::new(),
104
0
        }
105
0
    }
106
}
107
108
#[cfg(test)]
109
mod tests {
110
    use std::ptr;
111
112
    use super::*;
113
114
    fn hello_world_buf() -> BufList<Bytes> {
115
        BufList {
116
            bufs: vec![Bytes::from("Hello"), Bytes::from(" "), Bytes::from("World")].into(),
117
        }
118
    }
119
120
    #[test]
121
    fn to_bytes_shorter() {
122
        let mut bufs = hello_world_buf();
123
        let old_ptr = bufs.chunk().as_ptr();
124
        let start = bufs.copy_to_bytes(4);
125
        assert_eq!(start, "Hell");
126
        assert!(ptr::eq(old_ptr, start.as_ptr()));
127
        assert_eq!(bufs.chunk(), b"o");
128
        assert!(ptr::eq(old_ptr.wrapping_add(4), bufs.chunk().as_ptr()));
129
        assert_eq!(bufs.remaining(), 7);
130
    }
131
132
    #[test]
133
    fn to_bytes_eq() {
134
        let mut bufs = hello_world_buf();
135
        let old_ptr = bufs.chunk().as_ptr();
136
        let start = bufs.copy_to_bytes(5);
137
        assert_eq!(start, "Hello");
138
        assert!(ptr::eq(old_ptr, start.as_ptr()));
139
        assert_eq!(bufs.chunk(), b" ");
140
        assert_eq!(bufs.remaining(), 6);
141
    }
142
143
    #[test]
144
    fn to_bytes_longer() {
145
        let mut bufs = hello_world_buf();
146
        let start = bufs.copy_to_bytes(7);
147
        assert_eq!(start, "Hello W");
148
        assert_eq!(bufs.remaining(), 4);
149
    }
150
151
    #[test]
152
    fn one_long_buf_to_bytes() {
153
        let mut buf = BufList::default();
154
        buf.push(b"Hello World" as &[_]);
155
        assert_eq!(buf.copy_to_bytes(5), "Hello");
156
        assert_eq!(buf.chunk(), b" World");
157
    }
158
159
    #[test]
160
    #[should_panic(expected = "`len` greater than remaining")]
161
    fn buf_to_bytes_too_many() {
162
        hello_world_buf().copy_to_bytes(42);
163
    }
164
}