mirror of
https://gitlab.com/xmpp-rs/xmpp-rs.git
synced 2024-07-12 22:21:53 +00:00
data_forms: Split field parsing into its own TryFrom impl.
This commit is contained in:
parent
37d1ae64ad
commit
58760fc28d
1 changed files with 74 additions and 64 deletions
|
@ -57,6 +57,78 @@ pub struct Field {
|
||||||
pub media: Vec<MediaElement>,
|
pub media: Vec<MediaElement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Field {
|
||||||
|
fn is_list(&self) -> bool {
|
||||||
|
self.type_ == FieldType::ListSingle ||
|
||||||
|
self.type_ == FieldType::ListMulti
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Element> for Field {
|
||||||
|
type Err = Error;
|
||||||
|
|
||||||
|
fn try_from(elem: Element) -> Result<Field, Error> {
|
||||||
|
let mut field = Field {
|
||||||
|
var: get_attr!(elem, "var", required),
|
||||||
|
type_: get_attr!(elem, "type", default),
|
||||||
|
label: get_attr!(elem, "label", optional),
|
||||||
|
required: false,
|
||||||
|
options: vec!(),
|
||||||
|
values: vec!(),
|
||||||
|
media: vec!(),
|
||||||
|
};
|
||||||
|
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."));
|
||||||
|
}
|
||||||
|
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."));
|
||||||
|
}
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
} 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."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(field)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Field> for Element {
|
impl From<Field> for Element {
|
||||||
fn from(field: Field) -> Element {
|
fn from(field: Field) -> Element {
|
||||||
Element::builder("field")
|
Element::builder("field")
|
||||||
|
@ -129,70 +201,8 @@ impl TryFrom<Element> for DataForm {
|
||||||
}
|
}
|
||||||
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 var: String = get_attr!(child, "var", required);
|
let field = Field::try_from(child.clone())?;
|
||||||
let field_type = get_attr!(child, "type", default);
|
if field.var == "FORM_TYPE" && field.type_ == FieldType::Hidden {
|
||||||
let label = get_attr!(child, "label", optional);
|
|
||||||
|
|
||||||
let is_form_type = var == "FORM_TYPE" && field_type == FieldType::Hidden;
|
|
||||||
let is_list = field_type == FieldType::ListSingle || field_type == FieldType::ListMulti;
|
|
||||||
let mut field = Field {
|
|
||||||
var: var,
|
|
||||||
type_: field_type,
|
|
||||||
label: label,
|
|
||||||
required: false,
|
|
||||||
options: vec!(),
|
|
||||||
values: vec!(),
|
|
||||||
media: vec!(),
|
|
||||||
};
|
|
||||||
for element in child.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."));
|
|
||||||
}
|
|
||||||
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."));
|
|
||||||
}
|
|
||||||
field.required = true;
|
|
||||||
} else if element.is("option", ns::DATA_FORMS) {
|
|
||||||
if !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,
|
|
||||||
});
|
|
||||||
} 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."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if is_form_type {
|
|
||||||
if form.form_type.is_some() {
|
if form.form_type.is_some() {
|
||||||
return Err(Error::ParseError("More than one FORM_TYPE in a data form."));
|
return Err(Error::ParseError("More than one FORM_TYPE in a data form."));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue