use std::ops::Deref;
use std::sync::Arc;
#[cfg(feature = "global_static")]
use std::sync::LazyLock;
use crate::alternate_formats::AlternateFormats;
use crate::enums::Region;
use crate::interfaces::AsOriginal;
use crate::phonenumber_matcher::leniency::Leniency;
use crate::phonenumber_matcher::matcher_internal::{
PhoneNumberMatcher, PhoneNumberMatcherFallible,
};
use crate::phonenumber_matcher::matcher_regex::MatcherRegex;
use crate::phonenumberutil::phonenumberutil_internal::PhoneNumberUtilInternal;
#[cfg(feature = "global_static")]
use crate::{PHONE_NUMBER_UTIL, PhoneNumberUtil};
#[derive(Clone)]
pub struct PhoneNumberMatcherFactory<
U: AsOriginal<PhoneNumberUtilInternal>,
T: Deref<Target = U> + Clone,
> {
regexps: Arc<MatcherRegex>,
alternate_formats: Option<Arc<AlternateFormats>>,
phone_util: T,
}
impl<U: AsOriginal<PhoneNumberUtilInternal>, T: Deref<Target = U> + Clone>
PhoneNumberMatcherFactory<U, T>
{
#[cfg(feature = "builtin_metadata")]
pub fn new_for_util(phone_util: T) -> Self {
Self::new_for_util_with_formats(phone_util, Some(Arc::new(AlternateFormats::new())))
}
pub fn new_for_util_with_formats(
phone_util: T,
formats: Option<Arc<AlternateFormats>>,
) -> Self {
Self {
alternate_formats: formats,
phone_util,
regexps: Arc::new(MatcherRegex::new()),
}
}
pub fn matcher_builder<'a, 'f>(&'f self, text: &'a str) -> MatcherBuilder<'a, 'f, U, T> {
MatcherBuilder::new(self, text)
}
pub fn create_matcher<'a>(
&self,
text: &'a str,
leniency: Leniency,
max_tries: u64,
preferred_region: Option<Region>,
) -> PhoneNumberMatcher<'a, U, T> {
PhoneNumberMatcher::new_for_util(
self.phone_util.clone(),
self.regexps.clone(),
text,
preferred_region,
leniency,
max_tries,
self.alternate_formats.clone(),
)
}
pub fn create_matcher_fallible<'a>(
&self,
text: &'a str,
leniency: Leniency,
max_tries: u64,
preferred_region: Option<Region>,
) -> PhoneNumberMatcherFallible<'a, U, T> {
PhoneNumberMatcherFallible::new_for_util(
self.phone_util.clone(),
self.regexps.clone(),
text,
preferred_region,
leniency,
max_tries,
self.alternate_formats.clone(),
)
}
}
#[cfg(feature = "global_static")]
impl PhoneNumberMatcherFactory<PhoneNumberUtil, &'static PhoneNumberUtil> {
pub fn new() -> Self {
Self::new_for_util(&PHONE_NUMBER_UTIL)
}
}
#[cfg(feature = "global_static")]
impl Default for PhoneNumberMatcherFactory<PhoneNumberUtil, &'static PhoneNumberUtil> {
fn default() -> Self {
Self::new()
}
}
pub struct MatcherBuilder<
'a,
'f,
U: AsOriginal<PhoneNumberUtilInternal>,
T: Deref<Target = U> + Clone,
> {
factory: &'f PhoneNumberMatcherFactory<U, T>,
text: &'a str,
leniency: Leniency,
max_tries: u64,
preferred_region: Option<Region>,
}
impl<'a, 'f, U: AsOriginal<PhoneNumberUtilInternal>, T: Deref<Target = U> + Clone>
MatcherBuilder<'a, 'f, U, T>
{
fn new(factory: &'f PhoneNumberMatcherFactory<U, T>, text: &'a str) -> Self {
Self {
factory,
text,
leniency: Leniency::Valid, max_tries: u64::MAX, preferred_region: None,
}
}
pub fn leniency(mut self, leniency: Leniency) -> Self {
self.leniency = leniency;
self
}
pub fn max_tries(mut self, max_tries: u64) -> Self {
self.max_tries = max_tries;
self
}
pub fn preferred_region(mut self, region: impl Into<Option<Region>>) -> Self {
self.preferred_region = region.into();
self
}
pub fn build(self) -> PhoneNumberMatcher<'a, U, T> {
self.factory.create_matcher(
self.text,
self.leniency,
self.max_tries,
self.preferred_region,
)
}
pub fn build_fallible(self) -> PhoneNumberMatcherFallible<'a, U, T> {
self.factory.create_matcher_fallible(
self.text,
self.leniency,
self.max_tries,
self.preferred_region,
)
}
}
#[cfg(feature = "global_static")]
pub static PHONE_MATCHER_FACTORY: LazyLock<
PhoneNumberMatcherFactory<PhoneNumberUtil, &'static PhoneNumberUtil>,
> = LazyLock::new(PhoneNumberMatcherFactory::new);
#[cfg(feature = "global_static")]
pub trait FindNumberExt {
fn find_phone_numbers(
&self,
) -> PhoneNumberMatcher<'_, PhoneNumberUtil, &'static PhoneNumberUtil>;
fn find_phone_numbers_with_leniency(
&self,
leniency: Leniency,
) -> PhoneNumberMatcher<'_, PhoneNumberUtil, &'static PhoneNumberUtil>;
fn find_phone_numbers_with_preferred_region(
&self,
region: impl Into<Option<Region>>,
) -> PhoneNumberMatcher<'_, PhoneNumberUtil, &'static PhoneNumberUtil>;
fn phone_number_matcher_builder(
&self,
) -> MatcherBuilder<'_, 'static, PhoneNumberUtil, &'static PhoneNumberUtil>;
}
#[cfg(feature = "global_static")]
impl FindNumberExt for str {
fn find_phone_numbers(
&self,
) -> PhoneNumberMatcher<'_, PhoneNumberUtil, &'static PhoneNumberUtil> {
self.phone_number_matcher_builder().build()
}
fn find_phone_numbers_with_leniency(
&self,
leniency: Leniency,
) -> PhoneNumberMatcher<'_, PhoneNumberUtil, &'static PhoneNumberUtil> {
self.phone_number_matcher_builder()
.leniency(leniency)
.build()
}
fn find_phone_numbers_with_preferred_region(
&self,
region: impl Into<Option<Region>>,
) -> PhoneNumberMatcher<'_, PhoneNumberUtil, &'static PhoneNumberUtil> {
self.phone_number_matcher_builder()
.preferred_region(region)
.build()
}
fn phone_number_matcher_builder(
&self,
) -> MatcherBuilder<'_, 'static, PhoneNumberUtil, &'static PhoneNumberUtil> {
PHONE_MATCHER_FACTORY.matcher_builder(self)
}
}