async-trait-fn

Cargo Crates.io

This is a fork of the widely acclaimed async-trait crate. This crate adds two experimental attributes to async-trait that can be applied to asynchronous trait methods and associated functions to avoid heap memory allocation.

Note that, the main author of async-trait did not want to add such options, therefore this fork will not be merged into the upstream.

See async-trait for more details about async-trait.

Examples

unboxed turns an asynchronous trait method or associated function into a synchronous one returning an impl Future<..> by adding a generic associated type for the method or associated function.

```rust use asynctraitfn::{asynctrait, unboxedsimple};

[async_trait]

pub trait SelfToUsize { #[unboxed] async fn get(&self) -> usize; }

[async_trait]

impl SelfToUsize for u32 { #[unboxed] async fn get(&self) -> usize { *self as usize } } ```

The compiler generates the following code.

```rust pub trait SelfToUsize { fn get<'life0, 'asynctrait>(&'life0 self) -> Self::RetTypeOfGet<'life0, 'asynctrait> where 'life0: 'asynctrait, Self: 'asynctrait; type RetTypeOfGet<'life0, 'asynctrait>: ::core::future::Future + ::core::marker::Send + 'asynctrait where 'life0: 'asynctrait, Self: 'asynctrait, Self: 'life0; }

impl SelfToUsize for u32 { fn get<'life0, 'asynctrait>(&'life0 self) -> Self::RetTypeOfGet<'life0, 'asynctrait> where 'life0: 'asynctrait, Self: 'asynctrait, { async move { if let ::core::option::Option::Some(ret) = ::core::option::Option::None:: { return _ret; } let _self = self; let _ret: usize = { *self as usize }; #[allow(unreachablecode)] _ret } } type RetTypeOfGet<'life0, 'asynctrait> = impl ::core::future::Future + ::core::marker::Send + 'asynctrait where 'life0: 'asynctrait, Self: 'async_trait, Self: 'life0 ; } ```

unboxed_simple is identical to unboxed except that it substitutes all the lifetime bounds and parameters with a single, fixed lifetime: 'async_trait. When code around an unboxed attribute does not compile, unboxed_simple might help.

```rust use asynctraitfn::{asynctrait, unboxedsimple};

[async_trait]

pub trait AddOther { #[unboxed_simple] async fn add<'s, 'o>(&'a self, other: &'o usize) -> usize; }

[async_trait]

impl AddOther for u32 { #[unboxed_simple] async fn add<'s, 'o>(&'a self, other: &'o usize) -> usize { (*self as usize) + *other } }

```

The above code expands to the following code; all the lifetime parameters are replaced with 'async_trait.

```rust pub trait AddOther { fn add<'asynctrait>( &'asynctrait self, other: &'asynctrait usize, ) -> Self::RetTypeOfAdd<'asynctrait> where Self: 'asynctrait; type RetTypeOfAdd<'asynctrait>: ::core::future::Future + ::core::marker::Send + 'asynctrait where Self: 'asynctrait, Self: 'async_trait; }

impl AddOther for u32 { fn add<'asynctrait>( &'asynctrait self, other: &'asynctrait usize, ) -> Self::RetTypeOfAdd<'asynctrait> where Self: 'asynctrait, { async move { if let ::core::option::Option::Some(ret) = ::core::option::Option::None:: { return _ret; } let _self = self; let other = other; let _ret: usize = { (*self as usize) + *other }; #[allow(unreachablecode)] _ret } } type RetTypeOfAdd<'asynctrait> = impl ::core::future::Future + ::core::marker::Send + 'asynctrait where Self: 'asynctrait, Self: 'asynctrait; } ```