parsers: Add support for XEP-0335: JSON Containers

Maxime “pep” Buquet created

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>

Change summary

parsers/Cargo.toml             |  3 +
parsers/ChangeLog              |  1 
parsers/doap.xml               |  8 ++++
parsers/src/json_containers.rs | 62 ++++++++++++++++++++++++++++++++++++
parsers/src/lib.rs             |  3 +
parsers/src/ns.rs              |  3 +
6 files changed, 79 insertions(+), 1 deletion(-)

Detailed changes

parsers/Cargo.toml 🔗

@@ -25,8 +25,9 @@ log = { version = "0.4", optional = true }
 # same repository dependencies
 jid = { version = "0.12", path = "../jid", features = ["minidom"] }
 minidom = { version = "0.16", path = "../minidom" }
-xso = { version = "0.1", path = "../xso", features = ["macros", "minidom", "panicking-into-impl", "jid", "uuid", "base64"] }
+xso = { version = "0.1", path = "../xso", features = ["macros", "minidom", "panicking-into-impl", "jid", "uuid", "base64", "serde_json"] }
 uuid = { version = "1.9.1", features = ["v4"] }
+serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
 
 [features]
 # Build xmpp-parsers to make components instead of clients.

parsers/ChangeLog 🔗

@@ -78,6 +78,7 @@ XXXX-YY-ZZ RELEASER <admin@example.com>
       - RFC 6120 stream errors
       - XEP-0045 mediated invites
       - Push Notifications (XEP-0357) (!543)
+      - JSON Containers (XEP-0335) (!546)
     * Improvements:
       - Add support for `<optional/> in XEP-0198 feature advertisment
       - Add support application-specific error conditions in XEP-0198

parsers/doap.xml 🔗

@@ -514,6 +514,14 @@
             <xmpp:since>0.16.0</xmpp:since>
         </xmpp:SupportedXep>
     </implements>
+    <implements>
+        <xmpp:SupportedXep>
+            <xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0335.html"/>
+            <xmpp:status>complete</xmpp:status>
+            <xmpp:version>0.1.1</xmpp:version>
+            <xmpp:since>NEXT</xmpp:since>
+        </xmpp:SupportedXep>
+    </implements>
     <implements>
         <xmpp:SupportedXep>
             <xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0338.html"/>

parsers/src/json_containers.rs 🔗

@@ -0,0 +1,62 @@
+// Copyright (c) 2025 Maxime “pep” Buquet <pep@bouah.net>
+//
+// 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/.
+
+use crate::ns;
+
+use xso::{AsXml, FromXml};
+
+/// Structure representing a `<json xmlns='urn:xmpp:json:0'/>` element.
+#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
+#[xml(namespace = ns::JSON_CONTAINERS, name = "json")]
+pub struct JsonContainer(#[xml(text)] serde_json::Value);
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use minidom::Element;
+
+    use crate::Error::TextParseError;
+    use xso::error::FromElementError;
+
+    #[cfg(target_pointer_width = "32")]
+    #[test]
+    fn test_size() {
+        assert_size!(JsonContainer, 16);
+    }
+
+    #[cfg(target_pointer_width = "64")]
+    #[test]
+    fn test_size() {
+        assert_size!(JsonContainer, 32);
+    }
+
+    #[test]
+    fn test_empty() {
+        let elem: Element = "<json xmlns='urn:xmpp:json:0'/>".parse().unwrap();
+        let error = JsonContainer::try_from(elem.clone()).unwrap_err();
+        match error {
+            FromElementError::Invalid(TextParseError(err)) => {
+                assert_eq!(
+                    err.to_string(),
+                    "EOF while parsing a value at line 1 column 0"
+                );
+            }
+            _ => panic!(),
+        }
+    }
+
+    #[test]
+    fn test_simple() {
+        let elem: Element = "<json xmlns='urn:xmpp:json:0'>{\"a\": 1}</json>"
+            .parse()
+            .unwrap();
+        let result: serde_json::Value = "{\"a\": 1}".parse().unwrap();
+        match JsonContainer::try_from(elem.clone()) {
+            Ok(json) => assert_eq!(json.0, result),
+            _ => panic!(),
+        };
+    }
+}

parsers/src/lib.rs 🔗

@@ -233,6 +233,9 @@ pub mod jingle_dtls_srtp;
 /// XEP-0328: JID Prep
 pub mod jid_prep;
 
+/// XEP-0335: JSON Containers
+pub mod json_containers;
+
 /// XEP-0338: Jingle Grouping Framework
 pub mod jingle_grouping;
 

parsers/src/ns.rs 🔗

@@ -225,6 +225,9 @@ pub const JINGLE_DTLS: &str = "urn:xmpp:jingle:apps:dtls:0";
 /// XEP-0328: JID Prep
 pub const JID_PREP: &str = "urn:xmpp:jidprep:0";
 
+/// XEP-0335: JSON Containers
+pub const JSON_CONTAINERS: &str = "urn:xmpp:json:0";
+
 /// XEP-0338: Jingle Grouping Framework
 pub const JINGLE_GROUPING: &str = "urn:xmpp:jingle:apps:grouping:0";