rustix/
buffer.rs

1//! Utilities to help with buffering.
2
3#![allow(unsafe_code)]
4
5#[cfg(feature = "alloc")]
6use alloc::vec::Vec;
7use core::mem::MaybeUninit;
8use core::slice;
9
10/// A memory buffer that may be uninitialized.
11///
12/// There are three types that implement the `Buffer` trait, and the type you
13/// use determines the return type of the functions that use it:
14///
15/// | If you pass a…           | You get back a… |
16/// | ------------------------ | --------------- |
17/// | `&mut [u8]`              | `usize`, indicating the number of elements initialized. |
18/// | `&mut [MaybeUninit<u8>]` | `(&mut [u8], &mut [MaybeUninit<u8>])`, holding the initialized and uninitialized subslices. |
19/// | [`SpareCapacity`]        | `usize`, indicating the number of elements initialized. And the `Vec` is extended. |
20///
21/// # Examples
22///
23/// Passing a `&mut [u8]`:
24///
25/// ```rust
26/// # use rustix::io::read;
27/// # fn example(fd: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
28/// let mut buf = [0_u8; 64];
29/// let nread = read(fd, &mut buf)?;
30/// # Ok(())
31/// # }
32/// ```
33///
34/// Passing a `&mut [MaybeUninit<u8>]`:
35///
36/// ```rust
37/// # use rustix::io::read;
38/// # use std::mem::MaybeUninit;
39/// # fn example(fd: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
40/// let mut buf = [MaybeUninit::<u8>::uninit(); 64];
41/// let (init, uninit) = read(fd, &mut buf)?;
42/// // `init` is a `&mut [u8]` with the initialized bytes.
43/// // `uninit` is a `&mut [MaybeUninit<u8>]` with the remaining bytes.
44/// # Ok(())
45/// # }
46/// ```
47///
48/// Passing a [`SpareCapacity`], via the [`spare_capacity`] helper function:
49///
50/// ```rust
51/// # use rustix::io::read;
52/// # use rustix::buffer::spare_capacity;
53/// # fn example(fd: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
54/// let mut buf = Vec::with_capacity(64);
55/// let nread = read(fd, spare_capacity(&mut buf))?;
56/// // Also, `buf.len()` is now `nread` elements greater.
57/// # Ok(())
58/// # }
59/// ```
60///
61/// # Guide to error messages
62///
63/// Sometimes code using `Buffer` can encounter non-obvious error messages.
64/// Here are some we've encountered, along with ways to fix them.
65///
66/// If you see errors like
67/// "cannot move out of `self` which is behind a mutable reference"
68/// and
69/// "move occurs because `x` has type `&mut [u8]`, which does not implement the `Copy` trait",
70/// replace `x` with `&mut *x`. See `error_buffer_wrapper` in
71/// examples/buffer_errors.rs.
72///
73/// If you see errors like
74/// "type annotations needed"
75/// and
76/// "cannot infer type of the type parameter `Buf` declared on the function `read`",
77/// you may need to change a `&mut []` to `&mut [0_u8; 0]`. See
78/// `error_empty_slice` in examples/buffer_errors.rs.
79///
80/// If you see errors like
81/// "the trait bound `[MaybeUninit<u8>; 1]: Buffer<u8>` is not satisfied",
82/// add a `&mut` to pass the array by reference instead of by value. See
83/// `error_array_by_value` in examples/buffer_errors.rs.
84///
85/// If you see errors like
86/// "cannot move out of `x`, a captured variable in an `FnMut` closure",
87/// try replacing `x` with `&mut *x`, or, if that doesn't work, try moving a
88/// `let` into the closure body. See `error_retry_closure` and
89/// `error_retry_indirect_closure` in examples/buffer_errors.rs.
90///
91/// If you see errors like
92/// "captured variable cannot escape `FnMut` closure body",
93/// use an explicit loop instead of `retry_on_intr`, assuming you're using
94/// that. See `error_retry_closure_uninit` in examples.rs.
95pub trait Buffer<T>: private::Sealed<T> {}
96
97// Implement `Buffer` for all the types that implement `Sealed`.
98impl<T> Buffer<T> for &mut [T] {}
99impl<T, const N: usize> Buffer<T> for &mut [T; N] {}
100#[cfg(feature = "alloc")]
101impl<T> Buffer<T> for &mut Vec<T> {}
102impl<T> Buffer<T> for &mut [MaybeUninit<T>] {}
103impl<T, const N: usize> Buffer<T> for &mut [MaybeUninit<T>; N] {}
104#[cfg(feature = "alloc")]
105impl<T> Buffer<T> for &mut Vec<MaybeUninit<T>> {}
106#[cfg(feature = "alloc")]
107impl<'a, T> Buffer<T> for SpareCapacity<'a, T> {}
108
109impl<T> private::Sealed<T> for &mut [T] {
110    type Output = usize;
111
112    #[inline]
113    fn parts_mut(&mut self) -> (*mut T, usize) {
114        (self.as_mut_ptr(), self.len())
115    }
116
117    #[inline]
118    unsafe fn assume_init(self, len: usize) -> Self::Output {
119        len
120    }
121}
122
123impl<T, const N: usize> private::Sealed<T> for &mut [T; N] {
124    type Output = usize;
125
126    #[inline]
127    fn parts_mut(&mut self) -> (*mut T, usize) {
128        (self.as_mut_ptr(), N)
129    }
130
131    #[inline]
132    unsafe fn assume_init(self, len: usize) -> Self::Output {
133        len
134    }
135}
136
137// `Vec` implements `DerefMut` to `&mut [T]`, however it doesn't get
138// auto-derefed in a `impl Buffer<u8>`, so we add this `impl` so that our users
139// don't have to add an extra `*` in these situations.
140#[cfg(feature = "alloc")]
141impl<T> private::Sealed<T> for &mut Vec<T> {
142    type Output = usize;
143
144    #[inline]
145    fn parts_mut(&mut self) -> (*mut T, usize) {
146        (self.as_mut_ptr(), self.len())
147    }
148
149    #[inline]
150    unsafe fn assume_init(self, len: usize) -> Self::Output {
151        len
152    }
153}
154
155impl<'a, T> private::Sealed<T> for &'a mut [MaybeUninit<T>] {
156    type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
157
158    #[inline]
159    fn parts_mut(&mut self) -> (*mut T, usize) {
160        (self.as_mut_ptr().cast(), self.len())
161    }
162
163    #[inline]
164    unsafe fn assume_init(self, len: usize) -> Self::Output {
165        let (init, uninit) = self.split_at_mut(len);
166
167        // SAFETY: The user asserts that the slice is now initialized.
168        let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
169
170        (init, uninit)
171    }
172}
173
174impl<'a, T, const N: usize> private::Sealed<T> for &'a mut [MaybeUninit<T>; N] {
175    type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
176
177    #[inline]
178    fn parts_mut(&mut self) -> (*mut T, usize) {
179        (self.as_mut_ptr().cast(), self.len())
180    }
181
182    #[inline]
183    unsafe fn assume_init(self, len: usize) -> Self::Output {
184        let (init, uninit) = self.split_at_mut(len);
185
186        // SAFETY: The user asserts that the slice is now initialized.
187        let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
188
189        (init, uninit)
190    }
191}
192
193#[cfg(feature = "alloc")]
194impl<'a, T> private::Sealed<T> for &'a mut Vec<MaybeUninit<T>> {
195    type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
196
197    #[inline]
198    fn parts_mut(&mut self) -> (*mut T, usize) {
199        (self.as_mut_ptr().cast(), self.len())
200    }
201
202    #[inline]
203    unsafe fn assume_init(self, len: usize) -> Self::Output {
204        let (init, uninit) = self.split_at_mut(len);
205
206        // SAFETY: The user asserts that the slice is now initialized.
207        let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
208
209        (init, uninit)
210    }
211}
212
213/// A type that implements [`Buffer`] by appending to a `Vec`, up to its
214/// capacity.
215///
216/// To use this, use the [`spare_capacity`] function.
217///
218/// Because this uses the capacity, and never reallocates, the `Vec` should
219/// have some non-empty spare capacity.
220#[cfg(feature = "alloc")]
221#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
222pub struct SpareCapacity<'a, T>(&'a mut Vec<T>);
223
224/// Construct an [`SpareCapacity`], which implements [`Buffer`].
225///
226/// This wraps a `Vec` and uses the spare capacity of the `Vec` as the buffer
227/// to receive data in, automatically calling `set_len` on the `Vec` to set the
228/// length to include the received elements.
229///
230/// This uses the existing capacity, and never allocates, so the `Vec` should
231/// have some non-empty spare capacity!
232///
233/// # Examples
234///
235/// ```
236/// # fn test(input: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
237/// use rustix::buffer::spare_capacity;
238/// use rustix::io::{read, Errno};
239///
240/// let mut buf = Vec::with_capacity(1024);
241/// match read(input, spare_capacity(&mut buf)) {
242///     Ok(0) => { /* end of stream */ }
243///     Ok(n) => { /* `buf` is now `n` bytes longer */ }
244///     Err(Errno::INTR) => { /* `buf` is unmodified */ }
245///     Err(e) => {
246///         return Err(e);
247///     }
248/// }
249///
250/// # Ok(())
251/// # }
252/// ```
253#[cfg(feature = "alloc")]
254#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
255pub fn spare_capacity<'a, T>(v: &'a mut Vec<T>) -> SpareCapacity<'a, T> {
256    debug_assert_ne!(
257        v.capacity(),
258        0,
259        "`extend` uses spare capacity, and never allocates new memory, so the `Vec` passed to it \
260         should have some spare capacity."
261    );
262
263    SpareCapacity(v)
264}
265
266#[cfg(feature = "alloc")]
267impl<'a, T> private::Sealed<T> for SpareCapacity<'a, T> {
268    /// The mutated `Vec` reflects the number of bytes read. We also return
269    /// this number, and a value of 0 indicates the end of the stream has
270    /// been reached.
271    type Output = usize;
272
273    #[inline]
274    fn parts_mut(&mut self) -> (*mut T, usize) {
275        let spare = self.0.spare_capacity_mut();
276        (spare.as_mut_ptr().cast(), spare.len())
277    }
278
279    #[inline]
280    unsafe fn assume_init(self, len: usize) -> Self::Output {
281        // We initialized `len` elements; extend the `Vec` to include them.
282        self.0.set_len(self.0.len() + len);
283        len
284    }
285}
286
287mod private {
288    pub trait Sealed<T> {
289        /// The result of the process operation.
290        type Output;
291
292        /// Return a pointer and length for this buffer.
293        ///
294        /// It's tempting to have this return `&mut [MaybeUninit<T>]` instead,
295        /// however that would require this function to be `unsafe`, because
296        /// callers could use the `&mut [MaybeUninit<T>]` slice to set elements
297        /// to `MaybeUninit::<T>::uninit()`, which would be a problem if `Self`
298        /// is `&mut [T]` or similar.
299        fn parts_mut(&mut self) -> (*mut T, usize);
300
301        /// Convert a finished buffer pointer into its result.
302        ///
303        /// # Safety
304        ///
305        /// At least `len` bytes of the buffer must now be initialized.
306        unsafe fn assume_init(self, len: usize) -> Self::Output;
307    }
308}
309
310#[cfg(test)]
311mod tests {
312    #[allow(unused_imports)]
313    use super::*;
314
315    #[cfg(not(windows))]
316    #[test]
317    fn test_compilation() {
318        use crate::io::read;
319        use core::mem::MaybeUninit;
320
321        let input = std::fs::File::open("Cargo.toml").unwrap();
322
323        let mut buf = vec![0_u8; 3];
324        buf.reserve(32);
325        let _x: usize = read(&input, spare_capacity(&mut buf)).unwrap();
326        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) =
327            read(&input, buf.spare_capacity_mut()).unwrap();
328        let _x: usize = read(&input, &mut buf).unwrap();
329        let _x: usize = read(&input, &mut *buf).unwrap();
330        let _x: usize = read(&input, &mut buf[..]).unwrap();
331        let _x: usize = read(&input, &mut (*buf)[..]).unwrap();
332
333        let mut buf = [0, 0, 0];
334        let _x: usize = read(&input, &mut buf).unwrap();
335        let _x: usize = read(&input, &mut buf[..]).unwrap();
336
337        let mut buf = [
338            MaybeUninit::uninit(),
339            MaybeUninit::uninit(),
340            MaybeUninit::uninit(),
341        ];
342        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&input, &mut buf).unwrap();
343        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&input, &mut buf[..]).unwrap();
344
345        let mut buf = vec![
346            MaybeUninit::uninit(),
347            MaybeUninit::uninit(),
348            MaybeUninit::uninit(),
349        ];
350        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&input, &mut buf).unwrap();
351        let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&input, &mut buf[..]).unwrap();
352    }
353
354    #[cfg(not(windows))]
355    #[test]
356    fn test_slice() {
357        use crate::io::read;
358        use std::io::{Seek, SeekFrom};
359
360        let mut input = std::fs::File::open("Cargo.toml").unwrap();
361
362        let mut buf = [0_u8; 64];
363        let nread = read(&input, &mut buf).unwrap();
364        assert_eq!(nread, buf.len());
365        assert_eq!(&buf[..9], b"[package]");
366        input.seek(SeekFrom::End(-1)).unwrap();
367        let nread = read(&input, &mut buf).unwrap();
368        assert_eq!(nread, 1);
369        input.seek(SeekFrom::End(0)).unwrap();
370        let nread = read(&input, &mut buf).unwrap();
371        assert_eq!(nread, 0);
372    }
373
374    #[cfg(not(windows))]
375    #[test]
376    fn test_slice_uninit() {
377        use crate::io::read;
378        use core::mem::MaybeUninit;
379        use std::io::{Seek, SeekFrom};
380
381        let mut input = std::fs::File::open("Cargo.toml").unwrap();
382
383        let mut buf = [MaybeUninit::<u8>::uninit(); 64];
384        let (init, uninit) = read(&input, &mut buf).unwrap();
385        assert_eq!(uninit.len(), 0);
386        assert_eq!(&init[..9], b"[package]");
387        assert_eq!(init.len(), buf.len());
388        assert_eq!(
389            unsafe { core::mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(&mut buf[..9]) },
390            b"[package]"
391        );
392        input.seek(SeekFrom::End(-1)).unwrap();
393        let (init, uninit) = read(&input, &mut buf).unwrap();
394        assert_eq!(init.len(), 1);
395        assert_eq!(uninit.len(), buf.len() - 1);
396        input.seek(SeekFrom::End(0)).unwrap();
397        let (init, uninit) = read(&input, &mut buf).unwrap();
398        assert_eq!(init.len(), 0);
399        assert_eq!(uninit.len(), buf.len());
400    }
401
402    #[cfg(not(windows))]
403    #[test]
404    fn test_spare_capacity() {
405        use crate::io::read;
406        use std::io::{Seek, SeekFrom};
407
408        let mut input = std::fs::File::open("Cargo.toml").unwrap();
409
410        let mut buf = Vec::with_capacity(64);
411        let nread = read(&input, spare_capacity(&mut buf)).unwrap();
412        assert_eq!(nread, buf.capacity());
413        assert_eq!(nread, buf.len());
414        assert_eq!(&buf[..9], b"[package]");
415        buf.clear();
416        input.seek(SeekFrom::End(-1)).unwrap();
417        let nread = read(&input, spare_capacity(&mut buf)).unwrap();
418        assert_eq!(nread, 1);
419        assert_eq!(buf.len(), 1);
420        buf.clear();
421        input.seek(SeekFrom::End(0)).unwrap();
422        let nread = read(&input, spare_capacity(&mut buf)).unwrap();
423        assert_eq!(nread, 0);
424        assert!(buf.is_empty());
425    }
426}