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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
// 基于 "op T" 实现一元运算符 "op &T",其中 T 应该是可复制的
//
macro_rules! forward_ref_unop {
    (impl $imp:ident, $method:ident for $t:ty) => {
        forward_ref_unop!(impl $imp, $method for $t,
                #[stable(feature = "rust1", since = "1.0.0")]);
    };
    (impl $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => {
        #[$attr]
        impl $imp for &$t {
            type Output = <$t as $imp>::Output;

            #[inline]
            fn $method(self) -> <$t as $imp>::Output {
                $imp::$method(*self)
            }
        }
    }
}

// 基于 "T op U" 实现二进制运算符 "&T op U","T op &U","&T op &U",其中 T 和 U 应该是可复制的
//
macro_rules! forward_ref_binop {
    (impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
        forward_ref_binop!(impl $imp, $method for $t, $u,
                #[stable(feature = "rust1", since = "1.0.0")]);
    };
    (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
        #[$attr]
        impl<'a> $imp<$u> for &'a $t {
            type Output = <$t as $imp<$u>>::Output;

            #[inline]
            fn $method(self, other: $u) -> <$t as $imp<$u>>::Output {
                $imp::$method(*self, other)
            }
        }

        #[$attr]
        impl $imp<&$u> for $t {
            type Output = <$t as $imp<$u>>::Output;

            #[inline]
            fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output {
                $imp::$method(self, *other)
            }
        }

        #[$attr]
        impl $imp<&$u> for &$t {
            type Output = <$t as $imp<$u>>::Output;

            #[inline]
            fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output {
                $imp::$method(*self, *other)
            }
        }
    }
}

// 基于 "T op= U" 实现 "T op= &U",其中 U 应该是可复制的
//
macro_rules! forward_ref_op_assign {
    (impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
        forward_ref_op_assign!(impl $imp, $method for $t, $u,
                #[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]);
    };
    (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
        #[$attr]
        impl $imp<&$u> for $t {
            #[inline]
            fn $method(&mut self, other: &$u) {
                $imp::$method(self, *other);
            }
        }
    }
}

/// 创建一个与闭包类型相似的零大小类型,但命名为。
macro_rules! impl_fn_for_zst {
    ($(
        $( #[$attr: meta] )*
        struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn =
            |$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty
            $body: block;
    )+) => {
        $(
            $( #[$attr] )*
            struct $Name;

            impl $( <$( $lifetime ),+> )? Fn<($( $ArgTy, )*)> for $Name {
                #[inline]
                extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
                    $body
                }
            }

            impl $( <$( $lifetime ),+> )? FnMut<($( $ArgTy, )*)> for $Name {
                #[inline]
                extern "rust-call" fn call_mut(
                    &mut self,
                    ($( $arg, )*): ($( $ArgTy, )*)
                ) -> $ReturnTy {
                    Fn::call(&*self, ($( $arg, )*))
                }
            }

            impl $( <$( $lifetime ),+> )? FnOnce<($( $ArgTy, )*)> for $Name {
                type Output = $ReturnTy;

                #[inline]
                extern "rust-call" fn call_once(self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
                    Fn::call(&self, ($( $arg, )*))
                }
            }
        )+
    }
}

/// 用于定义 `#[cfg]` if-else 语句的宏。
///
/// `cfg_if` 类似于 `if/elif` C 预处理器宏,允许定义级联的 `#[cfg]` 情况,并发出首先匹配的实现。
///
///
/// 这使您可以方便地提供一长串 `#[cfg]` 代码块,而无需多次重写每个子句。
///
/// # Example
///
/// ```ignore(cannot-test-this-because-non-exported-macro)
/// cfg_if! {
///     if #[cfg(unix)] {
///         fn foo() { /* unix specific functionality */ }
///     } else if #[cfg(target_pointer_width = "32")] {
///         fn foo() { /* non-unix, 32-bit functionality */ }
///     } else {
///         fn foo() { /* fallback implementation */ }
///     }
/// }
///
/// # fn main() {}
/// ```
///
// 这是来自 `cfg_if` crate 的 `cfg_if!` 的副本。
// 如果它曾经被导出的话,递归调用应该使用 $crate。
macro_rules! cfg_if {
    // 将 if/else 链与最后的 `else` 匹配
    (
        $(
            if #[cfg( $i_meta:meta )] { $( $i_tokens:tt )* }
        ) else+
        else { $( $e_tokens:tt )* }
    ) => {
        cfg_if! {
            @__items () ;
            $(
                (( $i_meta ) ( $( $i_tokens )* )) ,
            )+
            (() ( $( $e_tokens )* )) ,
        }
    };

    // 用于发出所有项的内部宏和递归宏
    //
    // 在开始时将所有先前的 cfgs 收集在一个列表中,这样就可以对它们求反。
    // 分号后是所有剩余的项。
    (@__items ( $( $_:meta , )* ) ; ) => {};
    (
        @__items ( $( $no:meta , )* ) ;
        (( $( $yes:meta )? ) ( $( $tokens:tt )* )) ,
        $( $rest:tt , )*
    ) => {
        // 应用适当的 #[cfg],发出一个块内的所有项。
        // #[cfg] 将要求指定所有 `$yes` 匹配器,并且还必须否定所有以前的匹配器。
        //
        #[cfg(all(
            $( $yes , )?
            not(any( $( $no ),* ))
        ))]
        cfg_if! { @__identity $( $tokens )* }

        // 递归发射 `$rest` 中的所有其他项,当我们这样做时,将所有 `$yes` 匹配器添加到 `$no` 匹配器列表中,因为 future 发射也必须否定我们刚刚匹配的所有内容。
        //
        //
        cfg_if! {
            @__items ( $( $no , )* $( $yes , )? ) ;
            $( $rest , )*
        }
    };

    // 使 __apply 适合不同匹配类型的内部宏,因为宏是匹配或扩展内容的。
    //
    (@__identity $( $tokens:tt )* ) => {
        $( $tokens )*
    };
}