From a1bee56ee11d29ff3e9b6276391506a9413f07a5 Mon Sep 17 00:00:00 2001 From: mb Date: Wed, 30 Aug 2023 17:01:17 +0200 Subject: [PATCH] Support desc element in field From [XEP-0004: Data Forms](https://xmpp.org/extensions/xep-0004.html#protocol-field): > ... > The element MAY contain any of the following child elements: > > > The XML character data of this element provides a natural-language > description of the field, intended for presentation in a > user-agent (e.g., as a "tool-tip", help button, or explanatory text > provided near the field). The element SHOULD NOT contain > newlines (the \n and \r characters), since layout is the > responsibility of a user agent, and any handling of > newlines (e.g., presentation in a user interface) is unspecified > herein. (Note: To provide a description of a field, it > is RECOMMENDED to use a element rather than > a separate element of type "fixed".) > ... --- parsers/src/data_forms.rs | 38 ++++++++++++++++++++++++++++++++++-- parsers/src/pubsub/owner.rs | 2 ++ parsers/src/pubsub/pubsub.rs | 1 + parsers/src/server_info.rs | 7 +++++++ 4 files changed, 46 insertions(+), 2 deletions(-) diff --git a/parsers/src/data_forms.rs b/parsers/src/data_forms.rs index a9c4f9c..4b284c3 100644 --- a/parsers/src/data_forms.rs +++ b/parsers/src/data_forms.rs @@ -82,6 +82,9 @@ pub struct Field { /// The form will be rejected if this field isn’t present. pub required: bool, + /// The natural-language description of the field, intended for presentation in a user-agent + pub desc: Option, + /// A list of allowed values. pub options: Vec, @@ -100,6 +103,7 @@ impl Field { type_, label: None, required: false, + desc: None, options: Vec::new(), media: Vec::new(), values: Vec::new(), @@ -174,6 +178,7 @@ impl TryFrom for Field { type_: get_attr!(elem, "type", Default), label: get_attr!(elem, "label", Option), required: false, + desc: None, options: vec![], values: vec![], media: vec![], @@ -204,6 +209,10 @@ impl TryFrom for Field { } else if element.is("media", ns::MEDIA_ELEMENT) { let media_element = MediaElement::try_from(element.clone())?; field.media.push(media_element); + } else if element.is("desc", ns::DATA_FORMS) { + check_no_children!(element, "value"); + check_no_attributes!(element, "value"); + field.desc = Some(element.text()); } else { return Err(Error::ParseError( "Field child isn’t a value, option or media element.", @@ -374,7 +383,7 @@ mod tests { fn test_size() { assert_size!(Option_, 24); assert_size!(FieldType, 1); - assert_size!(Field, 64); + assert_size!(Field, 76); assert_size!(DataFormType, 1); assert_size!(DataForm, 52); } @@ -384,7 +393,7 @@ mod tests { fn test_size() { assert_size!(Option_, 48); assert_size!(FieldType, 1); - assert_size!(Field, 128); + assert_size!(Field, 152); assert_size!(DataFormType, 1); assert_size!(DataForm, 104); } @@ -428,6 +437,7 @@ mod tests { type_: FieldType::Fixed, label: None, required: false, + desc: None, options: vec![], values: vec!["Section 1: Bot Info".to_string()], media: vec![], @@ -435,6 +445,30 @@ mod tests { ); } + #[test] + fn test_desc() { + let elem: Element = + "Tell all your friends about your new bot!" + .parse() + .unwrap(); + let form = DataForm::try_from(elem).unwrap(); + assert_eq!(form.type_, DataFormType::Form); + assert!(form.form_type.is_none()); + assert_eq!( + form.fields, + vec![Field { + var: Some("invitelist".to_string()), + type_: FieldType::JidMulti, + label: Some("People to invite".to_string()), + required: false, + desc: Some("Tell all your friends about your new bot!".to_string()), + options: vec![], + values: vec![], + media: vec![], + }] + ); + } + #[test] fn test_invalid() { let elem: Element = "".parse().unwrap(); diff --git a/parsers/src/pubsub/owner.rs b/parsers/src/pubsub/owner.rs index f2ea00d..ee98f85 100644 --- a/parsers/src/pubsub/owner.rs +++ b/parsers/src/pubsub/owner.rs @@ -233,6 +233,7 @@ mod tests { type_: FieldType::ListSingle, label: None, required: false, + desc: None, options: vec![], values: vec![String::from("whitelist")], media: vec![], @@ -280,6 +281,7 @@ mod tests { type_: FieldType::ListSingle, label: None, required: false, + desc: None, options: vec![], values: vec![String::from("whitelist")], media: vec![], diff --git a/parsers/src/pubsub/pubsub.rs b/parsers/src/pubsub/pubsub.rs index c3b637e..b8a3f47 100644 --- a/parsers/src/pubsub/pubsub.rs +++ b/parsers/src/pubsub/pubsub.rs @@ -625,6 +625,7 @@ mod tests { type_: FieldType::ListSingle, label: None, required: false, + desc: None, options: vec![], values: vec![String::from("whitelist")], media: vec![], diff --git a/parsers/src/server_info.rs b/parsers/src/server_info.rs index 5f59e5f..4bd4955 100644 --- a/parsers/src/server_info.rs +++ b/parsers/src/server_info.rs @@ -91,6 +91,7 @@ pub fn generate_address_field>(var: S, values: Vec) -> F type_: FieldType::ListMulti, label: None, required: false, + desc: None, options: vec![], values, media: vec![], @@ -126,6 +127,7 @@ mod tests { type_: FieldType::ListMulti, label: None, required: false, + desc: None, options: vec![], values: vec![], media: vec![], @@ -135,6 +137,7 @@ mod tests { type_: FieldType::ListMulti, label: None, required: false, + desc: None, options: vec![], values: vec![ String::from("xmpp:admin@foo.bar"), @@ -148,6 +151,7 @@ mod tests { type_: FieldType::ListMulti, label: None, required: false, + desc: None, options: vec![], values: vec![], media: vec![], @@ -157,6 +161,7 @@ mod tests { type_: FieldType::ListMulti, label: None, required: false, + desc: None, options: vec![], values: vec![], media: vec![], @@ -166,6 +171,7 @@ mod tests { type_: FieldType::ListMulti, label: None, required: false, + desc: None, options: vec![], values: vec![ String::from("xmpp:security@foo.bar"), @@ -178,6 +184,7 @@ mod tests { type_: FieldType::ListMulti, label: None, required: false, + desc: None, options: vec![], values: vec![String::from("mailto:support@foo.bar")], media: vec![],