use crate::item::Node;
use crate::parser::combinators::alt::alt2;
use crate::parser::combinators::many::many1;
use crate::parser::combinators::map::{map, map_with_state_and_result};
use crate::parser::combinators::opt::opt;
use crate::parser::combinators::pair::pair;
use crate::parser::combinators::support::none_of;
use crate::parser::combinators::tag::tag;
use crate::parser::combinators::take::{take_one, take_while};
use crate::parser::combinators::tuple::{tuple2, tuple3};
use crate::parser::combinators::wellformed::wellformed;
use crate::parser::common::{is_namechar, is_namestartchar, is_ncnamechar, is_ncnamestartchar};
use crate::parser::xml::dtd::pereference::petextreference;
use crate::parser::{ParseError, ParseInput, StaticState};
use qualname::{NamespacePrefix, NamespaceUri, NcName, QName};
pub(crate) fn qualname_to_qname<'a, N: Node, L>()
-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, QName), ParseError>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
{
alt2(prefixed_name_to_qname(), unprefixed_name_to_qname())
}
pub(crate) fn qualname_to_parts<'a, N: Node, L>() -> impl Fn(
ParseInput<'a, N>,
&mut StaticState<L>,
) -> Result<
(ParseInput<'a, N>, (Option<String>, String)),
ParseError,
>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
{
alt2(prefixed_name_to_parts(), unprefixed_name_to_parts())
}
#[allow(dead_code)]
pub(crate) fn eqname_to_qname<'a, N: Node, L>()
-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, QName), ParseError>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
{
alt2(uriqualname(), qualname_to_qname())
}
#[allow(dead_code)]
pub(crate) fn uriqualname<'a, N: Node, L>()
-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, QName), ParseError>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
{
map(
pair(
tuple3(
tag("Q{"),
map(many1(none_of("{}")), |v| {
v.iter().fold(String::new(), |mut s, w| {
s.push_str(w);
s
})
}),
tag("}"),
),
ncname(),
),
|((_, uri, _), localpart)| {
QName::new_from_parts(
NcName::try_from(localpart.as_str()).expect("not a valid NcName"),
Some(NamespaceUri::try_from(uri.as_str()).expect("not a valid XML Namespace URI")),
)
},
)
}
fn unprefixed_name_to_qname<'a, N: Node, L>()
-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, QName), ParseError>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
{
map(alt2(petextreference(), ncname()), |localpart| {
QName::from_local_name(NcName::try_from(localpart.as_str()).expect("not a valid QName")) })
}
fn unprefixed_name_to_parts<'a, N: Node, L>() -> impl Fn(
ParseInput<'a, N>,
&mut StaticState<L>,
) -> Result<
(ParseInput<'a, N>, (Option<String>, String)),
ParseError,
>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
{
map(alt2(petextreference(), ncname()), |localpart| {
(None, localpart)
})
}
fn prefixed_name_to_parts<'a, N: Node, L>() -> impl Fn(
ParseInput<'a, N>,
&mut StaticState<L>,
) -> Result<
(ParseInput<'a, N>, (Option<String>, String)),
ParseError,
>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
{
map(
tuple3(
alt2(petextreference(), ncname()),
tag(":"),
alt2(petextreference(), ncname()),
),
|(prefix, _, localpart)| (Some(prefix), localpart),
)
}
fn prefixed_name_to_qname<'a, N: Node, L>()
-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, QName), ParseError>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
{
map_with_state_and_result(
tuple3(
alt2(petextreference::<N, L>(), ncname()),
tag(":"),
alt2(petextreference::<N, L>(), ncname()),
),
|(prefix, _, localpart), _state, ss| {
if let Some(f) = &mut ss.namespace {
if let Ok(uri) = f(&NamespacePrefix::try_from(prefix.as_str()).unwrap()) {
if let Ok(lp) = NcName::try_from(localpart.as_str()) {
Ok(QName::new_from_parts(lp, Some(uri)))
} else {
Err(ParseError::NSResolveError(format!(
"name \"{}\" is not valid",
localpart
)))
}
} else {
Err(ParseError::NSResolveError(format!(
"namespace resolver failed on prefix \"{}\"",
prefix
)))
}
} else {
Err(ParseError::NSResolveError(String::from(
"no closure to resolve prefix",
)))
}
},
)
}
pub(crate) fn ncname<'a, N: Node, L>()
-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, String), ParseError>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
{
map(
tuple2(
wellformed(
take_one(),
is_ncnamestartchar,
"invalid character in NcName",
),
opt(take_while(|c| is_ncnamechar(&c))),
),
|(a, b)| [a.to_string(), b.unwrap_or_default()].concat(),
)
}
pub(crate) fn name<'a, N: Node, L>()
-> impl Fn(ParseInput<'a, N>, &mut StaticState<L>) -> Result<(ParseInput<'a, N>, String), ParseError>
where
L: FnMut(&NamespacePrefix) -> Result<NamespaceUri, ParseError>,
{
map(
tuple2(
wellformed(take_one(), is_namestartchar, "invalid name start character"),
opt(take_while(|c| is_namechar(&c))),
),
|(nsc, nc)| match nc {
None => nsc.to_string(),
Some(nc) => [nsc.to_string(), nc].concat(),
},
)
}