sui_rust/ch02/
s8_metaprogramming.rs

1//! 第二章:Rust核心概念
2//! 2.7 元编程
3//!
4//! 内容包括:
5//!  - 反射
6//!  - 宏
7//!     - Rust 编译过程再解析
8//!     - 声明宏
9//!         - 标准库内置宏
10//!         - 自定义宏
11//!     - 过程宏
12//!         - bang 宏
13//!         - derive 宏
14//!         - 属性宏
15//!     - 过程宏实际项目的应用
16//!         - dervie_more
17//!         - metric
18//!         - reflect
19//!
20//!
21
22/**
23
24  # 动态自省
25
26  示例1:
27
28  [https://doc.rust-lang.org/std/any/index.html](https://doc.rust-lang.org/std/any/index.html)
29
30   示例2:
31
32   ```rust
33
34   use std::any::Any;
35
36   trait Foo: Any {
37       fn as_any(&self) -> &Any;
38   }
39
40   impl<T: Any> Foo for T {
41       fn as_any(&self) -> &Any {
42           self
43       }
44   }
45
46   struct Bar {}
47
48   struct Baz {}
49
50   impl PartialEq for Foo {
51       fn eq(&self, other: &Foo) -> bool {
52           let me = self.as_any();
53           let you = other.as_any();
54           if me.is::<Bar>() && you.is::<Bar>() {
55               true
56           } else if me.is::<Baz>() && you.is::<Baz>() {
57               true
58           } else {
59               false
60           }
61       }
62   }
63
64   fn main() {
65       let bar: Bar = Bar {};
66       let baz: Baz = Baz {};
67       let foo1: &Foo = &bar;
68       let foo2: &Foo = &baz;
69       println!("{:?}", foo1 == foo2);
70   }
71
72   ```
73
74   示例 3:
75
76   ```rust
77       use std::any::Any;
78       struct UnStatic<'a> { x: &'a i32 }
79       fn main() {
80           let a = 42;
81           let v = UnStatic { x: &a };
82           let mut any: &Any;
83           //any = &v;  // Compile Error!
84       }
85   ```
86
87   修正:
88
89   ```rust
90   use std::any::Any;
91   struct UnStatic<'a> { x: &'a i32 }
92   static ANSWER: i32 = 42;
93   fn main() {
94       let v = UnStatic { x: &ANSWER };
95       let mut a: &Any;
96       a = &v;
97       assert!(a.is::<UnStatic>());
98   }
99   ```
100
101   示例4:
102
103   oso 库应用
104
105   [https://github.com/osohq/oso/blob/main/languages/rust/oso/src/host/class.rs](https://github.com/osohq/oso/blob/main/languages/rust/oso/src/host/class.rs)
106
107   示例 5:
108
109   bevy_reflect 库应用
110
111   [https://github.com/bevyengine/bevy/blob/main/crates/bevy_reflect/src/lib.rs](https://github.com/bevyengine/bevy/blob/main/crates/bevy_reflect/src/lib.rs)
112
113*/
114pub fn any_refection() {}
115
116/**
117  # 声明宏
118
119  宏展开命令: cargo rustc -- -Z unstable-options --pretty=expanded
120
121  示例1:
122
123  ```rust
124    macro_rules! unless {
125        ($arg:expr, $branch:expr) => ( if !$arg { $branch };);
126    }
127    fn cmp(a: i32, b: i32) {
128        unless!( a > b, {
129            println!("{} < {}", a, b);
130        });
131    }
132    fn main() {
133        let (a, b) = (1, 2);
134        cmp(a, b);
135    }
136  ```
137
138  支持 token 类型:
139
140  ```text
141        item — an item, like a function, struct, module, etc.
142        block — a block (i.e. a block of statements and/or an expression, surrounded by braces)
143        stmt — a statement
144        pat — a pattern
145        expr — an expression
146        ty — a type
147        ident — an identifier
148        path — a path (e.g., foo, ::std::mem::replace, transmute::<_, int>, …)
149        meta — a meta item; the things that go inside #[...] and #![...] attributes
150        tt — a single token tree
151        vis — a possibly empty Visibility qualifier
152  ```
153
154
155  示例2:
156
157  ```rust
158
159    macro_rules! hashmap {
160        ($($key:expr => $value:expr),* ) => {
161            {
162                let mut _map = ::std::collections::HashMap::new();
163                $(
164                    _map.insert($key, $value);
165                )*
166                _map
167            }
168        };
169    }
170    fn main(){
171        let map = hashmap!{
172            "a" => 1,
173            "b" => 2
174        //  "c" => 3, // V1.0不支持结尾有逗号
175        };
176        assert_eq!(map["a"], 1);
177    }
178
179  ```
180
181  示例3:
182
183  ```rust
184    macro_rules! hashmap {
185        ($($key:expr => $value:expr,)*) =>
186            {  hashmap!($($key => $value),*) };
187        ($($key:expr => $value:expr),* ) => {
188            {
189                let mut _map = ::std::collections::HashMap::new();
190                $(
191                    _map.insert($key, $value);
192                )*
193            _map
194        }
195    };
196    }
197    fn main(){
198        let map = hashmap!{
199            "a" => 1,
200            "b" => 2,
201            "c" => 3,
202        };
203        assert_eq!(map["a"], 1);
204    }
205  ```
206
207  示例4:
208
209  ```rust
210    macro_rules! hashmap {
211        ($($key:expr => $value:expr),* $(,)*) => {
212            {
213                let mut _map = ::std::collections::HashMap::new();
214                $(
215                    _map.insert($key, $value);
216                )*
217                _map
218            }
219    };
220    }
221    fn main(){
222        let map = hashmap!{
223            "a" => 1,
224            "b" => 2,
225            "c" => 3,
226        };
227        assert_eq!(map["a"], 1);
228    }
229
230  ```
231
232  示例5:
233
234  ```rust
235    macro_rules! unit {
236        ($($x:tt)*) => (());
237    }
238    macro_rules! count {
239        ($($key:expr),*) => (<[()]>::len(&[$(unit!($key)),*]));
240    }
241    macro_rules! hashmap {
242        ($($key:expr => $value:expr),* $(,)*) => {
243            {
244            let _cap = count!($($key),*);
245            let mut _map
246                = ::std::collections::HashMap::with_capacity(_cap);
247            $(
248                _map.insert($key, $value);
249            )*
250            _map
251        }
252    };
253    }
254    fn main(){
255        let map = hashmap!{
256            "a" => 1,
257            "b" => 2,
258            "c" => 3,
259        };
260        assert_eq!(map["a"], 1);
261    }
262
263  ```
264
265  示例6:
266
267  ```rust
268    macro_rules! hashmap {
269        (@unit $($x:tt)*) => (());
270        (@count $($rest:expr),*) =>
271            (<[()]>::len(&[$(hashmap!(@unit $rest)),*]));
272        ($($key:expr => $value:expr),* $(,)*) => {
273            {
274                let _cap = hashmap!(@count $($key),*);
275                let mut _map =
276                    ::std::collections::HashMap::with_capacity(_cap);
277            $(
278                _map.insert($key, $value);
279            )*
280            _map
281        }
282    };
283    }
284    fn main(){
285    let map = hashmap!{
286        "a" => 1,
287        "b" => 2,
288        "c" => 3,
289    };
290    assert_eq!(map["a"], 1);
291    }
292  ```
293
294  示例7:
295
296  ```rust
297    macro_rules! sum {
298        ($e:expr) => ({
299            let a = 2;
300            $e + a
301        })
302    }
303    fn main(){
304        // error[E0425]: cannot find value `a` in this scope
305        let four = sum!(a);
306    }
307  ```
308*/
309pub fn declarative_macros() {}
310
311/**
312
313介绍:[serde.rs](https://serde.rs/)
314
315参阅 :  [https://github.com/ZhangHanDong/proc_codegen](https://github.com/ZhangHanDong/proc_codegen)
316
317过程宏三件套:
318
319- [syn](https://github.com/dtolnay/syn)
320- [quote](https://github.com/dtolnay/quote)
321- [proc-macro2](https://github.com/alexcrichton/proc-macro2)
322
323示例:封装 Diesel 方便 crud
324
325```rust
326
327    // find_by_or!{ Person -> people::[name:String || company_name:String]   }
328
329    use super::*;
330
331    pub struct DbOpByOrBy {
332        pub model: Type,
333        pub table: Ident,
334        pub bracket_token: token::Bracket,
335        pub content: FieldContentOr,
336    }
337
338    pub struct FieldContentOr {
339        pub name1: Ident,
340        pub ty1: Type,
341        pub name2: Ident,
342        pub ty2: Type,
343    }
344
345    impl Parse for DbOpByOrBy {
346        fn parse(input: ParseStream) -> Result<Self> {
347            let content;
348            let model: Type = input.parse()?;
349            input.parse::<Token![->]>()?;
350            let table: Ident = input.parse()?;
351            input.parse::<Token![::]>()?;
352            let bracket_token = bracketed!(content in input);
353            let content = content.parse()?;
354            Ok(DbOpByOrBy {
355                model,
356                table,
357                bracket_token,
358                content,
359            })
360        }
361    }
362
363    impl Parse for FieldContentOr {
364        fn parse(input: ParseStream) -> Result<Self> {
365            let name1: Ident = input.parse()?;
366            input.parse::<Token![:]>()?;
367            let ty1: Type = input.parse()?;
368            input.parse::<Token![||]>()?;
369            let name2: Ident = input.parse()?;
370            input.parse::<Token![:]>()?;
371            let ty2: Type = input.parse()?;
372            Ok(FieldContentOr {
373                name1,
374                ty1,
375                name2,
376                ty2,
377            })
378        }
379    }
380
381    // in lib.rs
382
383    // find_by_or!{ Person -> people::[name:String || company_name:String]   }
384
385    #[proc_macro]
386    pub fn find_by_or(input: TokenStream) -> TokenStream {
387        let DbOpByOrBy {
388            model,
389            table,
390            bracket_token,
391            content,
392        } = parse_macro_input!(input as DbOpByOrBy);
393        let (name1, name2) = (content.name1, content.name2);
394        let (ty1, ty2) = (content.ty1, content.ty2);
395        let fn_name = format!("find_by_{}_or_{}", name1, name2);
396        let fn_name = Ident::new(&fn_name, proc_macro2::Span::call_site());
397
398        let expanded = quote! {
399            impl #model {
400                pub fn #fn_name(conn: &PgConnection, #name1: #ty1, #name2: #ty2) -> QueryResult<#model> {
401                    #table::table
402                    .filter(#table::dsl::#name1.eq(#name1))
403                    .or_filter(#table::dsl::#name2.eq(#name2))
404                    .get_result(conn)
405                }
406            }
407        };
408        TokenStream::from(expanded)
409    }
410
411
412```
413
414有用的第三方库:
415
416- [derive_more](https://github.com/JelteF/derive_more)
417
418*/
419pub fn derive_proc_macros() {}
420
421/**
422
423    # 属性宏
424
425    案例:[magnet/metered-rs](https://github.com/magnet/metered-rs)
426
427    有用的第三方库介绍:[darling](https://github.com/TedDriggs/darling)
428
429    案例: [elichai/log-derive](https://github.com/elichai/log-derive)
430
431
432*/
433pub fn attributes_proc_macros() {}