tokio_util/io/read_arc.rs
1use std::io;
2use std::mem::MaybeUninit;
3use std::sync::Arc;
4use tokio::io::{AsyncRead, AsyncReadExt};
5
6/// Read data from an `AsyncRead` into an `Arc`.
7///
8/// This uses `Arc::new_uninit_slice` and reads into the resulting uninitialized `Arc`.
9///
10/// # Example
11///
12/// ```
13/// # #[tokio::main]
14/// # async fn main() -> std::io::Result<()> {
15/// use tokio_util::io::read_exact_arc;
16///
17/// let read = tokio::io::repeat(42);
18///
19/// let arc = read_exact_arc(read, 4).await?;
20///
21/// assert_eq!(&arc[..], &[42; 4]);
22/// # Ok(())
23/// # }
24/// ```
25pub async fn read_exact_arc<R: AsyncRead>(read: R, len: usize) -> io::Result<Arc<[u8]>> {
26 tokio::pin!(read);
27 // TODO(MSRV 1.82): When bumping MSRV, switch to `Arc::new_uninit_slice(len)`. The following is
28 // equivalent, and generates the same assembly, but works without requiring MSRV 1.82.
29 let arc: Arc<[MaybeUninit<u8>]> = (0..len).map(|_| MaybeUninit::uninit()).collect();
30 // TODO(MSRV future): Use `Arc::get_mut_unchecked` once it's stabilized.
31 // SAFETY: We're the only owner of the `Arc`, and we keep the `Arc` valid throughout this loop
32 // as we write through this reference.
33 let mut buf = unsafe { &mut *(Arc::as_ptr(&arc) as *mut [MaybeUninit<u8>]) };
34 while !buf.is_empty() {
35 if read.read_buf(&mut buf).await? == 0 {
36 return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "early eof"));
37 }
38 }
39 // TODO(MSRV 1.82): When bumping MSRV, switch to `arc.assume_init()`. The following is
40 // equivalent, and generates the same assembly, but works without requiring MSRV 1.82.
41 // SAFETY: This changes `[MaybeUninit<u8>]` to `[u8]`, and we've initialized all the bytes in
42 // the loop above.
43 Ok(unsafe { Arc::from_raw(Arc::into_raw(arc) as *const [u8]) })
44}