xmpp-parsers: Remove MIX support

Emmanuel Gil Peyrot created

This protocol has failed to gain any traction in the XMPP ecosystem and
is actively being replaced with better alternatives based on MUC.

Change summary

parsers/ChangeLog  |   3 
parsers/doap.xml   |   2 
parsers/src/lib.rs |   3 
parsers/src/mix.rs | 391 ------------------------------------------------
parsers/src/ns.rs  |  17 --
5 files changed, 4 insertions(+), 412 deletions(-)

Detailed changes

parsers/ChangeLog đź”—

@@ -1,6 +1,9 @@
 Version NEXT:
 XXXX-YY-ZZ RELEASER <admin@example.com>
     * Breaking
+      - MIX (XEP-0369) has been removed, it has failed to gain any traction in
+        the XMPP ecosystem and is actively being replaced with better
+        alternatives based on MUC.
       - The `alternate_address` field of
         `xmpp_parsers::stanza_error::StanzaError` has been moved into the
         corresponding enum variants of the

parsers/doap.xml đź”—

@@ -565,7 +565,7 @@
     <implements>
         <xmpp:SupportedXep>
             <xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0369.html"/>
-            <xmpp:status>complete</xmpp:status>
+            <xmpp:status>removed</xmpp:status>
             <xmpp:version>0.14.3</xmpp:version>
             <xmpp:since>0.18.0</xmpp:since>
         </xmpp:SupportedXep>

parsers/src/lib.rs đź”—

@@ -251,9 +251,6 @@ pub mod stanza_id;
 /// XEP-0363: HTTP File Upload
 pub mod http_upload;
 
-/// XEP-0369: Mediated Information eXchange (MIX)
-pub mod mix;
-
 /// XEP-0373: OpenPGP for XMPP
 pub mod openpgp;
 

parsers/src/mix.rs đź”—

@@ -1,391 +0,0 @@
-// Copyright (c) 2020 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
-//
-// This Source Code Form is subject to the terms of the Mozilla Public
-// 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/.
-
-// TODO: validate nicks by applying the “nickname” profile of the PRECIS OpaqueString class, as
-// defined in RFC 7700.
-
-use xso::{AsXml, FromXml};
-
-use crate::iq::{IqResultPayload, IqSetPayload};
-use crate::message::MessagePayload;
-use crate::ns;
-use crate::pubsub::{NodeName, PubSubPayload};
-use jid::BareJid;
-
-generate_id!(
-    /// The identifier a participant receives when joining a channel.
-    ParticipantId
-);
-
-impl ParticipantId {
-    /// Create a new ParticipantId.
-    pub fn new<P: Into<String>>(participant: P) -> ParticipantId {
-        ParticipantId(participant.into())
-    }
-}
-
-generate_id!(
-    /// A MIX channel identifier.
-    ChannelId
-);
-
-/// Represents a participant in a MIX channel, usually returned on the
-/// urn:xmpp:mix:nodes:participants PubSub node.
-#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
-#[xml(namespace = ns::MIX_CORE, name = "participant")]
-pub struct Participant {
-    /// The nick of this participant.
-    #[xml(extract(fields(text)))]
-    pub nick: String,
-
-    /// The bare JID of this participant.
-    #[xml(extract(fields(text)))]
-    pub jid: BareJid,
-}
-
-impl PubSubPayload for Participant {}
-
-impl Participant {
-    /// Create a new MIX participant.
-    pub fn new<J: Into<BareJid>, N: Into<String>>(jid: J, nick: N) -> Participant {
-        Participant {
-            nick: nick.into(),
-            jid: jid.into(),
-        }
-    }
-}
-
-/// A node to subscribe to.
-#[derive(FromXml, AsXml, 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.
-    pub fn new<N: Into<String>>(node: N) -> Subscribe {
-        Subscribe {
-            node: NodeName(node.into()),
-        }
-    }
-}
-
-/// A request from a user’s server to join a MIX channel.
-#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
-#[xml(namespace = ns::MIX_CORE, name = "join")]
-pub struct Join {
-    /// The participant identifier returned by the MIX service on successful join.
-    #[xml(attribute(default))]
-    pub id: Option<ParticipantId>,
-
-    /// The nick requested by the user or set by the service.
-    #[xml(extract(fields(text)))]
-    pub nick: String,
-
-    /// Which MIX nodes to subscribe to.
-    #[xml(child(n = ..))]
-    pub subscribes: Vec<Subscribe>,
-}
-
-impl IqSetPayload for Join {}
-impl IqResultPayload for Join {}
-
-impl Join {
-    /// Create a new Join element.
-    pub fn from_nick_and_nodes<N: Into<String>>(nick: N, nodes: &[&str]) -> Join {
-        let subscribes = nodes.iter().cloned().map(Subscribe::new).collect();
-        Join {
-            id: None,
-            nick: nick.into(),
-            subscribes,
-        }
-    }
-
-    /// Sets the JID on this update-subscription.
-    pub fn with_id<I: Into<String>>(mut self, id: I) -> Self {
-        self.id = Some(ParticipantId(id.into()));
-        self
-    }
-}
-
-/// 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 {}
-
-impl UpdateSubscription {
-    /// Create a new UpdateSubscription element.
-    pub fn from_nodes(nodes: &[&str]) -> UpdateSubscription {
-        let subscribes = nodes.iter().cloned().map(Subscribe::new).collect();
-        UpdateSubscription {
-            jid: None,
-            subscribes,
-        }
-    }
-
-    /// Sets the JID on this update-subscription.
-    pub fn with_jid(mut self, jid: BareJid) -> Self {
-        self.jid = Some(jid);
-        self
-    }
-}
-
-/// Request to leave a given MIX channel.  It will automatically unsubscribe the user from all
-/// nodes on this channel.
-#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
-#[xml(namespace = ns::MIX_CORE, name = "leave")]
-pub struct Leave;
-
-impl IqSetPayload for Leave {}
-impl IqResultPayload for Leave {}
-
-/// A request to change the user’s nick.
-#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
-#[xml(namespace = ns::MIX_CORE, name = "setnick")]
-pub struct SetNick {
-    /// The new requested nick.
-    #[xml(extract(fields(text)))]
-    pub nick: String,
-}
-
-impl IqSetPayload for SetNick {}
-impl IqResultPayload for SetNick {}
-
-impl SetNick {
-    /// Create a new SetNick element.
-    pub fn new<N: Into<String>>(nick: N) -> SetNick {
-        SetNick { nick: nick.into() }
-    }
-}
-
-/// Message payload describing who actually sent the message, since unlike in MUC, all messages
-/// are sent from the channel’s JID.
-#[derive(FromXml, AsXml, PartialEq, Debug, Clone)]
-#[xml(namespace = ns::MIX_CORE, name = "mix")]
-pub struct Mix {
-    /// The nick of the user who said something.
-    #[xml(extract(fields(text)))]
-    pub nick: String,
-
-    /// The JID of the user who said something.
-    #[xml(extract(fields(text)))]
-    pub jid: BareJid,
-}
-
-impl MessagePayload for Mix {}
-
-impl Mix {
-    /// Create a new Mix element.
-    pub fn new<N: Into<String>, J: Into<BareJid>>(nick: N, jid: J) -> Mix {
-        Mix {
-            nick: nick.into(),
-            jid: jid.into(),
-        }
-    }
-}
-
-/// Create a new MIX channel.
-#[derive(FromXml, AsXml, PartialEq, Clone, Debug, Default)]
-#[xml(namespace = ns::MIX_CORE, name = "create")]
-pub struct Create {
-    /// The requested channel identifier.
-    #[xml(attribute(default))]
-    pub channel: Option<ChannelId>,
-}
-
-impl IqSetPayload for Create {}
-impl IqResultPayload for Create {}
-
-impl Create {
-    /// Create a new ad-hoc Create element.
-    pub fn new() -> Create {
-        Create::default()
-    }
-
-    /// Create a new Create element with a channel identifier.
-    pub fn from_channel_id<C: Into<String>>(channel: C) -> Create {
-        Create {
-            channel: Some(ChannelId(channel.into())),
-        }
-    }
-}
-
-/// Destroy a given MIX channel.
-#[derive(FromXml, AsXml, 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 <destroy/> in the iq result unlike every
-// other section so far.
-impl IqSetPayload for Destroy {}
-
-impl Destroy {
-    /// Create a new Destroy element.
-    pub fn new<C: Into<String>>(channel: C) -> Destroy {
-        Destroy {
-            channel: ChannelId(channel.into()),
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use minidom::Element;
-
-    #[test]
-    fn participant() {
-        let elem: Element = "<participant xmlns='urn:xmpp:mix:core:1'><jid>foo@bar</jid><nick>coucou</nick></participant>"
-            .parse()
-            .unwrap();
-        let participant = Participant::try_from(elem).unwrap();
-        assert_eq!(participant.nick, "coucou");
-        assert_eq!(participant.jid.as_str(), "foo@bar");
-    }
-
-    #[test]
-    fn join() {
-        let elem: Element = "<join xmlns='urn:xmpp:mix:core:1'><subscribe node='urn:xmpp:mix:nodes:messages'/><subscribe node='urn:xmpp:mix:nodes:info'/><nick>coucou</nick></join>"
-            .parse()
-            .unwrap();
-        let join = Join::try_from(elem).unwrap();
-        assert_eq!(join.nick, "coucou");
-        assert_eq!(join.id, None);
-        assert_eq!(join.subscribes.len(), 2);
-        assert_eq!(join.subscribes[0].node.0, "urn:xmpp:mix:nodes:messages");
-        assert_eq!(join.subscribes[1].node.0, "urn:xmpp:mix:nodes:info");
-    }
-
-    #[test]
-    fn update_subscription() {
-        let elem: Element = "<update-subscription xmlns='urn:xmpp:mix:core:1'><subscribe node='urn:xmpp:mix:nodes:participants'/></update-subscription>"
-            .parse()
-            .unwrap();
-        let update_subscription = UpdateSubscription::try_from(elem).unwrap();
-        assert_eq!(update_subscription.jid, None);
-        assert_eq!(update_subscription.subscribes.len(), 1);
-        assert_eq!(
-            update_subscription.subscribes[0].node.0,
-            "urn:xmpp:mix:nodes:participants"
-        );
-    }
-
-    #[test]
-    fn leave() {
-        let elem: Element = "<leave xmlns='urn:xmpp:mix:core:1'/>".parse().unwrap();
-        Leave::try_from(elem).unwrap();
-    }
-
-    #[test]
-    fn setnick() {
-        let elem: Element = "<setnick xmlns='urn:xmpp:mix:core:1'><nick>coucou</nick></setnick>"
-            .parse()
-            .unwrap();
-        let setnick = SetNick::try_from(elem).unwrap();
-        assert_eq!(setnick.nick, "coucou");
-    }
-
-    #[test]
-    fn message_mix() {
-        let elem: Element =
-            "<mix xmlns='urn:xmpp:mix:core:1'><jid>foo@bar</jid><nick>coucou</nick></mix>"
-                .parse()
-                .unwrap();
-        let mix = Mix::try_from(elem).unwrap();
-        assert_eq!(mix.nick, "coucou");
-        assert_eq!(mix.jid.as_str(), "foo@bar");
-    }
-
-    #[test]
-    fn create() {
-        let elem: Element = "<create xmlns='urn:xmpp:mix:core:1' channel='coucou'/>"
-            .parse()
-            .unwrap();
-        let create = Create::try_from(elem).unwrap();
-        assert_eq!(create.channel.unwrap().0, "coucou");
-
-        let elem: Element = "<create xmlns='urn:xmpp:mix:core:1'/>".parse().unwrap();
-        let create = Create::try_from(elem).unwrap();
-        assert_eq!(create.channel, None);
-    }
-
-    #[test]
-    fn destroy() {
-        let elem: Element = "<destroy xmlns='urn:xmpp:mix:core:1' channel='coucou'/>"
-            .parse()
-            .unwrap();
-        let destroy = Destroy::try_from(elem).unwrap();
-        assert_eq!(destroy.channel.0, "coucou");
-    }
-
-    #[test]
-    fn serialise() {
-        let elem: Element = Join::from_nick_and_nodes("coucou", &["foo", "bar"]).into();
-        let xml = String::from(&elem);
-        assert_eq!(xml, "<join xmlns='urn:xmpp:mix:core:1'><nick>coucou</nick><subscribe node=\"foo\"/><subscribe node=\"bar\"/></join>");
-
-        let elem: Element = UpdateSubscription::from_nodes(&["foo", "bar"]).into();
-        let xml = String::from(&elem);
-        assert_eq!(xml, "<update-subscription xmlns='urn:xmpp:mix:core:1'><subscribe node=\"foo\"/><subscribe node=\"bar\"/></update-subscription>");
-
-        let elem: Element = Leave.into();
-        let xml = String::from(&elem);
-        assert_eq!(xml, "<leave xmlns='urn:xmpp:mix:core:1'/>");
-
-        let elem: Element = SetNick::new("coucou").into();
-        let xml = String::from(&elem);
-        assert_eq!(
-            xml,
-            "<setnick xmlns='urn:xmpp:mix:core:1'><nick>coucou</nick></setnick>"
-        );
-
-        let elem: Element = Mix::new("coucou", "coucou@example".parse::<BareJid>().unwrap()).into();
-        let xml = String::from(&elem);
-        assert_eq!(
-            xml,
-            "<mix xmlns='urn:xmpp:mix:core:1'><nick>coucou</nick><jid>coucou@example</jid></mix>"
-        );
-
-        let elem: Element = Create::new().into();
-        let xml = String::from(&elem);
-        assert_eq!(xml, "<create xmlns='urn:xmpp:mix:core:1'/>");
-
-        let elem: Element = Create::from_channel_id("coucou").into();
-        let xml = String::from(&elem);
-        assert_eq!(
-            xml,
-            "<create xmlns='urn:xmpp:mix:core:1' channel=\"coucou\"/>"
-        );
-
-        let elem: Element = Destroy::new("coucou").into();
-        let xml = String::from(&elem);
-        assert_eq!(
-            xml,
-            "<destroy xmlns='urn:xmpp:mix:core:1' channel=\"coucou\"/>"
-        );
-    }
-}

parsers/src/ns.rs đź”—

@@ -243,23 +243,6 @@ pub const SID: &str = "urn:xmpp:sid:0";
 /// XEP-0363: HTTP File Upload
 pub const HTTP_UPLOAD: &str = "urn:xmpp:http:upload:0";
 
-/// XEP-0369: Mediated Information eXchange (MIX)
-pub const MIX_CORE: &str = "urn:xmpp:mix:core:1";
-/// XEP-0369: Mediated Information eXchange (MIX)
-pub const MIX_CORE_SEARCHABLE: &str = "urn:xmpp:mix:core:1#searchable";
-/// XEP-0369: Mediated Information eXchange (MIX)
-pub const MIX_CORE_CREATE_CHANNEL: &str = "urn:xmpp:mix:core:1#create-channel";
-/// XEP-0369: Mediated Information eXchange (MIX)
-pub const MIX_NODES_PRESENCE: &str = "urn:xmpp:mix:nodes:presence";
-/// XEP-0369: Mediated Information eXchange (MIX)
-pub const MIX_NODES_PARTICIPANTS: &str = "urn:xmpp:mix:nodes:participants";
-/// XEP-0369: Mediated Information eXchange (MIX)
-pub const MIX_NODES_MESSAGES: &str = "urn:xmpp:mix:nodes:messages";
-/// XEP-0369: Mediated Information eXchange (MIX)
-pub const MIX_NODES_CONFIG: &str = "urn:xmpp:mix:nodes:config";
-/// XEP-0369: Mediated Information eXchange (MIX)
-pub const MIX_NODES_INFO: &str = "urn:xmpp:mix:nodes:info";
-
 /// XEP-0373: OpenPGP for XMPP
 pub const OX: &str = "urn:xmpp:openpgp:0";
 /// XEP-0373: OpenPGP for XMPP