Rust异步编程库futures-enum的使用:高效管理多种Future类型的枚举实现
Rust异步编程库futures-enum的使用:高效管理多种Future类型的枚举实现
使用说明
在您的Cargo.toml
中添加以下依赖:
[dependencies]
futures-enum = "0.1.16"
futures = "0.3"
编译器支持:需要rustc 1.36+
示例
use futures_enum::*;
use std::future::Future;
#[derive(Future, Stream, Sink, AsyncRead, AsyncWrite, AsyncSeek, AsyncBufRead)]
enum Either<A, B> {
A(A),
B(B),
}
fn foo(x: i32) -> impl Future<Output = i32> {
if x < 0 {
Either::A(async { 1 })
} else {
Either::B(async move { x })
}
}
futures-enum甚至在依赖仅包含子crate(如futures-core
、futures-io
、futures-sink
等)的情况下也能良好工作。
支持的trait
Future
Stream
Sink
AsyncRead
AsyncWrite
AsyncSeek
AsyncBufRead
完整示例demo
下面是一个更完整的示例,展示如何使用futures-enum来管理多种不同的Future类型:
use futures_enum::*;
use std::future::Future;
use futures::stream::Stream;
use tokio::time::{sleep, Duration};
// 定义一个可以包含多种Future类型的枚举
#[derive(Future)]
enum MyFuture {
Timeout(TimeoutFuture),
Immediate(ImmediateFuture),
}
// 模拟一个超时Future
struct TimeoutFuture;
impl Future for TimeoutFuture {
type Output = String;
fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll<Self::Output> {
sleep(Duration::from_secs(2)).await;
std::task::Poll::Ready("Timeout completed".to_string())
}
}
// 模拟一个立即完成的Future
struct ImmediateFuture;
impl Future for ImmediateFuture {
type Output = String;
fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> std::task::Poll<Self::Output> {
std::task::Poll::Ready("Immediate result".to_string())
}
}
// 根据条件返回不同类型的Future
fn get_future(use_timeout: bool) -> MyFuture {
if use_timeout {
MyFuture::Timeout(TimeoutFuture)
} else {
MyFuture::Immediate(ImmediateFuture)
}
}
#[tokio::main]
async fn main() {
let future1 = get_future(true);
let result1 = future1.await;
println!("Result 1: {}", result1);
let future2 = get_future(false);
let result2 = future2.await;
println!("Result 2: {}", result2);
}
这个示例展示了:
- 定义了一个包含两种不同Future类型的枚举
MyFuture
- 实现了两种不同的Future类型(
TimeoutFuture
和ImmediateFuture
) - 根据条件返回不同类型的Future
- 使用
#[derive(Future)]
自动为枚举实现Future trait - 可以像普通Future一样使用await等待结果
相关项目
- auto_enums: 一个允许通过自动生成的枚举实现多返回类型的库
- derive_utils: 用于轻松编写枚举派生宏的程序宏助手
- io-enum: #[derive(Read, Write, Seek, BufRead)] for enums
- iter-enum: #[derive(Iterator, DoubleEndedIterator, ExactSizeIterator, Extend)] for enums
许可证
根据Apache License, Version 2.0或MIT许可证授权。
1 回复
Rust异步编程库futures-enum的使用:高效管理多种Future类型的枚举实现
以下是基于您提供内容的完整示例demo,展示了futures-enum
库的实际用法:
完整示例代码
use futures_enum::*;
use tokio::time::{sleep, Duration};
use std::future::Ready;
// 1. 定义一个包含多种Future类型的枚举
#[derive(Future)]
enum NetworkOperation {
// HTTP请求
HttpRequest(reqwest::Response),
// 超时计时器
Timeout(tokio::time::Sleep),
// 缓存结果
Cached(std::future::Ready<String>),
}
async fn perform_network_operation() -> NetworkOperation {
// 创建5秒超时
let timeout = sleep(Duration::from_secs(5));
let client = reqwest::Client::new();
// 使用tokio::select!同时等待多个异步操作
tokio::select! {
// 尝试HTTP请求
resp = client.get("https://api.example.com/data").send() => {
match resp {
Ok(response) => NetworkOperation::HttpRequest(response),
Err(_) => {
// 请求失败时返回缓存结果
NetworkOperation::Cached(std::future::ready("cached data".to_string()))
}
}
},
// 超时处理
_ = timeout => NetworkOperation::Timeout(timeout),
}
}
#[tokio::main]
async fn main() {
let operation = perform_network_operation();
// 处理异步操作结果
match operation.await {
NetworkOperation::HttpRequest(response) => {
println!("Got HTTP response: {:?}", response.status());
},
NetworkOperation::Timeout(_) => {
println!("Request timed out");
},
NetworkOperation::Cached(data) => {
println!("Using cached data: {}", data);
}
}
}
示例说明
-
枚举定义:
- 使用
#[derive(Future)]
宏自动为NetworkOperation
枚举实现Future
trait - 包含三种不同的Future类型:HTTP请求、超时计时器和缓存结果
- 使用
-
异步操作:
perform_network_operation
函数演示了如何使用tokio::select!
处理竞争条件- 同时等待HTTP请求和超时计时器
-
结果处理:
- 使用
match
表达式处理不同的异步结果 - 每种情况都有明确的处理逻辑
- 使用
实际应用场景
这个示例展示了futures-enum
在以下场景中的典型用法:
- 网络请求与超时处理
- 主备方案(HTTP请求失败时回退到缓存)
- 多种异步操作的统一处理接口
注意事项
- 确保所有枚举变体返回相同类型,或使用
#[futures_enum]
属性指定不同输出类型 - 为复杂Future手动实现
Unpin
trait - 在no_std环境中需要额外配置