dataforge/
macros.rs

1//! 数据生成宏实现
2
3/// forge! 宏 - 用于生成结构化数据
4#[macro_export]
5macro_rules! forge {
6    ({ $($key:literal => $val:expr),+ $(,)? }) => {{
7        use serde_json::json;
8        json!({
9            $( $key: $val ),+
10        })
11    }};
12}
13
14/// regex! 宏 - 基于正则表达式生成数据
15#[macro_export]
16macro_rules! regex {
17    ($re:literal) => {{
18        use once_cell::sync::Lazy;
19        use rand::Rng;
20        use rand_regex::Regex;
21        use $crate::regions::china::rand_hanzi;
22
23        static CACHED_RE: Lazy<Regex> =
24            Lazy::new(|| Regex::compile($re, 100).expect("Invalid regex pattern"));
25
26        let mut rng = rand::thread_rng();
27        let mut s: String = CACHED_RE.sample_string(&mut rng, 10);
28
29        // 替换Unicode转义序列为实际汉字
30        let re = regex::Regex::new(r"\\[uU][0-9a-fA-F]{4}").unwrap();
31        s = re
32            .replace_all(&s, |_caps: &regex::Captures| -> String {
33                rand_hanzi().to_string()
34            })
35            .to_string();
36
37        if s.is_empty() {
38            let count = rng.gen_range(2..=5);
39            s = (0..count).map(|_| rand_hanzi()).collect::<String>() + "市";
40        }
41
42        s
43    }};
44}
45
46/// pattern! 宏 - 支持正则表达式模式生成
47#[macro_export]
48macro_rules! pattern {
49    ($pattern:literal) => {{
50        use rand::Rng;
51        
52        let mut rng = rand::thread_rng();
53        
54        match $pattern {
55            "1[3-9]\\d{9}" => {
56                let second_digit = rng.gen_range(3..=9);
57                let remaining: String = (0..9).map(|_| rng.gen_range(0..=9).to_string()).collect::<Vec<_>>().join("");
58                format!("1{}{}", second_digit, remaining)
59            },
60            "[a-z]{5,10}@[a-z]{3,8}\\.(com|cn|org)" => {
61                let name_len = rng.gen_range(5..=10);
62                let domain_len = rng.gen_range(3..=8);
63                let name: String = (0..name_len).map(|_| rng.gen_range(b'a'..=b'z') as char).collect();
64                let domain: String = (0..domain_len).map(|_| rng.gen_range(b'a'..=b'z') as char).collect();
65                let tld = ["com", "cn", "org"][rng.gen_range(0..3)];
66                format!("{}@{}.{}", name, domain, tld)
67            },
68            "\\d{17}[0-9X]" => {
69                let first_17: String = (0..17).map(|_| rng.gen_range(0..=9).to_string()).collect::<Vec<_>>().join("");
70                let last_char = if rng.gen_bool(0.9) { rng.gen_range(0..=9).to_string() } else { "X".to_string() };
71                format!("{}{}", first_17, last_char)
72            },
73            _ => $pattern.to_string()
74        }
75    }};
76}
77
78/// rand_num! 宏 - 生成随机数字
79#[macro_export]
80macro_rules! rand_num {
81    ($start:expr, $end:expr) => {{
82        use rand::Rng;
83        let mut rng = rand::thread_rng();
84        rng.gen_range($start..=$end)
85    }};
86}
87
88/// datetime! 宏 - 生成日期时间
89#[macro_export]
90macro_rules! datetime {
91    ("iso") => {{
92        use chrono::Utc;
93        Utc::now().to_rfc3339()
94    }};
95    ("timestamp") => {{
96        use chrono::Utc;
97        Utc::now().timestamp().to_string()
98    }};
99    ($format:literal) => {{
100        use chrono::Utc;
101        Utc::now().format($format).to_string()
102    }};
103}