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 | 28 ++++++++++++--------- parsers/src/rtt.rs | 21 ++++++++-------- parsers/src/sm.rs | 16 ++++++------ parsers/src/stanza_id.rs | 44 +++++++++++++++++++-------------- 13 files changed, 200 insertions(+), 151 deletions(-) diff --git a/parsers/Cargo.toml b/parsers/Cargo.toml index cb5f88efdd72650cf9faeb18f36ac3bcab4641aa..b15a4af506dd513700f9beb777ba5c86b74180ae 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 c2158a019ccf04c4382ce6b2bdf6c6cf65597dd4..866e3e350cc0f38f319dbf7dd650cc86b0dd4e39 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 dc3a582d133ff2ba1544f77ed3e36d262cfc4882..64dcca06975ca55e24699cbd39f36d5cb5dee3c9 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 b3fc33956093f9a3037116e9ddf6307264a2c088..082ab211440b7a64d43d3658973bf08dd3428988 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 c8456c6f32b6d2e7d452b17bd8fba04c90380a03..59b5770ee176c5478322c04879cf4c67d62aa402 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 e2920f01ffb5fcf4062824c4eae45ce25135e837..6b6442e9b0541cf151760835087d2104918d1709 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 adf92af87828e70f3ed2cf360712917c86b9fbf9..28399347eacb392d4a2a7d5160138b0bc93dde65 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 db3f7046d524b8949e07313eb4bf541a89749e55..e96bca7f5a169f9045fbb0ac438753f9cad65926 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 7f295731d3abb0ab195113ecf9375d383eab44ed..a7d699a09059b84783c04188c90ffcb79ec35129 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 a295e7c304e45de77ce10c602256c2c12aae9ba8..82f32da90038c1c55460997f531e2c4e7789398a 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", - - /// The affiliation you currently have on this node. - affiliation: Required = "affiliation", - ] -); +/// 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. + #[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 16992fd7425b23863b4afdb5352215dc50e0cd11..a9d5ac75a9fa1ceeff67e3ed9aea9654545f0b0d 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 e5483b710af864ddba46265f8f36065bc4246b67..56001e20b52ecb55f066b8fb50f46e7d8b552eb0 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 22b6e4e733d275e953524a3241a6c99f1f03a5ff..0e0bc359ce1240c9b93faa2a815802db5452b1c7 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", - - /// The entity who stamped this stanza-id. - by: Required = "by", - ] -); +/// 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. + #[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]