1use crate::{error::Error, parse::Parse, IResult, Name};
2use nom::{
3 branch::alt,
4 bytes::complete::tag,
5 character::complete::{anychar, char},
6 combinator::{map, verify},
7 sequence::{pair, preceded, tuple},
8};
9
10pub trait ParseNamespace<'a>: Parse<'a> + Sized {
11 fn parse_namespace_attribute_name(input: &str) -> IResult<&str, Name> {
13 let (input, name) = alt((Self::parse_name, Self::parse_prefixed_attribute_name))(input)?;
14 if name.prefix.is_none() && name.local_part != "xmlns" {
15 return Err(nom::Err::Error(Error::NomError(nom::error::Error::new(
16 input.into(),
17 nom::error::ErrorKind::Verify,
18 ))));
19 }
20
21 Ok((input, name))
22 }
23
24 fn parse_prefixed_attribute_name(input: &str) -> IResult<&str, Name> {
26 map(
27 preceded(tag("xmlns:"), Self::parse_non_colonized_name),
28 |local_part| Name {
29 prefix: Some("xmlns".into()),
30 local_part,
31 },
32 )(input)
33 }
34
35 fn parse_non_colonized_name(input: &str) -> IResult<&str, String> {
37 map(
38 pair(
39 Self::parse_name_start_char,
40 nom::bytes::complete::take_while1(|c: char| Self::is_name_char(c) && c != ':'),
41 ),
42 |(start_char, rest_chars)| {
43 let mut name = start_char.to_string();
44 name.push_str(rest_chars);
45 name
46 },
47 )(input)
48 }
49
50 fn parse_non_colonized_name_char(input: &str) -> IResult<&str, char> {
52 verify(Self::parse_name_char, |c| *c != ':')(input)
53 }
54
55 fn parse_non_colonized_name_start_char(input: &str) -> IResult<&str, char> {
57 verify(anychar, |c| *c != ':')(input)
58 }
59
60 fn parse_qualified_name(input: &str) -> IResult<&str, Name> {
62 alt((
63 Self::parse_prefixed_name,
64 map(Self::parse_non_colonized_name, |local_part| Name {
65 prefix: None,
66 local_part,
67 }),
68 Self::parse_name, ))(input)
70 }
71
72 fn parse_prefixed_name(input: &str) -> IResult<&str, Name> {
74 map(
75 tuple((
76 Self::parse_non_colonized_name,
77 char(':'),
78 Self::parse_non_colonized_name,
79 )),
80 |(prefix, _colon_literal, local_part)| Name {
81 prefix: Some(prefix),
82 local_part,
83 },
84 )(input)
85 }
86
87 }