From 9f27f200ca39d79520ae42aa7db5150396584830 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 10 Oct 2017 18:26:05 +0100 Subject: [PATCH] data_forms: Use the new helper macros to simplify parsing. --- src/data_forms.rs | 109 ++++++++++++++++++++++------------------------ 1 file changed, 51 insertions(+), 58 deletions(-) diff --git a/src/data_forms.rs b/src/data_forms.rs index 15135ef3df2edfde96108bf0015bce6bf59e46ed..e3a68f4680079b7069a89befb8de7ed4b16fca7b 100644 --- a/src/data_forms.rs +++ b/src/data_forms.rs @@ -14,25 +14,35 @@ use ns; use media_element::MediaElement; -generate_attribute!(FieldType, "type", { - Boolean => "boolean", - Fixed => "fixed", - Hidden => "hidden", - JidMulti => "jid-multi", - JidSingle => "jid-single", - ListMulti => "list-multi", - ListSingle => "list-single", - TextMulti => "text-multi", - TextPrivate => "text-private", - TextSingle => "text-single", -}, Default = TextSingle); - #[derive(Debug, Clone)] pub struct Option_ { pub label: Option, pub value: String, } +impl TryFrom for Option_ { + type Err = Error; + + fn try_from(elem: Element) -> Result { + check_self!(elem, "option", ns::DATA_FORMS); + check_no_unknown_attributes!(elem, "option", ["label"]); + let mut value = None; + for child in elem.children() { + if !child.is("value", ns::DATA_FORMS) { + return Err(Error::ParseError("Non-value element in option element")); + } + if value.is_some() { + return Err(Error::ParseError("More than one value element in option element")); + } + value = Some(child.text()); + } + Ok(Option_ { + label: get_attr!(elem, "label", optional), + value: value.ok_or(Error::ParseError("No value element in option element"))?, + }) + } +} + impl From for Element { fn from(option: Option_) -> Element { Element::builder("option") @@ -46,6 +56,19 @@ impl From for Element { } } +generate_attribute!(FieldType, "type", { + Boolean => "boolean", + Fixed => "fixed", + Hidden => "hidden", + JidMulti => "jid-multi", + JidSingle => "jid-single", + ListMulti => "list-multi", + ListSingle => "list-single", + TextMulti => "text-multi", + TextPrivate => "text-private", + TextSingle => "text-single", +}, Default = TextSingle); + #[derive(Debug, Clone)] pub struct Field { pub var: String, @@ -68,6 +91,8 @@ impl TryFrom for Field { type Err = Error; fn try_from(elem: Element) -> Result { + check_self!(elem, "field", ns::DATA_FORMS); + check_no_unknown_attributes!(elem, "field", ["label", "type", "var"]); let mut field = Field { var: get_attr!(elem, "var", required), type_: get_attr!(elem, "type", default), @@ -79,50 +104,27 @@ impl TryFrom for Field { }; for element in elem.children() { if element.is("value", ns::DATA_FORMS) { - for _ in element.children() { - return Err(Error::ParseError("Value element must not have any child.")); - } - for _ in element.attrs() { - return Err(Error::ParseError("Value element must not have any attribute.")); - } + check_no_children!(element, "value"); + check_no_unknown_attributes!(element, "value", []); field.values.push(element.text()); } else if element.is("required", ns::DATA_FORMS) { if field.required { return Err(Error::ParseError("More than one required element.")); } - for _ in element.children() { - return Err(Error::ParseError("Required element must not have any child.")); - } - for _ in element.attrs() { - return Err(Error::ParseError("Required element must not have any attribute.")); - } + check_no_children!(element, "required"); + check_no_unknown_attributes!(element, "required", []); field.required = true; } else if element.is("option", ns::DATA_FORMS) { if !field.is_list() { return Err(Error::ParseError("Option element found in non-list field.")); } - let label = get_attr!(element, "label", optional); - let mut value = None; - for child2 in element.children() { - if child2.is("value", ns::DATA_FORMS) { - if value.is_some() { - return Err(Error::ParseError("More than one value element in option element")); - } - value = Some(child2.text()); - } else { - return Err(Error::ParseError("Non-value element in option element")); - } - } - let value = value.ok_or(Error::ParseError("No value element in option element"))?; - field.options.push(Option_ { - label: label, - value: value, - }); + let option = Option_::try_from(element.clone())?; + field.options.push(option); } else if element.is("media", ns::MEDIA_ELEMENT) { let media_element = MediaElement::try_from(element.clone())?; field.media.push(media_element); } else { - return Err(Error::ParseError("Field child isn’t a value or media element.")); + return Err(Error::ParseError("Field child isn’t a value, option or media element.")); } } Ok(field) @@ -166,9 +168,8 @@ impl TryFrom for DataForm { type Err = Error; fn try_from(elem: Element) -> Result { - if !elem.is("x", ns::DATA_FORMS) { - return Err(Error::ParseError("This is not a data form element.")); - } + check_self!(elem, "x", ns::DATA_FORMS); + check_no_unknown_attributes!(elem, "x", ["type"]); let type_ = get_attr!(elem, "type", required); let mut form = DataForm { type_: type_, @@ -182,23 +183,15 @@ impl TryFrom for DataForm { if form.title.is_some() { return Err(Error::ParseError("More than one title in form element.")); } - for _ in child.children() { - return Err(Error::ParseError("Title element must not have any child.")); - } - for _ in child.attrs() { - return Err(Error::ParseError("Title element must not have any attribute.")); - } + check_no_children!(child, "title"); + check_no_unknown_attributes!(child, "title", []); form.title = Some(child.text()); } else if child.is("instructions", ns::DATA_FORMS) { if form.instructions.is_some() { return Err(Error::ParseError("More than one instructions in form element.")); } - for _ in child.children() { - return Err(Error::ParseError("instructions element must not have any child.")); - } - for _ in child.attrs() { - return Err(Error::ParseError("instructions element must not have any attribute.")); - } + check_no_children!(child, "instructions"); + check_no_unknown_attributes!(child, "instructions", []); form.instructions = Some(child.text()); } else if child.is("field", ns::DATA_FORMS) { let field = Field::try_from(child.clone())?;