Suppose I have an async function foo that returns some value. The value returned is different after each call (this could be e.g. something that reads chunks of data from a file or a random number generator).
I want to implement a wrapper struct around foo that implements AsyncRead. The wrapper reads the values from foo, processes them in some way, and then places them into the user-supplied buffer.
Here's what I've tried:
use futures::io::AsyncRead;
use pin_utils::pin_mut;
use std::io;
use std::pin::Pin;
use std::task::Context;
use std::task::Poll;
async fn foo() -> u8 {
b'x'
}
pub struct FooReader;
impl AsyncRead for FooReader {
fn poll_read(self: Pin<&mut Self>, ctx: &mut Context<'_>, buf: &mut [u8])
-> Poll<io::Result<usize>>
{
if buf.is_empty() {
return Poll::Ready(Ok(0));
}
match foo().poll() { // << problem here
Poll::Ready(byte) => {
buf[0] = byte;
Poll::Ready(Ok(1))
},
Poll::Pending => Poll::Pending,
}
}
}
This obviously doesn't compile because poll() wants a pinned value. Now, how do I pin the future returned by foo? I tried various combinations of Box::pin, Pin::new and pin_mut! but none of them worked.
Also, am I supposed to store the Future in my struct FooReader until it's ready? Or am I free to drop it after each call, even if it's pending?
EDIT: The following works:
let mut future: Pin<Box<dyn Future<Output = u8>>> = Box::pin(foo());
match future.as_mut().poll(ctx) {
...
}
For some reason I have to give future an explicit type annotation, otherwise it doesn't compile (somehow the compiler is making confusion between impl Future and dyn Future).
Even if it works, I would still like to know if this is the "official" way to do it.