bytes/buf/
take.rs

1use crate::Buf;
2
3use core::cmp;
4
5#[cfg(feature = "std")]
6use 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)]
13pub struct Take<T> {
14    inner: T,
15    limit: usize,
16}
17
18pub fn new<T>(inner: T, limit: usize) -> Take<T> {
19    Take { inner, limit }
20}
21
22impl<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    pub fn into_inner(self) -> T {
43        self.inner
44    }
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    pub fn get_ref(&self) -> &T {
60        &self.inner
61    }
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    pub fn get_mut(&mut self) -> &mut T {
81        &mut self.inner
82    }
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    pub fn limit(&self) -> usize {
103        self.limit
104    }
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    pub fn set_limit(&mut self, lim: usize) {
131        self.limit = lim
132    }
133}
134
135impl<T: Buf> Buf for Take<T> {
136    fn remaining(&self) -> usize {
137        cmp::min(self.inner.remaining(), self.limit)
138    }
139
140    fn chunk(&self) -> &[u8] {
141        let bytes = self.inner.chunk();
142        &bytes[..cmp::min(bytes.len(), self.limit)]
143    }
144
145    fn advance(&mut self, cnt: usize) {
146        assert!(cnt <= self.limit);
147        self.inner.advance(cnt);
148        self.limit -= cnt;
149    }
150
151    fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes {
152        assert!(len <= self.remaining(), "`len` greater than remaining");
153
154        let r = self.inner.copy_to_bytes(len);
155        self.limit -= len;
156        r
157    }
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}