#![doc(html_favicon_url = "https://zng-ui.github.io/res/zng-logo-icon.png")]
#![doc(html_logo_url = "https://zng-ui.github.io/res/zng-logo.png")]
#![doc = include_str!(concat!("../", std::env!("CARGO_PKG_README")))]
#![warn(unused_extern_crates)]
#![warn(missing_docs)]
#[macro_export]
macro_rules! clmv {
($($tt:tt)+) => { $crate::__clmv! { [][][] $($tt)+ } }
}
#[doc(hidden)]
#[macro_export]
macro_rules! __clmv {
([$($done:tt)*][][] mut $($rest:tt)+) => {
$crate::__clmv! {
[$($done)*]
[mut]
[]
$($rest)+
}
};
([$($done:tt)*][$($mut:tt)?][$($deref:tt)*] * $($rest:tt)+) => {
$crate::__clmv! {
[$($done)*]
[$($mut)?]
[$($deref)* *]
$($rest)+
}
};
([$($done:tt)*][$($mut:tt)?][$($deref:tt)*] $var:ident, $($rest:tt)+) => {
$crate::__clmv! {
[
$($done)*
let $($mut)? $var = ( $($deref)* $var ).clone();
]
[]
[]
$($rest)+
}
};
([$($done:tt)*][][] | $($rest:tt)+) => {
{
$($done)*
move | $($rest)+
}
};
([$($done:tt)*][][] || $($rest:tt)+) => {
{
$($done)*
move || $($rest)+
}
};
}
#[macro_export]
macro_rules! async_clmv {
($($tt:tt)+) => {
$crate::__async_clmv! { [][][] $($tt)+ }
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __async_clmv {
([$($done:tt)*][][] mut $($rest:tt)+) => {
$crate::__async_clmv! {
[$($done)*]
[mut]
[]
$($rest)+
}
};
([$($done:tt)*][$($mut:tt)?][$($deref:tt)*] * $($rest:tt)+) => {
$crate::__async_clmv! {
[$($done)*]
[$($mut)?]
[$($deref)* *]
$($rest)+
}
};
([$($done:tt)*][$($mut:tt)?][$($deref:tt)*] $var:ident, $($rest:tt)+) => {
$crate::__async_clmv! {
[
$($done)*
let $($mut)? $var = ( $($deref)* $var ).clone();
]
[]
[]
$($rest)+
}
};
([$($done:tt)*][][] { $($block:tt)* }) => {
{
$($done)*
async move { $($block)* }
}
};
}
#[macro_export]
macro_rules! async_clmv_fn {
($($tt:tt)+) => { $crate::__async_clmv_fn! { [{}{}][][] $($tt)+ } }
}
#[doc(hidden)]
#[macro_export]
macro_rules! __async_clmv_fn {
([$($done:tt)*][][] mut $($rest:tt)+) => {
$crate::__async_clmv_fn! {
[$($done)*]
[mut]
[]
$($rest)+
}
};
([$($done:tt)*][$($mut:tt)?][$($deref:tt)*] * $($rest:tt)+) => {
$crate::__async_clmv_fn! {
[$($done)*]
[$($mut)?]
[$($deref)* *]
$($rest)+
}
};
([$($done:tt)*][$($mut:tt)?][$($deref:tt)*] $var:ident, $($rest:tt)+) => {
$crate::__async_clmv_fn! {
@var
[$($done)*]
[$($mut)?]
[$($deref)*]
$var,
$($rest)+
}
};
(@var [ { $($closure_clones:tt)* }{ $($async_clones:tt)* } ][$($mut:tt)?][$($deref:tt)*] $var:ident, $($rest:tt)+) => {
$crate::__async_clmv_fn! {
[
{
$($closure_clones)*
let $var = ( $($deref)* $var ).clone();
}
{
$($async_clones)*
let $($mut)? $var = $var.clone();
}
]
[]
[]
$($rest)+
}
};
([$($done:tt)*][][] | $($rest:tt)+) => {
$crate::__async_clmv_fn! {
@args
[$($done)*]
[]
$($rest)+
}
};
([ { $($closure_clones:tt)* }{ $($async_clones:tt)* } ][][] || { $($rest:tt)+ }) => {
{
$($closure_clones)*
move || {
$($async_clones)*
async move {
$($rest)+
}
}
}
};
([ { $($closure_clones:tt)* }{ $($async_clones:tt)* } ][][] || $($rest:tt)+ ) => {
{
$($closure_clones)*
move || {
$($async_clones)*
async move {
$($rest)+
}
}
}
};
(@args [ { $($closure_clones:tt)* }{ $($async_clones:tt)* } ] [$($args:tt)*] | { $($rest:tt)+ }) => {
{
$($closure_clones)*
move |$($args)*| {
$($async_clones)*
async move {
$($rest)+
}
}
}
};
(@args [ { $($closure_clones:tt)* }{ $($async_clones:tt)* } ] [$($args:tt)*] | $($rest:tt)+) => {
{
$($closure_clones)*
move |$($args)*| {
$($async_clones)*
async move {
$($rest)+
}
}
}
};
(@args [$($done:tt)*] [$($args:tt)*] $arg_tt:tt $($rest:tt)+) => {
$crate::__async_clmv_fn! {
@args
[$($done)*]
[$($args)* $arg_tt]
$($rest)+
}
};
}
#[macro_export]
macro_rules! async_clmv_fn_once {
($($tt:tt)+) => { $crate::__async_clmv_fn_once! { [][][] $($tt)+ } }
}
#[doc(hidden)]
#[macro_export]
macro_rules! __async_clmv_fn_once {
([$($done:tt)*][][] mut $($rest:tt)+) => {
$crate::__async_clmv_fn_once! {
[$($done)*]
[mut]
[]
$($rest)+
}
};
([$($done:tt)*][$($mut:tt)?][$($deref:tt)*] * $($rest:tt)+) => {
$crate::__async_clmv_fn_once! {
[$($done)*]
[$($mut)?]
[$($deref)* *]
$($rest)+
}
};
([$($done:tt)*][$($mut:tt)?][$($deref:tt)*] $var:ident, $($rest:tt)+) => {
$crate::__async_clmv_fn_once! {
[
$($done)*
let $($mut)? $var = ( $($deref)* $var ).clone();
]
[]
[]
$($rest)+
}
};
([$($done:tt)*][][] | $($rest:tt)+) => {
$crate::__async_clmv_fn_once! {
@args
[$($done)*]
[]
$($rest)+
}
};
([$($done:tt)*][][] || { $($rest:tt)+ }) => {
{
$($done)*
move || {
async move {
$($rest)+
}
}
}
};
([$($done:tt)*][][] || $($rest:tt)+ ) => {
{
$($done)*
move || {
async move {
$($rest)+
}
}
}
};
(@args [$($done:tt)*] [$($args:tt)*] | { $($rest:tt)+ }) => {
{
$($done)*
move |$($args)*| {
async move {
$($rest)+
}
}
}
};
(@args [$($done:tt)*] [$($args:tt)*] | $($rest:tt)+) => {
{
$($done)*
move |$($args)*| {
async move {
$($rest)+
}
}
}
};
(@args [$($done:tt)*] [$($args:tt)*] $arg_tt:tt $($rest:tt)+) => {
$crate::__async_clmv_fn_once! {
@args
[$($done)*]
[$($args)* $arg_tt]
$($rest)+
}
};
}
#[cfg(test)]
#[allow(dead_code)]
#[allow(clippy::ptr_arg)]
mod async_clmv_fn_tests {
use std::{future::ready, sync::Arc};
fn no_clones_no_input() {
let _ = async_clmv_fn!(|| ready(true).await);
}
fn one_clone_no_input(a: &String) {
let _ = async_clmv_fn!(a, || {
let _: String = a;
ready(true).await
});
let _ = a;
}
fn one_clone_with_derefs_no_input(a: &Arc<String>) {
let _ = async_clmv_fn!(**a, || {
let _: String = a;
ready(true).await
});
let _ = a;
}
fn two_derefs_no_input(a: &String, b: Arc<String>) {
let _ = async_clmv_fn!(a, b, || {
let _: String = a;
let _: Arc<String> = b;
ready(true).await
});
let _ = (a, b);
}
fn one_input(a: &String) {
let _ = async_clmv_fn!(a, |_args: u32| {
let _: String = a;
ready(true).await
});
let _ = a;
}
fn two_inputs(a: &String) {
let _ = async_clmv_fn!(a, |_b: u32, _c: Box<dyn std::fmt::Debug>| {
let _: String = a;
ready(true).await
});
let _ = a;
}
}
#[cfg(test)]
#[allow(dead_code)]
#[allow(clippy::ptr_arg)]
mod async_clmv_fn_once_tests {
use std::{future::ready, sync::Arc};
fn no_clones_no_input() {
let _ = async_clmv_fn_once!(|| ready(true).await);
}
fn one_clone_no_input(a: &String) {
let _ = async_clmv_fn_once!(a, || {
let _: String = a;
ready(true).await
});
let _ = a;
}
fn one_clone_with_derefs_no_input(a: &Arc<String>) {
let _ = async_clmv_fn_once!(**a, || {
let _: String = a;
ready(true).await
});
let _ = a;
}
fn two_derefs_no_input(a: &String, b: Arc<String>) {
let _ = async_clmv_fn_once!(a, b, || {
let _: String = a;
let _: Arc<String> = b;
ready(true).await
});
let _ = (a, b);
}
fn one_input(a: &String) {
let _ = async_clmv_fn_once!(a, |_args: u32| {
let _: String = a;
ready(true).await
});
let _ = a;
}
fn two_inputs(a: &String) {
let _ = async_clmv_fn_once!(a, |_b: u32, _c: Box<dyn std::fmt::Debug>| {
let _: String = a;
ready(true).await
});
let _ = a;
}
}