aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar cel 🌸 <cel@bunny.garden>2025-04-01 21:40:23 +0100
committerLibravatar cel 🌸 <cel@bunny.garden>2025-04-01 21:40:23 +0100
commit9ce3827a7d25714d17f266f0f50bb29f41090175 (patch)
treeb34f4d9c947cf7bc21e90f1a6723fd58801e8e8f
parent448208337c3a404403e6b312dbe38555a2bf8ad5 (diff)
downloadluz-9ce3827a7d25714d17f266f0f50bb29f41090175.tar.gz
luz-9ce3827a7d25714d17f266f0f50bb29f41090175.tar.bz2
luz-9ce3827a7d25714d17f266f0f50bb29f41090175.zip
feat(stanza): xep-0131: stanza headers
-rw-r--r--stanza/Cargo.toml1
-rw-r--r--stanza/src/client/message.rs12
-rw-r--r--stanza/src/client/presence.rs12
-rw-r--r--stanza/src/lib.rs2
-rw-r--r--stanza/src/xep_0131.rs56
5 files changed, 83 insertions, 0 deletions
diff --git a/stanza/Cargo.toml b/stanza/Cargo.toml
index ad3bd0b..64962b6 100644
--- a/stanza/Cargo.toml
+++ b/stanza/Cargo.toml
@@ -15,5 +15,6 @@ xep_0004 = []
xep_0030 = []
xep_0059 = []
xep_0060 = ["xep_0004", "dep:chrono"]
+xep_0131 = []
xep_0199 = []
xep_0203 = ["dep:chrono"]
diff --git a/stanza/src/client/message.rs b/stanza/src/client/message.rs
index 192390b..e521613 100644
--- a/stanza/src/client/message.rs
+++ b/stanza/src/client/message.rs
@@ -6,6 +6,8 @@ use peanuts::{
DeserializeError, Element, XML_NS,
};
+#[cfg(feature = "xep_0131")]
+use crate::xep_0131::Headers;
#[cfg(feature = "xep_0203")]
use crate::xep_0203::Delay;
@@ -25,6 +27,8 @@ pub struct Message {
pub thread: Option<Thread>,
#[cfg(feature = "xep_0203")]
pub delay: Option<Delay>,
+ #[cfg(feature = "xep_0131")]
+ pub headers: Option<Headers>,
}
impl FromElement for Message {
@@ -45,6 +49,9 @@ impl FromElement for Message {
#[cfg(feature = "xep_0203")]
let delay = element.child_opt()?;
+ #[cfg(feature = "xep_0131")]
+ let headers = element.child_opt()?;
+
Ok(Message {
from,
id,
@@ -56,6 +63,8 @@ impl FromElement for Message {
thread,
#[cfg(feature = "xep_0203")]
delay,
+ #[cfg(feature = "xep_0131")]
+ headers,
})
}
}
@@ -81,6 +90,9 @@ impl IntoElement for Message {
#[cfg(feature = "xep_0203")]
let builder = builder.push_child_opt(self.delay.clone());
+ #[cfg(feature = "xep_0131")]
+ let builder = builder.push_child_opt(self.headers.clone());
+
builder
}
}
diff --git a/stanza/src/client/presence.rs b/stanza/src/client/presence.rs
index ae38756..8fb96be 100644
--- a/stanza/src/client/presence.rs
+++ b/stanza/src/client/presence.rs
@@ -6,6 +6,8 @@ use peanuts::{
DeserializeError, Element, XML_NS,
};
+#[cfg(feature = "xep_0131")]
+use crate::xep_0131::Headers;
#[cfg(feature = "xep_0203")]
use crate::xep_0203::Delay;
@@ -24,6 +26,8 @@ pub struct Presence {
pub priority: Option<Priority>,
#[cfg(feature = "xep_0203")]
pub delay: Option<Delay>,
+ #[cfg(feature = "xep_0131")]
+ pub headers: Option<Headers>,
// TODO: ##other
// other: Vec<Other>,
pub errors: Vec<Error>,
@@ -48,6 +52,9 @@ impl FromElement for Presence {
#[cfg(feature = "xep_0203")]
let delay = element.child_opt()?;
+ #[cfg(feature = "xep_0131")]
+ let headers = element.child_opt()?;
+
Ok(Presence {
from,
id,
@@ -60,6 +67,8 @@ impl FromElement for Presence {
errors,
#[cfg(feature = "xep_0203")]
delay,
+ #[cfg(feature = "xep_0131")]
+ headers,
})
}
}
@@ -80,6 +89,9 @@ impl IntoElement for Presence {
#[cfg(feature = "xep_0203")]
let builder = builder.push_child_opt(self.delay.clone());
+ #[cfg(feature = "xep_0131")]
+ let builder = builder.push_child_opt(self.headers.clone());
+
builder
}
}
diff --git a/stanza/src/lib.rs b/stanza/src/lib.rs
index 0bae7f7..0a71a26 100644
--- a/stanza/src/lib.rs
+++ b/stanza/src/lib.rs
@@ -17,6 +17,8 @@ pub mod xep_0030;
pub mod xep_0059;
#[cfg(feature = "xep_0060")]
pub mod xep_0060;
+#[cfg(feature = "xep_0131")]
+pub mod xep_0131;
#[cfg(feature = "xep_0199")]
pub mod xep_0199;
#[cfg(feature = "xep_0203")]
diff --git a/stanza/src/xep_0131.rs b/stanza/src/xep_0131.rs
new file mode 100644
index 0000000..27fc962
--- /dev/null
+++ b/stanza/src/xep_0131.rs
@@ -0,0 +1,56 @@
+use peanuts::{
+ element::{FromElement, IntoElement},
+ Element,
+};
+
+pub const XMLNS: &str = "http://jabber.org/protocol/disco#info";
+
+#[derive(Clone, Debug)]
+pub struct Headers(pub Vec<Header>);
+
+impl FromElement for Headers {
+ fn from_element(mut element: Element) -> peanuts::element::DeserializeResult<Self> {
+ element.check_name("headers")?;
+ element.check_namespace(XMLNS)?;
+
+ Ok(Self(element.pop_children()?))
+ }
+}
+
+impl IntoElement for Headers {
+ fn builder(&self) -> peanuts::element::ElementBuilder {
+ Element::builder("headers", Some(XMLNS)).push_children(self.0.clone())
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct Header {
+ name: String,
+ header: String,
+}
+
+impl FromElement for Header {
+ fn from_element(mut element: peanuts::Element) -> peanuts::element::DeserializeResult<Self> {
+ element.check_name("header")?;
+ element.check_namespace(XMLNS)?;
+
+ let name = element.attribute("name")?;
+
+ let header = element.pop_value_opt()?.unwrap_or_default();
+
+ Ok(Self { name, header })
+ }
+}
+
+impl IntoElement for Header {
+ fn builder(&self) -> peanuts::element::ElementBuilder {
+ let builder =
+ Element::builder("header", Some(XMLNS)).push_attribute("name", self.name.clone());
+
+ if self.header.is_empty() {
+ builder
+ } else {
+ builder.push_text(self.header.clone())
+ }
+ }
+}