From f37b7b4dfd890454791a4cc977727b26cd6adf96 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Sun, 4 Aug 2024 21:06:45 +0200 Subject: [PATCH] xmpp-parsers: Convert bind to xso --- parsers/src/bind.rs | 101 ++++++++------------------------------------ 1 file changed, 18 insertions(+), 83 deletions(-) diff --git a/parsers/src/bind.rs b/parsers/src/bind.rs index 8b44d0ae..27f79af1 100644 --- a/parsers/src/bind.rs +++ b/parsers/src/bind.rs @@ -4,23 +4,24 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. +use xso::{AsXml, FromXml}; + use crate::iq::{IqResultPayload, IqSetPayload}; use crate::ns; use jid::{FullJid, Jid}; -use minidom::Element; -use std::str::FromStr; -use xso::error::{Error, FromElementError}; /// The request for resource binding, which is the process by which a client /// can obtain a full JID and start exchanging on the XMPP network. /// /// See -#[derive(Debug, Clone, PartialEq)] +#[derive(FromXml, AsXml, Debug, Clone, PartialEq)] +#[xml(namespace = ns::BIND, name = "bind")] pub struct BindQuery { /// Requests this resource, the server may associate another one though. /// /// If this is None, we request no particular resource, and a random one /// will be affected by the server. + #[xml(extract(default, fields(text(type_ = String))))] resource: Option, } @@ -33,48 +34,14 @@ impl BindQuery { impl IqSetPayload for BindQuery {} -impl TryFrom for BindQuery { - type Error = FromElementError; - - fn try_from(elem: Element) -> Result { - check_self!(elem, "bind", BIND); - check_no_attributes!(elem, "bind"); - - let mut resource = None; - for child in elem.children() { - if resource.is_some() { - return Err(Error::Other("Bind can only have one child.").into()); - } - if child.is("resource", ns::BIND) { - check_no_attributes!(child, "resource"); - check_no_children!(child, "resource"); - resource = Some(child.text()); - } else { - return Err(Error::Other("Unknown element in bind request.").into()); - } - } - - Ok(BindQuery { resource }) - } -} - -impl From for Element { - fn from(bind: BindQuery) -> Element { - Element::builder("bind", ns::BIND) - .append_all( - bind.resource - .map(|resource| Element::builder("resource", ns::BIND).append(resource)), - ) - .build() - } -} - /// The response for resource binding, containing the client’s full JID. /// /// See -#[derive(Debug, Clone, PartialEq)] +#[derive(FromXml, AsXml, Debug, Clone, PartialEq)] +#[xml(namespace = ns::BIND, name = "bind")] pub struct BindResponse { /// The full JID returned by the server for this client. + #[xml(extract(fields(text(type_ = FullJid))))] jid: FullJid, } @@ -92,49 +59,11 @@ impl From for Jid { } } -impl TryFrom for BindResponse { - type Error = FromElementError; - - fn try_from(elem: Element) -> Result { - check_self!(elem, "bind", BIND); - check_no_attributes!(elem, "bind"); - - let mut jid = None; - for child in elem.children() { - if jid.is_some() { - return Err(Error::Other("Bind can only have one child.").into()); - } - if child.is("jid", ns::BIND) { - check_no_attributes!(child, "jid"); - check_no_children!(child, "jid"); - jid = Some(FullJid::from_str(&child.text()).map_err(Error::text_parse_error)?); - } else { - return Err(Error::Other("Unknown element in bind response.").into()); - } - } - - Ok(BindResponse { - jid: match jid { - None => { - return Err(Error::Other("Bind response must contain a jid element.").into()) - } - Some(jid) => jid, - }, - }) - } -} - -impl From for Element { - fn from(bind: BindResponse) -> Element { - Element::builder("bind", ns::BIND) - .append(Element::builder("jid", ns::BIND).append(bind.jid)) - .build() - } -} - #[cfg(test)] mod tests { use super::*; + use minidom::Element; + use xso::error::{Error, FromElementError}; #[cfg(target_pointer_width = "32")] #[test] @@ -188,7 +117,10 @@ mod tests { FromElementError::Invalid(Error::Other(string)) => string, _ => panic!(), }; - assert_eq!(message, "Unknown attribute in resource element."); + assert_eq!( + message, + "Unknown attribute in extraction for field 'resource' in BindQuery element." + ); let elem: Element = "resource" .parse() @@ -198,6 +130,9 @@ mod tests { FromElementError::Invalid(Error::Other(string)) => string, _ => panic!(), }; - assert_eq!(message, "Unknown child in resource element."); + assert_eq!( + message, + "Unknown child in extraction for field 'resource' in BindQuery element." + ); } }