dataforge/generators/
internet.rs

1//! 互联网相关数据生成器模块
2
3use rand::seq::SliceRandom;
4use rand::Rng;
5
6/// 邮箱域名
7const EMAIL_DOMAINS: &[&str] = &[
8    "gmail.com", "yahoo.com", "hotmail.com", "outlook.com", "qq.com",
9    "163.com", "126.com", "sina.com", "sohu.com", "example.com"
10];
11
12/// 顶级域名
13const TLDS: &[&str] = &[
14    "com", "org", "net", "edu", "gov", "mil", "int", "cn", "uk", "de", "fr", "jp"
15];
16
17/// 用户代理字符串
18const USER_AGENTS: &[&str] = &[
19    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
20    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36",
21    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36"
22];
23
24/// 生成邮箱地址
25pub fn email() -> String {
26    let mut rng = rand::thread_rng();
27    let username_len = rng.gen_range(5..=15);
28    let username: String = (0..username_len)
29        .map(|_| {
30            let chars = b"abcdefghijklmnopqrstuvwxyz0123456789";
31            chars[rng.gen_range(0..chars.len())] as char
32        })
33        .collect();
34    
35    let domain = EMAIL_DOMAINS.choose(&mut rng).unwrap();
36    format!("{}@{}", username, domain)
37}
38
39/// 生成用户名
40pub fn username() -> String {
41    let mut rng = rand::thread_rng();
42    let len = rng.gen_range(6..=20);
43    (0..len)
44        .map(|_| {
45            let chars = b"abcdefghijklmnopqrstuvwxyz0123456789_";
46            chars[rng.gen_range(0..chars.len())] as char
47        })
48        .collect()
49}
50
51/// 生成密码
52pub fn password(length: usize) -> String {
53    let mut rng = rand::thread_rng();
54    let chars = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*";
55    (0..length)
56        .map(|_| chars[rng.gen_range(0..chars.len())] as char)
57        .collect()
58}
59
60/// 生成强密码(包含大小写字母、数字和特殊字符)
61pub fn strong_password() -> String {
62    let mut rng = rand::thread_rng();
63    let length = rng.gen_range(12..=20);
64    
65    let mut password = String::new();
66    
67    // 确保至少包含一个大写字母
68    password.push(('A'..='Z').nth(rng.gen_range(0..26)).unwrap());
69    
70    // 确保至少包含一个小写字母
71    password.push(('a'..='z').nth(rng.gen_range(0..26)).unwrap());
72    
73    // 确保至少包含一个数字
74    password.push(('0'..='9').nth(rng.gen_range(0..10)).unwrap());
75    
76    // 确保至少包含一个特殊字符
77    let special_chars = "!@#$%^&*";
78    password.push(special_chars.chars().nth(rng.gen_range(0..special_chars.len())).unwrap());
79    
80    // 填充剩余长度
81    let all_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*";
82    for _ in 4..length {
83        password.push(all_chars.chars().nth(rng.gen_range(0..all_chars.len())).unwrap());
84    }
85    
86    // 打乱字符顺序
87    let mut chars: Vec<char> = password.chars().collect();
88    chars.shuffle(&mut rng);
89    chars.into_iter().collect()
90}
91
92/// 生成域名
93pub fn domain() -> String {
94    let mut rng = rand::thread_rng();
95    let name_len = rng.gen_range(5..=15);
96    let name: String = (0..name_len)
97        .map(|_| {
98            let chars = b"abcdefghijklmnopqrstuvwxyz";
99            chars[rng.gen_range(0..chars.len())] as char
100        })
101        .collect();
102    
103    let tld = TLDS.choose(&mut rng).unwrap();
104    format!("{}.{}", name, tld)
105}
106
107/// 生成URL
108pub fn url() -> String {
109    let mut rng = rand::thread_rng();
110    let protocols = ["http", "https"];
111    let protocol = protocols.choose(&mut rng).unwrap();
112    let domain = domain();
113    let path_len = rng.gen_range(0..=3);
114    
115    let mut url = format!("{}://{}", protocol, domain);
116    
117    for _ in 0..path_len {
118        let segment_len = rng.gen_range(3..=10);
119        let segment: String = (0..segment_len)
120            .map(|_| {
121                let chars = b"abcdefghijklmnopqrstuvwxyz0123456789";
122                chars[rng.gen_range(0..chars.len())] as char
123            })
124            .collect();
125        url.push('/');
126        url.push_str(&segment);
127    }
128    
129    url
130}
131
132/// 生成IP地址
133pub fn ip_address() -> String {
134    let mut rng = rand::thread_rng();
135    format!(
136        "{}.{}.{}.{}",
137        rng.gen_range(1..=255),
138        rng.gen_range(0..=255),
139        rng.gen_range(0..=255),
140        rng.gen_range(1..=254)
141    )
142}
143
144/// 生成IPv6地址
145pub fn ipv6_address() -> String {
146    let mut rng = rand::thread_rng();
147    (0..8)
148        .map(|_| format!("{:04x}", rng.gen_range(0..=0xffff)))
149        .collect::<Vec<_>>()
150        .join(":")
151}
152
153/// 生成MAC地址
154pub fn mac_address() -> String {
155    let mut rng = rand::thread_rng();
156    (0..6)
157        .map(|_| format!("{:02x}", rng.gen_range(0..=255)))
158        .collect::<Vec<_>>()
159        .join(":")
160}
161
162/// 生成IPv4地址(别名)
163pub fn ipv4() -> String {
164    ip_address()
165}
166
167/// 生成IPv6地址(别名)
168pub fn ipv6() -> String {
169    ipv6_address()
170}
171
172/// 生成默认长度密码
173pub fn default_password() -> String {
174    password(12)
175}
176
177/// 生成用户代理字符串
178pub fn user_agent() -> String {
179    let mut rng = rand::thread_rng();
180    USER_AGENTS.choose(&mut rng).unwrap().to_string()
181}
182
183/// 生成端口号
184pub fn port() -> u16 {
185    let mut rng = rand::thread_rng();
186    rng.gen_range(1024..=65535)
187}
188
189#[cfg(test)]
190mod tests {
191    use super::*;
192
193    #[test]
194    fn test_email() {
195        let email = email();
196        assert!(email.contains('@'));
197        assert!(email.contains('.'));
198    }
199
200    #[test]
201    fn test_strong_password() {
202        let password = strong_password();
203        assert!(password.len() >= 12);
204        assert!(password.chars().any(|c| c.is_uppercase()));
205        assert!(password.chars().any(|c| c.is_lowercase()));
206        assert!(password.chars().any(|c| c.is_ascii_digit()));
207        assert!(password.chars().any(|c| "!@#$%^&*".contains(c)));
208    }
209
210    #[test]
211    fn test_ip_address() {
212        let ip = ip_address();
213        let parts: Vec<&str> = ip.split('.').collect();
214        assert_eq!(parts.len(), 4);
215        
216        for part in parts {
217            let num: u16 = part.parse().unwrap();
218            assert!(num <= 255);
219        }
220    }
221
222    #[test]
223    fn test_mac_address() {
224        let mac = mac_address();
225        let parts: Vec<&str> = mac.split(':').collect();
226        assert_eq!(parts.len(), 6);
227        
228        for part in parts {
229            assert_eq!(part.len(), 2);
230            assert!(u8::from_str_radix(part, 16).is_ok());
231        }
232    }
233}