parsers: port more elements to derive macros

This commit is contained in:
Jonas Schäfer 2024-06-29 16:34:27 +02:00
commit 0e4865006c
18 changed files with 405 additions and 274 deletions

View file

@ -4,7 +4,10 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use xso::{FromXml, IntoXml};
use crate::hashes::Sha1HexAttribute; use crate::hashes::Sha1HexAttribute;
use crate::ns;
use crate::pubsub::PubSubPayload; use crate::pubsub::PubSubPayload;
use crate::util::text_node_codecs::{Codec, WhitespaceAwareBase64}; use crate::util::text_node_codecs::{Codec, WhitespaceAwareBase64};
@ -19,29 +22,34 @@ generate_element!(
impl PubSubPayload for Metadata {} impl PubSubPayload for Metadata {}
generate_element!( /// Communicates avatar metadata.
/// Communicates avatar metadata. #[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
Info, "info", AVATAR_METADATA, #[xml(namespace = ns::AVATAR_METADATA, name = "info")]
attributes: [ pub struct Info {
/// The size of the image data in bytes. /// The size of the image data in bytes.
bytes: Required<u32> = "bytes", #[xml(attribute)]
pub bytes: u32,
/// The width of the image in pixels. /// The width of the image in pixels.
width: Option<u16> = "width", #[xml(attribute(default))]
pub width: Option<u16>,
/// The height of the image in pixels. /// The height of the image in pixels.
height: Option<u16> = "height", #[xml(attribute(default))]
pub height: Option<u16>,
/// The SHA-1 hash of the image data for the specified content-type. /// The SHA-1 hash of the image data for the specified content-type.
id: Required<Sha1HexAttribute> = "id", #[xml(attribute)]
pub id: Sha1HexAttribute,
/// The IANA-registered content type of the image data. /// The IANA-registered content type of the image data.
type_: Required<String> = "type", #[xml(attribute = "type")]
pub type_: String,
/// The http: or https: URL at which the image data file is hosted. /// The http: or https: URL at which the image data file is hosted.
url: Option<String> = "url", #[xml(attribute(default))]
] pub url: Option<String>,
); }
generate_element!( generate_element!(
/// The actual avatar data. /// The actual avatar data.

View file

@ -16,9 +16,12 @@
//! //!
//! The [`Conference`][crate::bookmarks::Conference] struct used in [`private::Query`][`crate::private::Query`] is the one from this module. Only the querying mechanism changes from a legacy PubSub implementation here, to a legacy Private XML Query implementation in that other module. The [`Conference`][crate::bookmarks2::Conference] element from the [`bookmarks2`][crate::bookmarks2] module is a different structure, but conversion is possible from [`bookmarks::Conference`][crate::bookmarks::Conference] to [`bookmarks2::Conference`][crate::bookmarks2::Conference] via the [`Conference::into_bookmarks2`][crate::bookmarks::Conference::into_bookmarks2] method. //! The [`Conference`][crate::bookmarks::Conference] struct used in [`private::Query`][`crate::private::Query`] is the one from this module. Only the querying mechanism changes from a legacy PubSub implementation here, to a legacy Private XML Query implementation in that other module. The [`Conference`][crate::bookmarks2::Conference] element from the [`bookmarks2`][crate::bookmarks2] module is a different structure, but conversion is possible from [`bookmarks::Conference`][crate::bookmarks::Conference] to [`bookmarks2::Conference`][crate::bookmarks2::Conference] via the [`Conference::into_bookmarks2`][crate::bookmarks::Conference::into_bookmarks2] method.
use xso::{FromXml, IntoXml};
use jid::BareJid; use jid::BareJid;
pub use crate::bookmarks2::Autojoin; pub use crate::bookmarks2::Autojoin;
use crate::ns;
generate_element!( generate_element!(
/// A conference bookmark. /// A conference bookmark.
@ -59,17 +62,18 @@ impl Conference {
} }
} }
generate_element!( /// An URL bookmark.
/// An URL bookmark. #[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
Url, "url", BOOKMARKS, #[xml(namespace = ns::BOOKMARKS, name = "url")]
attributes: [ pub struct Url {
/// A user-defined name for this URL. /// A user-defined name for this URL.
name: Option<String> = "name", #[xml(attribute(default))]
pub name: Option<String>,
/// The URL of this bookmark. /// The URL of this bookmark.
url: Required<String> = "url", #[xml(attribute)]
] pub url: String,
); }
generate_element!( generate_element!(
/// Container element for multiple bookmarks. /// Container element for multiple bookmarks.

View file

@ -4,24 +4,29 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use xso::{
error::{Error, FromElementError},
FromXml, IntoXml,
};
use crate::data_forms::{DataForm, DataFormType}; use crate::data_forms::{DataForm, DataFormType};
use crate::iq::{IqGetPayload, IqResultPayload}; use crate::iq::{IqGetPayload, IqResultPayload};
use crate::ns; use crate::ns;
use crate::rsm::{SetQuery, SetResult}; use crate::rsm::{SetQuery, SetResult};
use crate::Element; use crate::Element;
use jid::Jid; use jid::Jid;
use xso::error::{Error, FromElementError};
generate_element!(
/// Structure representing a `<query xmlns='http://jabber.org/protocol/disco#info'/>` element. /// Structure representing a `<query xmlns='http://jabber.org/protocol/disco#info'/>` element.
/// ///
/// It should only be used in an `<iq type='get'/>`, as it can only represent /// It should only be used in an `<iq type='get'/>`, as it can only represent
/// the request, and not a result. /// the request, and not a result.
DiscoInfoQuery, "query", DISCO_INFO, #[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
attributes: [ #[xml(namespace = ns::DISCO_INFO, name = "query")]
pub struct DiscoInfoQuery {
/// Node on which we are doing the discovery. /// Node on which we are doing the discovery.
node: Option<String> = "node", #[xml(attribute(default))]
]); pub node: Option<String>,
}
impl IqGetPayload for DiscoInfoQuery {} impl IqGetPayload for DiscoInfoQuery {}
@ -197,17 +202,22 @@ children: [
impl IqGetPayload for DiscoItemsQuery {} impl IqGetPayload for DiscoItemsQuery {}
generate_element!(
/// Structure representing an `<item xmlns='http://jabber.org/protocol/disco#items'/>` element. /// Structure representing an `<item xmlns='http://jabber.org/protocol/disco#items'/>` element.
Item, "item", DISCO_ITEMS, #[derive(FromXml, IntoXml, Debug, Clone, PartialEq)]
attributes: [ #[xml(namespace = ns::DISCO_ITEMS, name = "item")]
pub struct Item {
/// JID of the entity pointed by this item. /// JID of the entity pointed by this item.
jid: Required<Jid> = "jid", #[xml(attribute)]
pub jid: Jid,
/// Node of the entity pointed by this item. /// Node of the entity pointed by this item.
node: Option<String> = "node", #[xml(attribute(default))]
pub node: Option<String>,
/// Name of the entity pointed by this item. /// Name of the entity pointed by this item.
name: Option<String> = "name", #[xml(attribute(default))]
]); pub name: Option<String>,
}
generate_element!( generate_element!(
/// Structure representing a `<query /// Structure representing a `<query

View file

@ -4,20 +4,24 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use crate::message::MessagePayload; use xso::{FromXml, IntoXml};
generate_element!( use crate::message::MessagePayload;
/// Structure representing an `<encryption xmlns='urn:xmpp:eme:0'/>` element. use crate::ns;
ExplicitMessageEncryption, "encryption", EME,
attributes: [ /// Structure representing an `<encryption xmlns='urn:xmpp:eme:0'/>` element.
#[derive(FromXml, IntoXml, Debug, Clone, PartialEq)]
#[xml(namespace = ns::EME, name = "encryption")]
pub struct ExplicitMessageEncryption {
/// Namespace of the encryption scheme used. /// Namespace of the encryption scheme used.
namespace: Required<String> = "namespace", #[xml(attribute)]
pub namespace: String,
/// User-friendly name for the encryption scheme, should be `None` for OTR, /// User-friendly name for the encryption scheme, should be `None` for OTR,
/// legacy OpenPGP and OX. /// legacy OpenPGP and OX.
name: Option<String> = "name", #[xml(attribute(default))]
] pub name: Option<String>,
); }
impl MessagePayload for ExplicitMessageEncryption {} impl MessagePayload for ExplicitMessageEncryption {}
@ -69,7 +73,8 @@ mod tests {
#[test] #[test]
fn test_invalid_child() { fn test_invalid_child() {
let elem: Element = "<encryption xmlns='urn:xmpp:eme:0'><coucou/></encryption>" let elem: Element =
"<encryption xmlns='urn:xmpp:eme:0' namespace='urn:xmpp:otr:0'><coucou/></encryption>"
.parse() .parse()
.unwrap(); .unwrap();
let error = ExplicitMessageEncryption::try_from(elem).unwrap_err(); let error = ExplicitMessageEncryption::try_from(elem).unwrap_err();
@ -77,7 +82,10 @@ mod tests {
FromElementError::Invalid(Error::Other(string)) => string, FromElementError::Invalid(Error::Other(string)) => string,
_ => panic!(), _ => panic!(),
}; };
assert_eq!(message, "Unknown child in encryption element."); assert_eq!(
message,
"Unknown child in ExplicitMessageEncryption element."
);
} }
#[test] #[test]

View file

@ -4,6 +4,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use xso::{FromXmlText, IntoXmlText};
use crate::util::text_node_codecs::{Base64, Codec}; use crate::util::text_node_codecs::{Base64, Codec};
use base64::{engine::general_purpose::STANDARD as Base64Engine, Engine}; use base64::{engine::general_purpose::STANDARD as Base64Engine, Engine};
use minidom::IntoAttributeValue; use minidom::IntoAttributeValue;
@ -184,6 +186,18 @@ impl FromStr for Sha1HexAttribute {
} }
} }
impl FromXmlText for Sha1HexAttribute {
fn from_xml_text(s: String) -> Result<Self, xso::error::Error> {
Self::from_str(&s).map_err(xso::error::Error::text_parse_error)
}
}
impl IntoXmlText for Sha1HexAttribute {
fn into_xml_text(self) -> Result<String, xso::error::Error> {
Ok(self.to_hex())
}
}
impl IntoAttributeValue for Sha1HexAttribute { impl IntoAttributeValue for Sha1HexAttribute {
fn into_attribute_value(self) -> Option<String> { fn into_attribute_value(self) -> Option<String> {
Some(self.to_hex()) Some(self.to_hex())

View file

@ -4,27 +4,31 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use xso::{FromXml, IntoXml}; use xso::{
error::{Error, FromElementError},
FromXml, IntoXml,
};
use crate::iq::{IqGetPayload, IqResultPayload}; use crate::iq::{IqGetPayload, IqResultPayload};
use crate::ns; use crate::ns;
use crate::Element; use crate::Element;
use xso::error::{Error, FromElementError};
generate_element!( /// Requesting a slot
/// Requesting a slot #[derive(FromXml, IntoXml, Debug, Clone, PartialEq)]
SlotRequest, "request", HTTP_UPLOAD, #[xml(namespace = ns::HTTP_UPLOAD, name = "request")]
attributes: [ pub struct SlotRequest {
/// The filename to be uploaded. /// The filename to be uploaded.
filename: Required<String> = "filename", #[xml(attribute)]
pub filename: String,
/// Size of the file to be uploaded. /// Size of the file to be uploaded.
size: Required<u64> = "size", #[xml(attribute)]
pub size: u64,
/// Content-Type of the file. /// Content-Type of the file.
content_type: Option<String> = "content-type", #[xml(attribute(name = "content-type"))]
] pub content_type: Option<String>,
); }
impl IqGetPayload for SlotRequest {} impl IqGetPayload for SlotRequest {}

View file

@ -4,7 +4,10 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use xso::{FromXml, IntoXml};
use crate::iq::IqSetPayload; use crate::iq::IqSetPayload;
use crate::ns;
use crate::util::text_node_codecs::{Base64, Codec}; use crate::util::text_node_codecs::{Base64, Codec};
generate_id!( generate_id!(
@ -59,13 +62,14 @@ Data, "data", IBB,
impl IqSetPayload for Data {} impl IqSetPayload for Data {}
generate_element!(
/// Close an open stream. /// Close an open stream.
Close, "close", IBB, #[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
attributes: [ #[xml(namespace = ns::IBB, name = "close")]
pub struct Close {
/// The identifier of the stream to be closed. /// The identifier of the stream to be closed.
sid: Required<StreamId> = "sid", #[xml(attribute)]
]); pub sid: StreamId,
}
impl IqSetPayload for Close {} impl IqSetPayload for Close {}

View file

@ -4,9 +4,13 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use crate::jingle_dtls_srtp::Fingerprint;
use std::net::IpAddr; use std::net::IpAddr;
use xso::{FromXml, IntoXml};
use crate::jingle_dtls_srtp::Fingerprint;
use crate::ns;
generate_element!( generate_element!(
/// Wrapper element for an ICE-UDP transport. /// Wrapper element for an ICE-UDP transport.
#[derive(Default)] #[derive(Default)]
@ -63,50 +67,61 @@ generate_attribute!(
} }
); );
generate_element!( /// A candidate for an ICE-UDP session.
/// A candidate for an ICE-UDP session. #[derive(FromXml, IntoXml, Debug, PartialEq, Clone)]
Candidate, "candidate", JINGLE_ICE_UDP, #[xml(namespace = ns::JINGLE_ICE_UDP, name = "candidate")]
attributes: [ pub struct Candidate {
/// A Component ID as defined in ICE-CORE. /// A Component ID as defined in ICE-CORE.
component: Required<u8> = "component", #[xml(attribute)]
pub component: u8,
/// A Foundation as defined in ICE-CORE. /// A Foundation as defined in ICE-CORE.
foundation: Required<String> = "foundation", #[xml(attribute)]
pub foundation: String,
/// An index, starting at 0, that enables the parties to keep track of updates to the /// An index, starting at 0, that enables the parties to keep track of updates to the
/// candidate throughout the life of the session. /// candidate throughout the life of the session.
generation: Required<u8> = "generation", #[xml(attribute)]
pub generation: u8,
/// A unique identifier for the candidate. /// A unique identifier for the candidate.
id: Required<String> = "id", #[xml(attribute)]
pub id: String,
/// The Internet Protocol (IP) address for the candidate transport mechanism; this can be /// The Internet Protocol (IP) address for the candidate transport mechanism; this can be
/// either an IPv4 address or an IPv6 address. /// either an IPv4 address or an IPv6 address.
ip: Required<IpAddr> = "ip", #[xml(attribute)]
pub ip: IpAddr,
/// The port at the candidate IP address. /// The port at the candidate IP address.
port: Required<u16> = "port", #[xml(attribute)]
pub port: u16,
/// A Priority as defined in ICE-CORE. /// A Priority as defined in ICE-CORE.
priority: Required<u32> = "priority", #[xml(attribute)]
pub priority: u32,
/// The protocol to be used. The only value defined by this specification is "udp". /// The protocol to be used. The only value defined by this specification is "udp".
protocol: Required<String> = "protocol", #[xml(attribute)]
pub protocol: String,
/// A related address as defined in ICE-CORE. /// A related address as defined in ICE-CORE.
rel_addr: Option<IpAddr> = "rel-addr", #[xml(attribute(default, name = "rel-addr"))]
pub rel_addr: Option<IpAddr>,
/// A related port as defined in ICE-CORE. /// A related port as defined in ICE-CORE.
rel_port: Option<u16> = "rel-port", #[xml(attribute(default, name = "rel-port"))]
pub rel_port: Option<u16>,
/// An index, starting at 0, referencing which network this candidate is on for a given /// An index, starting at 0, referencing which network this candidate is on for a given
/// peer. /// peer.
network: Option<u8> = "network", #[xml(attribute(default))]
pub network: Option<u8>,
/// A Candidate Type as defined in ICE-CORE. /// A Candidate Type as defined in ICE-CORE.
type_: Required<Type> = "type", #[xml(attribute(name = "type"))]
] pub type_: Type,
); }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -4,9 +4,13 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use crate::jingle_ice_udp::Type;
use std::net::IpAddr; use std::net::IpAddr;
use xso::{FromXml, IntoXml};
use crate::jingle_ice_udp::Type;
use crate::ns;
generate_element!( generate_element!(
/// Wrapper element for an raw UDP transport. /// Wrapper element for an raw UDP transport.
#[derive(Default)] #[derive(Default)]
@ -30,31 +34,36 @@ impl Transport {
} }
} }
generate_element!( /// A candidate for an ICE-UDP session.
/// A candidate for an ICE-UDP session. #[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
Candidate, "candidate", JINGLE_RAW_UDP, #[xml(namespace = ns::JINGLE_RAW_UDP, name = "candidate")]
attributes: [ pub struct Candidate {
/// A Component ID as defined in ICE-CORE. /// A Component ID as defined in ICE-CORE.
component: Required<u8> = "component", #[xml(attribute)]
pub component: u8,
/// An index, starting at 0, that enables the parties to keep track of updates to the /// An index, starting at 0, that enables the parties to keep track of updates to the
/// candidate throughout the life of the session. /// candidate throughout the life of the session.
generation: Required<u8> = "generation", #[xml(attribute)]
pub generation: u8,
/// A unique identifier for the candidate. /// A unique identifier for the candidate.
id: Required<String> = "id", #[xml(attribute)]
pub id: String,
/// The Internet Protocol (IP) address for the candidate transport mechanism; this can be /// The Internet Protocol (IP) address for the candidate transport mechanism; this can be
/// either an IPv4 address or an IPv6 address. /// either an IPv4 address or an IPv6 address.
ip: Required<IpAddr> = "ip", #[xml(attribute)]
pub ip: IpAddr,
/// The port at the candidate IP address. /// The port at the candidate IP address.
port: Required<u16> = "port", #[xml(attribute)]
pub port: u16,
/// A Candidate Type as defined in ICE-CORE. /// A Candidate Type as defined in ICE-CORE.
type_: Option<Type> = "type", #[xml(attribute(default, name = "type"))]
] pub type_: Option<Type>,
); }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -4,17 +4,22 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
generate_element!( use xso::{FromXml, IntoXml};
/// Wrapper element for a rtcp-fb.
RtcpFb, "rtcp-fb", JINGLE_RTCP_FB, use crate::ns;
attributes: [
/// Wrapper element for a rtcp-fb.
#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
#[xml(namespace = ns::JINGLE_RTCP_FB, name = "rtcp-fb")]
pub struct RtcpFb {
/// Type of this rtcp-fb. /// Type of this rtcp-fb.
type_: Required<String> = "type", #[xml(attribute = "type")]
pub type_: String,
/// Subtype of this rtcp-fb, if relevant. /// Subtype of this rtcp-fb, if relevant.
subtype: Option<String> = "subtype", #[xml(attribute(default))]
] pub subtype: Option<String>,
); }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -137,18 +137,19 @@ impl PayloadType {
} }
} }
generate_element!( /// Parameter related to a payload.
/// Parameter related to a payload. #[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
Parameter, "parameter", JINGLE_RTP, #[xml(namespace = ns::JINGLE_RTP, name = "parameter")]
attributes: [ pub struct Parameter {
/// The name of the parameter, from the list at /// The name of the parameter, from the list at
/// <https://www.iana.org/assignments/sdp-parameters/sdp-parameters.xhtml> /// <https://www.iana.org/assignments/sdp-parameters/sdp-parameters.xhtml>
name: Required<String> = "name", #[xml(attribute)]
pub name: String,
/// The value of this parameter. /// The value of this parameter.
value: Required<String> = "value", #[xml(attribute)]
] pub value: String,
); }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -4,6 +4,10 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use xso::{FromXml, IntoXml};
use crate::ns;
generate_element!( generate_element!(
/// Source element for the ssrc SDP attribute. /// Source element for the ssrc SDP attribute.
Source, "source", JINGLE_SSMA, Source, "source", JINGLE_SSMA,
@ -27,17 +31,18 @@ impl Source {
} }
} }
generate_element!( /// Parameter associated with a ssrc.
/// Parameter associated with a ssrc. #[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
Parameter, "parameter", JINGLE_SSMA, #[xml(namespace = ns::JINGLE_SSMA, name = "parameter")]
attributes: [ pub struct Parameter {
/// The name of the parameter. /// The name of the parameter.
name: Required<String> = "name", #[xml(attribute)]
pub name: String,
/// The optional value of the parameter. /// The optional value of the parameter.
value: Option<String> = "value", #[xml(attribute(default))]
] pub value: Option<String>,
); }
generate_attribute!( generate_attribute!(
/// From RFC5888, the list of allowed semantics. /// From RFC5888, the list of allowed semantics.

View file

@ -107,20 +107,22 @@ generate_element!(
] ]
); );
generate_element!( /// A subscription element, describing the state of a subscription.
/// A subscription element, describing the state of a subscription. #[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
SubscriptionElem, "subscription", PUBSUB_OWNER, #[xml(namespace = ns::PUBSUB_OWNER, name = "subscription")]
attributes: [ pub struct SubscriptionElem {
/// The JID affected by this subscription. /// The JID affected by this subscription.
jid: Required<Jid> = "jid", #[xml(attribute)]
pub jid: Jid,
/// The state of the subscription. /// The state of the subscription.
subscription: Required<Subscription> = "subscription", #[xml(attribute)]
pub subscription: Subscription,
/// Subscription unique id. /// Subscription unique id.
subid: Option<String> = "subid", #[xml(attribute(default))]
] pub subid: Option<String>,
); }
/// Main payload used to communicate with a PubSubOwner service. /// Main payload used to communicate with a PubSubOwner service.
/// ///

View file

@ -4,6 +4,11 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use xso::{
error::{Error, FromElementError},
FromXml, IntoXml,
};
use crate::data_forms::DataForm; use crate::data_forms::DataForm;
use crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload}; use crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload};
use crate::ns; use crate::ns;
@ -12,10 +17,6 @@ use crate::pubsub::{
}; };
use crate::Element; use crate::Element;
use jid::Jid; use jid::Jid;
use xso::{
error::{Error, FromElementError},
FromXml, IntoXml,
};
// TODO: a better solution would be to split this into a query and a result elements, like for // TODO: a better solution would be to split this into a query and a result elements, like for
// XEP-0030. // XEP-0030.
@ -220,17 +221,18 @@ impl From<SubscribeOptions> for Element {
} }
} }
generate_element!( /// A request to subscribe a JID to a node.
/// A request to subscribe a JID to a node. #[derive(FromXml, IntoXml, Debug, PartialEq, Clone)]
Subscribe, "subscribe", PUBSUB, #[xml(namespace = ns::PUBSUB, name = "subscribe")]
attributes: [ pub struct Subscribe {
/// The JID being subscribed. /// The JID being subscribed.
jid: Required<Jid> = "jid", #[xml(attribute)]
pub jid: Jid,
/// The node to subscribe to. /// The node to subscribe to.
node: Option<NodeName> = "node", #[xml(attribute)]
] pub node: Option<NodeName>,
); }
generate_element!( generate_element!(
/// A request for current subscriptions. /// A request for current subscriptions.
@ -267,20 +269,22 @@ generate_element!(
] ]
); );
generate_element!( /// An unsubscribe request.
/// An unsubscribe request. #[derive(FromXml, IntoXml, Debug, PartialEq, Clone)]
Unsubscribe, "unsubscribe", PUBSUB, #[xml(namespace = ns::PUBSUB, name = "unsubscribe")]
attributes: [ pub struct Unsubscribe {
/// The JID affected by this request. /// The JID affected by this request.
jid: Required<Jid> = "jid", #[xml(attribute)]
jid: Jid,
/// The node affected by this request. /// The node affected by this request.
node: Option<NodeName> = "node", #[xml(attribute)]
node: Option<NodeName>,
/// The subscription identifier for this subscription. /// The subscription identifier for this subscription.
subid: Option<SubscriptionId> = "subid", #[xml(attribute)]
] subid: Option<SubscriptionId>,
); }
/// Main payload used to communicate with a PubSub service. /// Main payload used to communicate with a PubSub service.
/// ///

View file

@ -109,31 +109,33 @@ generate_element!(
#[xml(namespace = ns::SM, name = "r")] #[xml(namespace = ns::SM, name = "r")]
pub struct R; pub struct R;
generate_element!( /// Requests a stream resumption.
/// Requests a stream resumption. #[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
Resume, "resume", SM, #[xml(namespace = ns::SM, name = "resume")]
attributes: [ pub struct Resume {
/// The last handled stanza. /// The last handled stanza.
h: Required<u32> = "h", #[xml(attribute)]
pub h: u32,
/// The previous id given by the server on /// The previous id given by the server on
/// [enabled](struct.Enabled.html). /// [enabled](struct.Enabled.html).
previd: Required<StreamId> = "previd", #[xml(attribute)]
] pub previd: StreamId,
); }
generate_element!( /// The response by the server for a successfully resumed stream.
/// The response by the server for a successfully resumed stream. #[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
Resumed, "resumed", SM, #[xml(namespace = ns::SM, name = "resumed")]
attributes: [ pub struct Resumed {
/// The last handled stanza. /// The last handled stanza.
h: Required<u32> = "h", #[xml(attribute)]
pub h: u32,
/// The previous id given by the server on /// The previous id given by the server on
/// [enabled](struct.Enabled.html). /// [enabled](struct.Enabled.html).
previd: Required<StreamId> = "previd", #[xml(attribute)]
] pub previd: StreamId,
); }
// TODO: add support for optional and required. // TODO: add support for optional and required.
/// Represents availability of Stream Management in `<stream:features/>`. /// Represents availability of Stream Management in `<stream:features/>`.

View file

@ -4,29 +4,37 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use xso::{FromXml, IntoXml};
use jid::BareJid; use jid::BareJid;
generate_element!( use crate::ns;
/// The stream opening for client-server communications.
Stream, "stream", STREAM, /// The stream opening for client-server communications.
attributes: [ #[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
#[xml(namespace = ns::STREAM, name = "stream")]
pub struct Stream {
/// The JID of the entity opening this stream. /// The JID of the entity opening this stream.
from: Option<BareJid> = "from", #[xml(attribute(default))]
pub from: Option<BareJid>,
/// The JID of the entity receiving this stream opening. /// The JID of the entity receiving this stream opening.
to: Option<BareJid> = "to", #[xml(attribute(default))]
to: Option<BareJid>,
/// The id of the stream, used for authentication challenges. /// The id of the stream, used for authentication challenges.
id: Option<String> = "id", #[xml(attribute(default))]
id: Option<String>,
/// The XMPP version used during this stream. /// The XMPP version used during this stream.
version: Option<String> = "version", #[xml(attribute(default))]
version: Option<String>,
/// The default human language for all subsequent stanzas, which will /// The default human language for all subsequent stanzas, which will
/// be transmitted to other entities for better localisation. /// be transmitted to other entities for better localisation.
xml_lang: Option<String> = "xml:lang", #[xml(attribute(default, name = "xml:lang"))]
] xml_lang: Option<String>,
); }
impl Stream { impl Stream {
/// Creates a simple client→server `<stream:stream>` element. /// Creates a simple client→server `<stream:stream>` element.

View file

@ -125,6 +125,26 @@ macro_rules! generate_attribute {
}) })
} }
} }
impl ::xso::FromXmlText for $elem {
fn from_xml_text(s: String) -> Result<$elem, xso::error::Error> {
s.parse().map_err(xso::error::Error::text_parse_error)
}
}
impl ::xso::IntoXmlText for $elem {
fn into_xml_text(self) -> Result<String, xso::error::Error> {
Ok(String::from(match self {
$($elem::$a => $b),+
}))
}
#[allow(unreachable_patterns)]
fn into_optional_xml_text(self) -> Result<Option<String>, xso::error::Error> {
Ok(Some(String::from(match self {
$elem::$default => return Ok(None),
$($elem::$a => $b),+
})))
}
}
impl ::minidom::IntoAttributeValue for $elem { impl ::minidom::IntoAttributeValue for $elem {
#[allow(unreachable_patterns)] #[allow(unreachable_patterns)]
fn into_attribute_value(self) -> Option<String> { fn into_attribute_value(self) -> Option<String> {

View file

@ -4,29 +4,37 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this // 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/. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
use xso::{FromXml, IntoXml};
use jid::BareJid; use jid::BareJid;
generate_element!( use crate::ns;
/// The stream opening for WebSocket.
Open, "open", WEBSOCKET, /// The stream opening for WebSocket.
attributes: [ #[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
#[xml(namespace = ns::WEBSOCKET, name = "open")]
pub struct Open {
/// The JID of the entity opening this stream. /// The JID of the entity opening this stream.
from: Option<BareJid> = "from", #[xml(attribute(default))]
pub from: Option<BareJid>,
/// The JID of the entity receiving this stream opening. /// The JID of the entity receiving this stream opening.
to: Option<BareJid> = "to", #[xml(attribute(default))]
pub to: Option<BareJid>,
/// The id of the stream, used for authentication challenges. /// The id of the stream, used for authentication challenges.
id: Option<String> = "id", #[xml(attribute(default))]
pub id: Option<String>,
/// The XMPP version used during this stream. /// The XMPP version used during this stream.
version: Option<String> = "version", #[xml(attribute(default))]
pub version: Option<String>,
/// The default human language for all subsequent stanzas, which will /// The default human language for all subsequent stanzas, which will
/// be transmitted to other entities for better localisation. /// be transmitted to other entities for better localisation.
xml_lang: Option<String> = "xml:lang", #[xml(attribute(default, name = "xml:lang"))]
] pub xml_lang: Option<String>,
); }
impl Open { impl Open {
/// Creates a simple client→server `<open/>` element. /// Creates a simple client→server `<open/>` element.