rust 具有较高等级特征绑定参数的异步函数参数不起作用,一种类型比另一种类型更通用

l2osamch  于 2023-01-17  发布在  其他
关注(0)|答案(1)|浏览(92)

我尝试在参数中传递一个函数指针作为回调函数,下面是一个从我的代码中剥离出来的例子:
Rust playground code

use std::{
    fs::File,
    io::{self, BufRead, BufReader},
    path::Path,
};

use futures::{executor, Future}; // 0.3.8

type DigestCallback<R> = fn(&[u8]) -> R;

async fn consume<T>(
    path: T,
    chunk_size: usize,
    digest: DigestCallback<impl Future<Output = ()>>,
) -> io::Result<()>
where
    T: AsRef<Path>,
{
    let file = File::open(path)?;
    let mut reader = BufReader::with_capacity(chunk_size, file);
    loop {
        let buffer = reader.fill_buf()?;
        let length = buffer.len();

        if length == 0 {
            break;
        }

        digest(buffer).await;
        reader.consume(length);
    }

    Ok(())
}

async fn digest_callback(chunk: &[u8]) -> () {
    ()
}

fn main() {
    executor::block_on(consume("my_file.bin", 64, digest_callback));
}

我得到了这个错误

error[E0308]: mismatched types
  --> src/main.rs:41:51
   |
36 | async fn digest_callback(chunk: &[u8]) -> () {
   |                                           -- the `Output` of this `async fn`'s found opaque type
...
41 |     executor::block_on(consume("my_file.bin", 64, digest_callback));
   |                                                   ^^^^^^^^^^^^^^^ one type is more general than the other
   |
   = note: expected fn pointer `for<'r> fn(&'r [u8]) -> impl futures::Future`
              found fn pointer `for<'_> fn(&[u8]) -> impl futures::Future`

当我把它做成Vec<u8>的时候,它可以工作,但是我担心性能问题,因为我正在处理潜在的巨大文件。有人能帮助我理解我做错了什么吗?我应该如何在Rust中做到这一点?有没有更好的方法来实现这一点?
更新:如果我删除Future和异步函数,并将函数类型改为type DigestCallback = for<'a> fn(&'a [u8]) -> ();,它似乎可以工作。但还不知道如何使它与异步函数一起工作
Rust playground code

use std::{
  fs::File,
  io::{self, BufRead, BufReader},
  path::Path,
};

type DigestCallback = for<'a> fn(&'a [u8]) -> ();

fn consume<T>(
  path: T,
  chunk_size: usize,
  digest: DigestCallback,
) -> io::Result<()>
where
  T: AsRef<Path>,
{
  let file = File::open(path)?;
  let mut reader = BufReader::with_capacity(chunk_size, file);
  loop {
    let buffer = reader.fill_buf()?;
    let length = buffer.len();
    
    if length == 0 {
      break;
    }
    
    digest(buffer);
    reader.consume(length);
  }

  Ok(())
}

fn digest_callback(_chunk: &[u8]) -> () {()}

fn main() {
  let _ = consume("my_file.bin", 64, digest_callback);
}
n9vozmp4

n9vozmp41#

你可以试试

fn consume<T, F >(
  path: T,
  chunk_size: usize,
  digest: F,
) -> io::Result<()>
where
  T: AsRef<Path>,
  F: for <'c> Fn(&'c mut Vec<u8>)->Pin<Box<dyn Future<Output = ()> + 'c>>

相关问题