macro_rules! async_owned_closure_mut { ( { $( $fields:ident : $t:ty = $init:expr ),* $(,)? }; async | $( $args:ident : $a:ty ),* $(,)? | -> $out:ty $e:block ) => { ... }; }
Expand description
Generate a value that is of unnamed closure type implemented with
AsyncFnMut
.
Syntax
Consisted of two parts:
- a block
{};
in which multiple assignmentsfield_name: field_type = field_value
are seperated by,
- an async closure
async |arg1: arg1_type, ...| -> return_type { /* any async code here */ }
Fields or arguments can be empty, i.e.
- empty fields:
{};
- empty arguments:
async | | -> return_type { /* async code and captured variables */ }
(note it’s| |
instead of||
, and the return_type is a must anyway)
Details:
component | rule / usage | trick / caveat |
---|---|---|
field_name | used as unnamed struct’s fields and variable names in async code | rebind when mutation is required |
field_type | owned types or referenced types | only 'static or 'a lifetime allowed |
field_value | any value expression as the initial states / captured variables | |
arg_name | used as variable names in async code (_ is not an ident thus disallowed) | rebind when mutation is required |
arg_type | owned types or referenced types (normally no need to annotate lifetimes ) | 'a is disallowed; but '_ is allowed |
return_type | a must (even when () is returned) |
Also note: arg_types and return_type must correspond to its AsyncFn*
generic types, i.e.
#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]
use async_closure::async_owned_closure_mut;
// correspond to `capture_no_lifetimes::AsyncFnMut<(), usize>`
// note that the concept of arguments is represented by a tuple
async_owned_closure_mut!({}; async | | -> usize { 0 });
// `for<'any> capture_no_lifetimes::AsyncFnMut<(&'any str,), usize>`
// note that single argument is represented by `(type,)` where the comma is important
async_owned_closure_mut!({}; async |_s: &str| -> usize { 0 });
// `for<'any> capture_no_lifetimes::AsyncFnMut<(&'any str, &'any mut Vec<u8>), ()>`
async_owned_closure_mut!({}; async |_s: &str, _buf: &mut Vec<u8>| -> () {});
// etc.
Examples
#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]
use async_closure::async_owned_closure_mut as cb;
let v = vec![];
// zero arguments
cb!({
v: Vec<u8> = v,
}; async | | -> usize {
// to show the type; you don't have to do this
let v: &mut Vec<u8> = v;
v.push(0);
v.len()
});
// one argument and returns unit type
cb!({
v: Vec<u8> = vec![],
}; async |_s: &mut [u8]| -> () { }); // `_` is not an ident, thus not allowed
// two arguments
use std::borrow::Cow;
cb!(
{ v: Vec<u8> = Vec::new() };
async |arg1: &mut [u8], arg2: Cow<'_, str>| -> () { }
);
// three arguments and rebinds the variables
cb!({ v: Vec<u8> = vec![] };
async |arg1: &mut [u8], arg2: Cow<'_, str>, vec: Vec<u8>| -> () {
let mut vec = vec; // rebinding
std::mem::swap(&mut vec, v); // v: &mut Vec<u8>
});