Rust 自定义 Macro

实现一个 json!

实现

 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
#[derive(Debug, PartialEq)]
pub enum Json {
    Null,
    Number(f64),
    Str(String),
    Array(Vec<Json>),
    Object(HashMap<String, Json>),
}

impl From<String> for Json {
    fn from(value: String) -> Self {
        Str(value)
    }
}

impl From<&str> for Json {
    fn from(value: &str) -> Self {
        Str(value.into())
    }
}

impl From<i32> for Json {
    fn from(value: i32) -> Self {
        Number(value as f64)
    }
}

#[macro_export]
macro_rules! json {
    (null) => {Json::Null};
    ([ $( $value:tt ),* ]) => {
        Json::Array(
            vec![$( json!($value) ),*]
        )
    };
    ({ $( $key:tt : $value:tt ),* }) => {
        Json::Object(
            vec![$( ($key.to_string(), json!($value)) ),*].into_iter().collect()
        )
    };
    ($value:tt) => {
        Json::from($value)
    }
}

调试方法

  • 在项目下执行命令,切换为 nightly toolchain
1
rustup override set nightly-x86_64-apple-darwin
  • main.rs 中开启 trace_macros
1
2
3
#![feature(trace_macros)]

trace_macros!(true);
  • 在编译时,控制台就会输出宏展开信息。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
note: trace_macro
  --> src/main.rs:23:13
   |
23 |     let v = json!(["1", "2", "3"]);
   |             ^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: expanding `json! { ["1", "2", "3"] }`
   = note: to `Json :: Array(vec! [json! ("1"), json! ("2"), json! ("3")])`
   = note: expanding `vec! { json! ("1"), json! ("2"), json! ("3") }`
   = note: to `< [_] > ::
           into_vec(#[rustc_box] $crate :: boxed :: Box ::
           new([json! ("1"), json! ("2"), json! ("3")]))`
   = note: expanding `json! { "1" }`
   = note: to `Json :: from("1")`
   = note: expanding `json! { "2" }`
   = note: to `Json :: from("2")`
   = note: expanding `json! { "3" }`
   = note: to `Json :: from("3")`

示例代码

github

0%