#![doc(html_favicon_url = "https://raw.githubusercontent.com/zng-ui/zng/main/examples/image/res/zng-logo-icon.png")]
#![doc(html_logo_url = "https://raw.githubusercontent.com/zng-ui/zng/main/examples/image/res/zng-logo.png")]
//!
//! Macros for declaring clone-move closures and async blocks.
//!
//! # Crate
//!
#![doc = include_str!(concat!("../", std::env!("CARGO_PKG_README")))]
#![warn(unused_extern_crates)]
#![warn(missing_docs)]
/// Clone move closure.
///
/// A common pattern when creating `'static` closures is to capture clones by `move`, this way the closure is `'static`
/// and the cloned values are still available after creating the closure. This macro facilitates this pattern.
///
/// # Examples
///
/// In the example `bar` is *clone-moved* into the `'static` closure given to `foo`.
///
/// ```
/// # use zng_clone_move::clmv;
/// fn foo(mut f: impl FnMut(bool) + 'static) {
/// f(true);
/// }
///
/// let bar = "Cool!".to_owned();
/// foo(clmv!(bar, |p| {
/// if p { println!("cloned: {bar}") }
/// }));
///
/// println!("original: {bar}");
/// ```
///
/// Expands to:
///
/// ```
/// # use zng_clone_move::clmv;
/// # fn foo(mut f: impl FnMut(bool) + 'static) {
/// # f(true);
/// # }
/// # let bar = "Cool!".to_owned();
/// foo({
/// let bar = bar.clone();
/// move |p| {
/// if p { println!("cloned: {bar}") }
/// }
/// });
/// # println!("original: {bar}");
/// ```
///
/// # Other Patterns
///
/// Sometimes you want to clone an *inner deref* of the value, or you want the clone to be `mut`, you can annotate the
/// variables cloned to achieve these effects.
///
/// ```
/// # use zng_clone_move::clmv;
/// # use std::sync::Arc;
/// fn foo(mut f: impl FnMut(bool) + 'static) {
/// f(true);
/// }
///
/// let bar = Arc::new("Cool!".to_string());
/// foo(clmv!(mut *bar, |p| {
/// bar.push_str("!");
/// if p { println!("cloned String not Arc: {bar}") }
/// }));
///
/// println!("original: {bar}");
/// ```
///
/// Expands to:
///
/// ```
/// # use zng_clone_move::clmv;
/// # use std::sync::Arc;
/// # fn foo(mut f: impl FnMut(bool) + 'static) {
/// # f(true);
/// # }
/// # let bar = Arc::new("Cool!".to_string());
/// foo({
/// let mut bar = (*bar).clone();
/// move |p| {
/// bar.push_str("!");
/// if p { println!("cloned String not Arc: {bar}") }
/// }
/// });
/// # println!("original: {bar}");
/// ```
///
/// # Async
///
/// See [`async_clmv_fn!`] for creating `async` closures or [`async_clmv!`] for creating clone move futures.
#[macro_export]
macro_rules! clmv {
($($tt:tt)+) => { $crate::__clmv! { [][][] $($tt)+ } }
}
#[doc(hidden)]
#[macro_export]
macro_rules! __clmv {
// match start of mut var
([$($done:tt)*][][] mut $($rest:tt)+) => {
$crate::__clmv! {
[$($done)*]
[mut]
[]
$($rest)+
}
};
// match one var deref (*)
([$($done:tt)*][$($mut:tt)?][$($deref:tt)*] * $($rest:tt)+) => {
$crate::__clmv! {
[$($done)*]
[$($mut)?]
[$($deref)* *]
$($rest)+
}
};
// match end of a variable
([$($done:tt)*][$($mut:tt)?][$($deref:tt)*] $var:ident, $($rest:tt)+) => {
$crate::__clmv! {
[
$($done)*
let $($mut)? $var = ( $($deref)* $var ).clone();
]
[]
[]
$($rest)+
}
};
// match start of closure
([$($done:tt)*][][] | $($rest:tt)+) => {
{
$($done)*
move | $($rest)+
}
};
// match start of closure without input
([$($done:tt)*][][] || $($rest:tt)+) => {
{
$($done)*
move || $($rest)+
}
};
}
/// Async clone move block.
///
/// This macro is similar to [`clmv!`], but creates a future instead of a closure.
///
/// A common pattern when creating `'static` futures is to capture clones by `move`, this way the future is `'static`
/// and the cloned values are still available after creating the future. This macro facilitates this pattern.
///
/// # Examples
///
/// In the example `bar` is *clone-moved* into the `'static` future given to `foo`.
///
/// ```
/// # use std::{future::Future, time::Duration};
/// # use zng_clone_move::*;
/// # trait TimeUnits { fn ms(self) -> Duration; }
/// # impl TimeUnits for u64 { fn ms(self) -> Duration { Duration::from_millis(self) } }
/// # async fn deadline(_d: Duration) { }
/// async fn foo(mut f: impl Future