Coverage Report

Created: 2025-11-16 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustix-1.1.2/src/buffer.rs
Line
Count
Source
1
//! Utilities for functions that return data via buffers.
2
3
#![allow(unsafe_code)]
4
5
#[cfg(feature = "alloc")]
6
use alloc::vec::Vec;
7
use core::mem::MaybeUninit;
8
use 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
)]
106
pub trait Buffer<T>: private::Sealed<T> {}
107
108
// Implement `Buffer` for all the types that implement `Sealed`.
109
impl<T> Buffer<T> for &mut [T] {}
110
impl<T, const N: usize> Buffer<T> for &mut [T; N] {}
111
#[cfg(feature = "alloc")]
112
impl<T> Buffer<T> for &mut Vec<T> {}
113
impl<T> Buffer<T> for &mut [MaybeUninit<T>] {}
114
impl<T, const N: usize> Buffer<T> for &mut [MaybeUninit<T>; N] {}
115
#[cfg(feature = "alloc")]
116
impl<T> Buffer<T> for &mut Vec<MaybeUninit<T>> {}
117
#[cfg(feature = "alloc")]
118
impl<'a, T> Buffer<T> for SpareCapacity<'a, T> {}
119
120
impl<T> private::Sealed<T> for &mut [T] {
121
    type Output = usize;
122
123
    #[inline]
124
0
    fn parts_mut(&mut self) -> (*mut T, usize) {
125
0
        (self.as_mut_ptr(), self.len())
126
0
    }
127
128
    #[inline]
129
0
    unsafe fn assume_init(self, len: usize) -> Self::Output {
130
0
        len
131
0
    }
132
}
133
134
impl<T, const N: usize> private::Sealed<T> for &mut [T; N] {
135
    type Output = usize;
136
137
    #[inline]
138
0
    fn parts_mut(&mut self) -> (*mut T, usize) {
139
0
        (self.as_mut_ptr(), N)
140
0
    }
141
142
    #[inline]
143
0
    unsafe fn assume_init(self, len: usize) -> Self::Output {
144
0
        len
145
0
    }
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")]
152
impl<T> private::Sealed<T> for &mut Vec<T> {
153
    type Output = usize;
154
155
    #[inline]
156
0
    fn parts_mut(&mut self) -> (*mut T, usize) {
157
0
        (self.as_mut_ptr(), self.len())
158
0
    }
159
160
    #[inline]
161
0
    unsafe fn assume_init(self, len: usize) -> Self::Output {
162
0
        len
163
0
    }
164
}
165
166
impl<'a, T> private::Sealed<T> for &'a mut [MaybeUninit<T>] {
167
    type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
168
169
    #[inline]
170
0
    fn parts_mut(&mut self) -> (*mut T, usize) {
171
0
        (self.as_mut_ptr().cast(), self.len())
172
0
    }
173
174
    #[inline]
175
0
    unsafe fn assume_init(self, len: usize) -> Self::Output {
176
0
        let (init, uninit) = self.split_at_mut(len);
177
178
        // SAFETY: The user asserts that the slice is now initialized.
179
0
        let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
180
181
0
        (init, uninit)
182
0
    }
183
}
184
185
impl<'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
0
    fn parts_mut(&mut self) -> (*mut T, usize) {
190
0
        (self.as_mut_ptr().cast(), self.len())
191
0
    }
192
193
    #[inline]
194
0
    unsafe fn assume_init(self, len: usize) -> Self::Output {
195
0
        let (init, uninit) = self.split_at_mut(len);
196
197
        // SAFETY: The user asserts that the slice is now initialized.
198
0
        let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
199
200
0
        (init, uninit)
201
0
    }
202
}
203
204
#[cfg(feature = "alloc")]
205
impl<'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
0
    fn parts_mut(&mut self) -> (*mut T, usize) {
210
0
        (self.as_mut_ptr().cast(), self.len())
211
0
    }
212
213
    #[inline]
214
0
    unsafe fn assume_init(self, len: usize) -> Self::Output {
215
0
        let (init, uninit) = self.split_at_mut(len);
216
217
        // SAFETY: The user asserts that the slice is now initialized.
218
0
        let init = slice::from_raw_parts_mut(init.as_mut_ptr().cast::<T>(), init.len());
219
220
0
        (init, uninit)
221
0
    }
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")))]
233
pub 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")))]
266
0
pub fn spare_capacity<'a, T>(v: &'a mut Vec<T>) -> SpareCapacity<'a, T> {
267
0
    debug_assert_ne!(
268
0
        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
0
    SpareCapacity(v)
275
0
}
276
277
#[cfg(feature = "alloc")]
278
impl<'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
0
    fn parts_mut(&mut self) -> (*mut T, usize) {
286
0
        let spare = self.0.spare_capacity_mut();
287
0
        (spare.as_mut_ptr().cast(), spare.len())
288
0
    }
289
290
    #[inline]
291
0
    unsafe fn assume_init(self, len: usize) -> Self::Output {
292
        // We initialized `len` elements; extend the `Vec` to include them.
293
0
        self.0.set_len(self.0.len() + len);
294
0
        len
295
0
    }
296
}
297
298
mod 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)]
326
mod 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
}