/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 | | } |