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