use super::AsStr;
use crate::error::Error;
pub use crate::i18n::InvalidUrl;
pub fn apply<T: Url>(v: &T, _: ()) -> Result<(), Error> {
if let Err(e) = v.validate_url() {
return Err(Error::new(i18n!(url_invalid, e)));
}
Ok(())
}
pub trait Url {
fn validate_url(&self) -> Result<(), InvalidUrl>;
}
impl<T: AsStr> Url for T {
fn validate_url(&self) -> Result<(), InvalidUrl> {
url::Url::parse(self.as_str())
.map(|_| ())
.map_err(InvalidUrl::from)
}
}
impl<T: Url> Url for Option<T> {
fn validate_url(&self) -> Result<(), InvalidUrl> {
match self {
Some(value) => value.validate_url(),
None => Ok(()),
}
}
}
impl From<url::ParseError> for InvalidUrl {
fn from(e: url::ParseError) -> Self {
match e {
url::ParseError::EmptyHost => InvalidUrl::EmptyHost,
url::ParseError::IdnaError => InvalidUrl::IdnaError,
url::ParseError::InvalidPort => InvalidUrl::InvalidPort,
url::ParseError::InvalidIpv4Address => InvalidUrl::InvalidIpv4Address,
url::ParseError::InvalidIpv6Address => InvalidUrl::InvalidIpv6Address,
url::ParseError::InvalidDomainCharacter => InvalidUrl::InvalidDomainCharacter,
url::ParseError::RelativeUrlWithoutBase => InvalidUrl::RelativeUrlWithoutBase,
url::ParseError::RelativeUrlWithCannotBeABaseBase => {
InvalidUrl::RelativeUrlWithCannotBeABaseBase
}
url::ParseError::SetHostOnCannotBeABaseUrl => InvalidUrl::SetHostOnCannotBeABaseUrl,
url::ParseError::Overflow => InvalidUrl::Overflow,
_ => InvalidUrl::Other,
}
}
}
impl super::length::HasSimpleLength for url::Url {
fn length(&self) -> usize {
self.as_str().len()
}
}
impl super::length::HasChars for url::Url {
fn num_chars(&self) -> usize {
self.as_str().chars().count()
}
}
#[cfg(feature = "unicode")]
impl super::length::HasGraphemes for url::Url {
fn num_graphemes(&self) -> usize {
use unicode_segmentation::UnicodeSegmentation;
self.as_str().graphemes(true).count()
}
}
impl super::length::HasBytes for url::Url {
fn num_bytes(&self) -> usize {
self.as_str().len()
}
}
impl super::length::HasUtf16CodeUnits for url::Url {
fn num_code_units(&self) -> usize {
self.as_str().encode_utf16().count()
}
}