10 个版本
0.2.4 | 2024 年 6 月 1 日 |
---|---|
0.2.3 | 2023 年 10 月 18 日 |
0.2.2 | 2023 年 9 月 25 日 |
0.2.1 | 2021 年 3 月 20 日 |
0.1.3 | 2020 年 8 月 31 日 |
#522 in 异步
164,495 个月下载
用于 142 个 crate (64 个直接使用)
24KB
245 行
async-compat
tokio 和 futures 之间的兼容性适配器。
tokio 和 futures 之间有两种兼容性问题
- Tokio 的类型不能在 tokio 上下文之外使用,所以任何尝试使用它们的操作都会导致 panic。
- 解决方案:如果您将
Compat
适配器应用于一个 future,该 future 将进入由此 crate 启动的全局单线程 tokio 运行时的上下文。这并不意味着 future 在 tokio 运行时上运行 - 这只意味着 future 设置了一个指向全局 tokio 运行时的线程局部变量,以便在内部可以使用 tokio 的类型。
- 解决方案:如果您将
- Tokio 和 futures 有相似但不同的 I/O 特性
AsyncRead
、AsyncWrite
、AsyncBufRead
和AsyncSeek
。- 解决方案:当
Compat
适配器应用于 I/O 类型时,它将实现相反类型的特性行为。这就是您可以在需要基于 futures 的类型的地方使用基于 tokio 的类型,反之亦然的原因。
- 解决方案:当
示例
此程序从 stdin 读取行并将它们回显到 stdout,但它不会正常工作
fn main() -> std::io::Result<()> {
futures::executor::block_on(async {
let stdin = tokio::io::stdin();
let mut stdout = tokio::io::stdout();
// The following line will not work for two reasons:
// 1. Runtime error because stdin and stdout are used outside tokio context.
// 2. Compilation error due to mismatched `AsyncRead` and `AsyncWrite` traits.
futures::io::copy(stdin, &mut stdout).await?;
Ok(())
})
}
为了解决兼容性问题,将 Compat
适配器应用于 stdin
、stdout
和 futures::io::copy()
use async_compat::CompatExt;
fn main() -> std::io::Result<()> {
futures::executor::block_on(async {
let stdin = tokio::io::stdin();
let mut stdout = tokio::io::stdout();
futures::io::copy(stdin.compat(), &mut stdout.compat_mut()).compat().await?;
Ok(())
})
}
还可以将 Compat
应用于传递给 futures::executor::block_on()
的外部 future,而不是 futures::io::copy()
本身。当应用于外部 future 时,单个内部 future 不需要适配器,因为它们现在都在 tokio 上下文中
use async_compat::{Compat, CompatExt};
fn main() -> std::io::Result<()> {
futures::executor::block_on(Compat::new(async {
let stdin = tokio::io::stdin();
let mut stdout = tokio::io::stdout();
futures::io::copy(stdin.compat(), &mut stdout.compat_mut()).await?;
Ok(())
}))
}
兼容适配器可以在任意方向上在基于tokio和基于futures的I/O类型之间进行转换。以下是使用tokio内部基于futures的I/O类型编写相同程序的方法
use async_compat::CompatExt;
use blocking::Unblock;
#[tokio::main]
async fn main() -> std::io::Result<()> {
let mut stdin = Unblock::new(std::io::stdin());
let mut stdout = Unblock::new(std::io::stdout());
tokio::io::copy(&mut stdin.compat_mut(), &mut stdout.compat_mut()).await?;
Ok(())
}
最后,我们可以使用任何基于tokio的crate来运行任何其他异步运行时。以下以reqwest和warp为例
use async_compat::{Compat, CompatExt};
use warp::Filter;
fn main() {
futures::executor::block_on(Compat::new(async {
// Make an HTTP GET request.
let response = reqwest::get("https://www.rust-lang.net.cn").await.unwrap();
println!("{}", response.text().await.unwrap());
// Start an HTTP server.
let routes = warp::any().map(|| "Hello from warp!");
warp::serve(routes).run(([127, 0, 0, 1], 8080)).await;
}))
}
许可协议
许可协议为以下之一
- Apache License,版本2.0(LICENSE-APACHE或http://www.apache.org/licenses/LICENSE-2.0)
- MIT许可协议(LICENSE-MIT或http://opensource.org/licenses/MIT)
任选其一。
贡献
除非您明确说明,否则根据Apache-2.0许可协议定义的,您有意提交并包含在作品中的任何贡献,将按上述方式双许可,不附加任何额外条款或条件。
依赖项
~2–3MB
~48K SLoC