use std::{
convert::Infallible,
fmt::{Debug, Display},
num::ParseIntError,
};
use thiserror::Error;
#[derive(Debug, PartialEq, Error, Clone)]
#[error("An error occurred while trying to create regex: {0}")]
pub struct InvalidRegexError(#[from] crate::regexp::Error);
#[derive(Debug, PartialEq, Error)]
pub enum ParseError {
#[error("Invalid country code")]
InvalidCountryCode,
#[error("Not a number: {0}")]
NotANumber(#[from] NotANumberError),
#[error("Too short after idd")]
TooShortAfterIdd,
#[error("Too short Nsn")]
TooShortNsn,
#[error("Too long nsn")]
TooLongNsn,
}
#[derive(Debug, PartialEq, Error)]
pub enum NotANumberError {
#[error("Number not matched a valid number pattern")]
NotMatchedValidNumberPattern,
#[error("Invalid phone context")]
InvalidPhoneContext,
#[error("{0}")]
FailedToParseNumberAsInt(#[from] ParseIntError),
#[error("{0}")]
FailedToExtractNumber(#[from] ExtractNumberError),
}
#[derive(Debug, PartialEq, Error)]
pub enum ExtractNumberError {
#[error("No valid start character found")]
NoValidStartCharacter,
#[error("Invalid number")]
NotANumber,
}
#[derive(Debug, PartialEq, Error)]
pub enum InternalError<T: Debug + Display> {
#[error("Wrapped error: {0}")]
Wrapped(T),
#[error("{0}")]
RegexError(#[from] InvalidRegexError),
}
pub type InternalRegexError = InternalError<Infallible>;
impl<T: Debug + Display> InternalError<T> {
pub fn translate<O: From<T> + Debug + Display>(self) -> InternalError<O> {
match self {
Self::RegexError(e) => InternalError::RegexError(e),
Self::Wrapped(e) => InternalError::Wrapped(e.into()),
}
}
}
impl InternalError<Infallible> {
pub fn translate_internal<O: Debug + Display>(self) -> InternalError<O> {
match self {
InternalError::RegexError(invalid_regex_error) => {
InternalError::RegexError(invalid_regex_error)
}
}
}
}
macro_rules! delegate_from {
($inner:ty : $($t:ty),*) => {
impl From<$inner> for InternalError<$inner> {
fn from(value: $inner) -> Self {
Self::Wrapped(value)
}
}
$(
impl From<$t> for InternalError<$inner> {
fn from(value: $t) -> Self {
InternalError::from(<$inner>::from(value))
}
}
)*
};
}
delegate_from!(GetExampleNumberError: ParseError);
delegate_from!(ParseError: NotANumberError);
delegate_from!(NotANumberError: ExtractNumberError);
#[derive(Debug, PartialEq, Error)]
pub enum GetExampleNumberError {
#[error("Parse error: {0}")]
FailedToParse(#[from] ParseError),
#[error("No example number")]
NoExampleNumber,
#[error("Could not get number")]
CouldNotGetNumber,
#[error("Invalid country code provided")]
InvalidRegionCode,
}
#[derive(Error, Debug, PartialEq)]
#[error("Invalid number given")]
pub struct InvalidNumberError(#[from] pub ParseError);
#[derive(Debug, Error, PartialEq)]
#[error("Metadata for valid region MUST not be null")]
pub struct InvalidMetadataForValidRegionError;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Error)]
pub enum ValidationError {
#[error("The number has an invalid country calling code")]
InvalidCountryCode,
#[error("The number is shorter than all valid numbers for this region")]
TooShort,
#[error(
"\
The number is longer than the shortest valid numbers for this region,\
shorter than the longest valid numbers for this region, and does not\
itself have a number length that matches valid numbers for this region\
"
)]
InvalidLength,
#[error("The number is longer than all valid numbers for this region")]
TooLong,
}
pub(crate) fn unwrap_internal<T: Debug + Display>(err: InternalError<T>) -> T {
match err {
InternalError::Wrapped(err) => err,
InternalError::RegexError(invalid_regex_error) => panic!(
"A valid regex is expected in metadata; this indicates a library bug: {}",
invalid_regex_error
),
}
}