Coverage Report

Created: 2025-07-11 07:02

/rust/registry/src/index.crates.io-6f17d22bba15001f/bytes-1.10.1/src/buf/take.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::Buf;
2
3
use core::cmp;
4
5
#[cfg(feature = "std")]
6
use std::io::IoSlice;
7
8
/// A `Buf` adapter which limits the bytes read from an underlying buffer.
9
///
10
/// This struct is generally created by calling `take()` on `Buf`. See
11
/// documentation of [`take()`](Buf::take) for more details.
12
#[derive(Debug)]
13
pub struct Take<T> {
14
    inner: T,
15
    limit: usize,
16
}
17
18
0
pub fn new<T>(inner: T, limit: usize) -> Take<T> {
19
0
    Take { inner, limit }
20
0
}
21
22
impl<T> Take<T> {
23
    /// Consumes this `Take`, returning the underlying value.
24
    ///
25
    /// # Examples
26
    ///
27
    /// ```rust
28
    /// use bytes::{Buf, BufMut};
29
    ///
30
    /// let mut buf = b"hello world".take(2);
31
    /// let mut dst = vec![];
32
    ///
33
    /// dst.put(&mut buf);
34
    /// assert_eq!(*dst, b"he"[..]);
35
    ///
36
    /// let mut buf = buf.into_inner();
37
    ///
38
    /// dst.clear();
39
    /// dst.put(&mut buf);
40
    /// assert_eq!(*dst, b"llo world"[..]);
41
    /// ```
42
0
    pub fn into_inner(self) -> T {
43
0
        self.inner
44
0
    }
45
46
    /// Gets a reference to the underlying `Buf`.
47
    ///
48
    /// It is inadvisable to directly read from the underlying `Buf`.
49
    ///
50
    /// # Examples
51
    ///
52
    /// ```rust
53
    /// use bytes::Buf;
54
    ///
55
    /// let buf = b"hello world".take(2);
56
    ///
57
    /// assert_eq!(11, buf.get_ref().remaining());
58
    /// ```
59
0
    pub fn get_ref(&self) -> &T {
60
0
        &self.inner
61
0
    }
62
63
    /// Gets a mutable reference to the underlying `Buf`.
64
    ///
65
    /// It is inadvisable to directly read from the underlying `Buf`.
66
    ///
67
    /// # Examples
68
    ///
69
    /// ```rust
70
    /// use bytes::{Buf, BufMut};
71
    ///
72
    /// let mut buf = b"hello world".take(2);
73
    /// let mut dst = vec![];
74
    ///
75
    /// buf.get_mut().advance(2);
76
    ///
77
    /// dst.put(&mut buf);
78
    /// assert_eq!(*dst, b"ll"[..]);
79
    /// ```
80
0
    pub fn get_mut(&mut self) -> &mut T {
81
0
        &mut self.inner
82
0
    }
83
84
    /// Returns the maximum number of bytes that can be read.
85
    ///
86
    /// # Note
87
    ///
88
    /// If the inner `Buf` has fewer bytes than indicated by this method then
89
    /// that is the actual number of available bytes.
90
    ///
91
    /// # Examples
92
    ///
93
    /// ```rust
94
    /// use bytes::Buf;
95
    ///
96
    /// let mut buf = b"hello world".take(2);
97
    ///
98
    /// assert_eq!(2, buf.limit());
99
    /// assert_eq!(b'h', buf.get_u8());
100
    /// assert_eq!(1, buf.limit());
101
    /// ```
102
0
    pub fn limit(&self) -> usize {
103
0
        self.limit
104
0
    }
105
106
    /// Sets the maximum number of bytes that can be read.
107
    ///
108
    /// # Note
109
    ///
110
    /// If the inner `Buf` has fewer bytes than `lim` then that is the actual
111
    /// number of available bytes.
112
    ///
113
    /// # Examples
114
    ///
115
    /// ```rust
116
    /// use bytes::{Buf, BufMut};
117
    ///
118
    /// let mut buf = b"hello world".take(2);
119
    /// let mut dst = vec![];
120
    ///
121
    /// dst.put(&mut buf);
122
    /// assert_eq!(*dst, b"he"[..]);
123
    ///
124
    /// dst.clear();
125
    ///
126
    /// buf.set_limit(3);
127
    /// dst.put(&mut buf);
128
    /// assert_eq!(*dst, b"llo"[..]);
129
    /// ```
130
0
    pub fn set_limit(&mut self, lim: usize) {
131
0
        self.limit = lim
132
0
    }
133
}
134
135
impl<T: Buf> Buf for Take<T> {
136
0
    fn remaining(&self) -> usize {
137
0
        cmp::min(self.inner.remaining(), self.limit)
138
0
    }
139
140
0
    fn chunk(&self) -> &[u8] {
141
0
        let bytes = self.inner.chunk();
142
0
        &bytes[..cmp::min(bytes.len(), self.limit)]
143
0
    }
144
145
0
    fn advance(&mut self, cnt: usize) {
146
0
        assert!(cnt <= self.limit);
147
0
        self.inner.advance(cnt);
148
0
        self.limit -= cnt;
149
0
    }
150
151
0
    fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes {
152
0
        assert!(len <= self.remaining(), "`len` greater than remaining");
153
154
0
        let r = self.inner.copy_to_bytes(len);
155
0
        self.limit -= len;
156
0
        r
157
0
    }
158
159
    #[cfg(feature = "std")]
160
    fn chunks_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize {
161
        if self.limit == 0 {
162
            return 0;
163
        }
164
165
        const LEN: usize = 16;
166
        let mut slices: [IoSlice<'a>; LEN] = [
167
            IoSlice::new(&[]),
168
            IoSlice::new(&[]),
169
            IoSlice::new(&[]),
170
            IoSlice::new(&[]),
171
            IoSlice::new(&[]),
172
            IoSlice::new(&[]),
173
            IoSlice::new(&[]),
174
            IoSlice::new(&[]),
175
            IoSlice::new(&[]),
176
            IoSlice::new(&[]),
177
            IoSlice::new(&[]),
178
            IoSlice::new(&[]),
179
            IoSlice::new(&[]),
180
            IoSlice::new(&[]),
181
            IoSlice::new(&[]),
182
            IoSlice::new(&[]),
183
        ];
184
185
        let cnt = self
186
            .inner
187
            .chunks_vectored(&mut slices[..dst.len().min(LEN)]);
188
        let mut limit = self.limit;
189
        for (i, (dst, slice)) in dst[..cnt].iter_mut().zip(slices.iter()).enumerate() {
190
            if let Some(buf) = slice.get(..limit) {
191
                // SAFETY: We could do this safely with `IoSlice::advance` if we had a larger MSRV.
192
                let buf = unsafe { std::mem::transmute::<&[u8], &'a [u8]>(buf) };
193
                *dst = IoSlice::new(buf);
194
                return i + 1;
195
            } else {
196
                // SAFETY: We could do this safely with `IoSlice::advance` if we had a larger MSRV.
197
                let buf = unsafe { std::mem::transmute::<&[u8], &'a [u8]>(slice) };
198
                *dst = IoSlice::new(buf);
199
                limit -= slice.len();
200
            }
201
        }
202
        cnt
203
    }
204
}