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.
97pub trait Buffer<T>: private::Sealed<T> {}
98
99// Implement `Buffer` for all the types that implement `Sealed`.
100impl<T> Buffer<T> for &mut [T] {}
101impl<T, const N: usize> Buffer<T> for &mut [T; N] {}
102#[cfg(feature = "alloc")]
103impl<T> Buffer<T> for &mut Vec<T> {}
104impl<T> Buffer<T> for &mut [MaybeUninit<T>] {}
105impl<T, const N: usize> Buffer<T> for &mut [MaybeUninit<T>; N] {}
106#[cfg(feature = "alloc")]
107impl<T> Buffer<T> for &mut Vec<MaybeUninit<T>> {}
108#[cfg(feature = "alloc")]
109impl<'a, T> Buffer<T> for SpareCapacity<'a, T> {}
110
111impl<T> private::Sealed<T> for &mut [T] {
112 type Output = usize;
113
114 #[inline]
115 fn parts_mut(&mut self) -> (*mut T, usize) {
116 (self.as_mut_ptr(), self.len())
117 }
118
119 #[inline]
120 unsafe fn assume_init(self, len: usize) -> Self::Output {
121 len
122 }
123}
124
125impl<T, const N: usize> private::Sealed<T> for &mut [T; N] {
126 type Output = usize;
127
128 #[inline]
129 fn parts_mut(&mut self) -> (*mut T, usize) {
130 (self.as_mut_ptr(), N)
131 }
132
133 #[inline]
134 unsafe fn assume_init(self, len: usize) -> Self::Output {
135 len
136 }
137}
138
139// `Vec` implements `DerefMut` to `&mut [T]`, however it doesn't get
140// auto-derefed in a `impl Buffer<u8>`, so we add this `impl` so that our users
141// don't have to add an extra `*` in these situations.
142#[cfg(feature = "alloc")]
143impl<T> private::Sealed<T> for &mut Vec<T> {
144 type Output = usize;
145
146 #[inline]
147 fn parts_mut(&mut self) -> (*mut T, usize) {
148 (self.as_mut_ptr(), self.len())
149 }
150
151 #[inline]
152 unsafe fn assume_init(self, len: usize) -> Self::Output {
153 len
154 }
155}
156
157impl<'a, T> private::Sealed<T> for &'a mut [MaybeUninit<T>] {
158 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
159
160 #[inline]
161 fn parts_mut(&mut self) -> (*mut T, usize) {
162 (self.as_mut_ptr().cast(), self.len())
163 }
164
165 #[inline]
166 unsafe fn assume_init(self, len: usize) -> Self::Output {
167 let (init: &mut [MaybeUninit], uninit: &mut [MaybeUninit]) = self.split_at_mut(mid:len);
168
169 // SAFETY: The user asserts that the slice is now initialized.
170 let init: &mut [T] = slice::from_raw_parts_mut(data:init.as_mut_ptr().cast::<T>(), init.len());
171
172 (init, uninit)
173 }
174}
175
176impl<'a, T, const N: usize> private::Sealed<T> for &'a mut [MaybeUninit<T>; N] {
177 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
178
179 #[inline]
180 fn parts_mut(&mut self) -> (*mut T, usize) {
181 (self.as_mut_ptr().cast(), self.len())
182 }
183
184 #[inline]
185 unsafe fn assume_init(self, len: usize) -> Self::Output {
186 let (init: &mut [MaybeUninit], uninit: &mut [MaybeUninit]) = self.split_at_mut(mid:len);
187
188 // SAFETY: The user asserts that the slice is now initialized.
189 let init: &mut [T] = slice::from_raw_parts_mut(data:init.as_mut_ptr().cast::<T>(), init.len());
190
191 (init, uninit)
192 }
193}
194
195#[cfg(feature = "alloc")]
196impl<'a, T> private::Sealed<T> for &'a mut Vec<MaybeUninit<T>> {
197 type Output = (&'a mut [T], &'a mut [MaybeUninit<T>]);
198
199 #[inline]
200 fn parts_mut(&mut self) -> (*mut T, usize) {
201 (self.as_mut_ptr().cast(), self.len())
202 }
203
204 #[inline]
205 unsafe fn assume_init(self, len: usize) -> Self::Output {
206 let (init: &mut [MaybeUninit], uninit: &mut [MaybeUninit]) = self.split_at_mut(mid:len);
207
208 // SAFETY: The user asserts that the slice is now initialized.
209 let init: &mut [T] = slice::from_raw_parts_mut(data:init.as_mut_ptr().cast::<T>(), init.len());
210
211 (init, uninit)
212 }
213}
214
215/// A type that implements [`Buffer`] by appending to a `Vec`, up to its
216/// capacity.
217///
218/// To use this, use the [`spare_capacity`] function.
219///
220/// Because this uses the capacity, and never reallocates, the `Vec` should
221/// have some non-empty spare capacity.
222#[cfg(feature = "alloc")]
223#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
224pub struct SpareCapacity<'a, T>(&'a mut Vec<T>);
225
226/// Construct an [`SpareCapacity`], which implements [`Buffer`].
227///
228/// This wraps a `Vec` and uses the spare capacity of the `Vec` as the buffer
229/// to receive data in, automatically calling `set_len` on the `Vec` to set the
230/// length to include the received elements.
231///
232/// This uses the existing capacity, and never allocates, so the `Vec` should
233/// have some non-empty spare capacity!
234///
235/// # Examples
236///
237/// ```
238/// # fn test(input: rustix::fd::BorrowedFd) -> rustix::io::Result<()> {
239/// use rustix::buffer::spare_capacity;
240/// use rustix::io::{read, Errno};
241///
242/// let mut buf = Vec::with_capacity(1024);
243/// match read(input, spare_capacity(&mut buf)) {
244/// Ok(0) => { /* end of stream */ }
245/// Ok(n) => { /* `buf` is now `n` bytes longer */ }
246/// Err(Errno::INTR) => { /* `buf` is unmodified */ }
247/// Err(e) => {
248/// return Err(e);
249/// }
250/// }
251///
252/// # Ok(())
253/// # }
254/// ```
255#[cfg(feature = "alloc")]
256#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
257pub fn spare_capacity<'a, T>(v: &'a mut Vec<T>) -> SpareCapacity<'a, T> {
258 debug_assert_ne!(
259 v.capacity(),
260 0,
261 "`extend` uses spare capacity, and never allocates new memory, so the `Vec` passed to it \
262 should have some spare capacity."
263 );
264
265 SpareCapacity(v)
266}
267
268#[cfg(feature = "alloc")]
269impl<'a, T> private::Sealed<T> for SpareCapacity<'a, T> {
270 /// The mutated `Vec` reflects the number of bytes read. We also return
271 /// this number, and a value of 0 indicates the end of the stream has
272 /// been reached.
273 type Output = usize;
274
275 #[inline]
276 fn parts_mut(&mut self) -> (*mut T, usize) {
277 let spare: &mut [MaybeUninit] = self.0.spare_capacity_mut();
278 (spare.as_mut_ptr().cast(), spare.len())
279 }
280
281 #[inline]
282 unsafe fn assume_init(self, len: usize) -> Self::Output {
283 // We initialized `len` elements; extend the `Vec` to include them.
284 self.0.set_len(self.0.len() + len);
285 len
286 }
287}
288
289mod private {
290 pub trait Sealed<T> {
291 /// The result of the process operation.
292 type Output;
293
294 /// Return a pointer and length for this buffer.
295 ///
296 /// The length is the number of elements of type `T`, not a number of
297 /// bytes.
298 ///
299 /// It's tempting to have this return `&mut [MaybeUninit<T>]` instead,
300 /// however that would require this function to be `unsafe`, because
301 /// callers could use the `&mut [MaybeUninit<T>]` slice to set elements
302 /// to `MaybeUninit::<T>::uninit()`, which would be a problem if `Self`
303 /// is `&mut [T]` or similar.
304 fn parts_mut(&mut self) -> (*mut T, usize);
305
306 /// Convert a finished buffer pointer into its result.
307 ///
308 /// # Safety
309 ///
310 /// At least `len` elements of the buffer must now be initialized.
311 #[must_use]
312 unsafe fn assume_init(self, len: usize) -> Self::Output;
313 }
314}
315
316#[cfg(test)]
317mod tests {
318 #[allow(unused_imports)]
319 use super::*;
320
321 #[cfg(not(windows))]
322 #[test]
323 fn test_compilation() {
324 use crate::io::read;
325 use core::mem::MaybeUninit;
326
327 // We need to obtain input stream, so open our own source file.
328 let input = std::fs::File::open("src/buffer.rs").unwrap();
329
330 let mut buf = vec![0_u8; 3];
331 buf.reserve(32);
332 let _x: usize = read(&input, spare_capacity(&mut buf)).unwrap();
333 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) =
334 read(&input, buf.spare_capacity_mut()).unwrap();
335 let _x: usize = read(&input, &mut buf).unwrap();
336 let _x: usize = read(&input, &mut *buf).unwrap();
337 let _x: usize = read(&input, &mut buf[..]).unwrap();
338 let _x: usize = read(&input, &mut (*buf)[..]).unwrap();
339
340 let mut buf = [0, 0, 0];
341 let _x: usize = read(&input, &mut buf).unwrap();
342 let _x: usize = read(&input, &mut buf[..]).unwrap();
343
344 let mut buf = [
345 MaybeUninit::uninit(),
346 MaybeUninit::uninit(),
347 MaybeUninit::uninit(),
348 ];
349 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&input, &mut buf).unwrap();
350 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&input, &mut buf[..]).unwrap();
351
352 let mut buf = vec![
353 MaybeUninit::uninit(),
354 MaybeUninit::uninit(),
355 MaybeUninit::uninit(),
356 ];
357 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&input, &mut buf).unwrap();
358 let _x: (&mut [u8], &mut [MaybeUninit<u8>]) = read(&input, &mut buf[..]).unwrap();
359 }
360
361 #[cfg(not(windows))]
362 #[test]
363 fn test_slice() {
364 use crate::io::read;
365 use std::io::{Seek, SeekFrom};
366
367 // We need to obtain input stream with contents that we can compare
368 // against, so open our own source file.
369 let mut input = std::fs::File::open("src/buffer.rs").unwrap();
370
371 let mut buf = [0_u8; 64];
372 let nread = read(&input, &mut buf).unwrap();
373 assert_eq!(nread, buf.len());
374 assert_eq!(
375 &buf[..58],
376 b"//! Utilities for functions that return data via buffers.\n"
377 );
378 input.seek(SeekFrom::End(-1)).unwrap();
379 let nread = read(&input, &mut buf).unwrap();
380 assert_eq!(nread, 1);
381 input.seek(SeekFrom::End(0)).unwrap();
382 let nread = read(&input, &mut buf).unwrap();
383 assert_eq!(nread, 0);
384 }
385
386 #[cfg(not(windows))]
387 #[test]
388 fn test_slice_uninit() {
389 use crate::io::read;
390 use core::mem::MaybeUninit;
391 use std::io::{Seek, SeekFrom};
392
393 // We need to obtain input stream with contents that we can compare
394 // against, so open our own source file.
395 let mut input = std::fs::File::open("src/buffer.rs").unwrap();
396
397 let mut buf = [MaybeUninit::<u8>::uninit(); 64];
398 let (init, uninit) = read(&input, &mut buf).unwrap();
399 assert_eq!(uninit.len(), 0);
400 assert_eq!(
401 &init[..58],
402 b"//! Utilities for functions that return data via buffers.\n"
403 );
404 assert_eq!(init.len(), buf.len());
405 assert_eq!(
406 unsafe { core::mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(&mut buf[..58]) },
407 b"//! Utilities for functions that return data via buffers.\n"
408 );
409 input.seek(SeekFrom::End(-1)).unwrap();
410 let (init, uninit) = read(&input, &mut buf).unwrap();
411 assert_eq!(init.len(), 1);
412 assert_eq!(uninit.len(), buf.len() - 1);
413 input.seek(SeekFrom::End(0)).unwrap();
414 let (init, uninit) = read(&input, &mut buf).unwrap();
415 assert_eq!(init.len(), 0);
416 assert_eq!(uninit.len(), buf.len());
417 }
418
419 #[cfg(not(windows))]
420 #[test]
421 fn test_spare_capacity() {
422 use crate::io::read;
423 use std::io::{Seek, SeekFrom};
424
425 // We need to obtain input stream with contents that we can compare
426 // against, so open our own source file.
427 let mut input = std::fs::File::open("src/buffer.rs").unwrap();
428
429 let mut buf = Vec::with_capacity(64);
430 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
431 assert_eq!(nread, buf.capacity());
432 assert_eq!(nread, buf.len());
433 assert_eq!(
434 &buf[..58],
435 b"//! Utilities for functions that return data via buffers.\n"
436 );
437 buf.clear();
438 input.seek(SeekFrom::End(-1)).unwrap();
439 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
440 assert_eq!(nread, 1);
441 assert_eq!(buf.len(), 1);
442 buf.clear();
443 input.seek(SeekFrom::End(0)).unwrap();
444 let nread = read(&input, spare_capacity(&mut buf)).unwrap();
445 assert_eq!(nread, 0);
446 assert!(buf.is_empty());
447 }
448}
449