mod allowed_tlds;
mod ip;
mod parenthesis_counter;
mod parse_link;
pub(crate) mod punycode_warning;
use nom::{
error::{ErrorKind, ParseError},
IResult, Slice,
};
pub use punycode_warning::PunycodeWarning;
use crate::parser::{link_url::parse_link::parse_link, parse_from_text::base_parsers::CustomError};
#[derive(Debug, PartialEq, Eq, Serialize, Clone)]
pub struct LinkDestination<'a> {
pub target: &'a str,
pub hostname: Option<&'a str>,
pub punycode: Option<PunycodeWarning>,
pub scheme: Option<&'a str>,
}
impl LinkDestination<'_> {
pub fn parse(input: &str) -> IResult<&str, LinkDestination, CustomError<&str>> {
if let Ok((rest, link_destination)) = parse_link(input) {
Ok((rest, link_destination))
} else {
Err(nom::Err::Error(CustomError::InvalidLink))
}
}
pub fn parse_labelled(input: &str) -> IResult<&str, LinkDestination, CustomError<&str>> {
let (mut remaining, mut link) = Self::parse(input)?;
if let Some(first) = remaining.chars().next() {
if matches!(first, ';' | '.' | ',' | ':' | '!') {
let point = link.target.len().saturating_add(1);
link.target = input.slice(..point);
remaining = input.slice(point..);
}
}
Ok((remaining, link))
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum LinkParseError<I> {
Nom(I, ErrorKind),
}
impl<I> ParseError<I> for LinkParseError<I> {
fn from_error_kind(input: I, kind: ErrorKind) -> Self {
LinkParseError::Nom(input, kind)
}
fn append(_: I, _: ErrorKind, other: Self) -> Self {
other
}
}