perspective_client/utils/
clone.rs

1// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
2// ┃ ██████ ██████ ██████       █      █      █      █      █ █▄  ▀███ █       ┃
3// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█  ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄  ▀█ █ ▀▀▀▀▀ ┃
4// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄   █ ▄▄▄▄▄ ┃
5// ┃ █      ██████ █  ▀█▄       █ ██████      █      ███▌▐███ ███████▄ █       ┃
6// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
7// ┃ Copyright (c) 2017, the Perspective Authors.                              ┃
8// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
9// ┃ This file is part of the Perspective library, distributed under the terms ┃
10// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
11// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
12
13/// A helper to for the pattern `let x2 = x;` necessary to clone structs
14/// destined for an `async` or `'static` closure stack.  This is like `move || {
15/// .. }` or `move async { .. }`, but for clone semantics.  `clone!()` works
16/// with symbols as well as properties and methods, using the last symbol name
17/// in the method chain, or an alias via `x = ...` syntax.
18///
19/// # Examples
20///
21/// ```
22/// clone!(my_struct.option_method(), alias = my_struct.prop1.my_rc);
23/// println!("These bindings exist: {:?} {:?}", option_method, alias);
24/// ```
25#[doc(hidden)]
26#[macro_export]
27macro_rules! clone {
28    (impl @bind $i:tt { $($orig:tt)* } { }) => {
29        let $i = $($orig)*.clone();
30    };
31
32    (impl @bind $i:tt { $($orig:tt)* } { @mut }) => {
33        let mut $i = $($orig)*.clone();
34    };
35
36    (impl @bind $i:tt { $($orig:tt)* } { $binder:tt }) => {
37        let $binder = $($orig)*.clone();
38    };
39
40    (impl @bind $i:tt { $($orig:tt)* } { @mut $binder:tt }) => {
41        let mut $binder = $($orig)*.clone();
42    };
43
44
45    (impl @expand { $($orig:tt)* } { $($binder:tt)* } $i:tt) => {
46        $crate::clone!(impl @bind $i { $($orig)* $i } { $($binder)* });
47    };
48
49
50    (impl @expand { $($orig:tt)* } { $($binder:tt)* } mut $i:tt) => {
51        $crate::clone!(impl @bind $i { $($orig)* $i } { @mut $($binder)* });
52    };
53
54    (impl @expand { $($orig:tt)* } { $($binder:tt)* } $i:tt ()) => {
55        $crate::clone!(impl @bind $i { $($orig)* $i () } { $($binder)* });
56    };
57
58    (impl @expand { $($orig:tt)* } { $($binder:tt)* } $i:tt . 0) => {
59        $crate::clone!(impl @bind $i { $($orig)* $i . 0 } { $($binder)* });
60    };
61
62    (impl @expand { $($orig:tt)* } { $($binder:tt)* } $i:tt . 1) => {
63        $crate::clone!(impl @bind $i { $($orig)* $i . 1 } { $($binder)* });
64    };
65
66    (impl @expand { $($orig:tt)* } { $($binder:tt)* } $i:tt . 2) => {
67        $crate::clone!(impl @bind $i { $($orig)* $i . 2 } { $($binder)* });
68    };
69
70    (impl @expand { $($orig:tt)* } { $($binder:tt)* } $i:tt . 3) => {
71        $crate::clone!(impl @bind $i { $($orig)* $i . 3 } { $($binder)* });
72    };
73
74    (impl @expand { $($orig:tt)* } { $($binder:tt)* } mut $i:tt = $($tail:tt)+) => {
75        $crate::clone!(impl @expand { $($orig)* } { @mut $i } $($tail)+);
76    };
77
78    (impl @expand { $($orig:tt)* } { $($binder:tt)* } $i:tt = $($tail:tt)+) => {
79        $crate::clone!(impl @expand { $($orig)* } { $i } $($tail)+);
80    };
81
82    (impl @expand { $($orig:tt)* } { $($binder:tt)* } $i:tt $($tail:tt)+) => {
83        $crate::clone!(impl @expand { $($orig)* $i } { $($binder)* } $($tail)+)
84    };
85
86    (impl @context { $($orig:tt)* } $tail:tt) => {
87        $crate::clone!(impl @expand { } { } $($orig)* $tail)
88    };
89
90    (impl @context { $($orig:tt)* } , $($tail:tt)+) => {
91        $crate::clone!(impl @expand { } { } $($orig)*);
92        $crate::clone!(impl @context { } $($tail)+);
93    };
94
95    (impl @context { $($orig:tt)* } $i:tt $($tail:tt)+) => {
96        $crate::clone!(impl @context { $($orig)* $i } $($tail)+)
97    };
98
99    ($($tail:tt)+) => {
100        $crate::clone!(impl @context { } $($tail)+);
101    }
102}
103
104#[doc(hidden)]
105#[macro_export]
106macro_rules! asyncfn {
107    // Munch function args
108    (impl @bindings { $($args:tt)* } { $($clones:tt)* } !{ } | $($tail:tt)+) => {{
109        move |$($args)*| {
110            $($clones)*
111            async move {
112                $($tail)+
113            }
114        }
115    }};
116
117    (impl @bindings { $($args:tt)* } { $($clones:tt)* } !{ } $i:tt $($tail:tt)+) => {
118        $crate::asyncfn!(impl @bindings { $($args)* $i } { $($clones)* } !{ } $($tail)+)
119    };
120
121    // Munch function start
122    (impl @context { $($clones:tt)* } !{ } async move || $($tail:tt)+) => {{
123        move || {
124            $($clones)*
125            async move {
126                $($tail)+
127            }
128        }
129    }};
130
131    (impl @context { $($clones:tt)* } !{ } async move | $($tail:tt)+) => {
132        $crate::asyncfn!(impl @bindings { } { $($clones)* } !{ } $($tail)+)
133    };
134
135    // Munch clone bindings
136    (impl @context { $($clones:tt)* } !{ $($stack:tt)* } , $($tail:tt)+) => {{
137        $crate::asyncfn!(impl @context { $crate::clone!($($stack)*); $($clones)* } !{ } $($tail)+)
138    }};
139
140    (impl @context { $($clones:tt)* } !{ $($stack:tt)* } $i:tt $($tail:tt)+) => {
141        $crate::asyncfn!(impl @context { $($clones)* } !{ $($stack)* $i } $($tail)+)
142    };
143
144    // Root
145    ($($tail:tt)+) => {
146        $crate::asyncfn!(impl @context { } !{ } $($tail)+)
147    }
148}