diff --git a/parsers/src/bookmarks.rs b/parsers/src/bookmarks.rs index 7b4769b3..efcd1fc3 100644 --- a/parsers/src/bookmarks.rs +++ b/parsers/src/bookmarks.rs @@ -75,18 +75,18 @@ pub struct Url { pub url: String, } -generate_element!( - /// Container element for multiple bookmarks. - #[derive(Default)] - Storage, "storage", BOOKMARKS, - children: [ - /// Conferences the user has expressed an interest in. - conferences: Vec = ("conference", BOOKMARKS) => Conference, +/// Container element for multiple bookmarks. +#[derive(FromXml, AsXml, PartialEq, Debug, Clone, Default)] +#[xml(namespace = ns::BOOKMARKS, name = "storage")] +pub struct Storage { + /// Conferences the user has expressed an interest in. + #[xml(child(n = ..))] + pub conferences: Vec, - /// URLs the user is interested in. - urls: Vec = ("url", BOOKMARKS) => Url - ] -); + /// URLs the user is interested in. + #[xml(child(n = ..))] + pub urls: Vec, +} impl Storage { /// Create an empty bookmarks storage. diff --git a/parsers/src/fast.rs b/parsers/src/fast.rs index 75b3b66b..3f632444 100644 --- a/parsers/src/fast.rs +++ b/parsers/src/fast.rs @@ -20,18 +20,18 @@ generate_attribute!( Tls0Rtt, "tls-0rtt", bool ); -generate_element!( /// This is the `` element sent by the server as a SASL2 inline feature. -FastQuery, "fast", FAST, -attributes: [ +#[derive(FromXml, AsXml, Debug, Clone, PartialEq)] +#[xml(namespace = ns::FAST, name = "fast")] +pub struct FastQuery { /// Whether TLS zero-roundtrip is possible. - tls_0rtt: Default = "tls-0rtt", -], -children: [ + #[xml(attribute(default, name = "tls-0rtt"))] + pub tls_0rtt: Tls0Rtt, + /// A list of `` elements, listing all server allowed mechanisms. - mechanisms: Vec = ("mechanism", FAST) => Mechanism -] -); + #[xml(child(n = ..))] + pub mechanisms: Vec, +} /// This is the `` element the client MUST include within its SASL2 authentication request. #[derive(FromXml, AsXml, Debug, Clone, PartialEq)] diff --git a/parsers/src/jingle_ft.rs b/parsers/src/jingle_ft.rs index bedca4da..56d40b4b 100644 --- a/parsers/src/jingle_ft.rs +++ b/parsers/src/jingle_ft.rs @@ -16,23 +16,23 @@ use xso::{ AsXml, FromXml, }; -generate_element!( - /// Represents a range in a file. - #[derive(Default)] - Range, "range", JINGLE_FT, - attributes: [ - /// The offset in bytes from the beginning of the file. - offset: Default = "offset", +/// Represents a range in a file. +#[derive(FromXml, AsXml, PartialEq, Debug, Clone, Default)] +#[xml(namespace = ns::JINGLE_FT, name = "range")] +pub struct Range { + /// The offset in bytes from the beginning of the file. + #[xml(attribute(default))] + pub offset: u64, - /// The length in bytes of the range, or None to be the entire - /// remaining of the file. - length: Option = "length" - ], - children: [ - /// List of hashes for this range. - hashes: Vec = ("hash", HASHES) => Hash - ] -); + /// The length in bytes of the range, or None to be the entire + /// remaining of the file. + #[xml(attribute(default))] + pub length: Option, + + /// List of hashes for this range. + #[xml(child(n = ..))] + pub hashes: Vec, +} impl Range { /// Creates a new range. @@ -632,6 +632,6 @@ mod tests { FromElementError::Invalid(Error::Other(string)) => string, _ => panic!(), }; - assert_eq!(message, "Unknown attribute in range element."); + assert_eq!(message, "Unknown attribute in Range element."); } } diff --git a/parsers/src/jingle_raw_udp.rs b/parsers/src/jingle_raw_udp.rs index 152645d4..4754fb17 100644 --- a/parsers/src/jingle_raw_udp.rs +++ b/parsers/src/jingle_raw_udp.rs @@ -11,15 +11,14 @@ use xso::{AsXml, FromXml}; use crate::jingle_ice_udp::Type; use crate::ns; -generate_element!( - /// Wrapper element for an raw UDP transport. - #[derive(Default)] - Transport, "transport", JINGLE_RAW_UDP, - children: [ - /// List of candidates for this raw UDP session. - candidates: Vec = ("candidate", JINGLE_RAW_UDP) => Candidate - ] -); +/// Wrapper element for an raw UDP transport. +#[derive(FromXml, AsXml, PartialEq, Debug, Clone, Default)] +#[xml(namespace = ns::JINGLE_RAW_UDP, name = "transport")] +pub struct Transport { + /// List of candidates for this raw UDP session. + #[xml(child(n = ..))] + pub candidates: Vec, +} impl Transport { /// Create a new ICE-UDP transport. diff --git a/parsers/src/mam.rs b/parsers/src/mam.rs index dd6b12c9..14243f0a 100644 --- a/parsers/src/mam.rs +++ b/parsers/src/mam.rs @@ -144,24 +144,24 @@ generate_attribute!( bool ); -generate_element!( - /// Notes the end of a page in a query. - Fin, "fin", MAM, - attributes: [ - /// True when the end of a MAM query has been reached. - complete: Default = "complete", - ], - children: [ - /// Describes the current page, it should contain at least [first] - /// (with an [index]) and [last], and generally [count]. - /// - /// [first]: ../rsm/struct.SetResult.html#structfield.first - /// [index]: ../rsm/struct.SetResult.html#structfield.first_index - /// [last]: ../rsm/struct.SetResult.html#structfield.last - /// [count]: ../rsm/struct.SetResult.html#structfield.count - set: Required = ("set", RSM) => SetResult - ] -); +/// Notes the end of a page in a query. +#[derive(FromXml, AsXml, Debug, Clone, PartialEq)] +#[xml(namespace = ns::MAM, name = "fin")] +pub struct Fin { + /// True when the end of a MAM query has been reached. + #[xml(attribute(default))] + pub complete: Complete, + + /// Describes the current page, it should contain at least [first] + /// (with an [index]) and [last], and generally [count]. + /// + /// [first]: ../rsm/struct.SetResult.html#structfield.first + /// [index]: ../rsm/struct.SetResult.html#structfield.first_index + /// [last]: ../rsm/struct.SetResult.html#structfield.last + /// [count]: ../rsm/struct.SetResult.html#structfield.count + #[xml(child)] + pub set: SetResult, +} impl IqResultPayload for Fin {} diff --git a/parsers/src/muc/user.rs b/parsers/src/muc/user.rs index 9e439f81..adf45a2a 100644 --- a/parsers/src/muc/user.rs +++ b/parsers/src/muc/user.rs @@ -219,31 +219,31 @@ generate_attribute!( pub struct Item { /// The affiliation of this user with the room. #[xml(attribute)] - affiliation: Affiliation, + pub affiliation: Affiliation, /// The real JID of this user, if you are allowed to see it. #[xml(attribute(default))] - jid: Option, + pub jid: Option, /// The current nickname of this user. #[xml(attribute(default))] - nick: Option, + pub nick: Option, /// The current role of this user. #[xml(attribute)] - role: Role, + pub role: Role, /// The actor affected by this item. #[xml(child(default))] - actor: Option, + pub actor: Option, /// Whether this continues a one-to-one discussion. #[xml(child(default))] - continue_: Option, + pub continue_: Option, /// A reason for this item. #[xml(child(default))] - reason: Option, + pub reason: Option, } impl Item { @@ -293,16 +293,18 @@ impl Item { } } -generate_element!( - /// The main muc#user element. - MucUser, "x", MUC_USER, children: [ - /// List of statuses applying to this item. - status: Vec = ("status", MUC_USER) => Status, +/// The main muc#user element. +#[derive(FromXml, AsXml, Debug, PartialEq, Clone)] +#[xml(namespace = ns::MUC_USER, name = "x")] +pub struct MucUser { + /// List of statuses applying to this item. + #[xml(child(n = ..))] + pub status: Vec, - /// List of items. - items: Vec = ("item", MUC_USER) => Item - ] -); + /// List of items. + #[xml(child(n = ..))] + pub items: Vec, +} impl Default for MucUser { fn default() -> Self { @@ -380,7 +382,7 @@ mod tests { FromElementError::Invalid(Error::Other(string)) => string, _ => panic!(), }; - assert_eq!(message, "Unknown child in x element."); + assert_eq!(message, "Unknown child in MucUser element."); } #[test] @@ -407,7 +409,7 @@ mod tests { FromElementError::Invalid(Error::Other(string)) => string, _ => panic!(), }; - assert_eq!(message, "Unknown attribute in x element."); + assert_eq!(message, "Unknown attribute in MucUser element."); } #[test] diff --git a/parsers/src/pubsub/pubsub.rs b/parsers/src/pubsub/pubsub.rs index 86bce5c9..ccae4b8f 100644 --- a/parsers/src/pubsub/pubsub.rs +++ b/parsers/src/pubsub/pubsub.rs @@ -167,21 +167,22 @@ generate_attribute!( bool ); -generate_element!( - /// A request to retract some items from a node. - Retract, "retract", PUBSUB, - attributes: [ - /// The node affected by this request. - node: Required = "node", +/// A request to retract some items from a node. +#[derive(FromXml, AsXml, Debug, PartialEq, Clone)] +#[xml(namespace = ns::PUBSUB, name = "retract")] +pub struct Retract { + /// The node affected by this request. + #[xml(attribute)] + pub node: NodeName, - /// Whether a retract request should notify subscribers or not. - notify: Default = "notify", - ], - children: [ - /// The items affected by this request. - items: Vec = ("item", PUBSUB) => Item - ] -); + /// Whether a retract request should notify subscribers or not. + #[xml(attribute(default))] + pub notify: Notify, + + /// The items affected by this request. + #[xml(child(n = ..))] + pub items: Vec, +} /// Indicate that the subscription can be configured. #[derive(Debug, Clone, PartialEq)] diff --git a/parsers/src/stream_features.rs b/parsers/src/stream_features.rs index fad98bd7..e699775c 100644 --- a/parsers/src/stream_features.rs +++ b/parsers/src/stream_features.rs @@ -45,24 +45,14 @@ pub struct RequiredStartTls; #[xml(namespace = ns::BIND, name = "bind")] pub struct Bind; -generate_element!( - /// List of supported SASL mechanisms - #[derive(Default)] - SaslMechanisms, "mechanisms", SASL, - children: [ - /// List of information elements describing this avatar. - mechanisms: Vec = ("mechanism", SASL) => SaslMechanism, - ] -); - -// TODO: Uncomment me when xso supports collections, see -// https://gitlab.com/xmpp-rs/xmpp-rs/-/issues/136 -// #[derive(FromXml, AsXml, PartialEq, Debug, Clone)] -// #[xml(namespace = ns::SASL, name = "mechanisms")] -// pub struct SaslMechanisms { -// #[xml(child(default))] -// mechanisms: Vec, -// } +/// List of supported SASL mechanisms +#[derive(FromXml, AsXml, PartialEq, Debug, Clone, Default)] +#[xml(namespace = ns::SASL, name = "mechanisms")] +pub struct SaslMechanisms { + /// List of information elements describing this avatar. + #[xml(child(n = ..))] + pub mechanisms: Vec, +} /// The name of a SASL mechanism. #[derive(FromXml, AsXml, PartialEq, Debug, Clone)] diff --git a/parsers/src/util/macros.rs b/parsers/src/util/macros.rs index 7d70c463..d5e03fd2 100644 --- a/parsers/src/util/macros.rs +++ b/parsers/src/util/macros.rs @@ -300,6 +300,24 @@ macro_rules! generate_attribute_enum { }) } } + + impl ::xso::FromXml for $elem { + type Builder = ::xso::minidom_compat::FromEventsViaElement<$elem>; + + fn from_events( + qname: ::xso::exports::rxml::QName, + attrs: ::xso::exports::rxml::AttrMap, + ) -> Result { + if qname.0 != crate::ns::$ns || qname.1 != $name { + return Err(::xso::error::FromEventsError::Mismatch { + name: qname, + attrs, + }) + } + Self::Builder::new(qname, attrs) + } + } + impl From<$elem> for minidom::Element { fn from(elem: $elem) -> minidom::Element { minidom::Element::builder($name, crate::ns::$ns) @@ -309,6 +327,14 @@ macro_rules! generate_attribute_enum { .build() } } + + impl ::xso::AsXml for $elem { + type ItemIter<'x> = ::xso::minidom_compat::AsItemsViaElement<'x>; + + fn as_xml_iter(&self) -> Result, ::xso::error::Error> { + ::xso::minidom_compat::AsItemsViaElement::new(self.clone()) + } + } ); }