Compare commits
No commits in common. "668270429f9b59f71c21daa7f92a28d422503bb7" and "35f164cdb6324c6dfb635f8de93a8221861a5991" have entirely different histories.
668270429f
...
35f164cdb6
|
@ -7,48 +7,81 @@ use peanuts::{
|
||||||
|
|
||||||
pub const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-tls";
|
pub const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-tls";
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub struct StartTls {
|
pub struct StartTls {
|
||||||
pub required: bool,
|
pub required: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoElement for StartTls {
|
impl IntoElement for StartTls {
|
||||||
fn builder(&self) -> peanuts::element::ElementBuilder {
|
fn into_element(&self) -> peanuts::Element {
|
||||||
let mut builder = Element::builder("starttls", Some(XMLNS));
|
let content;
|
||||||
|
if self.required == true {
|
||||||
if self.required {
|
let element = Content::Element(Element {
|
||||||
builder = builder.push_child(Element::builder("required", Some(XMLNS)))
|
name: Name {
|
||||||
|
namespace: Some(XMLNS.to_string()),
|
||||||
|
local_name: "required".to_string(),
|
||||||
|
},
|
||||||
|
namespace_declarations: HashSet::new(),
|
||||||
|
attributes: HashMap::new(),
|
||||||
|
content: Vec::new(),
|
||||||
|
});
|
||||||
|
content = vec![element];
|
||||||
|
} else {
|
||||||
|
content = Vec::new();
|
||||||
|
}
|
||||||
|
let mut namespace_declarations = HashSet::new();
|
||||||
|
namespace_declarations.insert(NamespaceDeclaration {
|
||||||
|
prefix: None,
|
||||||
|
namespace: XMLNS.to_string(),
|
||||||
|
});
|
||||||
|
Element {
|
||||||
|
name: Name {
|
||||||
|
namespace: Some(XMLNS.to_string()),
|
||||||
|
local_name: "starttls".to_string(),
|
||||||
|
},
|
||||||
|
namespace_declarations,
|
||||||
|
attributes: HashMap::new(),
|
||||||
|
content,
|
||||||
}
|
}
|
||||||
|
|
||||||
builder
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromElement for StartTls {
|
impl FromElement for StartTls {
|
||||||
fn from_element(
|
fn from_element(element: peanuts::Element) -> peanuts::Result<Self> {
|
||||||
mut element: peanuts::Element,
|
let Name {
|
||||||
) -> std::result::Result<StartTls, peanuts::DeserializeError> {
|
namespace,
|
||||||
element.check_name("starttls")?;
|
local_name,
|
||||||
element.check_namespace(XMLNS)?;
|
} = element.name;
|
||||||
|
if namespace.as_deref() == Some(XMLNS) && &local_name == "starttls" {
|
||||||
let mut required = false;
|
let mut required = false;
|
||||||
if let Some(_) = element.child_opt::<Required>()? {
|
if element.content.len() == 1 {
|
||||||
required = true;
|
match element.content.first().unwrap() {
|
||||||
}
|
Content::Element(element) => {
|
||||||
|
let Name {
|
||||||
|
namespace,
|
||||||
|
local_name,
|
||||||
|
} = &element.name;
|
||||||
|
|
||||||
Ok(StartTls { required })
|
if namespace.as_deref() == Some(XMLNS) && local_name == "required" {
|
||||||
|
required = true
|
||||||
|
} else {
|
||||||
|
return Err(peanuts::Error::UnexpectedElement(element.name.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
c => return Err(peanuts::Error::UnexpectedContent((*c).clone())),
|
||||||
#[derive(Debug)]
|
}
|
||||||
pub struct Required;
|
} else {
|
||||||
|
return Err(peanuts::Error::UnexpectedNumberOfContents(
|
||||||
impl FromElement for Required {
|
element.content.len(),
|
||||||
fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> {
|
));
|
||||||
element.check_name("required")?;
|
}
|
||||||
element.check_namespace(XMLNS)?;
|
return Ok(StartTls { required });
|
||||||
|
} else {
|
||||||
Ok(Required)
|
return Err(peanuts::Error::IncorrectName(Name {
|
||||||
|
namespace,
|
||||||
|
local_name,
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,33 +89,75 @@ impl FromElement for Required {
|
||||||
pub struct Proceed;
|
pub struct Proceed;
|
||||||
|
|
||||||
impl IntoElement for Proceed {
|
impl IntoElement for Proceed {
|
||||||
fn builder(&self) -> peanuts::element::ElementBuilder {
|
fn into_element(&self) -> Element {
|
||||||
Element::builder("proceed", Some(XMLNS))
|
let mut namespace_declarations = HashSet::new();
|
||||||
|
namespace_declarations.insert(NamespaceDeclaration {
|
||||||
|
prefix: None,
|
||||||
|
namespace: XMLNS.to_string(),
|
||||||
|
});
|
||||||
|
Element {
|
||||||
|
name: Name {
|
||||||
|
namespace: Some(XMLNS.to_string()),
|
||||||
|
local_name: "proceed".to_string(),
|
||||||
|
},
|
||||||
|
namespace_declarations,
|
||||||
|
attributes: HashMap::new(),
|
||||||
|
content: Vec::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromElement for Proceed {
|
impl FromElement for Proceed {
|
||||||
fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> {
|
fn from_element(element: Element) -> peanuts::Result<Self> {
|
||||||
element.check_name("proceed")?;
|
let Name {
|
||||||
element.check_namespace(XMLNS)?;
|
namespace,
|
||||||
|
local_name,
|
||||||
Ok(Proceed)
|
} = element.name;
|
||||||
|
if namespace.as_deref() == Some(XMLNS) && &local_name == "proceed" {
|
||||||
|
return Ok(Proceed);
|
||||||
|
} else {
|
||||||
|
return Err(peanuts::Error::IncorrectName(Name {
|
||||||
|
namespace,
|
||||||
|
local_name,
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Failure;
|
pub struct Failure;
|
||||||
|
|
||||||
impl IntoElement for Failure {
|
impl IntoElement for Failure {
|
||||||
fn builder(&self) -> peanuts::element::ElementBuilder {
|
fn into_element(&self) -> Element {
|
||||||
Element::builder("failure", Some(XMLNS))
|
let mut namespace_declarations = HashSet::new();
|
||||||
|
namespace_declarations.insert(NamespaceDeclaration {
|
||||||
|
prefix: None,
|
||||||
|
namespace: XMLNS.to_string(),
|
||||||
|
});
|
||||||
|
Element {
|
||||||
|
name: Name {
|
||||||
|
namespace: Some(XMLNS.to_string()),
|
||||||
|
local_name: "failure".to_string(),
|
||||||
|
},
|
||||||
|
namespace_declarations,
|
||||||
|
attributes: HashMap::new(),
|
||||||
|
content: Vec::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromElement for Failure {
|
impl FromElement for Failure {
|
||||||
fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> {
|
fn from_element(element: Element) -> peanuts::Result<Self> {
|
||||||
element.check_name("failure")?;
|
let Name {
|
||||||
element.check_namespace(XMLNS)?;
|
namespace,
|
||||||
|
local_name,
|
||||||
Ok(Failure)
|
} = element.name;
|
||||||
|
if namespace.as_deref() == Some(XMLNS) && &local_name == "failure" {
|
||||||
|
return Ok(Failure);
|
||||||
|
} else {
|
||||||
|
return Err(peanuts::Error::IncorrectName(Name {
|
||||||
|
namespace,
|
||||||
|
local_name,
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use peanuts::element::{Content, ElementBuilder, FromElement, IntoElement, NamespaceDeclaration};
|
use peanuts::element::{Content, FromElement, IntoElement, NamespaceDeclaration};
|
||||||
use peanuts::XML_NS;
|
use peanuts::XML_NS;
|
||||||
use peanuts::{element::Name, Element};
|
use peanuts::{element::Name, Element};
|
||||||
|
|
||||||
use crate::{Error, JID};
|
use crate::{Error, JID};
|
||||||
|
|
||||||
use super::starttls::{self, StartTls};
|
use super::starttls::StartTls;
|
||||||
|
|
||||||
pub const XMLNS: &str = "http://etherx.jabber.org/streams";
|
pub const XMLNS: &str = "http://etherx.jabber.org/streams";
|
||||||
pub const XMLNS_CLIENT: &str = "jabber:client";
|
pub const XMLNS_CLIENT: &str = "jabber:client";
|
||||||
|
@ -27,36 +27,108 @@ pub struct Stream {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromElement for Stream {
|
impl FromElement for Stream {
|
||||||
fn from_element(mut element: Element) -> std::result::Result<Self, peanuts::DeserializeError> {
|
fn from_element(element: Element) -> peanuts::Result<Self> {
|
||||||
element.check_namespace(XMLNS)?;
|
let Name {
|
||||||
element.check_name("stream")?;
|
namespace,
|
||||||
|
local_name,
|
||||||
let from = element.attribute_opt("from")?;
|
} = element.name;
|
||||||
let to = element.attribute_opt("to")?;
|
if namespace.as_deref() == Some(XMLNS) && &local_name == "stream" {
|
||||||
let id = element.attribute_opt("id")?;
|
let (mut from, mut to, mut id, mut version, mut lang) = (None, None, None, None, None);
|
||||||
let version = element.attribute_opt("version")?;
|
for (name, value) in element.attributes {
|
||||||
let lang = element.attribute_opt_namespaced("lang", peanuts::XML_NS)?;
|
match (name.namespace.as_deref(), name.local_name.as_str()) {
|
||||||
|
(None, "from") => from = Some(value.try_into()?),
|
||||||
Ok(Stream {
|
(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,
|
from,
|
||||||
to,
|
to,
|
||||||
id,
|
id,
|
||||||
version,
|
version,
|
||||||
lang,
|
lang,
|
||||||
})
|
});
|
||||||
|
} else {
|
||||||
|
return Err(peanuts::Error::IncorrectName(Name {
|
||||||
|
namespace,
|
||||||
|
local_name,
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoElement for Stream {
|
impl IntoElement for Stream {
|
||||||
fn builder(&self) -> ElementBuilder {
|
fn into_element(&self) -> Element {
|
||||||
Element::builder("stream", Some(XMLNS.to_string()))
|
let mut namespace_declarations = HashSet::new();
|
||||||
.push_namespace_declaration_override(Some("stream"), XMLNS)
|
namespace_declarations.insert(NamespaceDeclaration {
|
||||||
.push_namespace_declaration_override(None::<&str>, XMLNS_CLIENT)
|
prefix: Some("stream".to_string()),
|
||||||
.push_attribute_opt("to", self.to.clone())
|
namespace: XMLNS.to_string(),
|
||||||
.push_attribute_opt("from", self.from.clone())
|
});
|
||||||
.push_attribute_opt("id", self.id.clone())
|
namespace_declarations.insert(NamespaceDeclaration {
|
||||||
.push_attribute_opt("version", self.version.clone())
|
prefix: None,
|
||||||
.push_attribute_opt_namespaced(peanuts::XML_NS, "to", self.lang.clone())
|
// 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: "id".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(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,70 +168,64 @@ pub struct Features {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoElement for Features {
|
impl IntoElement for Features {
|
||||||
fn builder(&self) -> ElementBuilder {
|
fn into_element(&self) -> Element {
|
||||||
Element::builder("features", Some(XMLNS)).push_children(self.features.clone())
|
let mut content = Vec::new();
|
||||||
// let mut content = Vec::new();
|
for feature in &self.features {
|
||||||
// for feature in &self.features {
|
match feature {
|
||||||
// match feature {
|
Feature::StartTls(start_tls) => {
|
||||||
// Feature::StartTls(start_tls) => {
|
content.push(Content::Element(start_tls.into_element()))
|
||||||
// content.push(Content::Element(start_tls.into_element()))
|
}
|
||||||
// }
|
Feature::Sasl => {}
|
||||||
// Feature::Sasl => {}
|
Feature::Bind => {}
|
||||||
// Feature::Bind => {}
|
Feature::Unknown => {}
|
||||||
// Feature::Unknown => {}
|
}
|
||||||
// }
|
}
|
||||||
// }
|
Element {
|
||||||
// Element {
|
name: Name {
|
||||||
// name: Name {
|
namespace: Some(XMLNS.to_string()),
|
||||||
// namespace: Some(XMLNS.to_string()),
|
local_name: "features".to_string(),
|
||||||
// local_name: "features".to_string(),
|
},
|
||||||
// },
|
namespace_declarations: HashSet::new(),
|
||||||
// namespace_declaration_overrides: HashSet::new(),
|
attributes: HashMap::new(),
|
||||||
// attributes: HashMap::new(),
|
content,
|
||||||
// content,
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromElement for Features {
|
impl FromElement for Features {
|
||||||
fn from_element(
|
fn from_element(element: Element) -> peanuts::Result<Self> {
|
||||||
mut element: Element,
|
let Name {
|
||||||
) -> std::result::Result<Features, peanuts::DeserializeError> {
|
namespace,
|
||||||
element.check_namespace(XMLNS)?;
|
local_name,
|
||||||
element.check_name("features")?;
|
} = element.name;
|
||||||
|
if namespace.as_deref() == Some(XMLNS) && &local_name == "features" {
|
||||||
let features = element.children()?;
|
let mut features = Vec::new();
|
||||||
|
for feature in element.content {
|
||||||
Ok(Features { features })
|
match feature {
|
||||||
|
Content::Element(element) => {
|
||||||
|
if let Ok(start_tls) = FromElement::from_element(element) {
|
||||||
|
features.push(Feature::StartTls(start_tls))
|
||||||
|
} else {
|
||||||
|
features.push(Feature::Unknown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c => return Err(peanuts::Error::UnexpectedContent(c.clone())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(Self { features });
|
||||||
|
} else {
|
||||||
|
return Err(peanuts::Error::IncorrectName(Name {
|
||||||
|
namespace,
|
||||||
|
local_name,
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub enum Feature {
|
pub enum Feature {
|
||||||
StartTls(StartTls),
|
StartTls(StartTls),
|
||||||
Sasl,
|
Sasl,
|
||||||
Bind,
|
Bind,
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoElement for Feature {
|
|
||||||
fn builder(&self) -> ElementBuilder {
|
|
||||||
match self {
|
|
||||||
Feature::StartTls(start_tls) => start_tls.builder(),
|
|
||||||
Feature::Sasl => todo!(),
|
|
||||||
Feature::Bind => todo!(),
|
|
||||||
Feature::Unknown => todo!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromElement for Feature {
|
|
||||||
fn from_element(element: Element) -> peanuts::element::DeserializeResult<Self> {
|
|
||||||
match element.identify() {
|
|
||||||
(Some(starttls::XMLNS), "starttls") => {
|
|
||||||
Ok(Feature::StartTls(StartTls::from_element(element)?))
|
|
||||||
}
|
|
||||||
_ => Ok(Feature::Unknown),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue