use std::borrow::Cow;
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::{anychar, char},
combinator::{map, verify},
sequence::tuple,
IResult,
};
use crate::parse::Parse;
#[derive(Clone, PartialEq)]
pub struct QualifiedName<'a> {
pub prefix: Option<Cow<'a, str>>,
pub local_part: Cow<'a, str>,
}
pub trait ParseNamespace<'a>: Parse<'a> + Sized {
fn parse_namespace_attribute_name(input: &'a str) -> IResult<&'a str, Cow<'a, str>> {
let (input, name) = alt((
Self::parse_prefixed_attribute_name,
map(tag("xmlns"), Cow::Borrowed),
))(input)?;
Ok((input, name))
}
fn parse_prefixed_attribute_name(input: &'a str) -> IResult<&'a str, Cow<'a, str>> {
let (input, _) = tag("xmlns:")(input)?;
let (input, name) = Self::parse_non_colonized_name(input)?;
Ok((input, name))
}
fn parse_non_colonized_name(input: &'a str) -> IResult<&'a str, Cow<'a, str>> {
let (input, valid_name) =
verify(Self::parse_name, |name: &Cow<str>| !name.contains(':'))(input)?;
Ok((input, valid_name))
}
fn parse_non_colonized_name_char(input: &'a str) -> IResult<&'a str, char> {
let (input, valid_char) = verify(Self::parse_name_char, |c| *c != ':')(input)?;
Ok((input, valid_char))
}
fn parse_non_colonized_name_start_char(input: &'a str) -> IResult<&'a str, char> {
let (input, valid_char) = verify(anychar, |c| *c != ':')(input)?;
Ok((input, valid_char))
}
fn parse_qualified_name(input: &'a str) -> IResult<&'a str, QualifiedName> {
alt((
Self::parse_prefixed_name,
map(Self::parse_non_colonized_name, |local_part| QualifiedName {
prefix: None,
local_part,
}),
))(input)
}
fn parse_prefixed_name(input: &'a str) -> IResult<&'a str, QualifiedName<'a>> {
map(
tuple((
Self::parse_non_colonized_name,
char(':'),
Self::parse_non_colonized_name,
)),
|(prefix, _, local_part)| QualifiedName {
prefix: Some(prefix),
local_part,
},
)(input)
}
}