Search code examples
rustrust-tokio

Why do I get "no method named `read` found" when using AsyncRead for a reference to a byte array?


I'm using Tokio to create a Framed connection over TCP. I'm trying to substitute an in-memory buffer for the TCP connection in test code, but I'm running into the problem which the code below exemplifies.

use tokio::{self, io::{AsyncRead, AsyncReadExt}};

#[tokio::main]
async fn main() {
    let data = &[1u8, 2, 3, 4, 5];
    let buf = &mut [0u8; 5];

    let _ = data.read(buf).await;
}

I get this response from the compiler:

warning: unused import: `AsyncRead`
 --> src/lib.rs:1:24
  |
1 | use tokio::{self, io::{AsyncRead, AsyncReadExt}};
  |                        ^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

error[E0599]: no method named `read` found for type `&[u8; 5]` in the current scope
 --> src/lib.rs:8:18
  |
8 |     let _ = data.read(buf).await;
  |                  ^^^^ method not found in `&[u8; 5]`
  |
  = note: the method `read` exists but the following trait bounds were not satisfied:
          `&[u8; 5] : tokio::io::util::async_read_ext::AsyncReadExt`
          `[u8; 5] : tokio::io::util::async_read_ext::AsyncReadExt`
          `[u8] : tokio::io::util::async_read_ext::AsyncReadExt`

Solution

  • The trait is not implemented on arrays or references to arrays, only on slices:

    use tokio::{self, io::AsyncReadExt}; // 0.2.10
    
    #[tokio::main]
    async fn main() {
        let data = &[1u8, 2, 3, 4, 5];
        let buf = &mut [0u8; 5];
    
        let _ = data.as_ref().read(buf).await;
    
        // Or
        // let _ = (&data[..]).read(buf).await;
    
        // Or
        // let _ = (data as &[_]).read(buf).await;
    
        // Or define `data` as a slice originally.
    }
    

    See also: