aboutsummaryrefslogtreecommitdiffstats
path: root/src/stanza/stream.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/stanza/stream.rs')
-rw-r--r--src/stanza/stream.rs169
1 files changed, 132 insertions, 37 deletions
diff --git a/src/stanza/stream.rs b/src/stanza/stream.rs
index 9a21373..ac4badc 100644
--- a/src/stanza/stream.rs
+++ b/src/stanza/stream.rs
@@ -1,37 +1,141 @@
-use serde::Serialize;
+use std::collections::{HashMap, HashSet};
-use crate::JID;
+use peanuts::element::{Content, FromElement, IntoElement, NamespaceDeclaration};
+use peanuts::XML_NS;
+use peanuts::{element::Name, Element};
-pub static XMLNS: &str = "http://etherx.jabber.org/streams";
-pub static XMLNS_CLIENT: &str = "jabber:client";
+use crate::{Error, JID};
+
+pub const XMLNS: &str = "http://etherx.jabber.org/streams";
+pub const XMLNS_CLIENT: &str = "jabber:client";
// MUST be qualified by stream namespace
-#[derive(Serialize)]
-pub struct Stream<'s> {
- #[serde(rename = "@from")]
- from: Option<&'s JID>,
- #[serde(rename = "@to")]
- to: Option<&'s JID>,
- #[serde(rename = "@id")]
- id: Option<&'s str>,
- #[serde(rename = "@version")]
- version: Option<&'s str>,
+// #[derive(XmlSerialize, XmlDeserialize)]
+// #[peanuts(xmlns = XMLNS)]
+pub struct Stream {
+ pub from: Option<JID>,
+ to: Option<JID>,
+ id: Option<String>,
+ version: Option<String>,
// TODO: lang enum
- #[serde(rename = "@lang")]
- lang: Option<&'s str>,
- #[serde(rename = "@xmlns")]
- xmlns: &'s str,
- #[serde(rename = "@xmlns:stream")]
- xmlns_stream: &'s str,
+ lang: Option<String>,
+ // #[peanuts(content)]
+ // content: Message,
+}
+
+impl FromElement for Stream {
+ fn from_element(element: Element) -> peanuts::Result<Self> {
+ let Name {
+ namespace,
+ local_name,
+ } = element.name;
+ if namespace.as_deref() == Some(XMLNS) && &local_name == "stream" {
+ let (mut from, mut to, mut id, mut version, mut lang) = (None, None, None, None, None);
+ for (name, value) in element.attributes {
+ match (name.namespace.as_deref(), name.local_name.as_str()) {
+ (None, "from") => from = Some(value.try_into()?),
+ (None, "to") => to = Some(value.try_into()?),
+ (None, "id") => id = Some(value),
+ (None, "version") => version = Some(value),
+ (Some(XML_NS), "lang") => lang = Some(value),
+ _ => return Err(peanuts::Error::UnexpectedAttribute(name)),
+ }
+ }
+ return Ok(Stream {
+ from,
+ to,
+ id,
+ version,
+ lang,
+ });
+ } else {
+ return Err(peanuts::Error::IncorrectName(Name {
+ namespace,
+ local_name,
+ }));
+ }
+ }
+}
+
+impl IntoElement for Stream {
+ fn into_element(&self) -> Element {
+ let mut namespace_declarations = HashSet::new();
+ namespace_declarations.insert(NamespaceDeclaration {
+ prefix: Some("stream".to_string()),
+ namespace: XMLNS.to_string(),
+ });
+ namespace_declarations.insert(NamespaceDeclaration {
+ prefix: None,
+ // TODO: don't default to client
+ namespace: XMLNS_CLIENT.to_string(),
+ });
+
+ let mut attributes = HashMap::new();
+ self.from.as_ref().map(|from| {
+ attributes.insert(
+ Name {
+ namespace: None,
+ local_name: "from".to_string(),
+ },
+ from.to_string(),
+ );
+ });
+ self.to.as_ref().map(|to| {
+ attributes.insert(
+ Name {
+ namespace: None,
+ local_name: "to".to_string(),
+ },
+ to.to_string(),
+ );
+ });
+ self.id.as_ref().map(|id| {
+ attributes.insert(
+ Name {
+ namespace: None,
+ local_name: "version".to_string(),
+ },
+ id.clone(),
+ );
+ });
+ self.version.as_ref().map(|version| {
+ attributes.insert(
+ Name {
+ namespace: None,
+ local_name: "version".to_string(),
+ },
+ version.clone(),
+ );
+ });
+ self.lang.as_ref().map(|lang| {
+ attributes.insert(
+ Name {
+ namespace: Some(XML_NS.to_string()),
+ local_name: "lang".to_string(),
+ },
+ lang.to_string(),
+ );
+ });
+
+ Element {
+ name: Name {
+ namespace: Some(XMLNS.to_string()),
+ local_name: "stream".to_string(),
+ },
+ namespace_declarations,
+ attributes,
+ content: Vec::new(),
+ }
+ }
}
-impl<'s> Stream<'s> {
+impl<'s> Stream {
pub fn new(
- from: Option<&'s JID>,
- to: Option<&'s JID>,
- id: Option<&'s str>,
- version: Option<&'s str>,
- lang: Option<&'s str>,
+ from: Option<JID>,
+ to: Option<JID>,
+ id: Option<String>,
+ version: Option<String>,
+ lang: Option<String>,
) -> Self {
Self {
from,
@@ -39,27 +143,18 @@ impl<'s> Stream<'s> {
id,
version,
lang,
- xmlns: XMLNS_CLIENT,
- xmlns_stream: XMLNS,
}
}
/// 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<&'s JID>,
- to: &'s JID,
- id: Option<&'s str>,
- lang: &'s str,
- ) -> Self {
+ pub fn new_client(from: Option<JID>, to: JID, id: Option<String>, lang: String) -> Self {
Self {
from,
to: Some(to),
id,
- version: Some("1.0"),
+ version: Some("1.0".to_string()),
lang: Some(lang),
- xmlns: XMLNS_CLIENT,
- xmlns_stream: XMLNS,
}
}
}