parsers: port SASL over to derive macros
You may note that I removed the `exhaustive` flag on the DefinedCondition enum. This is because other elements in the same namespace may occur as siblings of that enum, hence using `exhaustive` may cause incorrect parse errors. (If parsing attempts to process the `<text/>` child as DefinedCondition first, DefinedCondition will return a fatal parser error if it is set as exhaustive because no condition matches `text`.)
This commit is contained in:
parent
1ecb95881c
commit
cbc4648b3c
1 changed files with 11 additions and 71 deletions
|
|
@ -4,14 +4,9 @@
|
|||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
use xso::{
|
||||
error::{Error, FromElementError},
|
||||
text::Base64,
|
||||
AsXml, FromXml,
|
||||
};
|
||||
use xso::{text::Base64, AsXml, FromXml};
|
||||
|
||||
use crate::ns;
|
||||
use minidom::Element;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
generate_attribute!(
|
||||
|
|
@ -99,7 +94,7 @@ pub struct Success {
|
|||
|
||||
/// List of possible failure conditions for SASL.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::SASL, exhaustive)]
|
||||
#[xml(namespace = ns::SASL)]
|
||||
pub enum DefinedCondition {
|
||||
/// The client aborted the authentication with
|
||||
/// [abort](struct.Abort.html).
|
||||
|
|
@ -153,82 +148,27 @@ pub enum DefinedCondition {
|
|||
type Lang = String;
|
||||
|
||||
/// Sent by the server on SASL failure.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(FromXml, AsXml, Debug, Clone)]
|
||||
#[xml(namespace = ns::SASL, name = "failure")]
|
||||
pub struct Failure {
|
||||
/// One of the allowed defined-conditions for SASL.
|
||||
#[xml(child)]
|
||||
pub defined_condition: DefinedCondition,
|
||||
|
||||
/// A human-readable explanation for the failure.
|
||||
#[xml(extract(n = .., name = "text", fields(
|
||||
attribute(type_ = String, name = "xml:lang"),
|
||||
text(type_ = String),
|
||||
)))]
|
||||
pub texts: BTreeMap<Lang, String>,
|
||||
}
|
||||
|
||||
impl TryFrom<Element> for Failure {
|
||||
type Error = FromElementError;
|
||||
|
||||
fn try_from(root: Element) -> Result<Failure, FromElementError> {
|
||||
check_self!(root, "failure", SASL);
|
||||
check_no_attributes!(root, "failure");
|
||||
|
||||
let mut defined_condition = None;
|
||||
let mut texts = BTreeMap::new();
|
||||
|
||||
for child in root.children() {
|
||||
if child.is("text", ns::SASL) {
|
||||
check_no_unknown_attributes!(child, "text", ["xml:lang"]);
|
||||
check_no_children!(child, "text");
|
||||
let lang = get_attr!(child, "xml:lang", Default);
|
||||
if texts.insert(lang, child.text()).is_some() {
|
||||
return Err(Error::Other(
|
||||
"Text element present twice for the same xml:lang in failure element.",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
} else if child.has_ns(ns::SASL) {
|
||||
if defined_condition.is_some() {
|
||||
return Err(Error::Other(
|
||||
"Failure must not have more than one defined-condition.",
|
||||
)
|
||||
.into());
|
||||
}
|
||||
check_no_attributes!(child, "defined-condition");
|
||||
check_no_children!(child, "defined-condition");
|
||||
let condition = match DefinedCondition::try_from(child.clone()) {
|
||||
Ok(condition) => condition,
|
||||
// TODO: do we really want to eat this error?
|
||||
Err(_) => DefinedCondition::NotAuthorized,
|
||||
};
|
||||
defined_condition = Some(condition);
|
||||
} else {
|
||||
return Err(Error::Other("Unknown element in Failure.").into());
|
||||
}
|
||||
}
|
||||
let defined_condition =
|
||||
defined_condition.ok_or(Error::Other("Failure must have a defined-condition."))?;
|
||||
|
||||
Ok(Failure {
|
||||
defined_condition,
|
||||
texts,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Failure> for Element {
|
||||
fn from(failure: Failure) -> Element {
|
||||
Element::builder("failure", ns::SASL)
|
||||
.append(failure.defined_condition)
|
||||
.append_all(failure.texts.into_iter().map(|(lang, text)| {
|
||||
Element::builder("text", ns::SASL)
|
||||
.attr("xml:lang", lang)
|
||||
.append(text)
|
||||
}))
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use minidom::Element;
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
#[test]
|
||||
fn test_size() {
|
||||
|
|
|
|||
Loading…
Reference in a new issue