1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//! Procedural macros for channels
extern crate proc_macro;
use TokenStream;
/// Replace identifiers with arbitrary code.
///
/// # Syntax
///
/// ```rust,no_run
/// channels_macros::replace! {
/// replace: { // <- This is the "replace section"
/// [ // <- This is a "replace list"
/// (src1 => dst11)
/// (src2 => dst12)
/// // ...
/// (srcN => dst1N)
/// ]
/// [ // <- This is a "replace list"
/// (src1 => dst21)
/// (src2 => dst22)
/// // ...
/// (srcN => dst2N)
/// ]
/// // ...
/// [ // <- This is a "replace list"
/// (src1 => dstM1)
/// (src2 => dstM2)
/// // ...
/// (srcN => dstMN)
/// ]
/// }
/// code: { // <- This is the "code section"
/// // <actual code>
/// }
/// }
/// ```
///
/// The code inside the code section will be generated `M` times, as many times
/// as there are replace lists. Each time the code is generated, if any identifier
/// from its respective replace list is found, then it will be replaced with the
/// code following its `=>` arrow. For example if `src1` is found, the first time
/// it will be replaced with `dst11`, the second with `dst21`, and so on.
///
/// # Example
///
/// ```rust
/// channels_macros::replace! {
/// replace: {
/// [
/// (my_fn => my_fn_1)
/// ]
/// [
/// (my_fn => my_fn_2)
/// ]
/// [
/// (my_fn => my_fn_3)
/// ]
/// }
/// code: {
/// pub fn my_fn() -> &'static str {
/// stringify!(my_fn)
/// }
/// }
/// }
///
/// assert_eq!(my_fn_1(), "my_fn_1");
/// assert_eq!(my_fn_2(), "my_fn_2");
/// assert_eq!(my_fn_3(), "my_fn_3");
/// ```
///
/// The above will expand to 3 different version of the `my_fn` function all with
/// different names.
///
/// ```rust,no_run
/// pub fn my_fn_1() -> &'static str {
/// stringify!(my_fn_1)
/// }
///
/// pub fn my_fn_2() -> &'static str {
/// stringify!(my_fn_2)
/// }
///
/// pub fn my_fn_3() -> &'static str {
/// stringify!(my_fn_3)
/// }
/// ```
///
/// This means you can generate both synchronous code and asynchronous code and
/// await only where necessary.
///
/// # Example
///
/// ```rust,no_run
/// channels_macros::replace! {
/// replace: {
/// [
/// (_connect => connect_sync)
/// (async =>)
/// (await =>)
/// (TcpStream => std::net::TcpStream)
/// ]
/// [
/// (_connect => connect_async)
/// (async => async)
/// (await => .await)
/// (TcpStream => tokio::net::TcpStream)
/// ]
/// }
/// code: {
/// pub async fn _connect(addr: &str) -> TcpStream {
/// TcpStream::connect(addr) await .unwrap()
/// }
/// }
/// }
///
/// async fn async_fn() {
/// let stream = connect_async("127.0.0.1:8080").await;
/// // ...
/// }
///
/// fn sync_fn() {
/// let stream = connect_sync("127.0.0.1:8080");
/// // ...
/// }
/// ```