Add some phonenumberutil functions
This commit is contained in:
@@ -6,7 +6,8 @@ mod phonenumberutil;
|
||||
mod regexp_cache;
|
||||
mod regex_based_matcher;
|
||||
pub mod i18n;
|
||||
pub mod regex_util;
|
||||
pub(crate) mod regex_util;
|
||||
pub(crate) mod string_util;
|
||||
|
||||
/// I decided to create this module because there are many
|
||||
/// boilerplate places in the code that can be replaced with macros,
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
use core::error;
|
||||
use std::num::ParseIntError;
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::regexp_cache::ErrorInvalidRegex;
|
||||
@@ -5,5 +8,38 @@ use crate::regexp_cache::ErrorInvalidRegex;
|
||||
#[derive(Debug, PartialEq, Error)]
|
||||
pub enum PhoneNumberUtilError {
|
||||
#[error("{0}")]
|
||||
InvalidRegexError(#[from] ErrorInvalidRegex)
|
||||
}
|
||||
InvalidRegexError(#[from] ErrorInvalidRegex),
|
||||
#[error("Parse error: {0}")]
|
||||
ParseError(#[from] ParseError),
|
||||
#[error("Extract number error: {0}")]
|
||||
ExtractNumberError(#[from] ExtractNumberError)
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Error)]
|
||||
pub enum ParseError {
|
||||
// Removed as OK variant
|
||||
// NoParsingError,
|
||||
#[error("Invalid country code")]
|
||||
InvalidCountryCodeError, // INVALID_COUNTRY_CODE in the java version.
|
||||
#[error("Not a number")]
|
||||
NotANumber,
|
||||
#[error("Too short after idd")]
|
||||
TooShortAfterIdd,
|
||||
#[error("Too short Nsn")]
|
||||
TooShortNsn,
|
||||
#[error("Too long nsn")]
|
||||
TooLongNsn, // TOO_LONG in the java version.
|
||||
#[error("{0}")]
|
||||
InvalidRegexError(#[from] ErrorInvalidRegex),
|
||||
#[error("{0}")]
|
||||
ParseNumberAsIntError(#[from] ParseIntError)
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Error)]
|
||||
pub enum ExtractNumberError {
|
||||
#[error("No valid start character found")]
|
||||
NoValidStartCharacter,
|
||||
#[error("Invalid number")]
|
||||
NotANumber,
|
||||
}
|
||||
|
||||
|
||||
31
src/phonenumberutil/helper_types.rs
Normal file
31
src/phonenumberutil/helper_types.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crate::proto_gen::phonenumber::phone_number::CountryCodeSource;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PhoneNumberWithCountryCodeSource<'a> {
|
||||
pub phone_number: Cow<'a, str>,
|
||||
pub country_code_source: CountryCodeSource
|
||||
}
|
||||
|
||||
impl<'a> PhoneNumberWithCountryCodeSource<'a> {
|
||||
pub fn new(phone_number: Cow<'a, str>, country_code_source: CountryCodeSource) -> Self {
|
||||
Self { phone_number, country_code_source }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PhoneNumberAndCarrierCode<'a> {
|
||||
pub carrier_code: Option<&'a str>,
|
||||
pub phone_number: Cow<'a, str>
|
||||
}
|
||||
|
||||
impl<'a> PhoneNumberAndCarrierCode<'a> {
|
||||
pub fn new<B: Into<Cow<'a, str>>>(carrier_code: Option<&'a str>, phone_number: B) -> Self {
|
||||
Self { carrier_code, phone_number: phone_number.into() }
|
||||
}
|
||||
|
||||
pub fn new_phone<B: Into<Cow<'a, str>>>(phone_number: B) -> Self {
|
||||
Self { carrier_code: None, phone_number: phone_number.into() }
|
||||
}
|
||||
}
|
||||
@@ -4,30 +4,15 @@ mod errors;
|
||||
mod enums;
|
||||
mod phonenumberutil;
|
||||
mod phone_number_regexps_and_mappings;
|
||||
pub(self) mod helper_types;
|
||||
|
||||
use std::sync::LazyLock;
|
||||
|
||||
pub use enums::{MatchType, PhoneNumberFormat, PhoneNumberType, ValidationResultErr, ValidNumberLenType};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::phonenumberutil::phonenumberutil::PhoneNumberUtil;
|
||||
// use crate::phonenumberutil::phonenumberutil::PhoneNumberUtil;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ErrorType {
|
||||
#[error("No parsing")]
|
||||
NoParsingError,
|
||||
#[error("Invalid country code")]
|
||||
InvalidCountryCodeError, // INVALID_COUNTRY_CODE in the java version.
|
||||
#[error("Not a number")]
|
||||
NotANumber,
|
||||
#[error("Too short after idd")]
|
||||
TooShortAfterIdd,
|
||||
#[error("Too short Nsn")]
|
||||
TooShortNsn,
|
||||
#[error("Too long nsn")]
|
||||
TooLongNsn, // TOO_LONG in the java version.
|
||||
}
|
||||
|
||||
static PHONE_NUMBER_UTIL: LazyLock<PhoneNumberUtil> = LazyLock::new(|| {
|
||||
PhoneNumberUtil::new()
|
||||
});
|
||||
// static PHONE_NUMBER_UTIL: LazyLock<PhoneNumberUtil> = LazyLock::new(|| {
|
||||
// PhoneNumberUtil::new()
|
||||
// });
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@ impl RegexBasedMatcher {
|
||||
|
||||
// find first occurrence
|
||||
if allow_prefix_match {
|
||||
Ok(regexp.consume_start(phone_number).is_some())
|
||||
Ok(regexp.matches_start(phone_number))
|
||||
} else {
|
||||
Ok(regexp.full_match(phone_number))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use regex::{Captures, Regex};
|
||||
use regex::{Captures, Match, Regex};
|
||||
|
||||
pub trait RegexFullMatch {
|
||||
/// Eq of C fullMatch
|
||||
@@ -8,18 +6,12 @@ pub trait RegexFullMatch {
|
||||
}
|
||||
|
||||
pub trait RegexConsume {
|
||||
/// Eq of C Consume
|
||||
fn consume_start<'a>(&self, s: &'a str) -> Option<Cow<'a, str>> {
|
||||
self.consume_start_capturing(s).map(| res| res.0)
|
||||
fn matches_start<'a>(&self, s: &'a str) -> bool {
|
||||
self.find_start(s).is_some()
|
||||
}
|
||||
|
||||
fn consume_start_capturing<'a>(&self, s: &'a str) -> Option<(Cow<'a, str>, Captures<'a>)>;
|
||||
|
||||
fn find_and_consume<'a>(&self, s: &'a str) -> Option<Cow<'a, str>> {
|
||||
self.find_and_consume_capturing(s).map(| res| res.0)
|
||||
}
|
||||
|
||||
fn find_and_consume_capturing<'a>(&self, s: &'a str) -> Option<(Cow<'a, str>, Captures<'a>)>;
|
||||
fn captures_start<'a>(&self, s: &'a str) -> Option<Captures<'a>>;
|
||||
fn find_start<'a>(&self, s: &'a str) -> Option<Match<'a>>;
|
||||
}
|
||||
|
||||
trait RegexMatchStart {
|
||||
@@ -48,24 +40,21 @@ impl RegexMatchStart for Regex {
|
||||
}
|
||||
|
||||
impl RegexConsume for Regex {
|
||||
fn consume_start_capturing<'a>(&self, s: &'a str) -> Option<(Cow<'a, str>, Captures<'a>)> {
|
||||
_consume(self, s, true)
|
||||
fn captures_start<'a>(&self, s: &'a str) -> Option<Captures<'a>> {
|
||||
let captures = self.captures(s)?;
|
||||
let full_capture = captures.get(0)?;
|
||||
if full_capture.start() != 0 {
|
||||
return None
|
||||
}
|
||||
|
||||
Some(captures)
|
||||
}
|
||||
|
||||
fn find_and_consume_capturing<'a>(&self, s: &'a str) -> Option<(Cow<'a, str>, Captures<'a>)> {
|
||||
_consume(self, s, false)
|
||||
fn find_start<'a>(&self, s: &'a str) -> Option<Match<'a>> {
|
||||
let found = self.find(s)?;
|
||||
if found.start() != 0 {
|
||||
return None
|
||||
}
|
||||
Some(found)
|
||||
}
|
||||
}
|
||||
|
||||
fn _consume<'a>(
|
||||
r: &Regex, input: &'a str,
|
||||
anchor_at_start: bool
|
||||
) -> Option<(Cow<'a, str>, Captures<'a>)> {
|
||||
let captures = r.captures(input)?;
|
||||
let full_capture = captures.get(0)?;
|
||||
if anchor_at_start && full_capture.start() != 0 {
|
||||
return None
|
||||
}
|
||||
|
||||
Some((Cow::Borrowed(&input[full_capture.end()..]), captures))
|
||||
}
|
||||
36
src/string_util.rs
Normal file
36
src/string_util.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
/// Strips prefix of given string Cow. Returns option with `Some` if
|
||||
/// prefix found and stripped.
|
||||
///
|
||||
/// Calls `drain` if string is owned and returns slice if string is borrowed
|
||||
pub fn strip_cow_prefix<'a>(cow: Cow<'a, str>, prefix: &str) -> Option<Cow<'a, str>> {
|
||||
match cow {
|
||||
Cow::Borrowed(s) => s.strip_prefix(prefix).map(| s | Cow::Borrowed(s)),
|
||||
Cow::Owned(mut s) => {
|
||||
if s.starts_with(prefix) {
|
||||
s.drain(0..prefix.len());
|
||||
return Some(Cow::Owned(s));
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crate::string_util::strip_cow_prefix;
|
||||
|
||||
#[test]
|
||||
fn test_usage() {
|
||||
let str_to_strip = Cow::Owned("test0:test".to_owned());
|
||||
let stripped = strip_cow_prefix(str_to_strip, "test0");
|
||||
assert_eq!(stripped, Some(Cow::Owned(":test".to_owned())));
|
||||
|
||||
let str_to_strip = Cow::Owned("test:test0".to_owned());
|
||||
let stripped = strip_cow_prefix(str_to_strip, "test0");
|
||||
assert_eq!(stripped, None)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user