【发布时间】:2021-08-16 14:58:03
【问题描述】:
我正在尝试在目录中递归查找带有扩展名的文件,这是我当前的实现:
use futures::future::BoxFuture;
use futures::Stream;
use std::io::ErrorKind;
use std::pin::Pin;
use std::result;
use tokio::fs::read_dir;
use tokio::sync::mpsc::{channel, Receiver, Sender};
use tokio_stream::wrappers::ReceiverStream;
type Result<T> = result::Result<T, std::io::Error>;
type FileNameStream = Pin<Box<dyn Stream<Item = Result<String>> + Send + Sync + 'static>>;
async fn list_all(root_path: String, ext: String) -> Result<FileNameStream> {
async fn one_level(path: String, tx: Sender<Result<String>>, ext: String) -> Result<()> {
let mut dir = read_dir(path).await?;
let mut files: Vec<String> = Vec::new();
while let Some(child) = dir.next_entry().await? {
if let Some(child_path) = child.path().to_str() {
if child.metadata().await?.is_dir() {
tokio::spawn(async {
one_level(child_path.to_string(), tx.clone(), ext.clone()).await;
});
} else {
if child_path.ends_with(&ext.clone()) {
files.push(child_path.to_string())
}
}
} else {
tx.send(Err(std::io::Error::new(
ErrorKind::Other,
"Invalid path".to_string(),
)));
}
}
for file in files {
tx.send(Ok(file));
}
Ok(())
}
let (tx, rx): (Sender<Result<String>>, Receiver<Result<String>>) = channel(2);
tokio::spawn(async {
one_level(root_path, tx, ext).await;
});
Ok(Box::pin(ReceiverStream::new(rx)))
}
我不太明白为什么编译器会抱怨:
14 | async fn one_level(path: String, tx: Sender<Result<String>>, ext: String) -> Result<()> {
| ^^^^^^^^^^
|
note: ...which requires borrow-checking `list_all::{closure#0}::one_level`...
--> src/main.rs:14:5
.....
.....
= note: ...which requires evaluating trait selection obligation `for<'r, 's, 't0> {std::future::ResumeTy, &'r str, std::string::String, &'s tokio::sync::mpsc::Sender<std::result::Result<std::string::String, std::io::Error>>, tokio::sync::mpsc::Sender<std::result::Result<std::string::String, std::io::Error>>, &'t0 std::string::String, impl futures::Future, ()}: std::marker::Send`...
= note: ...which again requires computing type of `list_all::{closure#0}::one_level::{opaque#0}`, completing the cycle
= note: cycle used when evaluating trait selection obligation `{std::future::ResumeTy, std::string::String, tokio::sync::mpsc::Sender<std::result::Result<std::string::String, std::io::Error>>, impl futures::Future, ()}: std::marker::Send`
是否可以将这样的递归函数定义为异步?我可以通过tokio::spwan并行列出目录的过程并加快速度吗?
【问题讨论】:
标签: recursion rust async-await