added functions

- get_length_of_geographical_area_code
- get_length_of_national_destination_code
- get_country_mobile_token
This commit is contained in:
Vlasislav Kashin
2025-07-10 01:44:46 +03:00
parent ee240e3277
commit b018ee99ce

View File

@@ -2182,6 +2182,91 @@ impl PhoneNumberUtil {
) )
} }
fn get_length_of_geographical_area_code(
&self, phone_number: &PhoneNumber
) -> RegexResult<usize> {
let region_code = self.get_region_code_for_number(phone_number)?;
let Some(metadata) = self.region_to_metadata_map.get(region_code) else {
return Ok(0)
};
let phone_number_type = self.get_number_type(phone_number)?;
let country_calling_code = phone_number.country_code();
// If a country doesn't use a national prefix, and this number doesn't have an
// Italian leading zero, we assume it is a closed dialling plan with no area
// codes.
// Note:this is our general assumption, but there are exceptions which are
// tracked in COUNTRIES_WITHOUT_NATIONAL_PREFIX_WITH_AREA_CODES.
if !metadata.has_national_prefix() && !phone_number.italian_leading_zero() &&
!self.reg_exps.countries_without_national_prefix_with_area_codes
.contains(&country_calling_code) {
return Ok(0);
}
if (matches!(phone_number_type, PhoneNumberType::Mobile) &&
!self.reg_exps.geo_mobile_countries_without_mobile_area_codes.contains(&country_calling_code)
) {
return Ok(0);
}
if !self.is_number_geographical_by_country_code_and_type(phone_number_type, country_calling_code) {
return Ok(0);
}
return self.get_length_of_national_destination_code(phone_number);
}
fn get_length_of_national_destination_code(
&self, phone_number: &PhoneNumber
) -> RegexResult<usize> {
let mut copied_proto = phone_number.clone();
if phone_number.has_extension() {
// Clear the extension so it's not included when formatting.
copied_proto.clear_extension();
}
let formatted_number = self.format(
&copied_proto, PhoneNumberFormat::International
)?;
const ITERATIONS_COUNT: usize = 3;
let mut captured_groups = [0; ITERATIONS_COUNT];
let (ndc_index, third_group) = (1, 2);
let mut capture_iter = self.reg_exps.capturing_ascii_digits_pattern
.captures_iter(&formatted_number);
for i in 0..ITERATIONS_COUNT {
if let Some(matches) = capture_iter.next().and_then(| captures | captures.get(1)) {
captured_groups[i] = matches.len();
} else {
return Ok(0)
}
}
if matches!(self.get_number_type(phone_number)?, PhoneNumberType::Mobile) {
// For example Argentinian mobile numbers, when formatted in the
// international format, are in the form of +54 9 NDC XXXX.... As a result,
// we take the length of the third group (NDC) and add the length of the
// mobile token, which also forms part of the national significant number.
// This assumes that the mobile token is always formatted separately from
// the rest of the phone number.
if let Some(mobile_token) = self.get_country_mobile_token(
phone_number.country_code()
) {
return Ok(captured_groups[third_group] + mobile_token.len_utf8())
}
}
Ok(captured_groups[ndc_index])
}
fn get_country_mobile_token(&self, country_calling_code: i32) -> Option<char> {
self
.reg_exps
.mobile_token_mappings
.get(&country_calling_code)
.copied()
}
/// Extracts country calling code from national_number, and returns tuple /// Extracts country calling code from national_number, and returns tuple
/// that contains national_number without calling code and calling code itself. /// that contains national_number without calling code and calling code itself.
/// ///