1#[macro_export]
12macro_rules! let_clone {
13 ($self:ident . { $($cloneable:ident $(: $rename:ident)?),+$(,)? }, $($tail:tt)+) => {
14 $crate::let_clone!($($self.$cloneable $(: $rename)?),+);
15 $crate::let_clone!($($tail)+);
16 };
17 ($self:ident . { $($cloneable:ident $(: $rename:ident)?),+$(,)? }) => {
18 $crate::let_clone!($($self.$cloneable $(: $rename)?),+);
19 };
20
21 ($($cloneable:ident).+ $(: $rename:ident)?, $($tail:tt)+) => {
22 $crate::let_clone!(@inner $($cloneable).+;;$($rename)?);
23 $crate::let_clone!($($tail)+);
24 };
25 ($($cloneable:ident).+ $(: $rename:ident)? $(,)?) => {
26 $crate::let_clone!(@inner $($cloneable).+;;$($rename)?);
27 };
28
29 (@inner $root:ident$(.$nested:ident)+; $($tail:ident).*; $($rename:ident)?) => {
30 $crate::let_clone!(@inner $($nested).+; $($tail.)*$root; $($rename)?);
31 };
32 (@inner $cloneable:ident; $($nested:ident).*; $rename:ident) => {
33 let $rename = $($nested.)*$cloneable.clone();
34 };
35 (@inner $cloneable:ident; $($nested:ident).*; ) => {
36 let $cloneable = $($nested.)*$cloneable.clone();
37 };
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43
44 #[test]
45 fn it_works() {
46 #[derive(Clone)]
47 struct Foo;
48 struct Bar {
49 baz: String,
50 boo: String,
51 }
52 impl Foo {
53 fn foobar(self, _baz: String) {}
54
55 fn run(&self, bar: &Bar) {
56 std::thread::spawn({
57 let_clone!(self: this, bar.baz, bar.{baz: baz2, boo}, bar.boo: boo2);
58 let _ = (baz2, boo, boo2);
59 move || this.foobar(baz)
60 });
61 }
62 }
63 Foo.run(&Bar {
64 baz: "baz".into(),
65 boo: "boo".into(),
66 });
67 }
68}