Allocating TUN device using async-std File

I used async_std::fs::File to create a tun device:

async fn new_tun() -> File {
    let file = OpenOptions::new()
            .read(true)
            .write(true)
            .open("/dev/net/tun")
            .await?;

    // ifreq is generated using bindgen and a wrapper around `if.h` header file
    let req = ifreq::new((IFF_TUN | IFF_NO_PI) as _).unwrap();

    // tunsetiff is generated using `ioctl_write_int!(tunsetiff, b'T', 202)`
    let ioctl_ret = unsafe { tunsetiff(file.as_raw_fd(), &req as *const ifreq as u64) }.unwrap();

    // ip commands to up device

    file
}

However, reading from tun file always returns zero bytes without waiting for incoming data events:

pub async fn read(&mut self, buf: &mut [u8]) {
    let mut buf = vec![0u8; 1024];
    loop {
        // Issue: always is Ready and returns immediately with zero bytes
        let n = self.file.read(&mut buf).await.unwrap();
        if n > 0 {
            // ...
        } else if n == 0 {
            // Always n is zero!
        }
        buf.clear();
    }
}

The loop causes a 100% CPU usage. Any idea to fix the issue?

A read call on a File from async-std is implemented as performing an ordinary blocking read on the file on some other threadpool. Due to this, you almost certainly have the same issue if you were using an std file.

Are you sure the issue isn't that buf.clear() in the loop?

The problem is before running buf.clear, it seems the problem is that the file is returning EOF. Maybe I should implement a custom type for tun and implement Read and Write for it.

as @alice mentioned, clearing the buffer truncates the vector to the length of zero:

let mut v = vec![0u8; 1024];
println!("{}", v.len()); // 1024
v.clear();
println!("{}", v.len()); // 0

So, after the first iteration, the length of buffer is zero, and read returns immediately with zero bytes.