How to async read into &mut [mem::MaybeUninit<u8>] with Tokio?

I have a reference to an uninitialized memory buffer in form of &mut [mem::MaybeUninit<u8>] and an AsyncRead implementation. I want to asynchronously read some data and write them to the buffer.
How to do that with Tokio?

async fn read_into(src: impl AsyncRead, dest: &mut [mem::MaybeUninit<u8>]) -> usize {
   /// how to asynchronously copy available data from `src` to `dest` and return the number of bytes copied?

I found the read_buf method in AsyncReadExt which looks like something I should probably use, however, that method does not accept my uninit buffer, but a BufMut implementation.

I have the following ideas:

  1. wrap my buffer into a custom struct and implement BufMut for it by hand.
  2. maybe Tokio or some other crate already provides such implementation? Looked at BufRead for a while, which can be initialized with my buffer, but it does not implement BufMut :frowning:

I don't have control over the creation of the uninitialized buffer, I get it from another crate, and I want to avoid additional copying (sure I could read into a temporary buffer and then copy, but this is a performance critical path). Therefore I don't think I can use bytes::BytesMut, because it looks like it maintains its own buffer and cannot wrap an existing one.

Thanks for help

This is easiest to do by calling poll_read. To do a single read, you can do this:

let mut read_buf = tokio::io::ReadBuf::uninit(dest);
poll_fn(|cx| src.poll_read(cx, &mut read_buf)).await?;

The number of bytes read will be available as read_buf.filled().len(), and the bytes themselves as read_buf.filled(). To read until the entire slice is filled, do this:

let len = dest.len();
let mut read_buf = tokio::io::ReadBuf::uninit(dest);
while read_buf.filled().len() < len {
    poll_fn(|cx| src.poll_read(cx, &mut read_buf)).await?;

This uses futures::future::poll_fn to do the reading.

Your idea with the wrapper struct that implements BufMut would also work.


Your idea with the wrapper struct that implements BufMut would also work.

Yeah, but why do this, when one can avoid it?
Big, big, thank you! I wasn't aware of poll_fn. Good that I asked.