aboutsummaryrefslogtreecommitdiffstats
path: root/stanza/src
diff options
context:
space:
mode:
Diffstat (limited to 'stanza/src')
-rw-r--r--stanza/src/bind.rs29
-rw-r--r--stanza/src/client/error.rs11
-rw-r--r--stanza/src/client/iq.rs48
-rw-r--r--stanza/src/client/message.rs123
-rw-r--r--stanza/src/client/mod.rs16
-rw-r--r--stanza/src/client/presence.rs25
-rw-r--r--stanza/src/lib.rs16
-rw-r--r--stanza/src/rfc_7395.rs94
-rw-r--r--stanza/src/roster.rs25
-rw-r--r--stanza/src/sasl.rs33
-rw-r--r--stanza/src/stanza_error.rs17
-rw-r--r--stanza/src/starttls.rs23
-rw-r--r--stanza/src/stream.rs30
-rw-r--r--stanza/src/stream_error.rs17
-rw-r--r--stanza/src/xep_0004.rs49
-rw-r--r--stanza/src/xep_0030/info.rs21
-rw-r--r--stanza/src/xep_0030/items.rs17
-rw-r--r--stanza/src/xep_0030/mod.rs4
-rw-r--r--stanza/src/xep_0059.rs41
-rw-r--r--stanza/src/xep_0060/errors.rs13
-rw-r--r--stanza/src/xep_0060/event.rs93
-rw-r--r--stanza/src/xep_0060/mod.rs4
-rw-r--r--stanza/src/xep_0060/owner.rs57
-rw-r--r--stanza/src/xep_0060/pubsub.rs103
-rw-r--r--stanza/src/xep_0084/data.rs31
-rw-r--r--stanza/src/xep_0084/metadata.rs107
-rw-r--r--stanza/src/xep_0084/mod.rs12
-rw-r--r--stanza/src/xep_0115.rs13
-rw-r--r--stanza/src/xep_0131.rs17
-rw-r--r--stanza/src/xep_0156.rs234
-rw-r--r--stanza/src/xep_0172.rs13
-rw-r--r--stanza/src/xep_0199.rs13
-rw-r--r--stanza/src/xep_0203.rs13
-rw-r--r--stanza/src/xep_0280.rs113
-rw-r--r--stanza/src/xep_0297.rs79
-rw-r--r--stanza/src/xep_0300.rs17
-rw-r--r--stanza/src/xep_0334.rs87
-rw-r--r--stanza/src/xep_0390.rs13
38 files changed, 1326 insertions, 345 deletions
diff --git a/stanza/src/bind.rs b/stanza/src/bind.rs
index f72c510..c04651c 100644
--- a/stanza/src/bind.rs
+++ b/stanza/src/bind.rs
@@ -1,8 +1,9 @@
-use jid::JID;
-use peanuts::{
- element::{FromElement, IntoElement},
- Element,
-};
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use jid::FullJID;
+use peanuts::{Element, FromElement, IntoElement};
pub const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-bind";
@@ -12,7 +13,7 @@ pub struct Bind {
}
impl FromElement for Bind {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("bind")?;
element.check_namespace(XMLNS)?;
@@ -23,7 +24,7 @@ impl FromElement for Bind {
}
impl IntoElement for Bind {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("bind", Some(XMLNS)).push_child_opt(self.r#type.clone())
}
}
@@ -35,7 +36,7 @@ pub enum BindType {
}
impl FromElement for BindType {
- fn from_element(element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
match element.identify() {
(Some(XMLNS), "resource") => {
Ok(BindType::Resource(ResourceType::from_element(element)?))
@@ -47,7 +48,7 @@ impl FromElement for BindType {
}
impl IntoElement for BindType {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
match self {
BindType::Resource(resource_type) => resource_type.builder(),
BindType::Jid(full_jid_type) => full_jid_type.builder(),
@@ -57,10 +58,10 @@ impl IntoElement for BindType {
// minLength 8 maxLength 3071
#[derive(Clone, Debug)]
-pub struct FullJidType(pub JID);
+pub struct FullJidType(pub FullJID);
impl FromElement for FullJidType {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("jid")?;
element.check_namespace(XMLNS)?;
@@ -71,7 +72,7 @@ impl FromElement for FullJidType {
}
impl IntoElement for FullJidType {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("jid", Some(XMLNS)).push_text(self.0.clone())
}
}
@@ -81,7 +82,7 @@ impl IntoElement for FullJidType {
pub struct ResourceType(pub String);
impl FromElement for ResourceType {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("resource")?;
element.check_namespace(XMLNS)?;
@@ -92,7 +93,7 @@ impl FromElement for ResourceType {
}
impl IntoElement for ResourceType {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("resource", Some(XMLNS)).push_text(self.0.clone())
}
}
diff --git a/stanza/src/client/error.rs b/stanza/src/client/error.rs
index c4ab517..7dac178 100644
--- a/stanza/src/client/error.rs
+++ b/stanza/src/client/error.rs
@@ -1,8 +1,11 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use std::fmt::Display;
use std::str::FromStr;
-use peanuts::element::{FromElement, IntoElement};
-use peanuts::{DeserializeError, Element};
+use peanuts::{DeserializeError, Element, FromElement, IntoElement};
use thiserror::Error;
use crate::stanza_error::Error as StanzaError;
@@ -40,7 +43,7 @@ impl Display for Error {
}
impl FromElement for Error {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("error")?;
element.check_name(XMLNS)?;
@@ -59,7 +62,7 @@ impl FromElement for Error {
}
impl IntoElement for Error {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("error", Some(XMLNS))
.push_attribute_opt("by", self.by.clone())
.push_attribute("type", self.r#type)
diff --git a/stanza/src/client/iq.rs b/stanza/src/client/iq.rs
index 50884aa..be2a3f1 100644
--- a/stanza/src/client/iq.rs
+++ b/stanza/src/client/iq.rs
@@ -1,11 +1,14 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use std::str::FromStr;
use jid::JID;
-use peanuts::{
- element::{FromElement, IntoElement},
- DeserializeError, Element, XML_NS,
-};
+use peanuts::{DeserializeError, Element, FromElement, IntoElement, XML_NS};
+#[cfg(feature = "xep_0280")]
+use crate::xep_0280::{self, Disable, Enable};
use crate::{
bind::{self, Bind},
client::error::Error,
@@ -18,7 +21,10 @@ use crate::roster;
use crate::xep_0030::{self, info, items};
#[cfg(feature = "xep_0060")]
-use crate::xep_0060::pubsub::{self, Pubsub};
+use crate::xep_0060::{
+ self,
+ pubsub::{self, Pubsub},
+};
#[cfg(feature = "xep_0199")]
use crate::xep_0199::{self, Ping};
@@ -47,15 +53,21 @@ pub enum Query {
DiscoItems(items::Query),
#[cfg(feature = "xep_0060")]
Pubsub(Pubsub),
+ #[cfg(feature = "xep_0060")]
+ PubsubOwner(xep_0060::owner::Pubsub),
#[cfg(feature = "xep_0199")]
Ping(Ping),
#[cfg(feature = "rfc_6121")]
Roster(roster::Query),
+ #[cfg(feature = "xep_0280")]
+ CarbonsEnable(Enable),
+ #[cfg(feature = "xep_0280")]
+ CarbonsDisable(Disable),
Unsupported,
}
impl FromElement for Query {
- fn from_element(element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
match element.identify() {
(Some(bind::XMLNS), "bind") => Ok(Query::Bind(Bind::from_element(element)?)),
#[cfg(feature = "xep_0199")]
@@ -74,13 +86,25 @@ impl FromElement for Query {
}
#[cfg(feature = "xep_0060")]
(Some(pubsub::XMLNS), "pubsub") => Ok(Query::Pubsub(Pubsub::from_element(element)?)),
+ #[cfg(feature = "xep_0060")]
+ (Some(xep_0060::owner::XMLNS), "pubsub") => Ok(Query::PubsubOwner(
+ xep_0060::owner::Pubsub::from_element(element)?,
+ )),
+ #[cfg(feature = "xep_0280")]
+ (Some(xep_0280::XMLNS), "enable") => {
+ Ok(Query::CarbonsEnable(Enable::from_element(element)?))
+ }
+ #[cfg(feature = "xep_0280")]
+ (Some(xep_0280::XMLNS), "disable") => {
+ Ok(Query::CarbonsDisable(Disable::from_element(element)?))
+ }
_ => Ok(Query::Unsupported),
}
}
}
impl IntoElement for Query {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
match self {
Query::Bind(bind) => bind.builder(),
#[cfg(feature = "xep_0199")]
@@ -95,12 +119,18 @@ impl IntoElement for Query {
Query::DiscoItems(query) => query.builder(),
#[cfg(feature = "xep_0060")]
Query::Pubsub(pubsub) => pubsub.builder(),
+ #[cfg(feature = "xep_0060")]
+ Query::PubsubOwner(pubsub) => pubsub.builder(),
+ #[cfg(feature = "xep_0280")]
+ Query::CarbonsEnable(enable) => enable.builder(),
+ #[cfg(feature = "xep_0280")]
+ Query::CarbonsDisable(disable) => disable.builder(),
}
}
}
impl FromElement for Iq {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("iq")?;
element.check_namespace(XMLNS)?;
@@ -125,7 +155,7 @@ impl FromElement for Iq {
}
impl IntoElement for Iq {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("iq", Some(XMLNS))
.push_attribute_opt("from", self.from.clone())
.push_attribute("id", self.id.clone())
diff --git a/stanza/src/client/message.rs b/stanza/src/client/message.rs
index d94b82e..a489201 100644
--- a/stanza/src/client/message.rs
+++ b/stanza/src/client/message.rs
@@ -1,17 +1,26 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use std::str::FromStr;
use jid::JID;
-use peanuts::{
- element::{FromElement, IntoElement},
- DeserializeError, Element, XML_NS,
-};
+use peanuts::{DeserializeError, Element, FromElement, IntoElement, XML_NS};
+#[cfg(feature = "xep_0060")]
+use crate::xep_0060::event::Event;
#[cfg(feature = "xep_0131")]
use crate::xep_0131::Headers;
#[cfg(feature = "xep_0172")]
use crate::xep_0172::Nick;
#[cfg(feature = "xep_0203")]
use crate::xep_0203::Delay;
+#[cfg(feature = "xep_0280")]
+use crate::xep_0280::{Private, Received, Sent};
+#[cfg(feature = "xep_0297")]
+use crate::xep_0297::Forwarded;
+#[cfg(feature = "xep_0334")]
+use crate::xep_0334::{NoCopy, NoPermanentStore, NoStore, Store};
use super::XMLNS;
@@ -33,10 +42,28 @@ pub struct Message {
pub headers: Option<Headers>,
#[cfg(feature = "xep_0172")]
pub nick: Option<Nick>,
+ #[cfg(feature = "xep_0060")]
+ pub event: Option<Event>,
+ #[cfg(feature = "xep_0297")]
+ pub forwarded: Option<Forwarded>,
+ #[cfg(feature = "xep_0280")]
+ pub sent: Option<Sent>,
+ #[cfg(feature = "xep_0280")]
+ pub received: Option<Received>,
+ #[cfg(feature = "xep_0280")]
+ pub private: Option<Private>,
+ #[cfg(feature = "xep_0334")]
+ pub no_permanent_store: Option<NoPermanentStore>,
+ #[cfg(feature = "xep_0334")]
+ pub no_store: Option<NoStore>,
+ #[cfg(feature = "xep_0334")]
+ pub no_copy: Option<NoCopy>,
+ #[cfg(feature = "xep_0334")]
+ pub store: Option<Store>,
}
impl FromElement for Message {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("message")?;
element.check_namespace(XMLNS)?;
@@ -59,6 +86,33 @@ impl FromElement for Message {
#[cfg(feature = "xep_0172")]
let nick = element.child_opt()?;
+ #[cfg(feature = "xep_0060")]
+ let event = element.child_opt()?;
+
+ #[cfg(feature = "xep_0297")]
+ let forwarded = element.child_opt()?;
+
+ #[cfg(feature = "xep_0280")]
+ let sent = element.child_opt()?;
+
+ #[cfg(feature = "xep_0280")]
+ let received = element.child_opt()?;
+
+ #[cfg(feature = "xep_0280")]
+ let private = element.child_opt()?;
+
+ #[cfg(feature = "xep_0334")]
+ let no_permanent_store = element.child_opt()?;
+
+ #[cfg(feature = "xep_0334")]
+ let no_store = element.child_opt()?;
+
+ #[cfg(feature = "xep_0334")]
+ let no_copy = element.child_opt()?;
+
+ #[cfg(feature = "xep_0334")]
+ let store = element.child_opt()?;
+
Ok(Message {
from,
id,
@@ -74,12 +128,30 @@ impl FromElement for Message {
headers,
#[cfg(feature = "xep_0172")]
nick,
+ #[cfg(feature = "xep_0060")]
+ event,
+ #[cfg(feature = "xep_0297")]
+ forwarded,
+ #[cfg(feature = "xep_0280")]
+ sent,
+ #[cfg(feature = "xep_0280")]
+ received,
+ #[cfg(feature = "xep_0280")]
+ private,
+ #[cfg(feature = "xep_0334")]
+ no_permanent_store,
+ #[cfg(feature = "xep_0334")]
+ no_store,
+ #[cfg(feature = "xep_0334")]
+ no_copy,
+ #[cfg(feature = "xep_0334")]
+ store,
})
}
}
impl IntoElement for Message {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
let builder = Element::builder("message", Some(XMLNS))
.push_attribute_opt("from", self.from.clone())
.push_attribute_opt("id", self.id.clone())
@@ -105,6 +177,33 @@ impl IntoElement for Message {
#[cfg(feature = "xep_0172")]
let builder = builder.push_child_opt(self.nick.clone());
+ #[cfg(feature = "xep_0060")]
+ let builder = builder.push_child_opt(self.event.clone());
+
+ #[cfg(feature = "xep_0297")]
+ let builder = builder.push_child_opt(self.forwarded.clone());
+
+ #[cfg(feature = "xep_0280")]
+ let builder = builder.push_child_opt(self.sent.clone());
+
+ #[cfg(feature = "xep_0280")]
+ let builder = builder.push_child_opt(self.received.clone());
+
+ #[cfg(feature = "xep_0280")]
+ let builder = builder.push_child_opt(self.private.clone());
+
+ #[cfg(feature = "xep_0334")]
+ let builder = builder.push_child_opt(self.no_permanent_store);
+
+ #[cfg(feature = "xep_0334")]
+ let builder = builder.push_child_opt(self.no_store);
+
+ #[cfg(feature = "xep_0334")]
+ let builder = builder.push_child_opt(self.no_copy);
+
+ #[cfg(feature = "xep_0334")]
+ let builder = builder.push_child_opt(self.store);
+
builder
}
}
@@ -154,7 +253,7 @@ pub struct Body {
}
impl FromElement for Body {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("body")?;
element.check_namespace(XMLNS)?;
@@ -166,7 +265,7 @@ impl FromElement for Body {
}
impl IntoElement for Body {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("body", Some(XMLNS))
.push_attribute_opt_namespaced(XML_NS, "lang", self.lang.clone())
.push_text_opt(self.body.clone())
@@ -180,7 +279,7 @@ pub struct Subject {
}
impl FromElement for Subject {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("subject")?;
element.check_namespace(XMLNS)?;
@@ -192,7 +291,7 @@ impl FromElement for Subject {
}
impl IntoElement for Subject {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("subject", Some(XMLNS))
.push_attribute_opt_namespaced(XML_NS, "lang", self.lang.clone())
.push_text_opt(self.subject.clone())
@@ -206,7 +305,7 @@ pub struct Thread {
}
impl FromElement for Thread {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("thread")?;
element.check_namespace(XMLNS)?;
@@ -218,7 +317,7 @@ impl FromElement for Thread {
}
impl IntoElement for Thread {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("thread", Some(XMLNS))
.push_attribute_opt("parent", self.parent.clone())
.push_text_opt(self.thread.clone())
diff --git a/stanza/src/client/mod.rs b/stanza/src/client/mod.rs
index a1b2de5..00ad3ed 100644
--- a/stanza/src/client/mod.rs
+++ b/stanza/src/client/mod.rs
@@ -1,9 +1,11 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use peanuts::{Content, ContentBuilder, DeserializeError, FromContent, FromElement, IntoContent};
+
use iq::Iq;
use message::Message;
-use peanuts::{
- element::{Content, ContentBuilder, FromContent, FromElement, IntoContent},
- DeserializeError,
-};
use presence::Presence;
use super::stream::{self, Error as StreamError};
@@ -26,7 +28,7 @@ pub enum Stanza {
}
impl FromContent for Stanza {
- fn from_content(content: Content) -> peanuts::element::DeserializeResult<Self> {
+ fn from_content(content: Content) -> peanuts::DeserializeResult<Self> {
match content {
Content::Element(element) => Ok(Stanza::from_element(element)?),
Content::Text(_) => Ok(Stanza::OtherContent(content)),
@@ -37,7 +39,7 @@ impl FromContent for Stanza {
}
impl FromElement for Stanza {
- fn from_element(element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
match element.identify() {
(Some(XMLNS), "message") => Ok(Stanza::Message(Message::from_element(element)?)),
(Some(XMLNS), "presence") => Ok(Stanza::Presence(Presence::from_element(element)?)),
@@ -51,7 +53,7 @@ impl FromElement for Stanza {
}
impl IntoContent for Stanza {
- fn builder(&self) -> peanuts::element::ContentBuilder {
+ fn builder(&self) -> peanuts::ContentBuilder {
match self {
Stanza::Message(message) => <Message as IntoContent>::builder(message),
Stanza::Presence(presence) => <Presence as IntoContent>::builder(presence),
diff --git a/stanza/src/client/presence.rs b/stanza/src/client/presence.rs
index a8c35d0..02de229 100644
--- a/stanza/src/client/presence.rs
+++ b/stanza/src/client/presence.rs
@@ -1,10 +1,11 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use std::str::FromStr;
use jid::JID;
-use peanuts::{
- element::{FromElement, IntoElement},
- DeserializeError, Element, XML_NS,
-};
+use peanuts::{DeserializeError, Element, FromElement, IntoElement, XML_NS};
#[cfg(feature = "xep_0115")]
use crate::xep_0115::C;
@@ -41,7 +42,7 @@ pub struct Presence {
}
impl FromElement for Presence {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("presence")?;
element.check_namespace(XMLNS)?;
@@ -91,7 +92,7 @@ impl FromElement for Presence {
}
impl IntoElement for Presence {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
let builder = Element::builder("presence", Some(XMLNS))
.push_attribute_opt("from", self.from.clone())
.push_attribute_opt("id", self.id.clone())
@@ -174,7 +175,7 @@ pub enum Show {
}
impl FromElement for Show {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("show")?;
element.check_namespace(XMLNS)?;
@@ -197,7 +198,7 @@ impl FromStr for Show {
}
impl IntoElement for Show {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("show", Some(XMLNS)).push_text(*self)
}
}
@@ -220,7 +221,7 @@ pub struct Status {
}
impl FromElement for Status {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("status")?;
element.check_namespace(XMLNS)?;
@@ -232,7 +233,7 @@ impl FromElement for Status {
}
impl IntoElement for Status {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("status", Some(XMLNS))
.push_attribute_opt_namespaced(XML_NS, "lang", self.lang.clone())
.push_text(self.status.clone())
@@ -263,7 +264,7 @@ impl ToString for String1024 {
pub struct Priority(pub i8);
impl FromElement for Priority {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("priority")?;
element.check_namespace(XMLNS)?;
@@ -272,7 +273,7 @@ impl FromElement for Priority {
}
impl IntoElement for Priority {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("priority", Some(XMLNS)).push_text(self.0)
}
}
diff --git a/stanza/src/lib.rs b/stanza/src/lib.rs
index 3ecace0..8cc3755 100644
--- a/stanza/src/lib.rs
+++ b/stanza/src/lib.rs
@@ -1,7 +1,13 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use peanuts::declaration::VersionInfo;
pub mod bind;
pub mod client;
+#[cfg(feature = "rfc_7395")]
+pub mod rfc_7395;
#[cfg(feature = "rfc_6121")]
pub mod roster;
pub mod sasl;
@@ -17,18 +23,28 @@ pub mod xep_0030;
pub mod xep_0059;
#[cfg(feature = "xep_0060")]
pub mod xep_0060;
+#[cfg(feature = "xep_0084")]
+pub mod xep_0084;
#[cfg(feature = "xep_0115")]
pub mod xep_0115;
#[cfg(feature = "xep_0131")]
pub mod xep_0131;
+#[cfg(feature = "xep_0156")]
+pub mod xep_0156;
#[cfg(feature = "xep_0172")]
pub mod xep_0172;
#[cfg(feature = "xep_0199")]
pub mod xep_0199;
#[cfg(feature = "xep_0203")]
pub mod xep_0203;
+#[cfg(feature = "xep_0280")]
+pub mod xep_0280;
+#[cfg(feature = "xep_0297")]
+pub mod xep_0297;
#[cfg(feature = "xep_0300")]
pub mod xep_0300;
+#[cfg(feature = "xep_0334")]
+pub mod xep_0334;
#[cfg(feature = "xep_0390")]
pub mod xep_0390;
diff --git a/stanza/src/rfc_7395.rs b/stanza/src/rfc_7395.rs
new file mode 100644
index 0000000..c632116
--- /dev/null
+++ b/stanza/src/rfc_7395.rs
@@ -0,0 +1,94 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use jid::BareJID;
+use peanuts::{Element, ElementBuilder, FromElement, IntoElement};
+
+pub const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-framing";
+
+#[derive(Debug)]
+pub struct Open {
+ pub from: Option<BareJID>,
+ pub to: Option<BareJID>,
+ pub id: Option<String>,
+ pub version: Option<String>,
+ pub lang: Option<String>,
+}
+
+impl FromElement for Open {
+ fn from_element(mut element: Element) -> std::result::Result<Self, peanuts::DeserializeError> {
+ element.check_name("open")?;
+ element.check_namespace(XMLNS)?;
+
+ let from = element.attribute_opt("from")?;
+ let to = element.attribute_opt("to")?;
+ let id = element.attribute_opt("id")?;
+ let version = element.attribute_opt("version")?;
+ let lang = element.attribute_opt_namespaced("lang", peanuts::XML_NS)?;
+
+ Ok(Open {
+ from,
+ to,
+ id,
+ version,
+ lang,
+ })
+ }
+}
+
+impl IntoElement for Open {
+ fn builder(&self) -> ElementBuilder {
+ Element::builder("open", Some(XMLNS.to_string()))
+ .push_attribute_opt("to", self.to.clone())
+ .push_attribute_opt("from", self.from.clone())
+ .push_attribute_opt("id", self.id.clone())
+ .push_attribute_opt("version", self.version.clone())
+ .push_attribute_opt_namespaced(peanuts::XML_NS, "lang", self.lang.clone())
+ }
+}
+
+#[derive(Debug, Default)]
+pub struct Close {
+ pub from: Option<BareJID>,
+ pub to: Option<BareJID>,
+ pub id: Option<String>,
+ pub version: Option<String>,
+ pub lang: Option<String>,
+ pub see_other_uri: Option<String>,
+}
+
+impl FromElement for Close {
+ fn from_element(mut element: Element) -> std::result::Result<Self, peanuts::DeserializeError> {
+ element.check_name("close")?;
+ element.check_namespace(XMLNS)?;
+
+ let from = element.attribute_opt("from")?;
+ let to = element.attribute_opt("to")?;
+ let id = element.attribute_opt("id")?;
+ let version = element.attribute_opt("version")?;
+ let lang = element.attribute_opt_namespaced("lang", peanuts::XML_NS)?;
+ let see_other_uri = element.attribute_opt("see-other-uri")?;
+
+ Ok(Close {
+ from,
+ to,
+ id,
+ version,
+ lang,
+ see_other_uri,
+ })
+ }
+}
+
+impl IntoElement for Close {
+ fn builder(&self) -> ElementBuilder {
+ Element::builder("close", Some(XMLNS.to_string()))
+ .push_attribute_opt("to", self.to.clone())
+ .push_attribute_opt("from", self.from.clone())
+ .push_attribute_opt("id", self.id.clone())
+ .push_attribute_opt("version", self.version.clone())
+ .push_attribute_opt_namespaced(peanuts::XML_NS, "lang", self.lang.clone())
+ .push_attribute_opt("see-other-uri", self.see_other_uri.clone())
+ }
+}
diff --git a/stanza/src/roster.rs b/stanza/src/roster.rs
index 0181193..fe67ad1 100644
--- a/stanza/src/roster.rs
+++ b/stanza/src/roster.rs
@@ -1,10 +1,11 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use std::str::FromStr;
-use jid::JID;
-use peanuts::{
- element::{FromElement, IntoElement},
- DeserializeError, Element,
-};
+use jid::BareJID;
+use peanuts::{DeserializeError, Element, FromElement, IntoElement};
pub const XMLNS: &str = "jabber:iq:roster";
@@ -15,7 +16,7 @@ pub struct Query {
}
impl FromElement for Query {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("query")?;
element.check_namespace(XMLNS)?;
@@ -27,7 +28,7 @@ impl FromElement for Query {
}
impl IntoElement for Query {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("query", Some(XMLNS))
.push_attribute_opt("ver", self.ver.clone())
.push_children(self.items.clone())
@@ -41,7 +42,7 @@ pub struct Item {
/// signals subscription sub-states (server only)
pub ask: bool,
/// uniquely identifies item
- pub jid: JID,
+ pub jid: BareJID,
/// handle that is determined by user, not contact
pub name: Option<String>,
/// state of the presence subscription
@@ -50,7 +51,7 @@ pub struct Item {
}
impl FromElement for Item {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("item")?;
element.check_namespace(XMLNS)?;
@@ -83,7 +84,7 @@ impl FromElement for Item {
}
impl IntoElement for Item {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("item", Some(XMLNS))
.push_attribute_opt("approved", self.approved)
.push_attribute_opt(
@@ -143,7 +144,7 @@ impl ToString for Subscription {
pub struct Group(pub Option<String>);
impl FromElement for Group {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("group")?;
element.check_namespace(XMLNS)?;
@@ -154,7 +155,7 @@ impl FromElement for Group {
}
impl IntoElement for Group {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("group", Some(XMLNS)).push_text_opt(self.0.clone())
}
}
diff --git a/stanza/src/sasl.rs b/stanza/src/sasl.rs
index 598a91b..2935923 100644
--- a/stanza/src/sasl.rs
+++ b/stanza/src/sasl.rs
@@ -1,9 +1,10 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use std::{fmt::Display, ops::Deref};
-use peanuts::{
- element::{FromElement, IntoElement},
- DeserializeError, Element,
-};
+use peanuts::{DeserializeError, Element, FromElement, IntoElement};
use thiserror::Error;
pub const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-sasl";
@@ -14,7 +15,7 @@ pub struct Mechanisms {
}
impl FromElement for Mechanisms {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("mechanisms")?;
element.check_namespace(XMLNS)?;
let mechanisms: Vec<Mechanism> = element.pop_children()?;
@@ -27,7 +28,7 @@ impl FromElement for Mechanisms {
}
impl IntoElement for Mechanisms {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("mechanisms", Some(XMLNS)).push_children(
self.mechanisms
.iter()
@@ -40,7 +41,7 @@ impl IntoElement for Mechanisms {
pub struct Mechanism(String);
impl FromElement for Mechanism {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("mechanism")?;
element.check_namespace(XMLNS)?;
@@ -51,7 +52,7 @@ impl FromElement for Mechanism {
}
impl IntoElement for Mechanism {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("mechanism", Some(XMLNS)).push_text(self.0.clone())
}
}
@@ -71,7 +72,7 @@ pub struct Auth {
}
impl IntoElement for Auth {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("auth", Some(XMLNS))
.push_attribute("mechanism", self.mechanism.clone())
.push_text(self.sasl_data.clone())
@@ -90,7 +91,7 @@ impl Deref for Challenge {
}
impl FromElement for Challenge {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("challenge")?;
element.check_namespace(XMLNS)?;
@@ -112,7 +113,7 @@ impl Deref for Success {
}
impl FromElement for Success {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("success")?;
element.check_namespace(XMLNS)?;
@@ -130,7 +131,7 @@ pub enum ServerResponse {
}
impl FromElement for ServerResponse {
- fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
match element.identify() {
(Some(XMLNS), "challenge") => {
Ok(ServerResponse::Challenge(Challenge::from_element(element)?))
@@ -164,7 +165,7 @@ impl Deref for Response {
}
impl IntoElement for Response {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("response", Some(XMLNS)).push_text(self.0.clone())
}
}
@@ -212,7 +213,7 @@ impl Display for Failure {
}
impl FromElement for Failure {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("failure")?;
element.check_namespace(XMLNS)?;
@@ -250,7 +251,7 @@ pub enum FailureType {
}
impl FromElement for FailureType {
- fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
match element.identify() {
(Some(XMLNS), "aborted") => Ok(FailureType::Aborted),
(Some(XMLNS), "account-disabled") => Ok(FailureType::AccountDisabled),
@@ -276,7 +277,7 @@ pub struct Text {
}
impl FromElement for Text {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("text")?;
element.check_namespace(XMLNS)?;
diff --git a/stanza/src/stanza_error.rs b/stanza/src/stanza_error.rs
index 664a168..bb0c24f 100644
--- a/stanza/src/stanza_error.rs
+++ b/stanza/src/stanza_error.rs
@@ -1,9 +1,10 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
// https://datatracker.ietf.org/doc/html/rfc6120#appendix-A.8
-use peanuts::{
- element::{FromElement, IntoElement},
- Element, XML_NS,
-};
+use peanuts::{Element, FromElement, IntoElement, XML_NS};
use thiserror::Error;
#[cfg(feature = "xep_0060")]
@@ -64,7 +65,7 @@ pub enum Error {
}
impl FromElement for Error {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
let error;
match element.identify() {
(Some(XMLNS), "bad-request") => error = Error::BadRequest,
@@ -101,7 +102,7 @@ impl FromElement for Error {
}
impl IntoElement for Error {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
match self {
Error::BadRequest => Element::builder("bad-request", Some(XMLNS)),
Error::Conflict => Element::builder("conflict", Some(XMLNS)),
@@ -142,7 +143,7 @@ pub struct Text {
}
impl FromElement for Text {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("text")?;
element.check_name(XMLNS)?;
@@ -154,7 +155,7 @@ impl FromElement for Text {
}
impl IntoElement for Text {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("text", Some(XMLNS))
.push_attribute_opt_namespaced(XML_NS, "lang", self.lang.clone())
.push_text_opt(self.text.clone())
diff --git a/stanza/src/starttls.rs b/stanza/src/starttls.rs
index b0e0f0f..92ae315 100644
--- a/stanza/src/starttls.rs
+++ b/stanza/src/starttls.rs
@@ -1,7 +1,8 @@
-use peanuts::{
- element::{FromElement, IntoElement},
- Element,
-};
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use peanuts::{Element, FromElement, IntoElement};
pub const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-tls";
@@ -11,7 +12,7 @@ pub struct StartTls {
}
impl IntoElement for StartTls {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
let mut builder = Element::builder("starttls", Some(XMLNS));
if self.required {
@@ -42,7 +43,7 @@ impl FromElement for StartTls {
pub struct Required;
impl FromElement for Required {
- fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("required")?;
element.check_namespace(XMLNS)?;
@@ -51,7 +52,7 @@ impl FromElement for Required {
}
impl IntoElement for Required {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("required", Some(XMLNS))
}
}
@@ -60,13 +61,13 @@ impl IntoElement for Required {
pub struct Proceed;
impl IntoElement for Proceed {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("proceed", Some(XMLNS))
}
}
impl FromElement for Proceed {
- fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("proceed")?;
element.check_namespace(XMLNS)?;
@@ -77,13 +78,13 @@ impl FromElement for Proceed {
pub struct Failure;
impl IntoElement for Failure {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("failure", Some(XMLNS))
}
}
impl FromElement for Failure {
- fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("failure")?;
element.check_namespace(XMLNS)?;
diff --git a/stanza/src/stream.rs b/stanza/src/stream.rs
index 732a826..f8aef33 100644
--- a/stanza/src/stream.rs
+++ b/stanza/src/stream.rs
@@ -1,8 +1,11 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use std::fmt::Display;
-use jid::JID;
-use peanuts::element::{ElementBuilder, FromElement, IntoElement};
-use peanuts::Element;
+use jid::BareJID;
+use peanuts::{Element, ElementBuilder, FromElement, IntoElement};
use thiserror::Error;
use crate::bind;
@@ -19,8 +22,8 @@ pub const XMLNS: &str = "http://etherx.jabber.org/streams";
// #[peanuts(xmlns = XMLNS)]
#[derive(Debug)]
pub struct Stream {
- pub from: Option<JID>,
- to: Option<JID>,
+ pub from: Option<BareJID>,
+ to: Option<BareJID>,
id: Option<String>,
version: Option<String>,
// TODO: lang enum
@@ -59,14 +62,14 @@ impl IntoElement for Stream {
.push_attribute_opt("from", self.from.clone())
.push_attribute_opt("id", self.id.clone())
.push_attribute_opt("version", self.version.clone())
- .push_attribute_opt_namespaced(peanuts::XML_NS, "to", self.lang.clone())
+ .push_attribute_opt_namespaced(peanuts::XML_NS, "lang", self.lang.clone())
}
}
impl<'s> Stream {
pub fn new(
- from: Option<JID>,
- to: Option<JID>,
+ from: Option<BareJID>,
+ to: Option<BareJID>,
id: Option<String>,
version: Option<String>,
lang: Option<String>,
@@ -82,7 +85,12 @@ impl<'s> Stream {
/// For initial stream headers, the initiating entity SHOULD include the 'xml:lang' attribute.
/// For privacy, it is better to not set `from` when sending a client stanza over an unencrypted connection.
- pub fn new_client(from: Option<JID>, to: JID, id: Option<String>, lang: String) -> Self {
+ pub fn new_client(
+ from: Option<BareJID>,
+ to: BareJID,
+ id: Option<String>,
+ lang: String,
+ ) -> Self {
Self {
from,
to: Some(to),
@@ -165,7 +173,7 @@ impl IntoElement for Feature {
}
impl FromElement for Feature {
- fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
match element.identify() {
(Some(starttls::XMLNS), "starttls") => {
Ok(Feature::StartTls(StartTls::from_element(element)?))
@@ -198,7 +206,7 @@ impl Display for Error {
}
impl FromElement for Error {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("error")?;
element.check_namespace(XMLNS)?;
diff --git a/stanza/src/stream_error.rs b/stanza/src/stream_error.rs
index 03d48eb..e068cbf 100644
--- a/stanza/src/stream_error.rs
+++ b/stanza/src/stream_error.rs
@@ -1,7 +1,8 @@
-use peanuts::{
- element::{FromElement, IntoElement},
- DeserializeError, Element, XML_NS,
-};
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use peanuts::{DeserializeError, Element, FromElement, IntoElement, XML_NS};
use thiserror::Error;
pub const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-streams";
@@ -61,7 +62,7 @@ pub enum Error {
}
impl FromElement for Error {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
let error;
match element.identify() {
(Some(XMLNS), "bad-format") => error = Error::BadFormat,
@@ -99,7 +100,7 @@ impl FromElement for Error {
}
impl IntoElement for Error {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
match self {
Error::BadFormat => Element::builder("bad-format", Some(XMLNS)),
Error::BadNamespacePrefix => Element::builder("bad-namespace-prefix", Some(XMLNS)),
@@ -143,7 +144,7 @@ pub struct Text {
}
impl FromElement for Text {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("text")?;
element.check_name(XMLNS)?;
@@ -155,7 +156,7 @@ impl FromElement for Text {
}
impl IntoElement for Text {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("text", Some(XMLNS))
.push_attribute_opt_namespaced(XML_NS, "lang", self.lang.clone())
.push_text_opt(self.text.clone())
diff --git a/stanza/src/xep_0004.rs b/stanza/src/xep_0004.rs
index f929517..b7b4878 100644
--- a/stanza/src/xep_0004.rs
+++ b/stanza/src/xep_0004.rs
@@ -1,9 +1,10 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use std::str::FromStr;
-use peanuts::{
- element::{FromElement, IntoElement},
- DeserializeError, Element,
-};
+use peanuts::{DeserializeError, Element, FromElement, IntoElement};
pub const XMLNS: &str = "jabber:x:data";
@@ -18,7 +19,7 @@ pub struct X {
}
impl FromElement for X {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("x")?;
element.check_namespace(XMLNS)?;
@@ -42,7 +43,7 @@ impl FromElement for X {
}
impl IntoElement for X {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("x", Some(XMLNS))
.push_attribute("type", self.r#type.clone())
.push_children(self.instructions.clone())
@@ -91,7 +92,7 @@ impl ToString for XType {
pub struct Instructions(pub String);
impl FromElement for Instructions {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("instructions")?;
element.check_namespace(XMLNS)?;
@@ -100,7 +101,7 @@ impl FromElement for Instructions {
}
impl IntoElement for Instructions {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("instructions", Some(XMLNS)).push_text(self.0.clone())
}
}
@@ -109,7 +110,7 @@ impl IntoElement for Instructions {
pub struct Title(pub String);
impl FromElement for Title {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("instructions")?;
element.check_namespace(XMLNS)?;
@@ -118,7 +119,7 @@ impl FromElement for Title {
}
impl IntoElement for Title {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("title", Some(XMLNS)).push_text(self.0.clone())
}
}
@@ -135,7 +136,7 @@ pub struct Field {
}
impl FromElement for Field {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("field")?;
element.check_namespace(XMLNS)?;
@@ -166,7 +167,7 @@ impl FromElement for Field {
}
impl IntoElement for Field {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
let mut builder = Element::builder("field", Some(XMLNS))
.push_attribute_opt("label", self.label.clone())
.push_attribute_opt("type", self.r#type.clone())
@@ -239,7 +240,7 @@ impl ToString for FieldType {
pub struct Desc(pub String);
impl FromElement for Desc {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("desc")?;
element.check_namespace(XMLNS)?;
@@ -248,7 +249,7 @@ impl FromElement for Desc {
}
impl IntoElement for Desc {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("desc", Some(XMLNS)).push_text(self.0.clone())
}
}
@@ -257,7 +258,7 @@ impl IntoElement for Desc {
pub struct Required;
impl FromElement for Required {
- fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("required")?;
element.check_namespace(XMLNS)?;
@@ -266,7 +267,7 @@ impl FromElement for Required {
}
impl IntoElement for Required {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("required", Some(XMLNS))
}
}
@@ -278,7 +279,7 @@ pub struct XOption {
}
impl FromElement for XOption {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("option")?;
element.check_namespace(XMLNS)?;
@@ -291,7 +292,7 @@ impl FromElement for XOption {
}
impl IntoElement for XOption {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("option", Some(XMLNS))
.push_attribute_opt("label", self.label.clone())
.push_child(self.value.clone())
@@ -302,7 +303,7 @@ impl IntoElement for XOption {
pub struct Value(pub String);
impl FromElement for Value {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("value")?;
element.check_namespace(XMLNS)?;
@@ -311,7 +312,7 @@ impl FromElement for Value {
}
impl IntoElement for Value {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("value", Some(XMLNS)).push_text(self.0.clone())
}
}
@@ -323,7 +324,7 @@ pub struct Reported {
}
impl FromElement for Reported {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("reported")?;
element.check_namespace(XMLNS)?;
@@ -334,7 +335,7 @@ impl FromElement for Reported {
}
impl IntoElement for Reported {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("reported", Some(XMLNS)).push_children(self.fields.clone())
}
}
@@ -345,7 +346,7 @@ pub struct Item {
}
impl FromElement for Item {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("item")?;
element.check_namespace(XMLNS)?;
@@ -356,7 +357,7 @@ impl FromElement for Item {
}
impl IntoElement for Item {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("item", Some(XMLNS)).push_children(self.fields.clone())
}
}
diff --git a/stanza/src/xep_0030/info.rs b/stanza/src/xep_0030/info.rs
index 539934f..69c795d 100644
--- a/stanza/src/xep_0030/info.rs
+++ b/stanza/src/xep_0030/info.rs
@@ -1,7 +1,8 @@
-use peanuts::{
- element::{FromElement, IntoElement},
- DeserializeError, Element, XML_NS,
-};
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use peanuts::{DeserializeError, Element, FromElement, IntoElement, XML_NS};
#[cfg(feature = "xep_0128")]
use crate::xep_0004::X;
@@ -22,7 +23,7 @@ pub struct Query {
}
impl FromElement for Query {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("query")?;
element.check_namespace(XMLNS)?;
@@ -50,7 +51,7 @@ impl FromElement for Query {
}
impl IntoElement for Query {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
let builder = Element::builder("query", Some(XMLNS))
.push_attribute_opt("node", self.node.clone())
.push_children(self.features.clone())
@@ -78,7 +79,7 @@ pub struct Identity {
}
impl FromElement for Identity {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("identity")?;
element.check_namespace(XMLNS)?;
@@ -109,7 +110,7 @@ impl FromElement for Identity {
}
impl IntoElement for Identity {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("identity", Some(XMLNS))
.push_attribute("category", self.category.clone())
.push_attribute_opt("name", self.name.clone())
@@ -124,7 +125,7 @@ pub struct Feature {
}
impl FromElement for Feature {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("feature")?;
element.check_namespace(XMLNS)?;
@@ -135,7 +136,7 @@ impl FromElement for Feature {
}
impl IntoElement for Feature {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("feature", Some(XMLNS)).push_attribute("var", self.var.clone())
}
}
diff --git a/stanza/src/xep_0030/items.rs b/stanza/src/xep_0030/items.rs
index 471f3e1..4096707 100644
--- a/stanza/src/xep_0030/items.rs
+++ b/stanza/src/xep_0030/items.rs
@@ -1,8 +1,9 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use jid::JID;
-use peanuts::{
- element::{FromElement, IntoElement},
- Element,
-};
+use peanuts::{Element, FromElement, IntoElement};
#[cfg(feature = "xep_0059")]
use crate::xep_0059::Set;
@@ -18,7 +19,7 @@ pub struct Query {
}
impl FromElement for Query {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("query")?;
element.check_namespace(XMLNS)?;
@@ -39,7 +40,7 @@ impl FromElement for Query {
}
impl IntoElement for Query {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
let builder = Element::builder("query", Some(XMLNS))
.push_attribute_opt("node", self.node.clone())
.push_children(self.items.clone());
@@ -59,7 +60,7 @@ pub struct Item {
}
impl FromElement for Item {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("item")?;
element.check_namespace(XMLNS)?;
@@ -72,7 +73,7 @@ impl FromElement for Item {
}
impl IntoElement for Item {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("item", Some(XMLNS))
.push_attribute("jid", self.jid.clone())
.push_attribute_opt("name", self.name.clone())
diff --git a/stanza/src/xep_0030/mod.rs b/stanza/src/xep_0030/mod.rs
index 914c17b..0faaf04 100644
--- a/stanza/src/xep_0030/mod.rs
+++ b/stanza/src/xep_0030/mod.rs
@@ -1,2 +1,6 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
pub mod info;
pub mod items;
diff --git a/stanza/src/xep_0059.rs b/stanza/src/xep_0059.rs
index 01dbc6c..84f84ff 100644
--- a/stanza/src/xep_0059.rs
+++ b/stanza/src/xep_0059.rs
@@ -1,7 +1,8 @@
-use peanuts::{
- element::{FromElement, IntoElement},
- Element,
-};
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use peanuts::{Element, FromElement, IntoElement};
pub const XMLNS: &str = "http://jabber.org/protocol/rsm";
@@ -17,7 +18,7 @@ pub struct Set {
}
impl FromElement for Set {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("set")?;
element.check_namespace(XMLNS)?;
@@ -42,7 +43,7 @@ impl FromElement for Set {
}
impl IntoElement for Set {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("set", Some(XMLNS))
.push_child_opt(self.after.clone())
.push_child_opt(self.before.clone())
@@ -58,7 +59,7 @@ impl IntoElement for Set {
pub struct After(pub String);
impl FromElement for After {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("after")?;
element.check_namespace(XMLNS)?;
@@ -67,7 +68,7 @@ impl FromElement for After {
}
impl IntoElement for After {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
// TODO: better way for push_text to work, empty string should be empty element no matter what
let builder = Element::builder("after", Some(XMLNS));
@@ -83,7 +84,7 @@ impl IntoElement for After {
pub struct Before(pub String);
impl FromElement for Before {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("before")?;
element.check_namespace(XMLNS)?;
@@ -92,7 +93,7 @@ impl FromElement for Before {
}
impl IntoElement for Before {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
// TODO: better way for push_text to work, empty string should be empty element no matter what
let builder = Element::builder("before", Some(XMLNS));
@@ -108,7 +109,7 @@ impl IntoElement for Before {
pub struct Count(pub i32);
impl FromElement for Count {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("count")?;
element.check_namespace(XMLNS)?;
@@ -117,7 +118,7 @@ impl FromElement for Count {
}
impl IntoElement for Count {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("count", Some(XMLNS)).push_text(self.0)
}
}
@@ -126,7 +127,7 @@ impl IntoElement for Count {
pub struct Index(pub i32);
impl FromElement for Index {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("index")?;
element.check_namespace(XMLNS)?;
@@ -135,7 +136,7 @@ impl FromElement for Index {
}
impl IntoElement for Index {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("index", Some(XMLNS)).push_text(self.0)
}
}
@@ -144,7 +145,7 @@ impl IntoElement for Index {
pub struct Last(pub String);
impl FromElement for Last {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("last")?;
element.check_namespace(XMLNS)?;
@@ -153,7 +154,7 @@ impl FromElement for Last {
}
impl IntoElement for Last {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
// TODO: better way for push_text to work, empty string should be empty element no matter what
let builder = Element::builder("last", Some(XMLNS));
@@ -169,7 +170,7 @@ impl IntoElement for Last {
pub struct Max(pub i32);
impl FromElement for Max {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("max")?;
element.check_namespace(XMLNS)?;
@@ -178,7 +179,7 @@ impl FromElement for Max {
}
impl IntoElement for Max {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("max", Some(XMLNS)).push_text(self.0)
}
}
@@ -190,7 +191,7 @@ pub struct First {
}
impl FromElement for First {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("first")?;
element.check_namespace(XMLNS)?;
@@ -203,7 +204,7 @@ impl FromElement for First {
}
impl IntoElement for First {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
let builder =
Element::builder("first", Some(XMLNS)).push_attribute_opt("index", self.index);
diff --git a/stanza/src/xep_0060/errors.rs b/stanza/src/xep_0060/errors.rs
index e6817ac..a52ea85 100644
--- a/stanza/src/xep_0060/errors.rs
+++ b/stanza/src/xep_0060/errors.rs
@@ -1,9 +1,10 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use std::{fmt::Display, str::FromStr};
-use peanuts::{
- element::{FromElement, IntoElement},
- DeserializeError, Element,
-};
+use peanuts::{DeserializeError, Element, FromElement, IntoElement};
use thiserror::Error;
use crate::{client::error::ErrorType, stanza_error::Error as StanzaError};
@@ -121,7 +122,7 @@ impl Error {
}
impl FromElement for Error {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
match element.identify() {
(Some(XMLNS), "closed-node") => Ok(Self::ClosedNode),
(Some(XMLNS), "configuration-required") => Ok(Self::ConfigurationRequired),
@@ -154,7 +155,7 @@ impl FromElement for Error {
}
impl IntoElement for Error {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
match self {
Error::ClosedNode => Element::builder("closed-node", Some(XMLNS)),
Error::ConfigurationRequired => Element::builder("configuration-required", Some(XMLNS)),
diff --git a/stanza/src/xep_0060/event.rs b/stanza/src/xep_0060/event.rs
index d2c150a..f3cae8b 100644
--- a/stanza/src/xep_0060/event.rs
+++ b/stanza/src/xep_0060/event.rs
@@ -1,13 +1,16 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use std::str::FromStr;
use chrono::{DateTime, Utc};
use jid::JID;
-use peanuts::{
- element::{FromElement, IntoElement},
- DeserializeError, Element,
-};
+use peanuts::{DeserializeError, Element, FromElement, IntoElement};
use crate::xep_0004::X;
+#[cfg(feature = "xep_0084")]
+use crate::xep_0084;
#[cfg(feature = "xep_0172")]
use crate::xep_0172::{self, Nick};
@@ -24,7 +27,7 @@ pub enum Event {
}
impl FromElement for Event {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("event")?;
element.check_namespace(XMLNS)?;
@@ -47,7 +50,7 @@ impl FromElement for Event {
}
impl IntoElement for Event {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
let builder = Element::builder("event", Some(XMLNS));
match self {
@@ -68,7 +71,7 @@ pub struct Collection {
}
impl FromElement for Collection {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("node")?;
element.check_namespace(XMLNS)?;
@@ -80,7 +83,7 @@ impl FromElement for Collection {
}
impl IntoElement for Collection {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("collection", Some(XMLNS))
.push_attribute_opt("node", self.node.clone())
.push_child(self.r#type.clone())
@@ -94,7 +97,7 @@ pub enum CollectionType {
}
impl FromElement for CollectionType {
- fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
match element.identify() {
(Some(XMLNS), "associate") => {
Ok(CollectionType::Associate(Associate::from_element(element)?))
@@ -108,7 +111,7 @@ impl FromElement for CollectionType {
}
impl IntoElement for CollectionType {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
match self {
CollectionType::Associate(associate) => associate.builder(),
CollectionType::Disassociate(disassociate) => disassociate.builder(),
@@ -122,7 +125,7 @@ pub struct Associate {
}
impl FromElement for Associate {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("associate")?;
element.check_namespace(XMLNS)?;
@@ -133,7 +136,7 @@ impl FromElement for Associate {
}
impl IntoElement for Associate {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("associate", Some(XMLNS)).push_attribute("node", self.node.clone())
}
}
@@ -144,7 +147,7 @@ pub struct Disassociate {
}
impl FromElement for Disassociate {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("disassociate")?;
element.check_namespace(XMLNS)?;
@@ -155,7 +158,7 @@ impl FromElement for Disassociate {
}
impl IntoElement for Disassociate {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("disassociate", Some(XMLNS)).push_attribute("node", self.node.clone())
}
}
@@ -167,7 +170,7 @@ pub struct Configuration {
}
impl FromElement for Configuration {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("configuration")?;
element.check_namespace(XMLNS)?;
@@ -183,7 +186,7 @@ impl FromElement for Configuration {
}
impl IntoElement for Configuration {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("configuration", Some(XMLNS))
.push_attribute_opt("node", self.node.clone())
.push_child_opt(self.configuration.clone())
@@ -197,7 +200,7 @@ pub struct Delete {
}
impl FromElement for Delete {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("delete")?;
element.check_namespace(XMLNS)?;
@@ -210,7 +213,7 @@ impl FromElement for Delete {
}
impl IntoElement for Delete {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("delete", Some(XMLNS))
.push_attribute("node", self.node.clone())
.push_child_opt(self.redirect.clone())
@@ -219,12 +222,12 @@ impl IntoElement for Delete {
#[derive(Clone, Debug)]
pub struct Items {
- node: String,
- items: ItemsType,
+ pub node: String,
+ pub items: ItemsType,
}
impl FromElement for Items {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("items")?;
element.check_namespace(XMLNS)?;
@@ -241,7 +244,7 @@ impl FromElement for Items {
}
impl IntoElement for Items {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
let builder =
Element::builder("items", Some(XMLNS)).push_attribute("node", self.node.clone());
@@ -260,13 +263,13 @@ pub enum ItemsType {
#[derive(Clone, Debug)]
pub struct Item {
- id: Option<String>,
- publisher: Option<String>,
- item: Option<Content>,
+ pub id: Option<String>,
+ pub publisher: Option<String>,
+ pub item: Option<Content>,
}
impl FromElement for Item {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("item")?;
element.check_namespace(XMLNS)?;
@@ -284,7 +287,7 @@ impl FromElement for Item {
}
impl IntoElement for Item {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("item", Some(XMLNS))
.push_attribute_opt("id", self.id.clone())
.push_attribute_opt("publisher", self.publisher.clone())
@@ -296,24 +299,40 @@ impl IntoElement for Item {
pub enum Content {
#[cfg(feature = "xep_0172")]
Nick(Nick),
+ #[cfg(feature = "xep_0084")]
+ AvatarData(xep_0084::Data),
+ #[cfg(feature = "xep_0084")]
+ AvatarMetadata(xep_0084::Metadata),
Unknown(Element),
}
impl FromElement for Content {
- fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
match element.identify() {
#[cfg(feature = "xep_0172")]
(Some(xep_0172::XMLNS), "nick") => Ok(Content::Nick(Nick::from_element(element)?)),
+ #[cfg(feature = "xep_0084")]
+ (Some(xep_0084::data::XMLNS), "data") => {
+ Ok(Content::AvatarData(xep_0084::Data::from_element(element)?))
+ }
+ #[cfg(feature = "xep_0084")]
+ (Some(xep_0084::metadata::XMLNS), "metadata") => Ok(Content::AvatarMetadata(
+ xep_0084::Metadata::from_element(element)?,
+ )),
_ => Ok(Self::Unknown(element)),
}
}
}
impl IntoElement for Content {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
match self {
#[cfg(feature = "xep_0172")]
Content::Nick(nick) => nick.builder(),
+ #[cfg(feature = "xep_0084")]
+ Content::AvatarData(data) => data.builder(),
+ #[cfg(feature = "xep_0084")]
+ Content::AvatarMetadata(metadata) => metadata.builder(),
Content::Unknown(_e) => panic!("unknown content cannot be serialized"),
}
}
@@ -325,7 +344,7 @@ pub struct Purge {
}
impl FromElement for Purge {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("purge")?;
element.check_namespace(XMLNS)?;
@@ -336,7 +355,7 @@ impl FromElement for Purge {
}
impl IntoElement for Purge {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("purge", Some(XMLNS)).push_attribute("node", self.node.clone())
}
}
@@ -347,7 +366,7 @@ pub struct Redirect {
}
impl FromElement for Redirect {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("redirect")?;
element.check_namespace(XMLNS)?;
@@ -358,7 +377,7 @@ impl FromElement for Redirect {
}
impl IntoElement for Redirect {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("redirect", Some(XMLNS)).push_attribute("uri", self.uri.clone())
}
}
@@ -369,7 +388,7 @@ pub struct Retract {
}
impl FromElement for Retract {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("retract")?;
element.check_namespace(XMLNS)?;
@@ -380,7 +399,7 @@ impl FromElement for Retract {
}
impl IntoElement for Retract {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("retract", Some(XMLNS)).push_attribute("id", self.id.clone())
}
}
@@ -395,7 +414,7 @@ pub struct Subscription {
}
impl FromElement for Subscription {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("subscription")?;
element.check_namespace(XMLNS)?;
@@ -416,7 +435,7 @@ impl FromElement for Subscription {
}
impl IntoElement for Subscription {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("subscription", Some(XMLNS))
.push_attribute_opt("expiry", self.expiry)
.push_attribute("jid", self.jid.clone())
diff --git a/stanza/src/xep_0060/mod.rs b/stanza/src/xep_0060/mod.rs
index 566310f..ac8a849 100644
--- a/stanza/src/xep_0060/mod.rs
+++ b/stanza/src/xep_0060/mod.rs
@@ -1,3 +1,7 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
pub mod errors;
pub mod event;
pub mod owner;
diff --git a/stanza/src/xep_0060/owner.rs b/stanza/src/xep_0060/owner.rs
index 1fedc60..3b6c6f6 100644
--- a/stanza/src/xep_0060/owner.rs
+++ b/stanza/src/xep_0060/owner.rs
@@ -1,10 +1,11 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use std::str::FromStr;
-use jid::JID;
-use peanuts::{
- element::{FromElement, IntoElement},
- DeserializeError, Element,
-};
+use jid::{BareJID, JID};
+use peanuts::{DeserializeError, Element, FromElement, IntoElement};
use crate::xep_0004::X;
@@ -21,7 +22,7 @@ pub enum Pubsub {
}
impl FromElement for Pubsub {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("pubsub")?;
element.check_namespace(XMLNS)?;
@@ -44,7 +45,7 @@ impl FromElement for Pubsub {
}
impl IntoElement for Pubsub {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
let builder = Element::builder("pubsub", Some(XMLNS));
match self {
@@ -65,7 +66,7 @@ pub struct Affiliations {
}
impl FromElement for Affiliations {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("affiliations")?;
element.check_namespace(XMLNS)?;
@@ -78,7 +79,7 @@ impl FromElement for Affiliations {
}
impl IntoElement for Affiliations {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("affiliations", Some(XMLNS))
.push_attribute("node", self.node.clone())
.push_children(self.affiliations.clone())
@@ -88,11 +89,11 @@ impl IntoElement for Affiliations {
#[derive(Clone, Debug)]
pub struct Affiliation {
affiliation: AffiliationType,
- jid: JID,
+ jid: BareJID,
}
impl FromElement for Affiliation {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("affiliation")?;
element.check_namespace(XMLNS)?;
@@ -104,7 +105,7 @@ impl FromElement for Affiliation {
}
impl IntoElement for Affiliation {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("affiliation", Some(XMLNS))
.push_attribute("affiliation", self.affiliation.clone())
.push_attribute("jid", self.jid.clone())
@@ -158,7 +159,7 @@ pub struct Configure {
}
impl FromElement for Configure {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("configure")?;
element.check_namespace(XMLNS)?;
@@ -171,7 +172,7 @@ impl FromElement for Configure {
}
impl IntoElement for Configure {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("configure", Some(XMLNS))
.push_attribute_opt("node", self.node.clone())
.push_child_opt(self.configure.clone())
@@ -182,7 +183,7 @@ impl IntoElement for Configure {
pub struct Default(Option<X>);
impl FromElement for Default {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("default")?;
element.check_namespace(XMLNS)?;
@@ -191,19 +192,19 @@ impl FromElement for Default {
}
impl IntoElement for Default {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("default", Some(XMLNS)).push_child_opt(self.0.clone())
}
}
#[derive(Clone, Debug)]
pub struct Delete {
- node: String,
- redirect: Option<Redirect>,
+ pub node: String,
+ pub redirect: Option<Redirect>,
}
impl FromElement for Delete {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("delete")?;
element.check_namespace(XMLNS)?;
@@ -216,7 +217,7 @@ impl FromElement for Delete {
}
impl IntoElement for Delete {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("delete", Some(XMLNS))
.push_attribute("node", self.node.clone())
.push_child_opt(self.redirect.clone())
@@ -229,7 +230,7 @@ pub struct Purge {
}
impl FromElement for Purge {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("purge")?;
element.check_namespace(XMLNS)?;
@@ -240,7 +241,7 @@ impl FromElement for Purge {
}
impl IntoElement for Purge {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("purge", Some(XMLNS)).push_attribute("node", self.node.clone())
}
}
@@ -251,7 +252,7 @@ pub struct Redirect {
}
impl FromElement for Redirect {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("redirect")?;
element.check_namespace(XMLNS)?;
@@ -262,7 +263,7 @@ impl FromElement for Redirect {
}
impl IntoElement for Redirect {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("redirect", Some(XMLNS)).push_attribute("uri", self.uri.clone())
}
}
@@ -274,7 +275,7 @@ pub struct Subscriptions {
}
impl FromElement for Subscriptions {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("subscriptions")?;
element.check_namespace(XMLNS)?;
@@ -290,7 +291,7 @@ impl FromElement for Subscriptions {
}
impl IntoElement for Subscriptions {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("subscriptions", Some(XMLNS))
.push_attribute("node", self.node.clone())
.push_children(self.subscriptions.clone())
@@ -304,7 +305,7 @@ pub struct Subscription {
}
impl FromElement for Subscription {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("subscription")?;
element.check_namespace(XMLNS)?;
@@ -316,7 +317,7 @@ impl FromElement for Subscription {
}
impl IntoElement for Subscription {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("subscription", Some(XMLNS))
.push_attribute("subscription", self.subscription.clone())
.push_attribute("jid", self.jid.clone())
diff --git a/stanza/src/xep_0060/pubsub.rs b/stanza/src/xep_0060/pubsub.rs
index 25fc405..94277b9 100644
--- a/stanza/src/xep_0060/pubsub.rs
+++ b/stanza/src/xep_0060/pubsub.rs
@@ -1,12 +1,15 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use std::str::FromStr;
use jid::JID;
-use peanuts::{
- element::{FromElement, IntoElement},
- DeserializeError, Element,
-};
+use peanuts::{DeserializeError, Element, FromElement, IntoElement};
use crate::xep_0004::X;
+#[cfg(feature = "xep_0084")]
+use crate::xep_0084;
#[cfg(feature = "xep_0172")]
use crate::xep_0172::{self, Nick};
@@ -28,7 +31,7 @@ pub enum Pubsub {
}
impl FromElement for Pubsub {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("pubsub")?;
element.check_namespace(XMLNS)?;
@@ -79,7 +82,7 @@ impl FromElement for Pubsub {
}
impl IntoElement for Pubsub {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
let element = Element::builder("pubsub", Some(XMLNS));
match self {
@@ -111,7 +114,7 @@ pub struct Affiliations {
}
impl FromElement for Affiliations {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("affiliations")?;
element.check_namespace(XMLNS)?;
@@ -124,7 +127,7 @@ impl FromElement for Affiliations {
}
impl IntoElement for Affiliations {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("affilations", Some(XMLNS))
.push_attribute_opt("node", self.node.clone())
.push_children(self.affiliations.clone())
@@ -139,7 +142,7 @@ pub struct Affiliation {
}
impl FromElement for Affiliation {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("affiliation")?;
element.check_namespace(XMLNS)?;
@@ -151,7 +154,7 @@ impl FromElement for Affiliation {
}
impl IntoElement for Affiliation {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("affiliation", Some(XMLNS))
.push_attribute("affiliation", self.affiliation.clone())
.push_attribute("node", self.node.clone())
@@ -202,7 +205,7 @@ impl ToString for AffiliationType {
pub struct Configure(Option<X>);
impl FromElement for Configure {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("configure")?;
element.check_namespace(XMLNS)?;
@@ -211,7 +214,7 @@ impl FromElement for Configure {
}
impl IntoElement for Configure {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("configure", Some(XMLNS)).push_child_opt(self.0.clone())
}
}
@@ -222,7 +225,7 @@ pub struct Create {
}
impl FromElement for Create {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("create")?;
element.check_namespace(XMLNS)?;
@@ -233,7 +236,7 @@ impl FromElement for Create {
}
impl IntoElement for Create {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("create", Some(XMLNS)).push_attribute_opt("node", self.node.clone())
}
}
@@ -247,7 +250,7 @@ pub struct Default {
}
impl FromElement for Default {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("default")?;
element.check_namespace(XMLNS)?;
@@ -265,7 +268,7 @@ impl FromElement for Default {
}
impl IntoElement for Default {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("default", Some(XMLNS))
.push_attribute_opt("node", self.node.clone())
.push_attribute_opt("type", self.r#type.clone())
@@ -310,7 +313,7 @@ pub struct Items {
}
impl FromElement for Items {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("items")?;
element.check_namespace(XMLNS)?;
@@ -330,7 +333,7 @@ impl FromElement for Items {
}
impl IntoElement for Items {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("items", Some(XMLNS))
.push_attribute_opt("max_items", self.max_items)
.push_attribute("node", self.node.clone())
@@ -347,7 +350,7 @@ pub struct Item {
}
impl FromElement for Item {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("item")?;
element.check_namespace(XMLNS)?;
@@ -365,7 +368,7 @@ impl FromElement for Item {
}
impl IntoElement for Item {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("item", Some(XMLNS))
.push_attribute_opt("id", self.id.clone())
.push_attribute_opt("publisher", self.publisher.clone())
@@ -377,24 +380,40 @@ impl IntoElement for Item {
pub enum Content {
#[cfg(feature = "xep_0172")]
Nick(Nick),
+ #[cfg(feature = "xep_0084")]
+ AvatarData(xep_0084::Data),
+ #[cfg(feature = "xep_0084")]
+ AvatarMetadata(xep_0084::Metadata),
Unknown(Element),
}
impl FromElement for Content {
- fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
match element.identify() {
#[cfg(feature = "xep_0172")]
(Some(xep_0172::XMLNS), "nick") => Ok(Content::Nick(Nick::from_element(element)?)),
+ #[cfg(feature = "xep_0084")]
+ (Some(xep_0084::data::XMLNS), "data") => {
+ Ok(Content::AvatarData(xep_0084::Data::from_element(element)?))
+ }
+ #[cfg(feature = "xep_0084")]
+ (Some(xep_0084::metadata::XMLNS), "metadata") => Ok(Content::AvatarMetadata(
+ xep_0084::Metadata::from_element(element)?,
+ )),
_ => Ok(Self::Unknown(element)),
}
}
}
impl IntoElement for Content {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
match self {
#[cfg(feature = "xep_0172")]
Content::Nick(nick) => nick.builder(),
+ #[cfg(feature = "xep_0084")]
+ Content::AvatarData(data) => data.builder(),
+ #[cfg(feature = "xep_0084")]
+ Content::AvatarMetadata(metadata) => metadata.builder(),
Content::Unknown(_e) => panic!("unknown content cannot be serialized"),
}
}
@@ -409,7 +428,7 @@ pub struct Options {
}
impl FromElement for Options {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("options")?;
element.check_namespace(XMLNS)?;
@@ -429,7 +448,7 @@ impl FromElement for Options {
}
impl IntoElement for Options {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("options", Some(XMLNS))
.push_attribute("jid", self.jid.clone())
.push_attribute_opt("node", self.node.clone())
@@ -445,7 +464,7 @@ pub struct Publish {
}
impl FromElement for Publish {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("publish")?;
element.check_namespace(XMLNS)?;
@@ -458,7 +477,7 @@ impl FromElement for Publish {
}
impl IntoElement for Publish {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("publish", Some(XMLNS))
.push_attribute("node", self.node.clone())
.push_children(self.items.clone())
@@ -469,7 +488,7 @@ impl IntoElement for Publish {
pub struct PublishOptions(pub Option<X>);
impl FromElement for PublishOptions {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("publish-options")?;
element.check_namespace(XMLNS)?;
@@ -478,7 +497,7 @@ impl FromElement for PublishOptions {
}
impl IntoElement for PublishOptions {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("publish-options", Some(XMLNS)).push_child_opt(self.0.clone())
}
}
@@ -492,7 +511,7 @@ pub struct Retract {
}
impl FromElement for Retract {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("retract")?;
element.check_namespace(XMLNS)?;
@@ -510,7 +529,7 @@ impl FromElement for Retract {
}
impl IntoElement for Retract {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("retract", Some(XMLNS))
.push_attribute("node", self.node.clone())
.push_attribute_opt("notify", self.notify)
@@ -525,7 +544,7 @@ pub struct SubscribeOptions {
}
impl FromElement for SubscribeOptions {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("subscribe-options")?;
element.check_namespace(XMLNS)?;
@@ -541,7 +560,7 @@ impl FromElement for SubscribeOptions {
}
impl IntoElement for SubscribeOptions {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
let builder = Element::builder("subscribe-options", Some(XMLNS));
if self.required {
@@ -555,7 +574,7 @@ impl IntoElement for SubscribeOptions {
pub struct Required;
impl FromElement for Required {
- fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("required")?;
element.check_namespace(XMLNS)?;
@@ -564,7 +583,7 @@ impl FromElement for Required {
}
impl IntoElement for Required {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("required", Some(XMLNS))
}
}
@@ -576,7 +595,7 @@ pub struct Subscribe {
}
impl FromElement for Subscribe {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("subscribe")?;
element.check_namespace(XMLNS)?;
@@ -588,7 +607,7 @@ impl FromElement for Subscribe {
}
impl IntoElement for Subscribe {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("subscribe", Some(XMLNS))
.push_attribute("jid", self.jid.clone())
.push_attribute_opt("node", self.node.clone())
@@ -602,7 +621,7 @@ pub struct Subscriptions {
}
impl FromElement for Subscriptions {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("subscriptions")?;
element.check_namespace(XMLNS)?;
@@ -618,7 +637,7 @@ impl FromElement for Subscriptions {
}
impl IntoElement for Subscriptions {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("subscriptions", Some(XMLNS))
.push_attribute_opt("node", self.node.clone())
.push_children(self.subscriptions.clone())
@@ -635,7 +654,7 @@ pub struct Subscription {
}
impl FromElement for Subscription {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("subscription")?;
element.check_namespace(XMLNS)?;
@@ -657,7 +676,7 @@ impl FromElement for Subscription {
}
impl IntoElement for Subscription {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("subscription", Some(XMLNS))
.push_attribute("jid", self.jid.clone())
.push_attribute_opt("node", self.node.clone())
@@ -709,7 +728,7 @@ pub struct Unsubscribe {
}
impl FromElement for Unsubscribe {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("unsubscribe")?;
element.check_namespace(XMLNS)?;
@@ -722,7 +741,7 @@ impl FromElement for Unsubscribe {
}
impl IntoElement for Unsubscribe {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("unsubscribe", Some(XMLNS))
.push_attribute("jid", self.jid.clone())
.push_attribute_opt("node", self.node.clone())
diff --git a/stanza/src/xep_0084/data.rs b/stanza/src/xep_0084/data.rs
new file mode 100644
index 0000000..d147550
--- /dev/null
+++ b/stanza/src/xep_0084/data.rs
@@ -0,0 +1,31 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use peanuts::{Element, FromElement, IntoElement};
+
+pub const XMLNS: &str = "urn:xmpp:avatar:data";
+
+#[derive(Debug, Clone)]
+pub struct Data(pub String);
+
+impl FromElement for Data {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("data")?;
+ element.check_namespace(XMLNS)?;
+
+ Ok(Self(element.pop_value_opt()?.unwrap_or_default()))
+ }
+}
+
+impl IntoElement for Data {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ let builder = Element::builder("data", Some(XMLNS));
+
+ if self.0.is_empty() {
+ builder
+ } else {
+ builder.push_text(self.0.clone())
+ }
+ }
+}
diff --git a/stanza/src/xep_0084/metadata.rs b/stanza/src/xep_0084/metadata.rs
new file mode 100644
index 0000000..b9d3e60
--- /dev/null
+++ b/stanza/src/xep_0084/metadata.rs
@@ -0,0 +1,107 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use peanuts::{Element, FromElement, IntoElement};
+
+pub const XMLNS: &str = "urn:xmpp:avatar:metadata";
+
+#[derive(Debug, Clone)]
+pub struct Metadata {
+ pub info: Vec<Info>,
+ pub pointers: Vec<Pointer>,
+}
+
+impl FromElement for Metadata {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("metadata")?;
+ element.check_namespace(XMLNS)?;
+
+ let info = element.pop_children()?;
+ let pointers = element.pop_children()?;
+
+ Ok(Self { info, pointers })
+ }
+}
+
+impl IntoElement for Metadata {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("metadata", Some(XMLNS))
+ .push_children(self.info.clone())
+ .push_children(self.pointers.clone())
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct Info {
+ pub bytes: u32,
+ pub height: Option<u16>,
+ pub id: String,
+ pub r#type: String,
+ pub url: Option<String>,
+ pub width: Option<u16>,
+}
+
+impl FromElement for Info {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("info")?;
+ element.check_namespace(XMLNS)?;
+
+ let bytes = element.attribute("bytes")?;
+ let height = element.attribute_opt("height")?;
+ let id = element.attribute("id")?;
+ let r#type = element.attribute("type")?;
+ let url = element.attribute_opt("url")?;
+ let width = element.attribute_opt("width")?;
+
+ Ok(Self {
+ bytes,
+ height,
+ id,
+ r#type,
+ url,
+ width,
+ })
+ }
+}
+
+impl IntoElement for Info {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("info", Some(XMLNS))
+ .push_attribute("bytes", self.bytes)
+ .push_attribute_opt("height", self.height)
+ .push_attribute("id", self.id.clone())
+ .push_attribute("type", self.r#type.clone())
+ .push_attribute_opt("url", self.url.clone())
+ .push_attribute_opt("width", self.width)
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct Pointer(pub PointerInner);
+
+impl FromElement for Pointer {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("pointer")?;
+ element.check_namespace(XMLNS)?;
+
+ Ok(Self(PointerInner::Unsupported(element.pop_child_one()?)))
+ }
+}
+
+impl IntoElement for Pointer {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ let _builder = Element::builder("pointer", Some(XMLNS));
+
+ match &self.0 {
+ PointerInner::Unsupported(_element) => {
+ panic!("cannot serialize unsupported PointerInner")
+ }
+ }
+ }
+}
+
+#[derive(Debug, Clone)]
+pub enum PointerInner {
+ Unsupported(Element),
+}
diff --git a/stanza/src/xep_0084/mod.rs b/stanza/src/xep_0084/mod.rs
new file mode 100644
index 0000000..1e80c9a
--- /dev/null
+++ b/stanza/src/xep_0084/mod.rs
@@ -0,0 +1,12 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+pub use data::Data;
+pub use metadata::Info;
+pub use metadata::Metadata;
+pub use metadata::Pointer;
+pub use metadata::PointerInner;
+
+pub mod data;
+pub mod metadata;
diff --git a/stanza/src/xep_0115.rs b/stanza/src/xep_0115.rs
index 1c2ef69..c983f2b 100644
--- a/stanza/src/xep_0115.rs
+++ b/stanza/src/xep_0115.rs
@@ -1,7 +1,8 @@
-use peanuts::{
- element::{FromElement, IntoElement},
- Element,
-};
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use peanuts::{Element, FromElement, IntoElement};
pub const XMLNS: &str = "http://jabber.org/protocol/caps";
@@ -14,7 +15,7 @@ pub struct C {
}
impl FromElement for C {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("c")?;
element.check_namespace(XMLNS)?;
@@ -33,7 +34,7 @@ impl FromElement for C {
}
impl IntoElement for C {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("c", Some(XMLNS))
.push_attribute_opt("ext", self.ext.clone())
.push_attribute("hash", self.hash.clone())
diff --git a/stanza/src/xep_0131.rs b/stanza/src/xep_0131.rs
index 27fc962..8d296b3 100644
--- a/stanza/src/xep_0131.rs
+++ b/stanza/src/xep_0131.rs
@@ -1,7 +1,8 @@
-use peanuts::{
- element::{FromElement, IntoElement},
- Element,
-};
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use peanuts::{Element, FromElement, IntoElement};
pub const XMLNS: &str = "http://jabber.org/protocol/disco#info";
@@ -9,7 +10,7 @@ pub const XMLNS: &str = "http://jabber.org/protocol/disco#info";
pub struct Headers(pub Vec<Header>);
impl FromElement for Headers {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("headers")?;
element.check_namespace(XMLNS)?;
@@ -18,7 +19,7 @@ impl FromElement for Headers {
}
impl IntoElement for Headers {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("headers", Some(XMLNS)).push_children(self.0.clone())
}
}
@@ -30,7 +31,7 @@ pub struct Header {
}
impl FromElement for Header {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("header")?;
element.check_namespace(XMLNS)?;
@@ -43,7 +44,7 @@ impl FromElement for Header {
}
impl IntoElement for Header {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
let builder =
Element::builder("header", Some(XMLNS)).push_attribute("name", self.name.clone());
diff --git a/stanza/src/xep_0156.rs b/stanza/src/xep_0156.rs
new file mode 100644
index 0000000..8b3d07c
--- /dev/null
+++ b/stanza/src/xep_0156.rs
@@ -0,0 +1,234 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use chrono::{DateTime, Utc};
+use peanuts::{Element, FromElement, IntoElement, XML_NS};
+
+pub const XMLNS: &str = "http://docs.oasis-open.org/ns/xri/xrd-1.0";
+pub const SIGNATURE_XMLNS: &str = "http://www.w3.org/2000/09/xmldsig#";
+
+#[derive(Debug, Clone)]
+pub struct XRD {
+ pub id: Option<String>,
+ pub expires: Option<Expires>,
+ pub subject: Option<Subject>,
+ pub aliases: Vec<Alias>,
+ pub properties: Vec<Property>,
+ pub links: Vec<Link>,
+ pub signature: Vec<Signature>,
+}
+
+impl FromElement for XRD {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("XRD")?;
+ element.check_namespace(XMLNS)?;
+
+ let id = element.attribute_opt_namespaced("id", XML_NS)?;
+
+ let expires = element.child_opt()?;
+ let subject = element.child_opt()?;
+ let aliases = element.children()?;
+ let properties = element.children()?;
+ let links = element.children()?;
+ let signature = element.children()?;
+
+ Ok(Self {
+ id,
+ expires,
+ subject,
+ aliases,
+ properties,
+ links,
+ signature,
+ })
+ }
+}
+
+impl IntoElement for XRD {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("XRD", Some(XMLNS))
+ .push_attribute_opt_namespaced(XML_NS, "id", self.id.clone())
+ .push_child_opt(self.expires.clone())
+ .push_child_opt(self.subject.clone())
+ .push_children(self.aliases.clone())
+ .push_children(self.properties.clone())
+ .push_children(self.links.clone())
+ .push_children(self.signature.clone())
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct Expires(pub DateTime<Utc>);
+
+impl FromElement for Expires {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("Expires")?;
+ element.check_namespace(XMLNS)?;
+
+ Ok(Self(element.pop_value()?))
+ }
+}
+
+impl IntoElement for Expires {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("Expires", Some(XMLNS))
+ .push_text(self.0.format("%C%y-%m-%dT%H:%M:%S%.3f%:z"))
+ }
+}
+
+// anyURI
+#[derive(Debug, Clone)]
+pub struct Subject(pub String);
+
+impl FromElement for Subject {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("Subject")?;
+ element.check_namespace(XMLNS)?;
+
+ Ok(Self(element.pop_value()?))
+ }
+}
+
+impl IntoElement for Subject {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("Subject", Some(XMLNS)).push_text(self.0.clone())
+ }
+}
+
+// anyURI
+#[derive(Debug, Clone)]
+pub struct Alias(pub String);
+
+impl FromElement for Alias {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("Alias")?;
+ element.check_namespace(XMLNS)?;
+
+ Ok(Self(element.pop_value()?))
+ }
+}
+
+impl IntoElement for Alias {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("Alias", Some(XMLNS)).push_text(self.0.clone())
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct Property {
+ pub r#type: String,
+ pub property: Option<String>,
+}
+
+impl FromElement for Property {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("Property")?;
+ element.check_name(XMLNS)?;
+
+ let r#type = element.attribute("type")?;
+
+ let property = element.pop_value_opt()?;
+
+ Ok(Self { r#type, property })
+ }
+}
+
+impl IntoElement for Property {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("Property", Some(XMLNS))
+ .push_attribute("type", self.r#type.clone())
+ .push_text_opt(self.property.clone())
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct Link {
+ pub rel: Option<String>,
+ pub r#type: Option<String>,
+ pub href: Option<String>,
+ pub template: Option<String>,
+ pub titles: Vec<Title>,
+ pub properties: Vec<Property>,
+}
+
+impl FromElement for Link {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("Link")?;
+ element.check_namespace(XMLNS)?;
+
+ let rel = element.attribute_opt("rel")?;
+ let r#type = element.attribute_opt("type")?;
+ let href = element.attribute_opt("href")?;
+ let template = element.attribute_opt("template")?;
+
+ let titles = element.children()?;
+ let properties = element.children()?;
+
+ Ok(Self {
+ rel,
+ r#type,
+ href,
+ template,
+ titles,
+ properties,
+ })
+ }
+}
+
+impl IntoElement for Link {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("Link", Some(XMLNS))
+ .push_attribute_opt("rel", self.rel.clone())
+ .push_attribute_opt("type", self.r#type.clone())
+ .push_attribute_opt("href", self.href.clone())
+ .push_attribute_opt("template", self.template.clone())
+ .push_children(self.titles.clone())
+ .push_children(self.properties.clone())
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct Title {
+ pub lang: Option<String>,
+ pub title: String,
+}
+
+impl FromElement for Title {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("Title")?;
+ element.check_namespace(XMLNS)?;
+
+ let lang = element.attribute_opt_namespaced("lang", XML_NS)?;
+
+ let title = element.pop_value_opt()?.unwrap_or_default();
+
+ Ok(Self { lang, title })
+ }
+}
+
+impl IntoElement for Title {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("Title", Some(XMLNS))
+ .push_attribute_opt_namespaced(XML_NS, "lang", self.lang.clone())
+ .push_text(self.title.clone())
+ }
+}
+
+#[derive(Debug, Clone, Copy)]
+pub struct Signature;
+
+impl FromElement for Signature {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("Signature")?;
+ element.check_namespace(SIGNATURE_XMLNS)?;
+
+ Ok(Self)
+ }
+}
+
+impl IntoElement for Signature {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("Signature", Some(SIGNATURE_XMLNS))
+ }
+}
diff --git a/stanza/src/xep_0172.rs b/stanza/src/xep_0172.rs
index 1c24200..8374bab 100644
--- a/stanza/src/xep_0172.rs
+++ b/stanza/src/xep_0172.rs
@@ -1,7 +1,8 @@
-use peanuts::{
- element::{FromElement, IntoElement},
- Element,
-};
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use peanuts::{Element, FromElement, IntoElement};
pub const XMLNS: &str = "http://jabber.org/protocol/nick";
@@ -9,7 +10,7 @@ pub const XMLNS: &str = "http://jabber.org/protocol/nick";
pub struct Nick(pub String);
impl FromElement for Nick {
- fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("nick")?;
element.check_namespace(XMLNS)?;
@@ -18,7 +19,7 @@ impl FromElement for Nick {
}
impl IntoElement for Nick {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
let builder = Element::builder("nick", Some(XMLNS));
if self.0.is_empty() {
diff --git a/stanza/src/xep_0199.rs b/stanza/src/xep_0199.rs
index 9605721..17e9fd4 100644
--- a/stanza/src/xep_0199.rs
+++ b/stanza/src/xep_0199.rs
@@ -1,7 +1,8 @@
-use peanuts::{
- element::{FromElement, IntoElement},
- Element,
-};
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use peanuts::{Element, FromElement, IntoElement};
pub const XMLNS: &str = "urn:xmpp:ping";
@@ -9,7 +10,7 @@ pub const XMLNS: &str = "urn:xmpp:ping";
pub struct Ping;
impl FromElement for Ping {
- fn from_element(element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
element.check_name("ping")?;
element.check_namespace(XMLNS)?;
@@ -20,7 +21,7 @@ impl FromElement for Ping {
}
impl IntoElement for Ping {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("ping", Some(XMLNS))
}
}
diff --git a/stanza/src/xep_0203.rs b/stanza/src/xep_0203.rs
index b8f9239..0f4b298 100644
--- a/stanza/src/xep_0203.rs
+++ b/stanza/src/xep_0203.rs
@@ -1,9 +1,10 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use chrono::{DateTime, Utc};
use jid::JID;
-use peanuts::{
- element::{FromElement, IntoElement},
- Element,
-};
+use peanuts::{Element, FromElement, IntoElement};
pub const XMLNS: &str = "urn:xmpp:delay";
@@ -14,7 +15,7 @@ pub struct Delay {
}
impl FromElement for Delay {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("delay")?;
element.check_namespace(XMLNS)?;
@@ -26,7 +27,7 @@ impl FromElement for Delay {
}
impl IntoElement for Delay {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("delay", Some(XMLNS))
.push_attribute_opt("from", self.from.clone())
.push_attribute("stamp", self.stamp.format("%C%y-%m-%dT%H:%M:%S%.3f%:z"))
diff --git a/stanza/src/xep_0280.rs b/stanza/src/xep_0280.rs
new file mode 100644
index 0000000..74d2897
--- /dev/null
+++ b/stanza/src/xep_0280.rs
@@ -0,0 +1,113 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use peanuts::{Element, FromElement, IntoElement};
+
+use crate::xep_0297::Forwarded;
+
+pub const XMLNS: &str = "urn:xmpp:carbons:2";
+
+#[derive(Clone, Debug)]
+pub struct Disable;
+
+impl FromElement for Disable {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("disable")?;
+ element.check_namespace(XMLNS)?;
+
+ element.no_more_content()?;
+
+ Ok(Self)
+ }
+}
+
+impl IntoElement for Disable {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("disable", Some(XMLNS))
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct Enable;
+
+impl FromElement for Enable {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("enable")?;
+ element.check_namespace(XMLNS)?;
+
+ element.no_more_content()?;
+
+ Ok(Self)
+ }
+}
+
+impl IntoElement for Enable {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("enable", Some(XMLNS))
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct Private;
+
+impl FromElement for Private {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("private")?;
+ element.check_namespace(XMLNS)?;
+
+ element.no_more_content()?;
+
+ Ok(Self)
+ }
+}
+
+impl IntoElement for Private {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("private", Some(XMLNS))
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct Received {
+ forwarded: Forwarded,
+}
+
+impl FromElement for Received {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("received")?;
+ element.check_namespace(XMLNS)?;
+
+ let forwarded = element.pop_child_one()?;
+
+ Ok(Self { forwarded })
+ }
+}
+
+impl IntoElement for Received {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("received", Some(XMLNS)).push_child(self.forwarded.clone())
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct Sent {
+ forwarded: Forwarded,
+}
+
+impl FromElement for Sent {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("sent")?;
+ element.check_namespace(XMLNS)?;
+
+ let forwarded = element.pop_child_one()?;
+
+ Ok(Self { forwarded })
+ }
+}
+
+impl IntoElement for Sent {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("sent", Some(XMLNS)).push_child(self.forwarded.clone())
+ }
+}
diff --git a/stanza/src/xep_0297.rs b/stanza/src/xep_0297.rs
new file mode 100644
index 0000000..d686e49
--- /dev/null
+++ b/stanza/src/xep_0297.rs
@@ -0,0 +1,79 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use peanuts::{Element, FromElement, IntoElement};
+
+use crate::{
+ client::{self, iq::Iq, message::Message, presence::Presence},
+ xep_0203::Delay,
+};
+
+pub const XMLNS: &str = "urn:xmpp:forward:0";
+
+#[derive(Clone, Debug)]
+pub struct Forwarded {
+ delay: Option<Delay>,
+ stanza: Option<Box<Stanza>>,
+}
+
+// TODO: raw stanza source option
+pub enum ForwardedStanza {
+ Parsed(Box<Stanza>),
+ Raw(String),
+}
+
+impl FromElement for Forwarded {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("forwarded")?;
+ element.check_namespace(XMLNS)?;
+
+ let delay = element.pop_child_opt()?;
+ let stanza = element.pop_child_opt()?;
+ let stanza = stanza.map(|stanza| Box::new(stanza));
+
+ Ok(Self { delay, stanza })
+ }
+}
+
+impl IntoElement for Forwarded {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("forwarded", Some(XMLNS))
+ .push_child_opt(self.delay.clone())
+ .push_child_opt(self.stanza.clone().map(|stanza| *stanza))
+ }
+}
+
+#[derive(Clone, Debug)]
+pub enum Stanza {
+ Message(Message),
+ Presence(Presence),
+ Iq(Iq),
+ // TODO: raw elements are received with reads.
+ // Raw(Element),
+}
+
+impl FromElement for Stanza {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
+ match element.identify() {
+ (Some(client::XMLNS), "message") => {
+ Ok(Stanza::Message(Message::from_element(element)?))
+ }
+ (Some(client::XMLNS), "presence") => {
+ Ok(Stanza::Presence(Presence::from_element(element)?))
+ }
+ (Some(client::XMLNS), "iq") => Ok(Stanza::Iq(Iq::from_element(element)?)),
+ _ => Err(peanuts::DeserializeError::UnexpectedElement(element)),
+ }
+ }
+}
+
+impl IntoElement for Stanza {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ match self {
+ Stanza::Message(message) => message.builder(),
+ Stanza::Presence(presence) => presence.builder(),
+ Stanza::Iq(iq) => iq.builder(),
+ }
+ }
+}
diff --git a/stanza/src/xep_0300.rs b/stanza/src/xep_0300.rs
index 71a2c36..5a2a88b 100644
--- a/stanza/src/xep_0300.rs
+++ b/stanza/src/xep_0300.rs
@@ -1,9 +1,10 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use std::{convert::Infallible, str::FromStr};
-use peanuts::{
- element::{FromElement, IntoElement},
- Element,
-};
+use peanuts::{Element, FromElement, IntoElement};
pub const XMLNS: &str = "urn:xmpp:hashes:2";
@@ -14,7 +15,7 @@ pub struct Hash {
}
impl FromElement for Hash {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("hash")?;
element.check_namespace(XMLNS)?;
@@ -27,7 +28,7 @@ impl FromElement for Hash {
}
impl IntoElement for Hash {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
let builder =
Element::builder("hash", Some(XMLNS)).push_attribute("algo", self.algo.clone());
@@ -46,7 +47,7 @@ pub struct HashUsed {
}
impl FromElement for HashUsed {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("hash-used")?;
element.check_namespace(XMLNS)?;
@@ -57,7 +58,7 @@ impl FromElement for HashUsed {
}
impl IntoElement for HashUsed {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("hash-used", Some(XMLNS)).push_attribute("algo", self.algo.clone())
}
}
diff --git a/stanza/src/xep_0334.rs b/stanza/src/xep_0334.rs
new file mode 100644
index 0000000..a13e125
--- /dev/null
+++ b/stanza/src/xep_0334.rs
@@ -0,0 +1,87 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
+use peanuts::{Element, FromElement, IntoElement};
+
+pub const XMLNS: &str = "urn:xmpp:hints";
+
+#[derive(Clone, Copy, Debug)]
+pub struct NoPermanentStore;
+
+impl FromElement for NoPermanentStore {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("no-permanent-store")?;
+ element.check_namespace(XMLNS)?;
+
+ element.no_more_content()?;
+
+ Ok(Self)
+ }
+}
+
+impl IntoElement for NoPermanentStore {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("no-permanent-store", Some(XMLNS))
+ }
+}
+
+#[derive(Clone, Copy, Debug)]
+pub struct NoStore;
+
+impl FromElement for NoStore {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("no-store")?;
+ element.check_namespace(XMLNS)?;
+
+ element.no_more_content()?;
+
+ Ok(Self)
+ }
+}
+
+impl IntoElement for NoStore {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("no-store", Some(XMLNS))
+ }
+}
+
+#[derive(Clone, Copy, Debug)]
+pub struct NoCopy;
+
+impl FromElement for NoCopy {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("no-copy")?;
+ element.check_namespace(XMLNS)?;
+
+ element.no_more_content()?;
+
+ Ok(Self)
+ }
+}
+
+impl IntoElement for NoCopy {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("no-copy", Some(XMLNS))
+ }
+}
+
+#[derive(Clone, Copy, Debug)]
+pub struct Store;
+
+impl FromElement for Store {
+ fn from_element(element: Element) -> peanuts::DeserializeResult<Self> {
+ element.check_name("store")?;
+ element.check_namespace(XMLNS)?;
+
+ element.no_more_content()?;
+
+ Ok(Self)
+ }
+}
+
+impl IntoElement for Store {
+ fn builder(&self) -> peanuts::ElementBuilder {
+ Element::builder("store", Some(XMLNS))
+ }
+}
diff --git a/stanza/src/xep_0390.rs b/stanza/src/xep_0390.rs
index bcd331d..248ff9a 100644
--- a/stanza/src/xep_0390.rs
+++ b/stanza/src/xep_0390.rs
@@ -1,8 +1,9 @@
+// SPDX-FileCopyrightText: 2025 cel <cel@bunny.garden>
+//
+// SPDX-License-Identifier: AGPL-3.0-or-later
+
use crate::xep_0300::Hash;
-use peanuts::{
- element::{FromElement, IntoElement},
- Element,
-};
+use peanuts::{Element, FromElement, IntoElement};
pub const XMLNS: &str = "urn:xmpp:caps";
@@ -11,7 +12,7 @@ pub const XMLNS: &str = "urn:xmpp:caps";
pub struct C(pub Vec<Hash>);
impl FromElement for C {
- fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ fn from_element(mut element: Element) -> peanuts::DeserializeResult<Self> {
element.check_name("c")?;
element.check_namespace(XMLNS)?;
@@ -20,7 +21,7 @@ impl FromElement for C {
}
impl IntoElement for C {
- fn builder(&self) -> peanuts::element::ElementBuilder {
+ fn builder(&self) -> peanuts::ElementBuilder {
Element::builder("c", Some(XMLNS)).push_children(self.0.clone())
}
}