From cea246a0fc0db31c78d87873d968bdc593f75033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Sch=C3=A4fer?= Date: Wed, 26 Jun 2024 13:13:02 +0200 Subject: [PATCH] parsers: port more generate_element! usages to derive macros --- parsers/Cargo.toml | 2 +- parsers/src/idle.rs | 35 ++++++++++++++++----------- parsers/src/jingle_ft.rs | 35 ++++++++++++++++----------- parsers/src/jingle_grouping.rs | 19 ++++++++------- parsers/src/jingle_thumnails.rs | 38 ++++++++++++++++++----------- parsers/src/legacy_omemo.rs | 19 ++++++++------- parsers/src/mix.rs | 32 ++++++++++++------------- parsers/src/openpgp.rs | 25 ++++++++++++-------- parsers/src/pubsub/owner.rs | 37 +++++++++++++++-------------- parsers/src/pubsub/pubsub.rs | 26 +++++++++++--------- parsers/src/rtt.rs | 21 +++++++++-------- parsers/src/sm.rs | 16 ++++++------- parsers/src/stanza_id.rs | 42 ++++++++++++++++++++------------- 13 files changed, 198 insertions(+), 149 deletions(-) diff --git a/parsers/Cargo.toml b/parsers/Cargo.toml index cb5f88ef..b15a4af5 100644 --- a/parsers/Cargo.toml +++ b/parsers/Cargo.toml @@ -24,7 +24,7 @@ chrono = { version = "0.4.5", default-features = false, features = ["std"] } # same repository dependencies jid = { version = "0.10", features = ["minidom"], path = "../jid" } minidom = { version = "0.15", path = "../minidom" } -xso = { version = "0.0.2", features = ["macros", "minidom", "panicking-into-impl"] } +xso = { version = "0.0.2", features = ["macros", "minidom", "panicking-into-impl", "jid"] } [features] # Build xmpp-parsers to make components instead of clients. diff --git a/parsers/src/idle.rs b/parsers/src/idle.rs index c2158a01..866e3e35 100644 --- a/parsers/src/idle.rs +++ b/parsers/src/idle.rs @@ -4,17 +4,20 @@ // 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/. +use xso::{FromXml, IntoXml}; + use crate::date::DateTime; +use crate::ns; use crate::presence::PresencePayload; -generate_element!( - /// Represents the last time the user interacted with their system. - Idle, "idle", IDLE, - attributes: [ - /// The time at which the user stopped interacting. - since: Required = "since", - ] -); +/// Represents the last time the user interacted with their system. +#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)] +#[xml(namespace = ns::IDLE, name = "idle")] +pub struct Idle { + /// The time at which the user stopped interacting. + #[xml(attribute)] + pub since: DateTime, +} impl PresencePayload for Idle {} @@ -40,15 +43,16 @@ mod tests { #[test] fn test_invalid_child() { - let elem: Element = "" - .parse() - .unwrap(); + let elem: Element = + "" + .parse() + .unwrap(); let error = Idle::try_from(elem).unwrap_err(); let message = match error { FromElementError::Invalid(Error::Other(string)) => string, - _ => panic!(), + other => panic!("unexpected result: {:?}", other), }; - assert_eq!(message, "Unknown child in idle element."); + assert_eq!(message, "Unknown child in Idle element."); } #[test] @@ -59,7 +63,10 @@ mod tests { FromElementError::Invalid(Error::Other(string)) => string, _ => panic!(), }; - assert_eq!(message, "Required attribute 'since' missing."); + assert_eq!( + message, + "Required attribute field 'since' on Idle element missing." + ); } #[test] diff --git a/parsers/src/jingle_ft.rs b/parsers/src/jingle_ft.rs index dc3a582d..64dcca06 100644 --- a/parsers/src/jingle_ft.rs +++ b/parsers/src/jingle_ft.rs @@ -11,7 +11,10 @@ use crate::ns; use minidom::{Element, Node}; use std::collections::BTreeMap; use std::str::FromStr; -use xso::error::{Error, FromElementError}; +use xso::{ + error::{Error, FromElementError}, + FromXml, IntoXml, +}; generate_element!( /// Represents a range in a file. @@ -319,17 +322,18 @@ impl From for Element { } } -generate_element!( - /// A notice that the file transfer has been completed. - Received, "received", JINGLE_FT, - attributes: [ - /// The content identifier of this Jingle session. - name: Required = "name", +/// A notice that the file transfer has been completed. +#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)] +#[xml(namespace = ns::JINGLE_FT, name = "received")] +pub struct Received { + /// The content identifier of this Jingle session. + #[xml(attribute)] + pub name: ContentId, - /// The creator of this file transfer. - creator: Required = "creator", - ] -); + /// The creator of this file transfer. + #[xml(attribute)] + pub creator: Creator, +} #[cfg(test)] mod tests { @@ -479,7 +483,7 @@ mod tests { FromElementError::Invalid(Error::Other(string)) => string, _ => panic!(), }; - assert_eq!(message, "Unknown child in received element."); + assert_eq!(message, "Unknown child in Received element."); let elem: Element = "" @@ -490,7 +494,10 @@ mod tests { FromElementError::Invalid(Error::Other(string)) => string, _ => panic!(), }; - assert_eq!(message, "Required attribute 'name' missing."); + assert_eq!( + message, + "Required attribute field 'name' on Received element missing." + ); let elem: Element = "".parse().unwrap(); let error = Received::try_from(elem).unwrap_err(); @@ -513,7 +520,7 @@ mod tests { FromElementError::Invalid(Error::Other(string)) => string, _ => panic!(), }; - assert_eq!(message, "Unknown attribute in received element."); + assert_eq!(message, "Unknown attribute in Received element."); } #[test] diff --git a/parsers/src/jingle_grouping.rs b/parsers/src/jingle_grouping.rs index b3fc3395..082ab211 100644 --- a/parsers/src/jingle_grouping.rs +++ b/parsers/src/jingle_grouping.rs @@ -4,7 +4,10 @@ // 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/. +use xso::{FromXml, IntoXml}; + use crate::jingle::ContentId; +use crate::ns; generate_attribute!( /// The semantics of the grouping. @@ -17,14 +20,14 @@ generate_attribute!( } ); -generate_element!( - /// Describes a content that should be grouped with other ones. - Content, "content", JINGLE_GROUPING, - attributes: [ - /// The name of the matching [`Content`](crate::jingle::Content). - name: Required = "name", - ] -); +/// Describes a content that should be grouped with other ones. +#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)] +#[xml(namespace = ns::JINGLE_GROUPING, name = "content")] +pub struct Content { + /// The name of the matching [`Content`](crate::jingle::Content). + #[xml(attribute)] + pub name: ContentId, +} impl Content { /// Creates a new \ element. diff --git a/parsers/src/jingle_thumnails.rs b/parsers/src/jingle_thumnails.rs index c8456c6f..59b5770e 100644 --- a/parsers/src/jingle_thumnails.rs +++ b/parsers/src/jingle_thumnails.rs @@ -6,20 +6,30 @@ // 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/. -generate_element!( - /// A Jingle thumbnail. - Thumbnail, "thumbnail", JINGLE_THUMBNAILS, - attributes: [ - /// The URI of the thumbnail. - uri: Required = "uri", - /// The media type of the thumbnail. - media_type: Required = "media-type", - /// The width of the thumbnail. - width: Required = "width", - /// The height of the thumbnail. - height: Required = "height", - ] -); +use xso::{FromXml, IntoXml}; + +use crate::ns; + +/// A Jingle thumbnail. +#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)] +#[xml(namespace = ns::JINGLE_THUMBNAILS, name = "thumbnail")] +pub struct Thumbnail { + /// The URI of the thumbnail. + #[xml(attribute)] + pub uri: String, + + /// The media type of the thumbnail. + #[xml(attribute = "media-type")] + pub media_type: String, + + /// The width of the thumbnail. + #[xml(attribute)] + pub width: u32, + + /// The height of the thumbnail. + #[xml(attribute)] + pub height: u32, +} #[cfg(test)] mod tests { diff --git a/parsers/src/legacy_omemo.rs b/parsers/src/legacy_omemo.rs index e2920f01..6b6442e9 100644 --- a/parsers/src/legacy_omemo.rs +++ b/parsers/src/legacy_omemo.rs @@ -4,18 +4,21 @@ // 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/. +use xso::{FromXml, IntoXml}; + use crate::message::MessagePayload; +use crate::ns; use crate::pubsub::PubSubPayload; use crate::util::text_node_codecs::{Base64, Codec}; -generate_element!( - /// Element of the device list - Device, "device", LEGACY_OMEMO, - attributes: [ - /// Device id - id: Required = "id" - ] -); +/// Element of the device list +#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)] +#[xml(namespace = ns::LEGACY_OMEMO, name = "device")] +pub struct Device { + /// Device id + #[xml(attribute)] + pub id: u32, +} generate_element!( /// A user's device list contains the OMEMO device ids of all the user's diff --git a/parsers/src/mix.rs b/parsers/src/mix.rs index adf92af8..28399347 100644 --- a/parsers/src/mix.rs +++ b/parsers/src/mix.rs @@ -58,14 +58,14 @@ impl Participant { } } -generate_element!( - /// A node to subscribe to. - Subscribe, "subscribe", MIX_CORE, - attributes: [ - /// The PubSub node to subscribe to. - node: Required = "node", - ] -); +/// A node to subscribe to. +#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)] +#[xml(namespace = ns::MIX_CORE, name = "subscribe")] +pub struct Subscribe { + /// The PubSub node to subscribe to. + #[xml(attribute)] + pub node: NodeName, +} impl Subscribe { /// Create a new Subscribe element. @@ -230,14 +230,14 @@ impl Create { } } -generate_element!( - /// Destroy a given MIX channel. - Destroy, "destroy", MIX_CORE, - attributes: [ - /// The channel identifier to be destroyed. - channel: Required = "channel", - ] -); +/// Destroy a given MIX channel. +#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)] +#[xml(namespace = ns::MIX_CORE, name = "destroy")] +pub struct Destroy { + /// The channel identifier to be destroyed. + #[xml(attribute)] + pub channel: ChannelId, +} // TODO: section 7.3.4, example 33, doesn’t mirror the in the iq result unlike every // other section so far. diff --git a/parsers/src/openpgp.rs b/parsers/src/openpgp.rs index db3f7046..e96bca7f 100644 --- a/parsers/src/openpgp.rs +++ b/parsers/src/openpgp.rs @@ -4,7 +4,10 @@ // 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/. +use xso::{FromXml, IntoXml}; + use crate::date::DateTime; +use crate::ns; use crate::pubsub::PubSubPayload; use crate::util::text_node_codecs::{Base64, Codec}; @@ -33,16 +36,18 @@ generate_element!( impl PubSubPayload for PubKey {} -generate_element!( - /// Public key metadata - PubKeyMeta, "pubkey-metadata", OX, - attributes: [ - /// OpenPGP v4 fingerprint - v4fingerprint: Required = "v4-fingerprint", - /// Time the key was published or updated - date: Required = "date", - ] -); +/// Public key metadata +#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)] +#[xml(namespace = ns::OX, name = "pubkey-metadata")] +pub struct PubKeyMeta { + /// OpenPGP v4 fingerprint + #[xml(attribute = "v4-fingerprint")] + pub v4fingerprint: String, + + /// Time the key was published or updated + #[xml(attribute = "date")] + pub date: DateTime, +} generate_element!( /// List of public key metadata diff --git a/parsers/src/pubsub/owner.rs b/parsers/src/pubsub/owner.rs index 7f295731..a7d699a0 100644 --- a/parsers/src/pubsub/owner.rs +++ b/parsers/src/pubsub/owner.rs @@ -28,17 +28,18 @@ generate_element!( ] ); -generate_element!( - /// An affiliation element. - Affiliation, "affiliation", PUBSUB_OWNER, - attributes: [ - /// The node this affiliation pertains to. - jid: Required = "jid", +/// An affiliation element. +#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)] +#[xml(namespace = ns::PUBSUB_OWNER, name = "affiliation")] +pub struct Affiliation { + /// The node this affiliation pertains to. + #[xml(attribute)] + jid: Jid, - /// The affiliation you currently have on this node. - affiliation: Required = "affiliation", - ] -); + /// The affiliation you currently have on this node. + #[xml(attribute)] + affiliation: AffiliationAttribute, +} generate_element!( /// Request to configure a node. @@ -84,14 +85,14 @@ pub struct Redirect { pub uri: String, } -generate_element!( - /// Request to delete a node. - Purge, "purge", PUBSUB_OWNER, - attributes: [ - /// The node to be configured. - node: Required = "node", - ] -); +/// Request to clear a node. +#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)] +#[xml(namespace = ns::PUBSUB_OWNER, name = "purge")] +pub struct Purge { + /// The node to be cleared. + #[xml(attribute)] + pub node: NodeName, +} generate_element!( /// A request for current subscriptions. diff --git a/parsers/src/pubsub/pubsub.rs b/parsers/src/pubsub/pubsub.rs index a295e7c3..82f32da9 100644 --- a/parsers/src/pubsub/pubsub.rs +++ b/parsers/src/pubsub/pubsub.rs @@ -12,7 +12,10 @@ use crate::pubsub::{ }; use crate::Element; use jid::Jid; -use xso::error::{Error, FromElementError}; +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 // XEP-0030. @@ -29,17 +32,18 @@ generate_element!( ] ); -generate_element!( - /// An affiliation element. - Affiliation, "affiliation", PUBSUB, - attributes: [ - /// The node this affiliation pertains to. - node: Required = "node", +/// An affiliation element. +#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)] +#[xml(namespace = ns::PUBSUB, name = "affiliation")] +pub struct Affiliation { + /// The node this affiliation pertains to. + #[xml(attribute)] + pub node: NodeName, - /// The affiliation you currently have on this node. - affiliation: Required = "affiliation", - ] -); + /// The affiliation you currently have on this node. + #[xml(attribute)] + pub affiliation: AffiliationAttribute, +} generate_element!( /// Request to configure a new node. diff --git a/parsers/src/rtt.rs b/parsers/src/rtt.rs index 16992fd7..a9d5ac75 100644 --- a/parsers/src/rtt.rs +++ b/parsers/src/rtt.rs @@ -4,6 +4,8 @@ // 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/. +use xso::{FromXml, IntoXml}; + use crate::ns; use crate::util::text_node_codecs::{Codec, OptionalCodec, Text}; use crate::Element; @@ -110,16 +112,15 @@ impl TryFrom for Erase { } } -generate_element!( - /// Allow for the transmission of intervals, between real-time text actions, to recreate the - /// pauses between key presses. - Wait, "w", RTT, - - attributes: [ - /// Amount of milliseconds to wait before the next action. - time: Required = "n", - ] -); +/// Allow for the transmission of intervals, between real-time text actions, to recreate the +/// pauses between key presses. +#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)] +#[xml(namespace = ns::RTT, name = "w")] +pub struct Wait { + /// Amount of milliseconds to wait before the next action. + #[xml(attribute = "n")] + pub time: u32, +} impl TryFrom for Wait { type Error = Error; diff --git a/parsers/src/sm.rs b/parsers/src/sm.rs index e5483b71..56001e20 100644 --- a/parsers/src/sm.rs +++ b/parsers/src/sm.rs @@ -9,14 +9,14 @@ use xso::{FromXml, IntoXml}; use crate::ns; use crate::stanza_error::DefinedCondition; -generate_element!( - /// Acknowledgement of the currently received stanzas. - A, "a", SM, - attributes: [ - /// The last handled stanza. - h: Required = "h", - ] -); +/// Acknowledgement of the currently received stanzas. +#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)] +#[xml(namespace = ns::SM, name = "a")] +pub struct A { + /// The last handled stanza. + #[xml(attribute)] + pub h: u32, +} impl A { /// Generates a new `` element. diff --git a/parsers/src/stanza_id.rs b/parsers/src/stanza_id.rs index 22b6e4e7..0e0bc359 100644 --- a/parsers/src/stanza_id.rs +++ b/parsers/src/stanza_id.rs @@ -10,18 +10,19 @@ use crate::message::MessagePayload; use crate::ns; use jid::Jid; -generate_element!( - /// Gives the identifier a service has stamped on this stanza, often in - /// order to identify it inside of [an archive](../mam/index.html). - StanzaId, "stanza-id", SID, - attributes: [ - /// The id associated to this stanza by another entity. - id: Required = "id", +/// Gives the identifier a service has stamped on this stanza, often in +/// order to identify it inside of [an archive](../mam/index.html). +#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)] +#[xml(namespace = ns::SID, name = "stanza-id")] +pub struct StanzaId { + /// The id associated to this stanza by another entity. + #[xml(attribute)] + pub id: String, - /// The entity who stamped this stanza-id. - by: Required = "by", - ] -); + /// The entity who stamped this stanza-id. + #[xml(attribute)] + pub by: Jid, +} impl MessagePayload for StanzaId {} @@ -76,15 +77,16 @@ mod tests { #[test] fn test_invalid_child() { - let elem: Element = "" - .parse() - .unwrap(); + let elem: Element = + "" + .parse() + .unwrap(); let error = StanzaId::try_from(elem).unwrap_err(); let message = match error { FromElementError::Invalid(Error::Other(string)) => string, _ => panic!(), }; - assert_eq!(message, "Unknown child in stanza-id element."); + assert_eq!(message, "Unknown child in StanzaId element."); } #[test] @@ -95,7 +97,10 @@ mod tests { FromElementError::Invalid(Error::Other(string)) => string, _ => panic!(), }; - assert_eq!(message, "Required attribute 'id' missing."); + assert_eq!( + message, + "Required attribute field 'id' on StanzaId element missing." + ); } #[test] @@ -108,7 +113,10 @@ mod tests { FromElementError::Invalid(Error::Other(string)) => string, _ => panic!(), }; - assert_eq!(message, "Required attribute 'by' missing."); + assert_eq!( + message, + "Required attribute field 'by' on StanzaId element missing." + ); } #[test]