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-corefutures-iofutures-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);
}

这个示例展示了:

  1. 定义了一个包含两种不同Future类型的枚举MyFuture
  2. 实现了两种不同的Future类型(TimeoutFutureImmediateFuture)
  3. 根据条件返回不同类型的Future
  4. 使用#[derive(Future)]自动为枚举实现Future trait
  5. 可以像普通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);
        }
    }
}

示例说明

  1. 枚举定义

    • 使用#[derive(Future)]宏自动为NetworkOperation枚举实现Future trait
    • 包含三种不同的Future类型:HTTP请求、超时计时器和缓存结果
  2. 异步操作

    • perform_network_operation函数演示了如何使用tokio::select!处理竞争条件
    • 同时等待HTTP请求和超时计时器
  3. 结果处理

    • 使用match表达式处理不同的异步结果
    • 每种情况都有明确的处理逻辑

实际应用场景

这个示例展示了futures-enum在以下场景中的典型用法:

  1. 网络请求与超时处理
  2. 主备方案(HTTP请求失败时回退到缓存)
  3. 多种异步操作的统一处理接口

注意事项

  1. 确保所有枚举变体返回相同类型,或使用#[futures_enum]属性指定不同输出类型
  2. 为复杂Future手动实现Unpin trait
  3. 在no_std环境中需要额外配置
回到顶部