rustix/
buffer.rs

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