Skip to content
This repository has been archived by the owner on Mar 23, 2024. It is now read-only.

wvwwvwwv/async-trait-fn

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

THE REPOSITORY/CRATE IS NO LONGER MAINTAINED

  • Use the async_fn_in_trait feature (Rust 1.75.0) or async_trait.

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.

  • The return type of an asynchronous trait method or associated function with the unboxed or unboxed_simple attribute is of impl Future<..> instead of Box<dyn Future<..>>.
  • Those attributes have a lot of limitations when used in a large software product due to known bugs in Rust generic associated types: e.g., 95719 and 90696.

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.

use async_trait_fn::{async_trait, unboxed_simple};

#[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.

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

impl SelfToUsize for u32 {
    fn get<'life0, 'async_trait>(&'life0 self) -> Self::RetTypeOfGet<'life0, 'async_trait>
    where
        'life0: 'async_trait,
        Self: 'async_trait,
    {
        async move {
            if let ::core::option::Option::Some(__ret) = ::core::option::Option::None::<usize> {
                return __ret;
            }
            let __self = self;
            let __ret: usize = { *__self as usize };
            #[allow(unreachable_code)]
            __ret
        }
    }
    type RetTypeOfGet<'life0, 'async_trait> = impl ::core::future::Future<Output = usize>
        + ::core::marker::Send
        + 'async_trait
    where
        'life0: 'async_trait,
        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.

use async_trait_fn::{async_trait, unboxed_simple};

#[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.

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

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

About

A fork of async-trait with some useful options

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Rust 100.0%