dataforge/generators/
address.rs1use rand::seq::SliceRandom;
4use rand::Rng;
5use once_cell::sync::Lazy;
6use std::fs;
7
8const PROVINCES: &[&str] = &[
10 "北京市", "天津市", "河北省", "山西省", "内蒙古自治区",
11 "辽宁省", "吉林省", "黑龙江省", "上海市", "江苏省",
12 "浙江省", "安徽省", "福建省", "江西省", "山东省",
13 "河南省", "湖北省", "湖南省", "广东省", "广西壮族自治区",
14 "海南省", "重庆市", "四川省", "贵州省", "云南省",
15 "西藏自治区", "陕西省", "甘肃省", "青海省", "宁夏回族自治区",
16 "新疆维吾尔自治区"
17];
18
19const CITY_SUFFIXES: &[&str] = &["市", "县", "区"];
21
22const STREET_SUFFIXES: &[&str] = &["街", "路", "大道", "巷", "胡同", "里"];
24
25static STREET_PREFIXES: Lazy<Vec<String>> = Lazy::new(|| {
27 load_data_from_file("data/generators/address/street_prefixes.txt")
28});
29
30static US_STATES: Lazy<Vec<String>> = Lazy::new(|| {
32 load_data_from_file("data/generators/address/us_states.txt")
33});
34
35static US_CITIES: Lazy<Vec<String>> = Lazy::new(|| {
37 load_data_from_file("data/generators/address/us_cities.txt")
38});
39
40fn load_data_from_file(file_path: &str) -> Vec<String> {
42 match fs::read_to_string(file_path) {
43 Ok(content) => content
44 .lines()
45 .map(|line| line.trim().to_string())
46 .filter(|line| !line.is_empty())
47 .collect(),
48 Err(_) => {
49 match file_path {
51 "data/generators/address/street_prefixes.txt" => vec![
52 "长安".to_string(), "中山".to_string(), "人民".to_string(),
53 "解放".to_string(), "建设".to_string(), "和平".to_string()
54 ],
55 "data/generators/address/us_states.txt" => vec![
56 "California".to_string(), "Texas".to_string(), "Florida".to_string(),
57 "New York".to_string(), "Illinois".to_string(), "Pennsylvania".to_string()
58 ],
59 "data/generators/address/us_cities.txt" => vec![
60 "New York".to_string(), "Los Angeles".to_string(), "Chicago".to_string(),
61 "Houston".to_string(), "Phoenix".to_string(), "Philadelphia".to_string()
62 ],
63 _ => vec!["Default".to_string()]
64 }
65 }
66 }
67}
68
69pub fn zh_province() -> String {
71 let mut rng = rand::thread_rng();
72 PROVINCES.choose(&mut rng).unwrap().to_string()
73}
74
75pub fn zh_city() -> String {
77 let mut rng = rand::thread_rng();
78 let prefix_len = rng.gen_range(2..=4);
79 let mut city = String::new();
80
81 for _ in 0..prefix_len {
83 city.push(crate::regions::china::rand_hanzi());
84 }
85
86 city.push_str(CITY_SUFFIXES.choose(&mut rng).unwrap());
88 city
89}
90
91pub fn zh_street() -> String {
93 let mut rng = rand::thread_rng();
94 let prefix = STREET_PREFIXES.choose(&mut rng).unwrap();
95 let suffix = STREET_SUFFIXES.choose(&mut rng).unwrap();
96 format!("{}{}", prefix, suffix)
97}
98
99pub fn zh_address() -> String {
101 let mut rng = rand::thread_rng();
102 let province = zh_province();
103 let city = zh_city();
104 let street = zh_street();
105 let number = rng.gen_range(1..=999);
106
107 format!("{}{}{}{number}号", province, city, street, number = number)
108}
109
110pub fn postal_code() -> String {
112 let mut rng = rand::thread_rng();
113 let first_digit = rng.gen_range(1..=8);
115 let remaining = rng.gen_range(10000..=99999);
116 format!("{}{:05}", first_digit, remaining)
117}
118
119pub fn us_state() -> String {
121 let mut rng = rand::thread_rng();
122 US_STATES.choose(&mut rng).unwrap().clone()
123}
124
125pub fn us_city() -> String {
127 let mut rng = rand::thread_rng();
128 US_CITIES.choose(&mut rng).unwrap().clone()
129}
130
131pub fn us_postal_code() -> String {
133 let mut rng = rand::thread_rng();
134 format!("{:05}", rng.gen_range(10000..=99999))
135}
136
137pub fn zh_postal_code() -> String {
139 postal_code()
140}
141
142pub fn coordinate() -> (f64, f64) {
144 coordinates()
145}
146
147pub fn china_coordinate() -> (f64, f64) {
149 let mut rng = rand::thread_rng();
150 let lat = rng.gen_range(18.0..=54.0); let lng = rng.gen_range(73.0..=135.0); (lat, lng)
153}
154
155pub fn us_address() -> String {
157 let mut rng = rand::thread_rng();
158 let number = rng.gen_range(1..=9999);
159 let street_names = ["Main St", "Oak Ave", "Pine Rd", "Elm Dr", "Maple Ln"];
160 let street = street_names.choose(&mut rng).unwrap();
161 let city = us_city();
162 let state = us_state();
163 let zip = rng.gen_range(10000..=99999);
164
165 format!("{} {}, {}, {} {}", number, street, city, state, zip)
166}
167
168pub fn longitude() -> f64 {
170 let mut rng = rand::thread_rng();
171 rng.gen_range(-180.0..=180.0)
172}
173
174pub fn latitude() -> f64 {
176 let mut rng = rand::thread_rng();
177 rng.gen_range(-90.0..=90.0)
178}
179
180pub fn coordinates() -> (f64, f64) {
182 (latitude(), longitude())
183}
184
185#[cfg(test)]
186mod tests {
187 use super::*;
188
189 #[test]
190 fn test_zh_province() {
191 let province = zh_province();
192 assert!(!province.is_empty());
193 assert!(PROVINCES.contains(&province.as_str()));
194 }
195
196 #[test]
197 fn test_zh_address() {
198 let address = zh_address();
199 assert!(!address.is_empty());
200 assert!(address.contains("号"));
201 }
202
203 #[test]
204 fn test_postal_code() {
205 let code = postal_code();
206 assert_eq!(code.len(), 6);
207 assert!(code.chars().all(|c| c.is_ascii_digit()));
208 }
209
210 #[test]
211 fn test_coordinates() {
212 let (lat, lng) = coordinates();
213
214 assert!(lng >= -180.0 && lng <= 180.0);
216 assert!(lat >= -90.0 && lat <= 90.0, "lat is: {}", lat);
217 }
218}