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() {}