clone-macro 1.0.0

Super simple utility macro for cloning before moving into a move closure/block.
Documentation
  • Coverage
  • 100%
    2 out of 2 items documented1 out of 1 items with examples
  • Size
  • Source code size: 8.72 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 1.14 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 12s Average build duration of successful builds.
  • all releases: 10s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • jquesada2016/clone-macro-rs
    6 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • jquesada2016

clone-macro

A simple macro to make cloning data before passing it into a move closure or block.

This macro is intentionally designed to be compatible with rustfmt formatting.

You can use this macro throughout your crate without needing to explicitly import it every time as follows:

#[macro_use]
extern crate clone_macro;

/* ... */

clone!(/* ... */);

Otherwise, you can use it as normal.

use clone_macro::clone;

/* ... */
clone!(/* ... */);

Syntax

The clone! macro takes a comma separated list of either one of two forms which can have an optional mut prefix modifier, followed by an arbitrary expression.

For example, the following is a valid call


let a = 1;
let b = 2;

clone!([mut a, b], ());

and desugars down to:

let a = 1;
let b = 2;

{
    let mut a = a.clone();
    let b = b.clone();

    ()
};

The clone list can also take a second form, which is an arbitrary expression followed by as and the name of the variable. For example:



let s = "Hello, there!";

clone!([{ s.len() } as len], move || {
    assert_eq!(len, "Hello, there!".len());
});

The above desugars into:


let s = "Hello, there!";

{
    let len = "Hello, there!".len();

    move || {
        assert_eq!(len, "Hello, there!".len());
    }
};

This macro is most useful when the second argument is a closure, and is what it is intended to work with, though not strictly so.

All forms mentioned above can be mixed and matched, including adding a mut modifier for the second form as:

mut { $expr } as $ident

Examples

Basic Usage

use clone_macro::clone;

let s = "You are a beautiful being!".to_string();

let c = clone!([s], move || {
    println!("{s}");
});

c();

// `s` wasn't directly moved, rather, cloned first, then moved; therefore,
// we can still use `s`
assert_eq!(s.as_str(), "You are a beautiful being!");

We can also declare the cloned move as mut:

use clone_macro::clone;

let a = 7;
let b = 0;
let d = 12;

le
t mut c = clone!([a, mut b, d], move || {
    b = 42 - a - d;

    println!("a + b + d = {}", a + b + d);
});

c();

assert_eq!(a, 7);
assert_eq!(b, 0);
assert_eq!(d, 12);

Advanced Usage

We can clone arbitrary expressions:

use clone_macro::clone;

struct MyStruct {
    some_field: String,
}

let s = MyStruct {
    some_field: "Beyond measure.".to_string(),
};

let mut c = clone!([{ s.some_field } as some_field, mut { s.some_field } as mut_some_field], move || {
    mut_some_field.clear();

    assert!(mut_some_field.is_empty());

    assert_eq!(some_field.as_str(), "Beyond measure.");
});

c();

assert_eq!(s.some_field.as_str(), "Beyond measure.");

License: MIT