rust_persian_tools/phone_number/
mod.rs1pub mod operators;
2
3use thiserror::Error;
4
5pub static PREFIXES: [&str; 4] = ["+98", "98", "0098", "0"];
6
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8#[derive(Error, Clone, Debug, Hash, PartialEq, Eq)]
9pub enum PhoneNumberError {
10 #[error("This prefix is not a valid phone number (prefix : `{0}`)")]
11 InvalidPrefix(String),
12 #[error("The phone number format is invalid")]
13 InvalidFormat,
14 #[error("Unexpected error happened !")]
15 Unknown,
16}
17
18pub fn is_phone_valid(phone_number: impl AsRef<str>) -> Result<(), PhoneNumberError> {
29 let phone_number = phone_number.as_ref();
30
31 let prefix = get_phone_prefix(phone_number).unwrap_or("");
32
33 let phone_number_without_prefix = &phone_number[prefix.len()..];
34
35 if phone_number_without_prefix.len() == 10 && phone_number_without_prefix.starts_with('9') {
36 return Ok(());
37 }
38
39 Err(PhoneNumberError::InvalidFormat)
40}
41
42pub fn get_phone_prefix(phone_number: impl AsRef<str>) -> Result<&'static str, PhoneNumberError> {
60 let phone_number = phone_number.as_ref();
61
62 let prefix = PREFIXES
63 .into_iter()
64 .find(|&prefix| phone_number.starts_with(prefix));
65
66 match prefix {
67 Some(pre) => Ok(pre),
68 None => Err(PhoneNumberError::InvalidFormat),
69 }
70}
71
72pub fn phone_number_normalizer(
86 phone_number: impl AsRef<str>,
87 new_prefix: impl AsRef<str>,
88) -> Result<String, PhoneNumberError> {
89 let phone_number = phone_number.as_ref();
90 let new_prefix = new_prefix.as_ref();
91
92 is_phone_valid(phone_number)?;
93
94 if let Ok(prefix) = get_phone_prefix(phone_number) {
95 let (_, splitted) = phone_number.split_at(prefix.len());
96 return Ok(format!("{new_prefix}{splitted}"));
97 }
98
99 Ok(format!("{new_prefix}{phone_number}"))
100}
101
102pub fn get_operator_prefix(phone_number: &str) -> Result<&str, PhoneNumberError> {
117 is_phone_valid(phone_number)?;
118
119 for prefix in PREFIXES {
120 if phone_number.starts_with(prefix) {
121 return Ok(&phone_number[prefix.len()..prefix.len() + 3]);
122 }
123 }
124
125 Err(PhoneNumberError::InvalidFormat)
126}
127
128#[cfg(test)]
129mod tests {
130 use super::*;
131
132 #[test]
133 fn check_phone_number_valid() {
134 assert!(is_phone_valid("9122221811").is_ok());
135 assert!(is_phone_valid("09122221811").is_ok());
136 assert!(is_phone_valid("+989122221811").is_ok());
137 assert!(is_phone_valid("12903908").is_err());
138 assert!(is_phone_valid("901239812390812908").is_err());
139 }
140
141 #[test]
142 fn test_phone_number_normalizer() {
143 assert_eq!(
146 phone_number_normalizer("+989373708555", "0").unwrap(),
147 "09373708555".to_string()
148 );
149
150 assert_eq!(
151 phone_number_normalizer("989373708555", "0").unwrap(),
152 "09373708555".to_string()
153 );
154
155 assert_eq!(
156 phone_number_normalizer("00989022002580", "0").unwrap(),
157 "09022002580".to_string()
158 );
159 assert_eq!(
160 phone_number_normalizer("09122002580", "0").unwrap(),
161 "09122002580".to_string()
162 );
163 assert_eq!(
164 phone_number_normalizer("9322002580", "0").unwrap(),
165 "09322002580".to_string()
166 );
167
168 assert_eq!(
170 phone_number_normalizer("09373708555", "+98").unwrap(),
171 "+989373708555".to_string()
172 );
173 assert_eq!(
174 phone_number_normalizer("09022002580", "+98").unwrap(),
175 "+989022002580".to_string()
176 );
177 assert_eq!(
178 phone_number_normalizer("09122002580", "+98").unwrap(),
179 "+989122002580".to_string()
180 );
181 assert_eq!(
182 phone_number_normalizer("9322002580", "+98").unwrap(),
183 "+989322002580".to_string()
184 );
185 assert_eq!(
186 phone_number_normalizer("00989022002580", "+98").unwrap(),
187 "+989022002580".to_string()
188 );
189 }
190
191 #[test]
192 fn test_phone_number_normalizer_invalid_phone() {
193 assert!(phone_number_normalizer("09132222", "+98").is_err());
194 assert!(phone_number_normalizer("9191282819921", "0").is_err());
195 }
196
197 #[test]
198 fn test_operator_prefix() {
199 assert_eq!(get_operator_prefix("+989373708555").unwrap(), "937");
200 assert_eq!(get_operator_prefix("00989013708555").unwrap(), "901");
201 assert!(get_operator_prefix("00988013708555").is_err());
202 }
203}