add format_out_of_country_keeping_alpha_chars fn
This commit is contained in:
@@ -1268,127 +1268,131 @@ impl PhoneNumberUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn FormatOutOfCountryKeepingAlphaChars<'a>(
|
fn format_out_of_country_keeping_alpha_chars<'a>(
|
||||||
&self,
|
&self,
|
||||||
phone_number: &'a PhoneNumber,
|
phone_number: &'a PhoneNumber,
|
||||||
calling_from: &str,
|
calling_from: &str,
|
||||||
) -> Cow<'a, str> {
|
) -> RegexResult<Cow<'a, str>> {
|
||||||
// If there is no raw input, then we can't keep alpha characters because there
|
// If there is no raw input, then we can't keep alpha characters because there
|
||||||
// aren't any. In this case, we return FormatOutOfCountryCallingNumber.
|
// aren't any. In this case, we return FormatOutOfCountryCallingNumber.
|
||||||
if (number.raw_input().empty()){
|
if phone_number.raw_input().is_empty() {
|
||||||
return self.format_out_of_country_calling_number(phone_number, calling_from);
|
return self.format_out_of_country_calling_number(phone_number, calling_from)
|
||||||
FormatOutOfCountryCallingNumber(number, calling_from, formatted_number);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
int country_code = number.country_code();
|
|
||||||
if (!HasValidCountryCallingCode(country_code))
|
let country_code = phone_number.country_code();
|
||||||
{
|
if !self.has_valid_country_calling_code(country_code) {
|
||||||
formatted_number->assign(number.raw_input());
|
return Ok(phone_number.raw_input().into())
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
// Strip any prefix such as country calling code, IDD, that was present. We do
|
// Strip any prefix such as country calling code, IDD, that was present. We do
|
||||||
// this by comparing the number in raw_input with the parsed number.
|
// this by comparing the number in raw_input with the parsed number.
|
||||||
string raw_input_copy(number.raw_input());
|
|
||||||
// Normalize punctuation. We retain number grouping symbols such as " " only.
|
// Normalize punctuation. We retain number grouping symbols such as " " only.
|
||||||
NormalizeHelper(reg_exps_->all_plus_number_grouping_symbols_, true,
|
let mut normalized_raw_input = helper_functions::normalize_helper(
|
||||||
&raw_input_copy);
|
&self.reg_exps.all_plus_number_grouping_symbols,
|
||||||
|
true,
|
||||||
|
phone_number.raw_input()
|
||||||
|
);
|
||||||
// Now we trim everything before the first three digits in the parsed number.
|
// Now we trim everything before the first three digits in the parsed number.
|
||||||
// We choose three because all valid alpha numbers have 3 digits at the start
|
// We choose three because all valid alpha numbers have 3 digits at the start
|
||||||
// - if it does not, then we don't trim anything at all. Similarly, if the
|
// - if it does not, then we don't trim anything at all. Similarly, if the
|
||||||
// national number was less than three digits, we don't trim anything at all.
|
// national number was less than three digits, we don't trim anything at all.
|
||||||
string national_number;
|
let national_number = Self::get_national_significant_number(phone_number);
|
||||||
GetNationalSignificantNumber(number, &national_number);
|
if national_number.len() > 3 {
|
||||||
if (national_number.length() > 3)
|
let first_national_number_digit = normalized_raw_input
|
||||||
{
|
.find(&national_number[0..3]);
|
||||||
size_t first_national_number_digit =
|
if let Some(first_national_number_digit) = first_national_number_digit {
|
||||||
raw_input_copy.find(national_number.substr(0, 3));
|
normalized_raw_input.drain(0..first_national_number_digit);
|
||||||
if (first_national_number_digit != string::npos)
|
|
||||||
{
|
|
||||||
raw_input_copy = raw_input_copy.substr(first_national_number_digit);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const PhoneMetadata *metadata = GetMetadataForRegion(calling_from);
|
let metadata = self.region_to_metadata_map.get(calling_from);
|
||||||
if (country_code == kNanpaCountryCode)
|
if country_code == NANPA_COUNTRY_CODE {
|
||||||
{
|
if self.nanpa_regions.contains(calling_from) {
|
||||||
if (IsNANPACountry(calling_from))
|
let mut buf = itoa::Buffer::new();
|
||||||
{
|
|
||||||
StrAppend(formatted_number, country_code, " ", raw_input_copy);
|
return Ok(fast_cat::concat_str!(
|
||||||
return;
|
buf.format(country_code), " ", &normalized_raw_input
|
||||||
|
).into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (metadata &&
|
else if let Some(metadata) = metadata.filter(
|
||||||
country_code == GetCountryCodeForValidRegion(calling_from))
|
|metadata| country_code == metadata.country_code()
|
||||||
{
|
) {
|
||||||
const NumberFormat *formatting_pattern =
|
let Some(formatting_pattern) = self.choose_formatting_pattern_for_number(
|
||||||
ChooseFormattingPatternForNumber(metadata->number_format(),
|
&metadata.number_format, &national_number
|
||||||
national_number);
|
)? else {
|
||||||
if (!formatting_pattern)
|
|
||||||
{
|
|
||||||
// If no pattern above is matched, we format the original input.
|
// If no pattern above is matched, we format the original input.
|
||||||
formatted_number->assign(raw_input_copy);
|
return Ok(normalized_raw_input.into())
|
||||||
return;
|
};
|
||||||
}
|
let mut new_format = formatting_pattern.clone();
|
||||||
NumberFormat new_format;
|
|
||||||
new_format.MergeFrom(*formatting_pattern);
|
|
||||||
// The first group is the first group of digits that the user wrote
|
// The first group is the first group of digits that the user wrote
|
||||||
// together.
|
// together.
|
||||||
new_format.set_pattern("(\\d+)(.*)");
|
new_format.set_pattern("(\\d+)(.*)".to_owned());
|
||||||
// Here we just concatenate them back together after the national prefix
|
// Here we just concatenate them back together after the national prefix
|
||||||
// has been fixed.
|
// has been fixed.
|
||||||
new_format.set_format("$1$2");
|
new_format.set_format("$1$2".to_owned());
|
||||||
// Now we format using this pattern instead of the default pattern, but
|
// Now we format using this pattern instead of the default pattern, but
|
||||||
// with the national prefix prefixed if necessary.
|
// with the national prefix prefixed if necessary.
|
||||||
// This will not work in the cases where the pattern (and not the
|
// This will not work in the cases where the pattern (and not the
|
||||||
// leading digits) decide whether a national prefix needs to be used, since
|
// leading digits) decide whether a national prefix needs to be used, since
|
||||||
// we have overridden the pattern to match anything, but that is not the
|
// we have overridden the pattern to match anything, but that is not the
|
||||||
// case in the metadata to date.
|
// case in the metadata to date.
|
||||||
FormatNsnUsingPattern(raw_input_copy, new_format, NATIONAL,
|
return self.format_nsn_using_pattern(
|
||||||
formatted_number);
|
&normalized_raw_input,
|
||||||
return;
|
&new_format,
|
||||||
|
PhoneNumberFormat::National
|
||||||
|
).map(| cow | Cow::Owned(cow.into_owned()) );
|
||||||
}
|
}
|
||||||
|
|
||||||
string international_prefix_for_formatting;
|
|
||||||
// If an unsupported region-calling-from is entered, or a country with
|
// If an unsupported region-calling-from is entered, or a country with
|
||||||
// multiple international prefixes, the international format of the number is
|
// multiple international prefixes, the international format of the number is
|
||||||
// returned, unless there is a preferred international prefix.
|
// returned, unless there is a preferred international prefix.
|
||||||
if (metadata)
|
let international_prefix_for_formatting = metadata.map(| metadata | {
|
||||||
{
|
let international_prefix = metadata.international_prefix();
|
||||||
const string &international_prefix = metadata->international_prefix();
|
if self.reg_exps.single_international_prefix
|
||||||
international_prefix_for_formatting =
|
.full_match(international_prefix) {
|
||||||
reg_exps_->single_international_prefix_->FullMatch(international_prefix)
|
international_prefix
|
||||||
? international_prefix
|
} else {
|
||||||
: metadata->preferred_international_prefix();
|
metadata.preferred_international_prefix()
|
||||||
}
|
}
|
||||||
if (!international_prefix_for_formatting.empty())
|
});
|
||||||
{
|
let formatted_number = if let Some(international_prefix_for_formatting) = international_prefix_for_formatting {
|
||||||
StrAppend(formatted_number, international_prefix_for_formatting, " ",
|
let mut buf = itoa::Buffer::new();
|
||||||
country_code, " ", raw_input_copy);
|
fast_cat::concat_str!(
|
||||||
}
|
international_prefix_for_formatting, " ",
|
||||||
else
|
buf.format(country_code), " ", &normalized_raw_input
|
||||||
{
|
)
|
||||||
|
} else {
|
||||||
// Invalid region entered as country-calling-from (so no metadata was found
|
// Invalid region entered as country-calling-from (so no metadata was found
|
||||||
// for it) or the region chosen has multiple international dialling
|
// for it) or the region chosen has multiple international dialling
|
||||||
// prefixes.
|
// prefixes.
|
||||||
if (!IsValidRegionCode(calling_from))
|
if !self.region_to_metadata_map.contains_key(calling_from) {
|
||||||
{
|
trace!(
|
||||||
VLOG(1) << "Trying to format number from invalid region " << calling_from
|
"Trying to format number from invalid region {}. International formatting applied.",
|
||||||
<< ". International formatting applied.";
|
calling_from
|
||||||
|
);
|
||||||
}
|
}
|
||||||
formatted_number->assign(raw_input_copy);
|
let mut formatted_number = normalized_raw_input;
|
||||||
PrefixNumberWithCountryCallingCode(country_code, INTERNATIONAL,
|
prefix_number_with_country_calling_code(country_code, PhoneNumberFormat::International, &mut formatted_number);
|
||||||
formatted_number);
|
formatted_number
|
||||||
}
|
};
|
||||||
std::string region_code;
|
let region_code = self.get_region_code_for_country_code(country_code);
|
||||||
GetRegionCodeForCountryCode(country_code, ®ion_code);
|
|
||||||
// Metadata cannot be null because the country code is valid.
|
// Metadata cannot be null because the country code is valid.
|
||||||
const PhoneMetadata *metadata_for_region =
|
let metadata_for_region = self
|
||||||
GetMetadataForRegionOrCallingCode(country_code, region_code);
|
.get_metadata_for_region_or_calling_code(country_code, region_code)
|
||||||
|
.expect("Metadata cannot be null because the country code is valid.");
|
||||||
|
|
||||||
// Strip any extension
|
// Strip any extension
|
||||||
std::string extension;
|
let (phone_number_without_extension, extension) = self
|
||||||
MaybeStripExtension(formatted_number, &extension);
|
.maybe_strip_extension(&formatted_number);
|
||||||
// Append the formatted extension
|
// Append the formatted extension
|
||||||
MaybeAppendFormattedExtension(number, *metadata_for_region, INTERNATIONAL,
|
let extension = Self::get_formatted_extension(phone_number, metadata_for_region, PhoneNumberFormat::International);
|
||||||
formatted_number);
|
Ok(
|
||||||
|
if let Some(extension) = extension {
|
||||||
|
fast_cat::concat_str!(phone_number_without_extension, &extension)
|
||||||
|
} else {
|
||||||
|
phone_number_without_extension.to_string()
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user