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 | pub trait Buffer<T>: private::Sealed<T> {} |
98 | |
99 | // Implement `Buffer` for all the types that implement `Sealed`. |
100 | impl<T> Buffer<T> for &mut [T] {} |
101 | impl<T, const N: usize> Buffer<T> for &mut [T; N] {} |
102 | #[cfg (feature = "alloc" )] |
103 | impl<T> Buffer<T> for &mut Vec<T> {} |
104 | impl<T> Buffer<T> for &mut [MaybeUninit<T>] {} |
105 | impl<T, const N: usize> Buffer<T> for &mut [MaybeUninit<T>; N] {} |
106 | #[cfg (feature = "alloc" )] |
107 | impl<T> Buffer<T> for &mut Vec<MaybeUninit<T>> {} |
108 | #[cfg (feature = "alloc" )] |
109 | impl<'a, T> Buffer<T> for SpareCapacity<'a, T> {} |
110 | |
111 | impl<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 | |
125 | impl<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" )] |
143 | impl<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 | |
157 | impl<'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 | |
176 | impl<'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" )] |
196 | impl<'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" )))] |
224 | pub 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" )))] |
257 | pub 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" )] |
269 | impl<'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 | |
289 | mod 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)] |
317 | mod 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 | |