parsers: port more generate_element! usages to derive macros
This commit is contained in:
parent
4e9c4883a3
commit
cea246a0fc
13 changed files with 198 additions and 149 deletions
|
@ -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.
|
||||
|
|
|
@ -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: [
|
||||
/// 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.
|
||||
since: Required<DateTime> = "since",
|
||||
]
|
||||
);
|
||||
#[xml(attribute)]
|
||||
pub since: DateTime,
|
||||
}
|
||||
|
||||
impl PresencePayload for Idle {}
|
||||
|
||||
|
@ -40,15 +43,16 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_invalid_child() {
|
||||
let elem: Element = "<idle xmlns='urn:xmpp:idle:1'><coucou/></idle>"
|
||||
let elem: Element =
|
||||
"<idle xmlns='urn:xmpp:idle:1' since='2017-05-21T20:19:55+01:00'><coucou/></idle>"
|
||||
.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]
|
||||
|
|
|
@ -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<Checksum> for Element {
|
|||
}
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// A notice that the file transfer has been completed.
|
||||
Received, "received", JINGLE_FT,
|
||||
attributes: [
|
||||
/// 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.
|
||||
name: Required<ContentId> = "name",
|
||||
#[xml(attribute)]
|
||||
pub name: ContentId,
|
||||
|
||||
/// The creator of this file transfer.
|
||||
creator: Required<Creator> = "creator",
|
||||
]
|
||||
);
|
||||
#[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 =
|
||||
"<received xmlns='urn:xmpp:jingle:apps:file-transfer:5' creator='initiator'/>"
|
||||
|
@ -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 = "<received xmlns='urn:xmpp:jingle:apps:file-transfer:5' name='coucou' creator='coucou'/>".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]
|
||||
|
|
|
@ -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: [
|
||||
/// 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).
|
||||
name: Required<ContentId> = "name",
|
||||
]
|
||||
);
|
||||
#[xml(attribute)]
|
||||
pub name: ContentId,
|
||||
}
|
||||
|
||||
impl Content {
|
||||
/// Creates a new \<content/\> element.
|
||||
|
|
|
@ -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: [
|
||||
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.
|
||||
uri: Required<String> = "uri",
|
||||
#[xml(attribute)]
|
||||
pub uri: String,
|
||||
|
||||
/// The media type of the thumbnail.
|
||||
media_type: Required<String> = "media-type",
|
||||
#[xml(attribute = "media-type")]
|
||||
pub media_type: String,
|
||||
|
||||
/// The width of the thumbnail.
|
||||
width: Required<u32> = "width",
|
||||
#[xml(attribute)]
|
||||
pub width: u32,
|
||||
|
||||
/// The height of the thumbnail.
|
||||
height: Required<u32> = "height",
|
||||
]
|
||||
);
|
||||
#[xml(attribute)]
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
|
|
@ -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: [
|
||||
/// Element of the device list
|
||||
#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::LEGACY_OMEMO, name = "device")]
|
||||
pub struct Device {
|
||||
/// Device id
|
||||
id: Required<u32> = "id"
|
||||
]
|
||||
);
|
||||
#[xml(attribute)]
|
||||
pub id: u32,
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// A user's device list contains the OMEMO device ids of all the user's
|
||||
|
|
|
@ -58,14 +58,14 @@ impl Participant {
|
|||
}
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// A node to subscribe to.
|
||||
Subscribe, "subscribe", MIX_CORE,
|
||||
attributes: [
|
||||
/// 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.
|
||||
node: Required<NodeName> = "node",
|
||||
]
|
||||
);
|
||||
#[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: [
|
||||
/// 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.
|
||||
channel: Required<ChannelId> = "channel",
|
||||
]
|
||||
);
|
||||
#[xml(attribute)]
|
||||
pub channel: ChannelId,
|
||||
}
|
||||
|
||||
// TODO: section 7.3.4, example 33, doesn’t mirror the <destroy/> in the iq result unlike every
|
||||
// other section so far.
|
||||
|
|
|
@ -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: [
|
||||
/// Public key metadata
|
||||
#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::OX, name = "pubkey-metadata")]
|
||||
pub struct PubKeyMeta {
|
||||
/// OpenPGP v4 fingerprint
|
||||
v4fingerprint: Required<String> = "v4-fingerprint",
|
||||
#[xml(attribute = "v4-fingerprint")]
|
||||
pub v4fingerprint: String,
|
||||
|
||||
/// Time the key was published or updated
|
||||
date: Required<DateTime> = "date",
|
||||
]
|
||||
);
|
||||
#[xml(attribute = "date")]
|
||||
pub date: DateTime,
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// List of public key metadata
|
||||
|
|
|
@ -28,17 +28,18 @@ generate_element!(
|
|||
]
|
||||
);
|
||||
|
||||
generate_element!(
|
||||
/// An affiliation element.
|
||||
Affiliation, "affiliation", PUBSUB_OWNER,
|
||||
attributes: [
|
||||
/// 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.
|
||||
jid: Required<Jid> = "jid",
|
||||
#[xml(attribute)]
|
||||
jid: Jid,
|
||||
|
||||
/// The affiliation you currently have on this node.
|
||||
affiliation: Required<AffiliationAttribute> = "affiliation",
|
||||
]
|
||||
);
|
||||
#[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<NodeName> = "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.
|
||||
|
|
|
@ -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: [
|
||||
/// An affiliation element.
|
||||
#[derive(FromXml, IntoXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::PUBSUB, name = "affiliation")]
|
||||
pub struct Affiliation {
|
||||
/// The node this affiliation pertains to.
|
||||
node: Required<NodeName> = "node",
|
||||
#[xml(attribute)]
|
||||
pub node: NodeName,
|
||||
|
||||
/// The affiliation you currently have on this node.
|
||||
affiliation: Required<AffiliationAttribute> = "affiliation",
|
||||
]
|
||||
);
|
||||
#[xml(attribute)]
|
||||
pub affiliation: AffiliationAttribute,
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// Request to configure a new node.
|
||||
|
|
|
@ -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<Action> 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: [
|
||||
/// 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.
|
||||
time: Required<u32> = "n",
|
||||
]
|
||||
);
|
||||
#[xml(attribute = "n")]
|
||||
pub time: u32,
|
||||
}
|
||||
|
||||
impl TryFrom<Action> for Wait {
|
||||
type Error = Error;
|
||||
|
|
|
@ -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: [
|
||||
/// 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.
|
||||
h: Required<u32> = "h",
|
||||
]
|
||||
);
|
||||
#[xml(attribute)]
|
||||
pub h: u32,
|
||||
}
|
||||
|
||||
impl A {
|
||||
/// Generates a new `<a/>` element.
|
||||
|
|
|
@ -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: [
|
||||
/// 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.
|
||||
id: Required<String> = "id",
|
||||
#[xml(attribute)]
|
||||
pub id: String,
|
||||
|
||||
/// The entity who stamped this stanza-id.
|
||||
by: Required<Jid> = "by",
|
||||
]
|
||||
);
|
||||
#[xml(attribute)]
|
||||
pub by: Jid,
|
||||
}
|
||||
|
||||
impl MessagePayload for StanzaId {}
|
||||
|
||||
|
@ -76,7 +77,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_invalid_child() {
|
||||
let elem: Element = "<stanza-id xmlns='urn:xmpp:sid:0'><coucou/></stanza-id>"
|
||||
let elem: Element =
|
||||
"<stanza-id xmlns='urn:xmpp:sid:0' by='a@b' id='x'><coucou/></stanza-id>"
|
||||
.parse()
|
||||
.unwrap();
|
||||
let error = StanzaId::try_from(elem).unwrap_err();
|
||||
|
@ -84,7 +86,7 @@ mod tests {
|
|||
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]
|
||||
|
|
Loading…
Reference in a new issue