data_forms: Use the new helper macros to simplify parsing.
This commit is contained in:
parent
a2c7529668
commit
9f27f200ca
1 changed files with 51 additions and 58 deletions
|
|
@ -14,25 +14,35 @@ use ns;
|
||||||
|
|
||||||
use media_element::MediaElement;
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Option_ {
|
pub struct Option_ {
|
||||||
pub label: Option<String>,
|
pub label: Option<String>,
|
||||||
pub value: String,
|
pub value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Element> for Option_ {
|
||||||
|
type Err = Error;
|
||||||
|
|
||||||
|
fn try_from(elem: Element) -> Result<Option_, Error> {
|
||||||
|
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<Option_> for Element {
|
impl From<Option_> for Element {
|
||||||
fn from(option: Option_) -> Element {
|
fn from(option: Option_) -> Element {
|
||||||
Element::builder("option")
|
Element::builder("option")
|
||||||
|
|
@ -46,6 +56,19 @@ impl From<Option_> 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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Field {
|
pub struct Field {
|
||||||
pub var: String,
|
pub var: String,
|
||||||
|
|
@ -68,6 +91,8 @@ impl TryFrom<Element> for Field {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
fn try_from(elem: Element) -> Result<Field, Error> {
|
fn try_from(elem: Element) -> Result<Field, Error> {
|
||||||
|
check_self!(elem, "field", ns::DATA_FORMS);
|
||||||
|
check_no_unknown_attributes!(elem, "field", ["label", "type", "var"]);
|
||||||
let mut field = Field {
|
let mut field = Field {
|
||||||
var: get_attr!(elem, "var", required),
|
var: get_attr!(elem, "var", required),
|
||||||
type_: get_attr!(elem, "type", default),
|
type_: get_attr!(elem, "type", default),
|
||||||
|
|
@ -79,50 +104,27 @@ impl TryFrom<Element> for Field {
|
||||||
};
|
};
|
||||||
for element in elem.children() {
|
for element in elem.children() {
|
||||||
if element.is("value", ns::DATA_FORMS) {
|
if element.is("value", ns::DATA_FORMS) {
|
||||||
for _ in element.children() {
|
check_no_children!(element, "value");
|
||||||
return Err(Error::ParseError("Value element must not have any child."));
|
check_no_unknown_attributes!(element, "value", []);
|
||||||
}
|
|
||||||
for _ in element.attrs() {
|
|
||||||
return Err(Error::ParseError("Value element must not have any attribute."));
|
|
||||||
}
|
|
||||||
field.values.push(element.text());
|
field.values.push(element.text());
|
||||||
} else if element.is("required", ns::DATA_FORMS) {
|
} else if element.is("required", ns::DATA_FORMS) {
|
||||||
if field.required {
|
if field.required {
|
||||||
return Err(Error::ParseError("More than one required element."));
|
return Err(Error::ParseError("More than one required element."));
|
||||||
}
|
}
|
||||||
for _ in element.children() {
|
check_no_children!(element, "required");
|
||||||
return Err(Error::ParseError("Required element must not have any child."));
|
check_no_unknown_attributes!(element, "required", []);
|
||||||
}
|
|
||||||
for _ in element.attrs() {
|
|
||||||
return Err(Error::ParseError("Required element must not have any attribute."));
|
|
||||||
}
|
|
||||||
field.required = true;
|
field.required = true;
|
||||||
} else if element.is("option", ns::DATA_FORMS) {
|
} else if element.is("option", ns::DATA_FORMS) {
|
||||||
if !field.is_list() {
|
if !field.is_list() {
|
||||||
return Err(Error::ParseError("Option element found in non-list field."));
|
return Err(Error::ParseError("Option element found in non-list field."));
|
||||||
}
|
}
|
||||||
let label = get_attr!(element, "label", optional);
|
let option = Option_::try_from(element.clone())?;
|
||||||
let mut value = None;
|
field.options.push(option);
|
||||||
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,
|
|
||||||
});
|
|
||||||
} else if element.is("media", ns::MEDIA_ELEMENT) {
|
} else if element.is("media", ns::MEDIA_ELEMENT) {
|
||||||
let media_element = MediaElement::try_from(element.clone())?;
|
let media_element = MediaElement::try_from(element.clone())?;
|
||||||
field.media.push(media_element);
|
field.media.push(media_element);
|
||||||
} else {
|
} 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)
|
Ok(field)
|
||||||
|
|
@ -166,9 +168,8 @@ impl TryFrom<Element> for DataForm {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
fn try_from(elem: Element) -> Result<DataForm, Error> {
|
fn try_from(elem: Element) -> Result<DataForm, Error> {
|
||||||
if !elem.is("x", ns::DATA_FORMS) {
|
check_self!(elem, "x", ns::DATA_FORMS);
|
||||||
return Err(Error::ParseError("This is not a data form element."));
|
check_no_unknown_attributes!(elem, "x", ["type"]);
|
||||||
}
|
|
||||||
let type_ = get_attr!(elem, "type", required);
|
let type_ = get_attr!(elem, "type", required);
|
||||||
let mut form = DataForm {
|
let mut form = DataForm {
|
||||||
type_: type_,
|
type_: type_,
|
||||||
|
|
@ -182,23 +183,15 @@ impl TryFrom<Element> for DataForm {
|
||||||
if form.title.is_some() {
|
if form.title.is_some() {
|
||||||
return Err(Error::ParseError("More than one title in form element."));
|
return Err(Error::ParseError("More than one title in form element."));
|
||||||
}
|
}
|
||||||
for _ in child.children() {
|
check_no_children!(child, "title");
|
||||||
return Err(Error::ParseError("Title element must not have any child."));
|
check_no_unknown_attributes!(child, "title", []);
|
||||||
}
|
|
||||||
for _ in child.attrs() {
|
|
||||||
return Err(Error::ParseError("Title element must not have any attribute."));
|
|
||||||
}
|
|
||||||
form.title = Some(child.text());
|
form.title = Some(child.text());
|
||||||
} else if child.is("instructions", ns::DATA_FORMS) {
|
} else if child.is("instructions", ns::DATA_FORMS) {
|
||||||
if form.instructions.is_some() {
|
if form.instructions.is_some() {
|
||||||
return Err(Error::ParseError("More than one instructions in form element."));
|
return Err(Error::ParseError("More than one instructions in form element."));
|
||||||
}
|
}
|
||||||
for _ in child.children() {
|
check_no_children!(child, "instructions");
|
||||||
return Err(Error::ParseError("instructions element must not have any child."));
|
check_no_unknown_attributes!(child, "instructions", []);
|
||||||
}
|
|
||||||
for _ in child.attrs() {
|
|
||||||
return Err(Error::ParseError("instructions element must not have any attribute."));
|
|
||||||
}
|
|
||||||
form.instructions = Some(child.text());
|
form.instructions = Some(child.text());
|
||||||
} else if child.is("field", ns::DATA_FORMS) {
|
} else if child.is("field", ns::DATA_FORMS) {
|
||||||
let field = Field::try_from(child.clone())?;
|
let field = Field::try_from(child.clone())?;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue