parsers: port more things to derive macros
This commit is contained in:
parent
93ba2797be
commit
2b346c4e87
18 changed files with 382 additions and 304 deletions
|
|
@ -13,14 +13,14 @@ use crate::hashes::Sha1HexAttribute;
|
|||
use crate::ns;
|
||||
use crate::pubsub::PubSubPayload;
|
||||
|
||||
generate_element!(
|
||||
/// Communicates information about an avatar.
|
||||
Metadata, "metadata", AVATAR_METADATA,
|
||||
children: [
|
||||
/// List of information elements describing this avatar.
|
||||
infos: Vec<Info> = ("info", AVATAR_METADATA) => Info
|
||||
]
|
||||
);
|
||||
/// Communicates information about an avatar.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::AVATAR_METADATA, name = "metadata")]
|
||||
pub struct Metadata {
|
||||
/// List of information elements describing this avatar.
|
||||
#[xml(child(n = ..))]
|
||||
pub infos: Vec<Info>,
|
||||
}
|
||||
|
||||
impl PubSubPayload for Metadata {}
|
||||
|
||||
|
|
|
|||
|
|
@ -56,14 +56,14 @@ generate_elem_id!(
|
|||
SASL_CERT
|
||||
);
|
||||
|
||||
generate_element!(
|
||||
/// A list of resources currently using this certificate.
|
||||
Users, "users", SASL_CERT,
|
||||
children: [
|
||||
/// Resources currently using this certificate.
|
||||
resources: Vec<Resource> = ("resource", SASL_CERT) => Resource
|
||||
]
|
||||
);
|
||||
/// A list of resources currently using this certificate.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::SASL_CERT, name = "users")]
|
||||
pub struct Users {
|
||||
/// Resources currently using this certificate.
|
||||
#[xml(child(n = ..))]
|
||||
pub resources: Vec<Resource>,
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// An X.509 certificate being set for this user.
|
||||
|
|
@ -83,14 +83,14 @@ generate_element!(
|
|||
]
|
||||
);
|
||||
|
||||
generate_element!(
|
||||
/// Server answers with the current list of X.509 certificates.
|
||||
ListCertsResponse, "items", SASL_CERT,
|
||||
children: [
|
||||
/// List of certificates.
|
||||
items: Vec<Item> = ("item", SASL_CERT) => Item
|
||||
]
|
||||
);
|
||||
/// Server answers with the current list of X.509 certificates.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::SASL_CERT, name = "items")]
|
||||
pub struct ListCertsResponse {
|
||||
/// List of certificates.
|
||||
#[xml(child(n = ..))]
|
||||
pub items: Vec<Item>,
|
||||
}
|
||||
|
||||
impl IqResultPayload for ListCertsResponse {}
|
||||
|
||||
|
|
|
|||
|
|
@ -220,25 +220,26 @@ pub struct Item {
|
|||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// Structure representing a `<query
|
||||
/// xmlns='http://jabber.org/protocol/disco#items'/>` element.
|
||||
///
|
||||
/// It should only be used in an `<iq type='result'/>`, as it can only
|
||||
/// represent the result, and not a request.
|
||||
DiscoItemsResult, "query", DISCO_ITEMS,
|
||||
attributes: [
|
||||
/// Node on which we have done this discovery.
|
||||
node: Option<String> = "node"
|
||||
],
|
||||
children: [
|
||||
/// List of items pointed by this entity.
|
||||
items: Vec<Item> = ("item", DISCO_ITEMS) => Item,
|
||||
/// Structure representing a `<query
|
||||
/// xmlns='http://jabber.org/protocol/disco#items'/>` element.
|
||||
///
|
||||
/// It should only be used in an `<iq type='result'/>`, as it can only
|
||||
/// represent the result, and not a request.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::DISCO_ITEMS, name = "query")]
|
||||
pub struct DiscoItemsResult {
|
||||
/// Node on which we have done this discovery.
|
||||
#[xml(attribute(default))]
|
||||
pub node: Option<String>,
|
||||
|
||||
/// Optional paging via Result Set Management
|
||||
rsm: Option<crate::rsm::SetResult> = ("set", RSM) => SetResult,
|
||||
]
|
||||
);
|
||||
/// List of items pointed by this entity.
|
||||
#[xml(child(n = ..))]
|
||||
pub items: Vec<Item>,
|
||||
|
||||
/// Optional paging via Result Set Management
|
||||
#[xml(child(default))]
|
||||
pub rsm: Option<SetResult>,
|
||||
}
|
||||
|
||||
impl IqResultPayload for DiscoItemsResult {}
|
||||
|
||||
|
|
|
|||
|
|
@ -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::{AsXml, FromXml};
|
||||
|
||||
use crate::data_forms::DataForm;
|
||||
use crate::disco::{DiscoInfoQuery, DiscoInfoResult, Feature, Identity};
|
||||
use crate::hashes::{Algo, Hash};
|
||||
|
|
@ -16,16 +18,16 @@ use sha2::{Sha256, Sha512};
|
|||
use sha3::{Sha3_256, Sha3_512};
|
||||
use xso::error::Error;
|
||||
|
||||
generate_element!(
|
||||
/// Represents a set of capability hashes, all of them must correspond to
|
||||
/// the same input [disco#info](../disco/struct.DiscoInfoResult.html),
|
||||
/// using different [algorithms](../hashes/enum.Algo.html).
|
||||
ECaps2, "c", ECAPS2,
|
||||
children: [
|
||||
/// Hashes of the [disco#info](../disco/struct.DiscoInfoResult.html).
|
||||
hashes: Vec<Hash> = ("hash", HASHES) => Hash
|
||||
]
|
||||
);
|
||||
/// Represents a set of capability hashes, all of them must correspond to
|
||||
/// the same input [disco#info](../disco/struct.DiscoInfoResult.html),
|
||||
/// using different [algorithms](../hashes/enum.Algo.html).
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::ECAPS2, name = "c")]
|
||||
pub struct ECaps2 {
|
||||
/// Hashes of the [disco#info](../disco/struct.DiscoInfoResult.html).
|
||||
#[xml(child(n = ..))]
|
||||
pub hashes: Vec<Hash>,
|
||||
}
|
||||
|
||||
impl PresencePayload for ECaps2 {}
|
||||
|
||||
|
|
@ -230,7 +232,7 @@ mod tests {
|
|||
FromElementError::Invalid(Error::Other(string)) => string,
|
||||
_ => panic!(),
|
||||
};
|
||||
assert_eq!(message, "Unknown child in c element.");
|
||||
assert_eq!(message, "Unknown child in ECaps2 element.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -104,37 +104,37 @@ impl IqGetPayload for Service {}
|
|||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::EXT_DISCO, name = "services")]
|
||||
pub struct ServicesQuery {
|
||||
/// TODO
|
||||
/// The type of service to filter for.
|
||||
#[xml(attribute(default, name = "type"))]
|
||||
pub type_: Option<Type>,
|
||||
}
|
||||
|
||||
impl IqGetPayload for ServicesQuery {}
|
||||
|
||||
generate_element!(
|
||||
/// Structure representing a `<services xmlns='urn:xmpp:extdisco:2'/>` element.
|
||||
ServicesResult, "services", EXT_DISCO,
|
||||
attributes: [
|
||||
/// TODO
|
||||
type_: Option<Type> = "type",
|
||||
],
|
||||
children: [
|
||||
/// List of services.
|
||||
services: Vec<Service> = ("service", EXT_DISCO) => Service
|
||||
]
|
||||
);
|
||||
/// Structure representing a `<services xmlns='urn:xmpp:extdisco:2'/>` element.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::EXT_DISCO, name = "services")]
|
||||
pub struct ServicesResult {
|
||||
/// The service type which was requested.
|
||||
#[xml(attribute(name = "type", default))]
|
||||
pub type_: Option<Type>,
|
||||
|
||||
/// List of services.
|
||||
#[xml(child(n = ..))]
|
||||
pub services: Vec<Service>,
|
||||
}
|
||||
|
||||
impl IqResultPayload for ServicesResult {}
|
||||
impl IqSetPayload for ServicesResult {}
|
||||
|
||||
generate_element!(
|
||||
/// Structure representing a `<credentials xmlns='urn:xmpp:extdisco:2'/>` element.
|
||||
Credentials, "credentials", EXT_DISCO,
|
||||
children: [
|
||||
/// List of services.
|
||||
services: Vec<Service> = ("service", EXT_DISCO) => Service
|
||||
]
|
||||
);
|
||||
/// Structure representing a `<credentials xmlns='urn:xmpp:extdisco:2'/>` element.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::EXT_DISCO, name = "credentials")]
|
||||
pub struct Credentials {
|
||||
/// List of services.
|
||||
#[xml(child(n = ..))]
|
||||
pub services: Vec<Service>,
|
||||
}
|
||||
|
||||
impl IqGetPayload for Credentials {}
|
||||
impl IqResultPayload for Credentials {}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,9 @@
|
|||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
use xso::{
|
||||
error::{Error, FromElementError},
|
||||
AsXml, FromXml,
|
||||
error::{Error, FromElementError, FromEventsError},
|
||||
exports::rxml,
|
||||
minidom_compat, AsXml, FromXml,
|
||||
};
|
||||
|
||||
use crate::iq::{IqGetPayload, IqResultPayload};
|
||||
|
|
@ -68,6 +69,20 @@ impl TryFrom<Element> for Header {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromXml for Header {
|
||||
type Builder = minidom_compat::FromEventsViaElement<Header>;
|
||||
|
||||
fn from_events(
|
||||
qname: rxml::QName,
|
||||
attrs: rxml::AttrMap,
|
||||
) -> Result<Self::Builder, FromEventsError> {
|
||||
if qname.0 != ns::HTTP_UPLOAD || qname.1 != "header" {
|
||||
return Err(FromEventsError::Mismatch { name: qname, attrs });
|
||||
}
|
||||
Self::Builder::new(qname, attrs)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Header> for Element {
|
||||
fn from(elem: Header) -> Element {
|
||||
let (attr, val) = match elem {
|
||||
|
|
@ -83,18 +98,26 @@ impl From<Header> for Element {
|
|||
}
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// Put URL
|
||||
Put, "put", HTTP_UPLOAD,
|
||||
attributes: [
|
||||
/// URL
|
||||
url: Required<String> = "url",
|
||||
],
|
||||
children: [
|
||||
/// Header list
|
||||
headers: Vec<Header> = ("header", HTTP_UPLOAD) => Header
|
||||
]
|
||||
);
|
||||
impl AsXml for Header {
|
||||
type ItemIter<'x> = minidom_compat::AsItemsViaElement<'x>;
|
||||
|
||||
fn as_xml_iter(&self) -> Result<Self::ItemIter<'_>, Error> {
|
||||
minidom_compat::AsItemsViaElement::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
/// Put URL
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::HTTP_UPLOAD, name = "put")]
|
||||
pub struct Put {
|
||||
/// URL
|
||||
#[xml(attribute)]
|
||||
pub url: String,
|
||||
|
||||
/// Header list
|
||||
#[xml(child(n = ..))]
|
||||
pub headers: Vec<Header>,
|
||||
}
|
||||
|
||||
/// Get URL
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
|
|
|
|||
|
|
@ -38,18 +38,18 @@ impl Content {
|
|||
}
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// A semantic group of contents.
|
||||
Group, "group", JINGLE_GROUPING,
|
||||
attributes: [
|
||||
/// Semantics of the grouping.
|
||||
semantics: Required<Semantics> = "semantics",
|
||||
],
|
||||
children: [
|
||||
/// List of contents that should be grouped with each other.
|
||||
contents: Vec<Content> = ("content", JINGLE_GROUPING) => Content
|
||||
]
|
||||
);
|
||||
/// A semantic group of contents.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::JINGLE_GROUPING, name = "group")]
|
||||
pub struct Group {
|
||||
/// Semantics of the grouping.
|
||||
#[xml(attribute)]
|
||||
pub semantics: Semantics,
|
||||
|
||||
/// List of contents that should be grouped with each other.
|
||||
#[xml(child(n = ..))]
|
||||
pub contents: Vec<Content>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
|
|
|||
|
|
@ -8,18 +8,18 @@ use xso::{AsXml, FromXml};
|
|||
|
||||
use crate::ns;
|
||||
|
||||
generate_element!(
|
||||
/// Source element for the ssrc SDP attribute.
|
||||
Source, "source", JINGLE_SSMA,
|
||||
attributes: [
|
||||
/// Maps to the ssrc-id parameter.
|
||||
id: Required<u32> = "ssrc",
|
||||
],
|
||||
children: [
|
||||
/// List of attributes for this source.
|
||||
parameters: Vec<Parameter> = ("parameter", JINGLE_SSMA) => Parameter
|
||||
]
|
||||
);
|
||||
/// Source element for the ssrc SDP attribute.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::JINGLE_SSMA, name = "source")]
|
||||
pub struct Source {
|
||||
/// Maps to the ssrc-id parameter.
|
||||
#[xml(attribute = "ssrc")]
|
||||
pub id: u32,
|
||||
|
||||
/// List of attributes for this source.
|
||||
#[xml(child(n = ..))]
|
||||
pub parameters: Vec<Parameter>,
|
||||
}
|
||||
|
||||
impl Source {
|
||||
/// Create a new SSMA Source element.
|
||||
|
|
@ -67,18 +67,18 @@ generate_attribute!(
|
|||
}
|
||||
);
|
||||
|
||||
generate_element!(
|
||||
/// Element grouping multiple ssrc.
|
||||
Group, "ssrc-group", JINGLE_SSMA,
|
||||
attributes: [
|
||||
/// The semantics of this group.
|
||||
semantics: Required<Semantics> = "semantics",
|
||||
],
|
||||
children: [
|
||||
/// The various ssrc concerned by this group.
|
||||
sources: Vec<Source> = ("source", JINGLE_SSMA) => Source
|
||||
]
|
||||
);
|
||||
/// Element grouping multiple ssrc.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::JINGLE_SSMA, name = "ssrc-group")]
|
||||
pub struct Group {
|
||||
/// The semantics of this group.
|
||||
#[xml(attribute)]
|
||||
pub semantics: Semantics,
|
||||
|
||||
/// The various ssrc concerned by this group.
|
||||
#[xml(child(n = ..))]
|
||||
pub sources: Vec<Source>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
|
|
|||
|
|
@ -19,15 +19,15 @@ pub struct Device {
|
|||
pub id: u32,
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// A user's device list contains the OMEMO device ids of all the user's
|
||||
/// devicse. These can be used to look up bundles and build a session.
|
||||
DeviceList, "list", LEGACY_OMEMO,
|
||||
children: [
|
||||
/// List of devices
|
||||
devices: Vec<Device> = ("device", LEGACY_OMEMO) => Device
|
||||
]
|
||||
);
|
||||
/// A user's device list contains the OMEMO device ids of all the user's
|
||||
/// devicse. These can be used to look up bundles and build a session.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::LEGACY_OMEMO, name = "list")]
|
||||
pub struct DeviceList {
|
||||
/// List of devices
|
||||
#[xml(child(n = ..))]
|
||||
pub devices: Vec<Device>,
|
||||
}
|
||||
|
||||
impl PubSubPayload for DeviceList {}
|
||||
|
||||
|
|
@ -64,15 +64,15 @@ pub struct IdentityKey {
|
|||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// List of (single use) PreKeys
|
||||
/// Part of a device's bundle
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::LEGACY_OMEMO, name = "prekeys")]
|
||||
pub struct Prekeys {
|
||||
/// List of (single use) PreKeys
|
||||
/// Part of a device's bundle
|
||||
Prekeys, "prekeys", LEGACY_OMEMO,
|
||||
children: [
|
||||
/// List of (single use) PreKeys
|
||||
keys: Vec<PreKeyPublic> = ("preKeyPublic", LEGACY_OMEMO) => PreKeyPublic,
|
||||
]
|
||||
);
|
||||
#[xml(child(n = ..))]
|
||||
pub keys: Vec<PreKeyPublic>,
|
||||
}
|
||||
|
||||
/// PreKey public key
|
||||
/// Part of a device's bundle
|
||||
|
|
@ -113,22 +113,23 @@ pub struct Bundle {
|
|||
|
||||
impl PubSubPayload for Bundle {}
|
||||
|
||||
generate_element!(
|
||||
/// The header contains encrypted keys for a message
|
||||
Header, "header", LEGACY_OMEMO,
|
||||
attributes: [
|
||||
/// The device id of the sender
|
||||
sid: Required<u32> = "sid",
|
||||
],
|
||||
children: [
|
||||
/// The key that the payload message is encrypted with, separately
|
||||
/// encrypted for each recipient device.
|
||||
keys: Vec<Key> = ("key", LEGACY_OMEMO) => Key,
|
||||
/// The header contains encrypted keys for a message
|
||||
#[derive(FromXml, AsXml, Debug, PartialEq, Clone)]
|
||||
#[xml(namespace = ns::LEGACY_OMEMO, name = "header")]
|
||||
pub struct Header {
|
||||
/// The device id of the sender
|
||||
#[xml(attribute)]
|
||||
pub sid: u32,
|
||||
|
||||
/// IV used for payload encryption
|
||||
iv: Required<IV> = ("iv", LEGACY_OMEMO) => IV
|
||||
]
|
||||
);
|
||||
/// The key that the payload message is encrypted with, separately
|
||||
/// encrypted for each recipient device.
|
||||
#[xml(child(n = ..))]
|
||||
pub keys: Vec<Key>,
|
||||
|
||||
/// IV used for payload encryption
|
||||
#[xml(child)]
|
||||
pub iv: IV,
|
||||
}
|
||||
|
||||
/// IV used for payload encryption
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
|
|
|
|||
|
|
@ -27,22 +27,23 @@ pub struct Uri {
|
|||
pub uri: String,
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// References a media element, to be used in [data
|
||||
/// forms](../data_forms/index.html).
|
||||
MediaElement, "media", MEDIA_ELEMENT,
|
||||
attributes: [
|
||||
/// The recommended display width in pixels.
|
||||
width: Option<usize> = "width",
|
||||
/// References a media element, to be used in [data
|
||||
/// forms](../data_forms/index.html).
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::MEDIA_ELEMENT, name = "media")]
|
||||
pub struct MediaElement {
|
||||
/// The recommended display width in pixels.
|
||||
#[xml(attribute(default))]
|
||||
pub width: Option<usize>,
|
||||
|
||||
/// The recommended display height in pixels.
|
||||
height: Option<usize> = "height"
|
||||
],
|
||||
children: [
|
||||
/// A list of URIs referencing this media.
|
||||
uris: Vec<Uri> = ("uri", MEDIA_ELEMENT) => Uri
|
||||
]
|
||||
);
|
||||
/// The recommended display height in pixels.
|
||||
#[xml(attribute(default))]
|
||||
pub height: Option<usize>,
|
||||
|
||||
/// A list of URIs referencing this media.
|
||||
#[xml(child(n = ..))]
|
||||
pub uris: Vec<Uri>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
|
@ -162,7 +163,7 @@ mod tests {
|
|||
FromElementError::Invalid(Error::Other(string)) => string,
|
||||
_ => panic!(),
|
||||
};
|
||||
assert_eq!(message, "Unknown child in media element.");
|
||||
assert_eq!(message, "Unknown child in MediaElement element.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -113,21 +113,21 @@ impl Join {
|
|||
}
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// Update a given subscription.
|
||||
UpdateSubscription, "update-subscription", MIX_CORE,
|
||||
attributes: [
|
||||
/// The JID of the user to be affected.
|
||||
// TODO: why is it not a participant id instead?
|
||||
jid: Option<BareJid> = "jid",
|
||||
],
|
||||
children: [
|
||||
/// The list of additional nodes to subscribe to.
|
||||
// TODO: what happens when we are already subscribed? Also, how do we unsubscribe from
|
||||
// just one?
|
||||
subscribes: Vec<Subscribe> = ("subscribe", MIX_CORE) => Subscribe
|
||||
]
|
||||
);
|
||||
/// Update a given subscription.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::MIX_CORE, name = "update-subscription")]
|
||||
pub struct UpdateSubscription {
|
||||
/// The JID of the user to be affected.
|
||||
// TODO: why is it not a participant id instead?
|
||||
#[xml(attribute(default))]
|
||||
pub jid: Option<BareJid>,
|
||||
|
||||
/// The list of additional nodes to subscribe to.
|
||||
// TODO: what happens when we are already subscribed? Also, how do we unsubscribe from
|
||||
// just one?
|
||||
#[xml(child(n = ..))]
|
||||
pub subscribes: Vec<Subscribe>,
|
||||
}
|
||||
|
||||
impl IqSetPayload for UpdateSubscription {}
|
||||
impl IqResultPayload for UpdateSubscription {}
|
||||
|
|
|
|||
|
|
@ -48,14 +48,14 @@ pub struct PubKeyMeta {
|
|||
pub date: DateTime,
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// List of public key metadata
|
||||
PubKeysMeta, "public-key-list", OX,
|
||||
children: [
|
||||
/// Public keys
|
||||
pubkeys: Vec<PubKeyMeta> = ("pubkey-metadata", OX) => PubKeyMeta
|
||||
]
|
||||
);
|
||||
/// List of public key metadata
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::OX, name = "public-key-list")]
|
||||
pub struct PubKeysMeta {
|
||||
/// Public keys
|
||||
#[xml(child(n = ..))]
|
||||
pub pubkeys: Vec<PubKeyMeta>,
|
||||
}
|
||||
|
||||
impl PubSubPayload for PubKeysMeta {}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,18 +15,18 @@ use jid::Jid;
|
|||
use minidom::Element;
|
||||
use xso::error::{Error, FromElementError};
|
||||
|
||||
generate_element!(
|
||||
/// A list of affiliations you have on a service, or on a node.
|
||||
Affiliations, "affiliations", PUBSUB_OWNER,
|
||||
attributes: [
|
||||
/// The node name this request pertains to.
|
||||
node: Required<NodeName> = "node",
|
||||
],
|
||||
children: [
|
||||
/// The actual list of affiliation elements.
|
||||
affiliations: Vec<Affiliation> = ("affiliation", PUBSUB_OWNER) => Affiliation
|
||||
]
|
||||
);
|
||||
/// A list of affiliations you have on a service, or on a node.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::PUBSUB_OWNER, name = "affiliations")]
|
||||
pub struct Affiliations {
|
||||
/// The node name this request pertains to.
|
||||
#[xml(attribute)]
|
||||
pub node: NodeName,
|
||||
|
||||
/// The actual list of affiliation elements.
|
||||
#[xml(child(n = ..))]
|
||||
pub affiliations: Vec<Affiliation>,
|
||||
}
|
||||
|
||||
/// An affiliation element.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
|
|
@ -94,18 +94,18 @@ pub struct Purge {
|
|||
pub node: NodeName,
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// A request for current subscriptions.
|
||||
Subscriptions, "subscriptions", PUBSUB_OWNER,
|
||||
attributes: [
|
||||
/// The node to query.
|
||||
node: Required<NodeName> = "node",
|
||||
],
|
||||
children: [
|
||||
/// The list of subscription elements returned.
|
||||
subscriptions: Vec<SubscriptionElem> = ("subscription", PUBSUB_OWNER) => SubscriptionElem
|
||||
]
|
||||
);
|
||||
/// A request for current subscriptions.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::PUBSUB_OWNER, name = "subscriptions")]
|
||||
pub struct Subscriptions {
|
||||
/// The node to query.
|
||||
#[xml(attribute)]
|
||||
pub node: NodeName,
|
||||
|
||||
/// The list of subscription elements returned.
|
||||
#[xml(child(n = ..))]
|
||||
pub subscriptions: Vec<SubscriptionElem>,
|
||||
}
|
||||
|
||||
/// A subscription element, describing the state of a subscription.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
|
|
|
|||
|
|
@ -21,18 +21,18 @@ use minidom::Element;
|
|||
|
||||
// TODO: a better solution would be to split this into a query and a result elements, like for
|
||||
// XEP-0030.
|
||||
generate_element!(
|
||||
/// A list of affiliations you have on a service, or on a node.
|
||||
Affiliations, "affiliations", PUBSUB,
|
||||
attributes: [
|
||||
/// The optional node name this request pertains to.
|
||||
node: Option<NodeName> = "node",
|
||||
],
|
||||
children: [
|
||||
/// The actual list of affiliation elements.
|
||||
affiliations: Vec<Affiliation> = ("affiliation", PUBSUB) => Affiliation
|
||||
]
|
||||
);
|
||||
/// A list of affiliations you have on a service, or on a node.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::PUBSUB, name = "affiliations")]
|
||||
pub struct Affiliations {
|
||||
/// The optional node name this request pertains to.
|
||||
#[xml(attribute(default))]
|
||||
pub node: Option<NodeName>,
|
||||
|
||||
/// The actual list of affiliation elements.
|
||||
#[xml(child(n = ..))]
|
||||
pub affiliations: Vec<Affiliation>,
|
||||
}
|
||||
|
||||
/// An affiliation element.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
|
|
@ -77,25 +77,27 @@ pub struct Default {
|
|||
// type_: Option<String>,
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// A request for a list of items.
|
||||
Items, "items", PUBSUB,
|
||||
attributes: [
|
||||
// TODO: should be an xs:positiveInteger, that is, an unbounded int ≥ 1.
|
||||
/// Maximum number of items returned.
|
||||
max_items: Option<u32> = "max_items",
|
||||
/// A request for a list of items.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::PUBSUB, name = "items")]
|
||||
pub struct Items {
|
||||
// TODO: should be an xs:positiveInteger, that is, an unbounded int ≥ 1.
|
||||
/// Maximum number of items returned.
|
||||
#[xml(attribute(name = "max_items" /*sic!*/, default))]
|
||||
pub max_items: Option<u32>,
|
||||
|
||||
/// The node queried by this request.
|
||||
node: Required<NodeName> = "node",
|
||||
/// The node queried by this request.
|
||||
#[xml(attribute)]
|
||||
pub node: NodeName,
|
||||
|
||||
/// The subscription identifier related to this request.
|
||||
subid: Option<SubscriptionId> = "subid",
|
||||
],
|
||||
children: [
|
||||
/// The actual list of items returned.
|
||||
items: Vec<Item> = ("item", PUBSUB) => Item
|
||||
]
|
||||
);
|
||||
/// The subscription identifier related to this request.
|
||||
#[xml(attribute(default))]
|
||||
pub subid: Option<SubscriptionId>,
|
||||
|
||||
/// The actual list of items returned.
|
||||
#[xml(child(n = ..))]
|
||||
pub items: Vec<Item>,
|
||||
}
|
||||
|
||||
impl Items {
|
||||
/// Create a new items request.
|
||||
|
|
@ -136,18 +138,18 @@ pub struct Options {
|
|||
pub form: Option<DataForm>,
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// Request to publish items to a node.
|
||||
Publish, "publish", PUBSUB,
|
||||
attributes: [
|
||||
/// The target node for this operation.
|
||||
node: Required<NodeName> = "node",
|
||||
],
|
||||
children: [
|
||||
/// The items you want to publish.
|
||||
items: Vec<Item> = ("item", PUBSUB) => Item
|
||||
]
|
||||
);
|
||||
/// Request to publish items to a node.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::PUBSUB, name = "publish")]
|
||||
pub struct Publish {
|
||||
/// The target node for this operation.
|
||||
#[xml(attribute)]
|
||||
pub node: NodeName,
|
||||
|
||||
/// The items you want to publish.
|
||||
#[xml(child(n = ..))]
|
||||
pub items: Vec<Item>,
|
||||
}
|
||||
|
||||
/// The options associated to a publish request.
|
||||
#[derive(FromXml, AsXml, Debug, PartialEq, Clone)]
|
||||
|
|
@ -259,18 +261,18 @@ pub struct Subscribe {
|
|||
pub node: Option<NodeName>,
|
||||
}
|
||||
|
||||
generate_element!(
|
||||
/// A request for current subscriptions.
|
||||
Subscriptions, "subscriptions", PUBSUB,
|
||||
attributes: [
|
||||
/// The node to query.
|
||||
node: Option<NodeName> = "node",
|
||||
],
|
||||
children: [
|
||||
/// The list of subscription elements returned.
|
||||
subscription: Vec<SubscriptionElem> = ("subscription", PUBSUB) => SubscriptionElem
|
||||
]
|
||||
);
|
||||
/// A request for current subscriptions.
|
||||
#[derive(FromXml, AsXml, Debug, PartialEq, Clone)]
|
||||
#[xml(namespace = ns::PUBSUB, name = "subscriptions")]
|
||||
pub struct Subscriptions {
|
||||
/// The node to query.
|
||||
#[xml(attribute(default))]
|
||||
pub node: Option<NodeName>,
|
||||
|
||||
/// The list of subscription elements returned.
|
||||
#[xml(child(n = ..))]
|
||||
pub subscription: Vec<SubscriptionElem>,
|
||||
}
|
||||
|
||||
/// A subscription element, describing the state of a subscription.
|
||||
#[derive(FromXml, AsXml, Debug, PartialEq, Clone)]
|
||||
|
|
|
|||
|
|
@ -9,18 +9,18 @@ use xso::{AsXml, FromXml};
|
|||
use crate::message::MessagePayload;
|
||||
use crate::ns;
|
||||
|
||||
generate_element!(
|
||||
/// Container for a set of reactions.
|
||||
Reactions, "reactions", REACTIONS,
|
||||
attributes: [
|
||||
/// The id of the message these reactions apply to.
|
||||
id: Required<String> = "id",
|
||||
],
|
||||
children: [
|
||||
/// The list of reactions.
|
||||
reactions: Vec<Reaction> = ("reaction", REACTIONS) => Reaction,
|
||||
]
|
||||
);
|
||||
/// Container for a set of reactions.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::REACTIONS, name = "reactions")]
|
||||
pub struct Reactions {
|
||||
/// The id of the message these reactions apply to.
|
||||
#[xml(attribute)]
|
||||
pub id: String,
|
||||
|
||||
/// The list of reactions.
|
||||
#[xml(child(n = ..))]
|
||||
pub reactions: Vec<Reaction>,
|
||||
}
|
||||
|
||||
impl MessagePayload for Reactions {}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,9 +4,13 @@
|
|||
// 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 crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload};
|
||||
use xso::{AsXml, FromXml};
|
||||
|
||||
use jid::BareJid;
|
||||
|
||||
use crate::iq::{IqGetPayload, IqResultPayload, IqSetPayload};
|
||||
use crate::ns;
|
||||
|
||||
generate_elem_id!(
|
||||
/// Represents a group a contact is part of.
|
||||
Group,
|
||||
|
|
@ -67,22 +71,22 @@ generate_element!(
|
|||
]
|
||||
);
|
||||
|
||||
generate_element!(
|
||||
/// The contact list of the user.
|
||||
Roster, "query", ROSTER,
|
||||
attributes: [
|
||||
/// Version of the contact list.
|
||||
///
|
||||
/// This is an opaque string that should only be sent back to the server on
|
||||
/// a new connection, if this client is storing the contact list between
|
||||
/// connections.
|
||||
ver: Option<String> = "ver"
|
||||
],
|
||||
children: [
|
||||
/// List of the contacts of the user.
|
||||
items: Vec<Item> = ("item", ROSTER) => Item
|
||||
]
|
||||
);
|
||||
/// The contact list of the user.
|
||||
#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
|
||||
#[xml(namespace = ns::ROSTER, name = "query")]
|
||||
pub struct Roster {
|
||||
/// Version of the contact list.
|
||||
///
|
||||
/// This is an opaque string that should only be sent back to the server on
|
||||
/// a new connection, if this client is storing the contact list between
|
||||
/// connections.
|
||||
#[xml(attribute(default))]
|
||||
pub ver: Option<String>,
|
||||
|
||||
/// List of the contacts of the user.
|
||||
#[xml(child(n = ..))]
|
||||
pub items: Vec<Item>,
|
||||
}
|
||||
|
||||
impl IqGetPayload for Roster {}
|
||||
impl IqSetPayload for Roster {}
|
||||
|
|
@ -273,7 +277,7 @@ mod tests {
|
|||
FromElementError::Invalid(Error::Other(string)) => string,
|
||||
_ => panic!(),
|
||||
};
|
||||
assert_eq!(message, "Unknown child in query element.");
|
||||
assert_eq!(message, "Unknown child in Roster element.");
|
||||
|
||||
let elem: Element = "<query xmlns='jabber:iq:roster' coucou=''/>"
|
||||
.parse()
|
||||
|
|
@ -283,7 +287,7 @@ mod tests {
|
|||
FromElementError::Invalid(Error::Other(string)) => string,
|
||||
_ => panic!(),
|
||||
};
|
||||
assert_eq!(message, "Unknown attribute in query element.");
|
||||
assert_eq!(message, "Unknown attribute in Roster element.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -172,6 +172,20 @@ impl TryFrom<Element> for SetResult {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromXml for SetResult {
|
||||
type Builder = minidom_compat::FromEventsViaElement<SetResult>;
|
||||
|
||||
fn from_events(
|
||||
qname: rxml::QName,
|
||||
attrs: rxml::AttrMap,
|
||||
) -> Result<Self::Builder, FromEventsError> {
|
||||
if qname.0 != crate::ns::RSM || qname.1 != "set" {
|
||||
return Err(FromEventsError::Mismatch { name: qname, attrs });
|
||||
}
|
||||
Self::Builder::new(qname, attrs)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SetResult> for Element {
|
||||
fn from(set: SetResult) -> Element {
|
||||
let first = set.first.clone().map(|first| {
|
||||
|
|
@ -193,6 +207,14 @@ impl From<SetResult> for Element {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsXml for SetResult {
|
||||
type ItemIter<'x> = minidom_compat::AsItemsViaElement<'x>;
|
||||
|
||||
fn as_xml_iter(&self) -> Result<Self::ItemIter<'_>, Error> {
|
||||
minidom_compat::AsItemsViaElement::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
|||
|
|
@ -762,6 +762,20 @@ macro_rules! impl_pubsub_item {
|
|||
}
|
||||
}
|
||||
|
||||
impl ::xso::FromXml for $item {
|
||||
type Builder = ::xso::minidom_compat::FromEventsViaElement<$item>;
|
||||
|
||||
fn from_events(
|
||||
qname: ::xso::exports::rxml::QName,
|
||||
attrs: ::xso::exports::rxml::AttrMap,
|
||||
) -> Result<Self::Builder, ::xso::error::FromEventsError> {
|
||||
if qname.0 != crate::ns::$ns || qname.1 != "item" {
|
||||
return Err(::xso::error::FromEventsError::Mismatch { name: qname, attrs });
|
||||
}
|
||||
Self::Builder::new(qname, attrs)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<$item> for minidom::Element {
|
||||
fn from(item: $item) -> minidom::Element {
|
||||
minidom::Element::builder("item", ns::$ns)
|
||||
|
|
@ -772,6 +786,14 @@ macro_rules! impl_pubsub_item {
|
|||
}
|
||||
}
|
||||
|
||||
impl ::xso::AsXml for $item {
|
||||
type ItemIter<'x> = ::xso::minidom_compat::AsItemsViaElement<'x>;
|
||||
|
||||
fn as_xml_iter(&self) -> Result<Self::ItemIter<'_>, ::xso::error::Error> {
|
||||
::xso::minidom_compat::AsItemsViaElement::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::ops::Deref for $item {
|
||||
type Target = crate::pubsub::Item;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue