use std::{borrow::Cow, collections::HashSet};
use crate::{
generated::proto::phonenumber::PhoneNumber, phonemetadata::PhoneMetadataCollection,
phonenumberutil::helper_functions::get_national_significant_number, unwrap_internal,
};
use super::{
enums::{MatchType, NumberLengthType, PhoneNumberFormat, PhoneNumberType},
errors::{GetExampleNumberError, ParseError, ValidationError},
phonenumberutil_internal::PhoneNumberUtilInternal,
};
const REGEXP_ERROR_EXPECT_MESSAGE: &str =
"A valid regex is expected in metadata; this indicates a library bug.";
pub struct PhoneNumberUtil {
util_internal: PhoneNumberUtilInternal,
}
impl PhoneNumberUtil {
pub fn new() -> Self {
Self {
util_internal: PhoneNumberUtilInternal::new().expect(REGEXP_ERROR_EXPECT_MESSAGE),
}
}
pub fn new_for_metadata(metadata_collection: PhoneMetadataCollection) -> Self {
Self {
util_internal: PhoneNumberUtilInternal::new_for_metadata(metadata_collection),
}
}
pub fn can_be_internationally_dialled(&self, phone_number: &PhoneNumber) -> bool {
self.util_internal
.can_be_internationally_dialled(phone_number)
.expect(REGEXP_ERROR_EXPECT_MESSAGE)
}
pub fn convert_alpha_characters_in_number(&self, number: impl AsRef<str>) -> String {
self.util_internal
.convert_alpha_characters_in_number(number.as_ref())
}
pub fn format<'a>(
&self,
phone_number: &'a PhoneNumber,
number_format: PhoneNumberFormat,
) -> Cow<'a, str> {
self.util_internal
.format(phone_number, number_format)
.expect(REGEXP_ERROR_EXPECT_MESSAGE)
}
pub fn format_in_original_format<'a>(
&self,
phone_number: &'a PhoneNumber,
region_calling_from: impl AsRef<str>,
) -> Cow<'a, str> {
self.util_internal
.format_in_original_format(phone_number, region_calling_from.as_ref())
.expect(REGEXP_ERROR_EXPECT_MESSAGE)
}
pub fn format_national_number_with_carrier_code(
&self,
phone_number: &PhoneNumber,
carrier_code: impl AsRef<str>,
) -> String {
self.util_internal
.format_national_number_with_carrier_code(phone_number, carrier_code.as_ref())
.expect(REGEXP_ERROR_EXPECT_MESSAGE)
}
pub fn format_number_for_mobile_dialing<'a>(
&self,
phone_number: &'a PhoneNumber,
region_calling_from: impl AsRef<str>,
with_formatting: bool,
) -> Option<Cow<'a, str>> {
self.util_internal
.format_number_for_mobile_dialing(
phone_number,
region_calling_from.as_ref(),
with_formatting,
)
.expect(REGEXP_ERROR_EXPECT_MESSAGE)
}
pub fn format_out_of_country_calling_number<'a>(
&self,
phone_number: &'a PhoneNumber,
region_calling_from: impl AsRef<str>,
) -> Cow<'a, str> {
self.util_internal
.format_out_of_country_calling_number(phone_number, region_calling_from.as_ref())
.expect(REGEXP_ERROR_EXPECT_MESSAGE)
}
pub fn format_out_of_country_keeping_alpha_chars<'a>(
&self,
phone_number: &'a PhoneNumber,
region_calling_from: impl AsRef<str>,
) -> Cow<'a, str> {
self.util_internal
.format_out_of_country_keeping_alpha_chars(phone_number, region_calling_from.as_ref())
.expect(REGEXP_ERROR_EXPECT_MESSAGE)
}
pub fn get_country_code_for_region(&self, region_code: impl AsRef<str>) -> Option<i32> {
self.util_internal
.get_country_code_for_region(region_code.as_ref())
}
pub fn get_example_number(
&self,
region_code: impl AsRef<str>,
) -> Result<PhoneNumber, GetExampleNumberError> {
self.util_internal
.get_example_number(region_code.as_ref())
.map_err(unwrap_internal)
}
pub fn get_example_number_for_type(
&self,
number_type: PhoneNumberType,
) -> Result<PhoneNumber, GetExampleNumberError> {
self.util_internal
.get_example_number_for_type(number_type)
.map_err(unwrap_internal)
}
pub fn get_invalid_example_number(
&self,
region_code: impl AsRef<str>,
) -> Result<PhoneNumber, GetExampleNumberError> {
self.util_internal
.get_invalid_example_number(region_code.as_ref())
.map_err(unwrap_internal)
}
pub fn get_example_number_for_non_geo_entity(
&self,
country_calling_code: i32,
) -> Result<PhoneNumber, GetExampleNumberError> {
self.util_internal
.get_example_number_for_non_geo_entity(country_calling_code)
.map_err(unwrap_internal)
}
pub fn is_possible_number_for_string(
&self,
phone_number: &str,
region_dialing_from: &str,
) -> bool {
self.util_internal
.is_possible_number_for_string(phone_number, region_dialing_from)
}
pub fn is_possible_number_for_type(
&self,
phone_number: &PhoneNumber,
phone_number_type: PhoneNumberType,
) -> bool {
self.util_internal
.is_possible_number_for_type(phone_number, phone_number_type)
}
pub fn get_supported_global_network_calling_codes(&self) -> impl Iterator<Item = i32> {
self.util_internal
.get_supported_global_network_calling_codes()
}
pub fn get_supported_calling_codes(&self) -> impl Iterator<Item = i32> {
self.util_internal.get_supported_calling_codes()
}
pub fn get_supported_types_for_region(
&self,
region_code: &str,
) -> Option<HashSet<PhoneNumberType>> {
self.util_internal
.get_supported_types_for_region(region_code)
}
pub fn get_supported_types_for_non_geo_entity(
&self,
country_calling_code: i32,
) -> Option<HashSet<PhoneNumberType>> {
self.util_internal
.get_supported_types_for_non_geo_entity(country_calling_code)
}
pub fn trim_unwanted_end_chars<'a>(&self, phone_number: &'a str) -> &'a str {
self.util_internal.trim_unwanted_end_chars(phone_number)
}
pub fn normalize_digits_only(&self, phone_number: &str) -> String {
self.util_internal.normalize_digits_only(phone_number)
}
pub fn normalize_diallable_chars_only(&self, phone_number: &str) -> String {
self.util_internal
.normalize_diallable_chars_only(phone_number)
}
pub fn get_length_of_geographical_area_code(&self, phone_number: &PhoneNumber) -> usize {
self.util_internal
.get_length_of_geographical_area_code(phone_number)
.expect(REGEXP_ERROR_EXPECT_MESSAGE)
}
pub fn get_length_of_national_destination_code(&self, phone_number: &PhoneNumber) -> usize {
self.util_internal
.get_length_of_national_destination_code(phone_number)
.expect(REGEXP_ERROR_EXPECT_MESSAGE)
}
pub fn get_national_significant_number(&self, phone_number: &PhoneNumber) -> String {
let mut buf = zeroes_itoa::LeadingZeroBuffer::new();
get_national_significant_number(phone_number, &mut buf).into()
}
pub fn get_number_type(&self, phone_number: &PhoneNumber) -> PhoneNumberType {
self.util_internal
.get_number_type(phone_number)
.expect(
"A valid regex and region is expected in metadata; this indicates a library bug.",
)
}
pub fn get_region_code_for_country_code(&self, country_code: i32) -> Option<&str> {
self.util_internal
.get_region_code_for_country_code(country_code)
}
pub fn get_region_code_for_number(&self, phone_number: &PhoneNumber) -> Option<&str> {
self.util_internal
.get_region_code_for_number(phone_number)
.expect(REGEXP_ERROR_EXPECT_MESSAGE)
}
pub fn get_region_codes_for_country_code(
&self,
country_code: i32,
) -> Option<impl ExactSizeIterator<Item = &str>> {
self.util_internal
.get_region_codes_for_country_calling_code(country_code)
}
pub fn get_supported_regions(&self) -> impl ExactSizeIterator<Item = &str> {
self.util_internal.get_supported_regions()
}
pub fn is_alpha_number(&self, number: impl AsRef<str>) -> bool {
self.util_internal.is_alpha_number(number.as_ref())
}
pub fn is_nanpa_country(&self, region_code: impl AsRef<str>) -> bool {
self.util_internal.is_nanpa_country(region_code.as_ref())
}
pub fn is_number_geographical(&self, phone_number: &PhoneNumber) -> bool {
self.util_internal
.is_number_geographical(phone_number)
.expect(REGEXP_ERROR_EXPECT_MESSAGE)
}
pub fn is_number_match(
&self,
first_number: &PhoneNumber,
second_number: &PhoneNumber,
) -> MatchType {
self.util_internal
.is_number_match(first_number, second_number)
}
pub fn is_possible_number(&self, phone_number: &PhoneNumber) -> bool {
self.util_internal.is_possible_number(phone_number)
}
pub fn is_possible_number_with_reason(
&self,
phone_number: &PhoneNumber,
) -> Result<NumberLengthType, ValidationError> {
self.util_internal
.is_possible_number_with_reason(phone_number)
}
pub fn is_valid_number(&self, phone_number: &PhoneNumber) -> bool {
self.util_internal
.is_valid_number(phone_number)
.expect(REGEXP_ERROR_EXPECT_MESSAGE)
}
pub fn is_valid_number_for_region(
&self,
phone_number: &PhoneNumber,
region: impl AsRef<str>,
) -> bool {
self.util_internal
.is_valid_number_for_region(phone_number, region.as_ref())
.expect(REGEXP_ERROR_EXPECT_MESSAGE)
}
pub fn parse_and_keep_raw_input_with_default_region(
&self,
number_to_parse: impl AsRef<str>,
default_region: impl AsRef<str>,
) -> Result<PhoneNumber, ParseError> {
self.util_internal
.parse_and_keep_raw_input(number_to_parse.as_ref(), Some(default_region.as_ref()))
.map_err(unwrap_internal)
}
pub fn parse_and_keep_raw_input(
&self,
number_to_parse: impl AsRef<str>,
) -> Result<PhoneNumber, ParseError> {
self.util_internal
.parse_and_keep_raw_input(number_to_parse.as_ref(), None)
.map_err(unwrap_internal)
}
pub fn parse_with_default_region(
&self,
number_to_parse: impl AsRef<str>,
default_region: impl AsRef<str>,
) -> Result<PhoneNumber, ParseError> {
self.util_internal
.parse(number_to_parse.as_ref(), Some(default_region.as_ref()))
.map_err(unwrap_internal)
}
pub fn parse(&self, number_to_parse: impl AsRef<str>) -> Result<PhoneNumber, ParseError> {
self.util_internal
.parse(number_to_parse.as_ref(), None)
.map_err(unwrap_internal)
}
pub fn truncate_too_long_number(&self, phone_number: &mut PhoneNumber) -> bool {
self.util_internal
.truncate_too_long_number(phone_number)
.expect(REGEXP_ERROR_EXPECT_MESSAGE)
}
pub fn is_number_match_with_two_strings(
&self,
first_number: &str,
second_number: &str,
) -> MatchType {
self.util_internal
.is_number_match_with_two_strings(first_number, second_number)
.expect(REGEXP_ERROR_EXPECT_MESSAGE)
}
}
impl Default for PhoneNumberUtil {
fn default() -> Self {
Self::new()
}
}