warlocks_cauldron/providers/
person.rs

1use std::str::FromStr;
2
3use sha2::{Sha256, Digest};
4use regex::Regex;
5
6use crate::data::serializers::{SurnamesOption, NationalityOption};
7use super::dependencies::*;
8
9
10pub enum SexType<'a> { ISO5218(u8), String(&'a str) }
11
12/// Struct for generating personal data
13pub struct Person<'a>(pub &'a Locale);
14
15impl<'a> Person<'a> {
16    /// Private. Return global parsed data from own locale
17    fn data(&self) -> &ParsedData { self.0.get_data() }
18
19    /// Get a random integer value
20    pub fn age(minimum: i32, maximum: i32) -> i32 {
21        randint(minimum, maximum)
22    }
23
24    /// Get a random integer value
25    pub fn work_experience(minimum: i32, maximum: i32) -> i32 {
26        randint(minimum, maximum)
27    }
28
29    /// Generate a random name
30    pub fn name(&self, gender: Option<Gender>) -> &str {
31        match validate_variant(gender, None) {
32            Gender::MALE => get_random_element(self.data().person.names.male.iter()),
33            Gender::FEMALE => get_random_element(self.data().person.names.female.iter()),
34            _ => panic!("Validation error!"),
35        }
36    }
37
38    /// Generate a random first name | *An allias for .name()*
39    pub fn first_name(&self, gender: Option<Gender>) -> &str {
40        self.name(gender)
41    }
42    
43    /// Generate a random surname | *An allias for .name()*
44    pub fn surname(&self, gender: Option<Gender>) -> String {
45        match self.data().person.get_surnames() {
46            SurnamesOption::Map(m) => match validate_variant(gender, None) {
47                Gender::MALE => get_random_element(m.male.into_iter()),
48                Gender::FEMALE => get_random_element(m.female.into_iter()),
49                _ => panic!("Validation surnames error!"),
50            },
51            SurnamesOption::Sequence(seq) => get_random_element(seq.into_iter()),
52            SurnamesOption::None => panic!("There is no surnames exists!"),
53        }
54    }
55
56    /// Generate a random last name | *An allias for .surname()*
57    pub fn last_name(&self, gender: Option<Gender>) -> String {
58        self.surname(gender)
59    }
60
61    /// Generate a random title for name
62    pub fn title(&self, gender: Option<Gender>, title_type: Option<TitleType>) -> &str {
63        get_random_element(match (validate_variant(gender, None), validate_variant(title_type, None)) {
64            (Gender::MALE, TitleType::TYPICAL) => self.data().person.title.male.typical.iter(),
65            (Gender::MALE, TitleType::ACADEMIC) => self.data().person.title.male.academic.iter(),
66            (Gender::FEMALE, TitleType::TYPICAL) => self.data().person.title.female.typical.iter(),
67            (Gender::FEMALE, TitleType::ACADEMIC) => self.data().person.title.female.academic.iter(),
68            _ => panic!("Validation error!"),
69        })
70    }
71
72    /// Generate a random full name
73    ///
74    /// ex: name surname
75    pub fn full_name(&self, gender: Option<Gender>, reverse: bool) -> String {
76        match reverse {
77            true => format!("{} {}", self.name(gender.clone()), self.surname(gender.clone())),
78            false => format!("{} {}",self.surname(gender.clone()), self.name(gender.clone())),
79        }
80    }
81
82    /// You can create many different usernames using masks:
83    ///
84    /// - **C** stands for capitalized username.
85    /// - **U** stands for uppercase username.
86    /// - **l** stands for lowercase username.
87    /// - **d** stands for digits in username.
88    ///
89    /// You can also use symbols to separate the different part of the username: **.** **_** **-**
90    pub fn username(mask: Option<&str>, drange: Option<(u32, u32)>) -> String {
91        let mask = mask.unwrap_or_else(|| "l_d");
92        let drange = drange.unwrap_or_else(|| (1800, 2100));
93
94        let mut output = String::new();
95        for tag in Regex::new(r"[CUld.\-_]").unwrap().find_iter(mask) {
96            let username = get_random_element(USERNAMES.iter());
97            output.push_str(&match tag.as_str() {
98                "C" => username[..1].to_uppercase() + &username[1..],
99                "U" => username.to_uppercase(),
100                "l" => username.to_lowercase(),
101                "d" => randint(drange.0, drange.1).to_string(),
102                other => String::from_str(other).unwrap(),
103            });
104        }
105
106        output
107    }
108
109    /// Generate a password or hash of password
110    pub fn password(length: usize, hashed: bool) -> String {
111        let characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~";
112        let password = get_random_elements(characters.chars(), length).iter().join("");
113
114        match hashed {
115            true => format!("{:x}", Sha256::new_with_prefix(password.as_bytes()).finalize()),
116            false => password,
117        }
118    }
119
120    /// Generate a random email
121    ///
122    /// Arguments:
123    /// * `domains` - List of custom domains for emails
124    /// * `unique` - Makes email addresses unique
125    pub fn email(domains: Option<Vec<&'static str>>, unique: bool) -> String {
126        let domain = match domains {
127            Some(d) => {
128                let domain = get_random_element(d.into_iter());
129                match domain.starts_with('@') {
130                    true => domain.to_string(),
131                    false => format!("@{domain}"),
132                }
133            },
134            None => get_random_element(EMAIL_DOMAINS.iter()).to_string(),
135        };
136
137        let name = match unique {
138            true => randstr(unique, 13),
139            false => Self::username(Some("ld"), Some((1800, 2100)))
140        };
141
142        format!("{name}{domain}")
143    }
144
145    /// Get a random gender
146    /// 
147    /// Arguments:
148    /// * `iso5218` - Codes for the representation of human sexes is an international standard (0 - not known, 1 - male, 2 - female, 9 - not applicable)
149    /// * `symbol` - Symbol of gender
150    pub fn gender(&self, iso_5218: bool, symbol: bool) -> SexType {
151        if iso_5218 {
152            return SexType::ISO5218(get_random_element(vec![1, 2, 3, 9].into_iter()));
153        }
154
155        if symbol {
156            return SexType::String(get_random_element(GENDER_SYMBOLS.iter()));
157        }
158
159        SexType::String(get_random_element(self.data().person.gender.iter()))
160    }
161
162
163    /// Get a random sex | *An allias for .gender()*
164    pub fn sex(&self, iso_5218: bool, symbol: bool) -> SexType {
165        self.gender(iso_5218, symbol)
166    }
167
168    /// Generate a random height
169    pub fn height(minimum: f32, maximum: f32) -> String {
170        format!("{:.2}", uniform(minimum, maximum))
171    }
172
173    /// Generate a random weight
174    pub fn weight(minimum: i32, maximum: i32) -> i32 {
175        randint(minimum, maximum)
176    }
177
178    /// Get a random blood type
179    pub fn blood_type() -> &'static str {
180        get_random_element(BLOOD_GROUPS.iter())
181    }
182
183    /// Get a random job
184    pub fn occupation(&self) -> &str {
185        get_random_element(self.data().person.occupation.iter())
186    }
187
188    /// Get a random political views
189    pub fn political_views(&self) -> &str {
190        get_random_element(self.data().person.political_views.iter())
191    }
192
193    /// Get a random political views
194    pub fn worldview(&self) -> &str {
195        get_random_element(self.data().person.worldview.iter())
196    }
197
198    /// Get a random political views
199    pub fn views_on(&self) -> &str {
200        get_random_element(self.data().person.views_on.iter())
201    }
202
203    /// Generate a random nationality | *An allias for .name()*
204    pub fn nationality(&self, gender: Option<Gender>) -> String {
205        match self.data().person.get_nationality() {
206            NationalityOption::Map(m) => match validate_variant(gender, None) {
207                Gender::MALE => get_random_element(m.male.into_iter()),
208                Gender::FEMALE => get_random_element(m.female.into_iter()),
209                _ => panic!("Validation nationality error!"),
210            },
211            NationalityOption::Sequence(seq) => get_random_element(seq.into_iter()),
212            NationalityOption::None => panic!("There is no nationality exists!"),
213        }
214    }
215
216    /// Get a random university
217    pub fn university(&self) -> &str {
218        get_random_element(self.data().person.university.iter())
219    }
220
221    /// Get a random academic degree
222    pub fn academic_degree(&self) -> &str {
223        get_random_element(self.data().person.academic_degree.iter())
224    }
225
226    /// Get a random language
227    pub fn language(&self) -> &str {
228        get_random_element(self.data().person.language.iter())
229    }
230
231    /// Generate a random phone number
232    /// 
233    /// Arguments:
234    /// * `mask` - The mask. Here ``@`` is a placeholder for characters and ``#`` is placeholder for digits
235    pub fn telephone(&self, mask: Option<&str>) -> String {
236        let mask = mask.unwrap_or_else(|| get_random_element(self.data().person.telephone_fmt.iter()));
237        custom_code(mask, '@', '#')
238    }
239
240    /// Generate a random identifier by mask
241    /// 
242    /// Arguments:
243    /// * `mask` - The mask. Here ``@`` is a placeholder for characters and ``#`` is placeholder for digits
244    pub fn identifier(&self, mask: Option<&str>) -> String {
245        let mask = mask.unwrap_or_else(|| "##-##/##");
246        custom_code(mask, '@', '#')
247    }
248}