1use crate::item::Node;
2use crate::parser::combinators::alt::alt2;
3use crate::parser::combinators::many::many1;
4use crate::parser::combinators::map::{map, map_with_state_and_result};
5use crate::parser::combinators::opt::opt;
6use crate::parser::combinators::pair::pair;
7use crate::parser::combinators::support::none_of;
8use crate::parser::combinators::tag::tag;
9use crate::parser::combinators::take::{take_one, take_while};
10use crate::parser::combinators::tuple::{tuple2, tuple3};
11use crate::parser::combinators::wellformed::wellformed;
13use crate::parser::common::{is_namechar, is_namestartchar, is_ncnamechar, is_ncnamestartchar};
14use crate::parser::xml::dtd::pereference::petextreference;
15use crate::parser::{ParseError, ParseInput, StaticState};
16use qualname::{NamespacePrefix, NamespaceUri, NcName, QName};
17
18pub(crate) fn qualname_to_qname<'a, N: Node, L>()
20-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, QName), ParseError>
21where
22 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
23{
24 alt2(prefixed_name_to_qname(), unprefixed_name_to_qname())
25}
26
27pub(crate) fn qualname_to_parts<'a, N: Node, L>() -> impl Fn(
30 ParseInput<'a, N>,
31 &mut StaticState<L>,
32) -> Result<
33 (ParseInput<'a, N>, (Option<String>, String)),
34 ParseError,
35>
36where
37 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
38{
39 alt2(prefixed_name_to_parts(), unprefixed_name_to_parts())
40}
41
42#[allow(dead_code)]
45pub(crate) fn eqname_to_qname<'a, N: Node, L>()
46-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, QName), ParseError>
47where
48 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
49{
50 alt2(uriqualname(), qualname_to_qname())
51}
52#[allow(dead_code)]
54pub(crate) fn uriqualname<'a, N: Node, L>()
55-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, QName), ParseError>
56where
57 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
58{
59 map(
60 pair(
61 tuple3(
62 tag("Q{"),
63 map(many1(none_of("{}")), |v| {
64 v.iter().fold(String::new(), |mut s, w| {
65 s.push_str(w);
66 s
67 })
68 }),
69 tag("}"),
72 ),
73 ncname(),
74 ),
75 |((_, uri, _), localpart)| {
76 QName::new_from_parts(
77 NcName::try_from(localpart.as_str()).expect("not a valid NcName"),
78 Some(NamespaceUri::try_from(uri.as_str()).expect("not a valid XML Namespace URI")),
79 )
80 },
81 )
82}
83
84fn unprefixed_name_to_qname<'a, N: Node, L>()
85-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, QName), ParseError>
86where
87 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
88{
89 map(alt2(petextreference(), ncname()), |localpart| {
90 QName::from_local_name(NcName::try_from(localpart.as_str()).expect("not a valid QName")) })
92}
93fn unprefixed_name_to_parts<'a, N: Node, L>() -> impl Fn(
94 ParseInput<'a, N>,
95 &mut StaticState<L>,
96) -> Result<
97 (ParseInput<'a, N>, (Option<String>, String)),
98 ParseError,
99>
100where
101 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
102{
103 map(alt2(petextreference(), ncname()), |localpart| {
104 (None, localpart)
105 })
106}
107fn prefixed_name_to_parts<'a, N: Node, L>() -> impl Fn(
108 ParseInput<'a, N>,
109 &mut StaticState<L>,
110) -> Result<
111 (ParseInput<'a, N>, (Option<String>, String)),
112 ParseError,
113>
114where
115 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
116{
117 map(
118 tuple3(
119 alt2(petextreference(), ncname()),
120 tag(":"),
121 alt2(petextreference(), ncname()),
122 ),
123 |(prefix, _, localpart)| (Some(prefix), localpart),
124 )
125}
126fn prefixed_name_to_qname<'a, N: Node, L>()
127-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, QName), ParseError>
128where
129 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
130{
131 map_with_state_and_result(
132 tuple3(
133 alt2(petextreference::<N, L>(), ncname()),
134 tag(":"),
135 alt2(petextreference::<N, L>(), ncname()),
136 ),
137 |(prefix, _, localpart), _state, ss| {
138 if let Some(f) = &mut ss.namespace {
139 if let Ok(uri) = f(&NamespacePrefix::try_from(prefix.as_str()).unwrap()) {
140 if let Ok(lp) = NcName::try_from(localpart.as_str()) {
141 Ok(QName::new_from_parts(lp, Some(uri)))
142 } else {
143 Err(ParseError::NSResolveError(format!(
144 "name \"{}\" is not valid",
145 localpart
146 )))
147 }
148 } else {
149 Err(ParseError::NSResolveError(format!(
150 "namespace resolver failed on prefix \"{}\"",
151 prefix
152 )))
153 }
154 } else {
155 Err(ParseError::NSResolveError(String::from(
157 "no closure to resolve prefix",
158 )))
159 }
160 },
161 )
162}
163
164pub(crate) fn ncname<'a, N: Node, L>()
169-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, String), ParseError>
170where
171 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
172{
173 map(
174 tuple2(
175 wellformed(
176 take_one(),
177 is_ncnamestartchar,
178 "invalid character in NcName",
179 ),
180 opt(take_while(|c| is_ncnamechar(&c))),
181 ),
182 |(a, b)| [a.to_string(), b.unwrap_or_default()].concat(),
183 )
184}
185
186pub(crate) fn name<'a, N: Node, L>()
188-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, String), ParseError>
189where
190 L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
191{
192 map(
193 tuple2(
194 wellformed(take_one(), is_namestartchar, "invalid name start character"),
195 opt(take_while(|c| is_namechar(&c))),
196 ),
197 |(nsc, nc)| match nc {
198 None => nsc.to_string(),
199 Some(nc) => [nsc.to_string(), nc].concat(),
200 },
201 )
202}