#async-await #async #await

无 std build_async

Rust 宏,用于统一同步和异步代码库

2 个版本

0.1.1 2024 年 8 月 1 日
0.1.0 2024 年 8 月 1 日
0.0.1 2024 年 7 月 29 日

#2219 in 异步

Download history 310/week @ 2024-07-28 13/week @ 2024-08-04 8/week @ 2024-08-11

每月 331 次下载
2 crates 中使用

GPL-3.0 许可证

11KB
96 行代码

Rust 宏,用于统一同步和异步代码库

async/await 机制已成为处理 I/O 绑定应用程序异步编程的有用工具。然而,它引入了一个重大挑战:异步代码是“传染性的”,意味着不能在同步环境中使用。因此,创建库的开发者必须提供两种实现:同步和异步。异步实现中很大一部分不需要并发,最终变得冗余,使用略微不同的语法描述了完全相同的逻辑。

此库提供了两个宏,#[_async]_await!(...),以解决必须在同步和异步版本中存在的非并发代码的管理问题。这些宏允许您注释此类代码,库将自动生成同步和异步版本。例如,以下代码

use build_async::*;

#[_async]
fn foo() {
    _await!(boo());
    _await!(x.zoo());
}

将展开为

fn foo() {
    boo();
    x.zoo();
}
async fn foo_async() {
    boo_async().await;
    x.zoo_async().await;
}

#[_async] 宏可以应用于任何非异步函数或方法定义,无论是否在 impltrait 定义内部。此宏生成函数的同步和异步版本。_await!(...) 宏可以应用于带有 #[_async] 的函数或方法定义中的显式函数或方法调用。根据上下文(同步或异步),_await!(...) 扩展为同步调用或使用 await 的异步调用。为了避免名称冲突,此机制生成的异步版本名称被赋予后缀 _async

这是一个更全面的例子,展示了如何在 traitimpl 定义中使用这些宏。该示例还展示了它们如何与同步和异步特性和类型集成,即使不遵循 _async 命名约定。

use build_async::*;

trait Writer {
    type Error; 

    #[_async]
    fn write(&mut self, bytes: &[u8]) -> Result<usize, Self::Error> {
        unimplemented!()
    }
}                   
                    
impl<T: std::io::Write> Writer for T {
    type Error = std::io::Error;

    fn write(&mut self, bytes: &[u8]) -> Result<usize, Self::Error> {
        self.write(self, bytes)
    }
}

impl<T: tokio::io::AsyncWriteExt> Writer for T {
    type Error = tokio::io::Error;

    async fn write_async(&mut self, bytes: &[u8]) -> Result<usize, Self::Error> {
        self.write(self, bytes).await
    }
}

trait Encoder {
    type Error;

    #[_async]
    fn encode_bool(&mut self, value: &bool) -> Result<(), Self::Error> {
        _await!(self.encode_u8(&(*value).into()))
    }   
    ...
}

trait Encode {
    #[_async]
    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error>;
}   

impl<T: Encode> Encode for Box<T> {
    #[_async]
    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), E::Error> {
        _await!(T::encode(self, encoder))?;
        Ok(())
    }
}

_await 宏假设它所应用的功能既有同步版本也有异步版本,其中异步版本是异步的,并且仅通过 _async 后缀在名称上有所不同。如果现有代码库中不遵循这些约定,可以实现如 Writer 之类的适配器来弥合差距。

有关实际示例,请参阅 crate cerditorustbif

最后,关于这个库的一个特殊细节:我们建议使用 use build_async::*; 隐式导入宏。否则,显式导入语句将如下所示:use build_async::{_async, _await_sync, _await_async}; 这可能会令人困惑,因为它提出了诸如“_await 在哪里?”和“为什么我需要导入 _await_sync_await_async?”等问题。原因是 _await 是一个“伪宏”。它看起来和感觉像一个宏,但它从未被定义过。当 _async 宏遇到 _await 时,它会根据上下文将其替换为 _await_sync_await_async

依赖关系

~260–710KB
~17K SLoC