Wrapping an AsyncRead

Viewed 627

I can't seem to get the compiler to let me wrap a Tokio AsyncRead:

use std::io::Result;
use core::pin::Pin;
use core::task::{Context, Poll};

use tokio::io::AsyncRead;

struct Wrapper<T: AsyncRead>{
    inner: T
}

impl<T: AsyncRead> AsyncRead for Wrapper<T> {
    fn poll_read(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut [u8]
    ) -> Poll<Result<usize>> {
        self.inner.poll_read(cx, buf)
    }
}

This seems like it should compile but the compiler complains that I didn't include the proper trait bound even though poll_read is available through AsyncRead: Playground Link

error[E0599]: no method named `poll_read` found for type parameter `T` in the current scope
  --> src/lib.rs:17:20
   |
17 |         self.inner.poll_read(cx, buf)
   |                    ^^^^^^^^^ method not found in `T`
   |
   = help: items from traits can only be used if the type parameter is bounded by the trait

What am I doing wrong?

1 Answers

Look at self in the signature for poll_read:

fn poll_read(
    self: Pin<&mut Self>, // Self is pinned!
    cx: &mut Context,
    buf: &mut [u8]
) -> Poll<Result<usize>>

Self is pinned, meaning that poll_read can only be called on Pin<&mut T>'s! self.inner is of type T which is why the compiler cannot find poll_read on it. To fix this we have to somehow get pinned access to the field.

There's a whole section of the Rust Pin documentation on this and a whole crate dedicated to solving this issue.

Related