dataforge/regions/
china.rs

1//! 中国行政区划数据模块
2
3use once_cell::sync::Lazy;
4use lazy_static::lazy_static;
5use rand::prelude::SliceRandom;
6use rand::Rng;
7use serde_json::Value;
8use std::fs;
9
10/// 从文件加载省份数据
11static PROVINCES: Lazy<Vec<String>> = Lazy::new(|| {
12    load_data_from_file("data/regions/china/provinces.txt")
13});
14
15/// 从文件加载街道后缀数据
16static STREET_SUFFIXES: Lazy<Vec<String>> = Lazy::new(|| {
17    load_data_from_file("data/regions/china/street_suffixes.txt")
18});
19
20/// 从文件加载数据的辅助函数
21fn load_data_from_file(file_path: &str) -> Vec<String> {
22    match fs::read_to_string(file_path) {
23        Ok(content) => content
24            .lines()
25            .map(|line| line.trim().to_string())
26            .filter(|line| !line.is_empty())
27            .collect(),
28        Err(_) => {
29            // 如果文件不存在,返回默认数据
30            match file_path {
31                "data/regions/china/provinces.txt" => vec![
32                    "北京市".to_string(), "天津市".to_string(), "河北省".to_string(),
33                    "山西省".to_string(), "内蒙古自治区".to_string(), "辽宁省".to_string(),
34                    "吉林省".to_string(), "黑龙江省".to_string(), "上海市".to_string(),
35                    "江苏省".to_string(), "浙江省".to_string(), "安徽省".to_string()
36                ],
37                "data/regions/china/street_suffixes.txt" => vec![
38                    "街".to_string(), "路".to_string(), "巷".to_string(),
39                    "大道".to_string(), "胡同".to_string(), "里".to_string()
40                ],
41                _ => vec!["Default".to_string()]
42            }
43        }
44    }
45}
46
47lazy_static! {
48    /// GB2312 一级汉字(3755个)和二级汉字(3008个)的 Unicode 范围
49    static ref GB2312_RANGES: [(u32, u32); 72] = [
50        // 一级汉字(16-55区)
51        (0xB0A1, 0xB0FE), // 16区
52        (0xB1A1, 0xB1FE), // 17区
53        (0xB2A1, 0xB2FE), // 18区
54        (0xB3A1, 0xB3FE), // 19区
55        (0xB4A1, 0xB4FE), // 20区
56        (0xB5A1, 0xB5FE), // 21区
57        (0xB6A1, 0xB6FE), // 22区
58        (0xB7A1, 0xB7FE), // 23区
59        (0xB8A1, 0xB8FE), // 24区
60        (0xB9A1, 0xB9FE), // 25区
61        (0xBAA1, 0xBAFE), // 26区
62        (0xBBA1, 0xBBFE), // 27区
63        (0xBCA1, 0xBCFE), // 28区
64        (0xBDA1, 0xBDFE), // 29区
65        (0xBEA1, 0xBEFE), // 30区
66        (0xBFA1, 0xBFFE), // 31区
67        (0xC0A1, 0xC0FE), // 32区
68        (0xC1A1, 0xC1FE), // 33区
69        (0xC2A1, 0xC2FE), // 34区
70        (0xC3A1, 0xC3FE), // 35区
71        (0xC4A1, 0xC4FE), // 36区
72        (0xC5A1, 0xC5FE), // 37区
73        (0xC6A1, 0xC6FE), // 38区
74        (0xC7A1, 0xC7FE), // 39区
75        (0xC8A1, 0xC8FE), // 40区
76        (0xC9A1, 0xC9FE), // 41区
77        (0xCAA1, 0xCAFE), // 42区
78        (0xCBA1, 0xCBFE), // 43区
79        (0xCCA1, 0xCCFE), // 44区
80        (0xCDA1, 0xCDFE), // 45区
81        (0xCEA1, 0xCEFE), // 46区
82        (0xCFA1, 0xCFFE), // 47区
83        (0xD0A1, 0xD0FE), // 48区
84        (0xD1A1, 0xD1FE), // 49区
85        (0xD2A1, 0xD2FE), // 50区
86        (0xD3A1, 0xD3FE), // 51区
87        (0xD4A1, 0xD4FE), // 52区
88        (0xD5A1, 0xD5FE), // 53区
89        (0xD6A1, 0xD6FE), // 54区
90        (0xD7A1, 0xD7FE), // 55区
91
92        // 二级汉字(56-87区)
93        (0xD8A1, 0xD8FE), // 56区
94        (0xD9A1, 0xD9FE), // 57区
95        (0xDAA1, 0xDAFE), // 58区
96        (0xDBA1, 0xDBFE), // 59区
97        (0xDCA1, 0xDCFE), // 60区
98        (0xDDA1, 0xDDFE), // 61区
99        (0xDEA1, 0xDEFE), // 62区
100        (0xDFA1, 0xDFFE), // 63区
101        (0xE0A1, 0xE0FE), // 64区
102        (0xE1A1, 0xE1FE), // 65区
103        (0xE2A1, 0xE2FE), // 66区
104        (0xE3A1, 0xE3FE), // 67区
105        (0xE4A1, 0xE4FE), // 68区
106        (0xE5A1, 0xE5FE), // 69区
107        (0xE6A1, 0xE6FE), // 70区
108        (0xE7A1, 0xE7FE), // 71区
109        (0xE8A1, 0xE8FE), // 72区
110        (0xE9A1, 0xE9FE), // 73区
111        (0xEAA1, 0xEAFE), // 74区
112        (0xEBA1, 0xEBFE), // 75区
113        (0xECA1, 0xECFE), // 76区
114        (0xEDA1, 0xEDFE), // 77区
115        (0xEEA1, 0xEEFE), // 78区
116        (0xEFA1, 0xEFFE), // 79区
117        (0xF0A1, 0xF0FE), // 80区
118        (0xF1A1, 0xF1FE), // 81区
119        (0xF2A1, 0xF2FE), // 82区
120        (0xF3A1, 0xF3FE), // 83区
121        (0xF4A1, 0xF4FE), // 84区
122        (0xF5A1, 0xF5FE), // 85区
123        (0xF6A1, 0xF6FE), // 86区
124        (0xF7A1, 0xF7FE)  // 87区
125    ];
126}
127
128/// 生成随机省份
129pub fn province() -> Value {
130    let mut rng = rand::thread_rng();
131    Value::String(PROVINCES.choose(&mut rng).unwrap().clone())
132}
133
134/// 生成指定长度的中文街道前缀
135pub fn rand_chinese(range: std::ops::Range<usize>) -> String {
136    let len = rand::Rng::gen_range(&mut rand::thread_rng(), range);
137    (0..len).map(|_| rand_hanzi()).collect()
138}
139
140/// 生成随机中文街道
141pub fn random_street() -> Value {
142    let mut rng = rand::thread_rng();
143    // 街道名前缀长度(2-4个汉字)
144    let prefix_len = rng.gen_range(2..=4);
145    let suffix = STREET_SUFFIXES.choose(&mut rng).unwrap();
146
147    let prefix: String = (0..prefix_len).map(|_| rand_hanzi()).collect();
148
149    Value::String(format!("{}{}", prefix, suffix))
150}
151
152/// 生成单个汉字(常用字范围), 限制到常用汉字范围(0x4E00-0x62FF)包含约5000常用字
153pub fn rand_hanzi() -> char {
154    let mut rng = rand::thread_rng();
155    // let unicode_chars: Vec<char> = (0..1)
156    //     .map(|_| rng.gen_range(0x4E00..=0x9FA5) as u32)
157    //     .map(std::char::from_u32)
158    //     .flatten()
159    //     .collect();
160    // unicode_chars.into_iter().collect()
161
162    let code = rng.gen_range(0x4E00..=0x9FA5);
163    std::char::from_u32(code).unwrap_or('汉')
164}
165
166/// 生成随机的Unicode字符
167/// 生成范围在0x4E00到0x9FFF之间的随机数,将其转换为Unicode字符,并将它们收集到一个Vec<char>中。
168/// 最后,通过迭代Vec<char>并将字符收集到一个String中,生成了一个随机的Unicode字符串
169///
170/// 请注意,这个方法生成了基本的CJK(中日韩)字符范围内的Unicode字符
171pub fn generate_random_unicode() -> String {
172    let mut rng = rand::thread_rng();
173    let unicode_chars: Vec<char> = (0..1)
174        .map(|_| rng.gen_range(0x4E00..=0x9FFF) as u32)
175        .map(std::char::from_u32)
176        .flatten()
177        .collect();
178
179    unicode_chars.into_iter().collect()
180}
181
182pub fn is_uncommon_hanzi(c: char) -> bool {
183    let code = c as u32;
184
185    !GB2312_RANGES.iter().any(|&(start, end)| code >= start && code <= end)
186        // || code.is_ascii()  // 排除ASCII字符
187        || c.is_ascii_punctuation() // 排除标点
188}