From 2e9c9411a30baa24478c306cba5e135d15d3ce4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Sch=C3=A4fer?= Date: Mon, 15 Apr 2024 17:03:57 +0200 Subject: [PATCH] jid: rewrite public types This moves InnerJid into Jid and reformulates BareJid and FullJid in terms of Jid. Doing this has the key advantage that FullJid and BareJid can deref to and borrow as Jid. This, in turn, has the advantage that they can be used much more flexibly in HashMaps. However, this is (as we say in Germany) future music; this commit only does the internal reworking. Oh and also, it saves 20% memory on Jid objects. Fixes #122 more thoroughly, or rather the original intent behind it. --- jid/src/inner.rs | 180 ------- jid/src/lib.rs | 628 ++++++++++++++++--------- jid/src/parts.rs | 14 +- parsers/src/bind.rs | 2 +- parsers/src/carbons.rs | 8 +- parsers/src/delay.rs | 4 +- parsers/src/disco.rs | 4 +- parsers/src/forwarding.rs | 4 +- parsers/src/iq.rs | 8 +- parsers/src/jid_prep.rs | 4 +- parsers/src/jingle.rs | 4 +- parsers/src/jingle_s5b.rs | 4 +- parsers/src/mam.rs | 4 +- parsers/src/message.rs | 4 +- parsers/src/presence.rs | 4 +- parsers/src/pubsub/owner.rs | 12 +- parsers/src/stanza_error.rs | 4 +- parsers/src/stanza_id.rs | 4 +- xmpp/examples/hello_bot.rs | 2 +- xmpp/src/message/receive/chat.rs | 6 +- xmpp/src/message/receive/group_chat.rs | 8 +- 21 files changed, 464 insertions(+), 448 deletions(-) delete mode 100644 jid/src/inner.rs diff --git a/jid/src/inner.rs b/jid/src/inner.rs deleted file mode 100644 index 781c940e7bcf6a96a12636f7d92dac8fb355f5c7..0000000000000000000000000000000000000000 --- a/jid/src/inner.rs +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright (c) 2023 Emmanuel Gil Peyrot -// -// This Source Code Form is subject to the terms of the Mozilla Public -// 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/. - -#![deny(missing_docs)] - -//! Provides a type for Jabber IDs. -//! -//! For usage, check the documentation on the `Jid` struct. - -use crate::Error; -use core::num::NonZeroU16; -use memchr::memchr; -use std::borrow::Cow; -use std::str::FromStr; -use stringprep::{nameprep, nodeprep, resourceprep}; - -use crate::parts::{DomainRef, NodeRef, ResourceRef}; - -fn length_check(len: usize, error_empty: Error, error_too_long: Error) -> Result<(), Error> { - if len == 0 { - Err(error_empty) - } else if len > 1023 { - Err(error_too_long) - } else { - Ok(()) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub(crate) struct InnerJid { - pub(crate) normalized: String, - pub(crate) at: Option, - pub(crate) slash: Option, -} - -impl InnerJid { - pub(crate) fn new(unnormalized: &str) -> Result { - let bytes = unnormalized.as_bytes(); - let mut orig_at = memchr(b'@', bytes); - let mut orig_slash = memchr(b'/', bytes); - if orig_at.is_some() && orig_slash.is_some() && orig_at > orig_slash { - // This is part of the resource, not a node@domain separator. - orig_at = None; - } - - let normalized = match (orig_at, orig_slash) { - (Some(at), Some(slash)) => { - let node = nodeprep(&unnormalized[..at]).map_err(|_| Error::NodePrep)?; - length_check(node.len(), Error::NodeEmpty, Error::NodeTooLong)?; - - let domain = nameprep(&unnormalized[at + 1..slash]).map_err(|_| Error::NamePrep)?; - length_check(domain.len(), Error::DomainEmpty, Error::DomainTooLong)?; - - let resource = - resourceprep(&unnormalized[slash + 1..]).map_err(|_| Error::ResourcePrep)?; - length_check(resource.len(), Error::ResourceEmpty, Error::ResourceTooLong)?; - - orig_at = Some(node.len()); - orig_slash = Some(node.len() + domain.len() + 1); - match (node, domain, resource) { - (Cow::Borrowed(_), Cow::Borrowed(_), Cow::Borrowed(_)) => { - unnormalized.to_string() - } - (node, domain, resource) => format!("{node}@{domain}/{resource}"), - } - } - (Some(at), None) => { - let node = nodeprep(&unnormalized[..at]).map_err(|_| Error::NodePrep)?; - length_check(node.len(), Error::NodeEmpty, Error::NodeTooLong)?; - - let domain = nameprep(&unnormalized[at + 1..]).map_err(|_| Error::NamePrep)?; - length_check(domain.len(), Error::DomainEmpty, Error::DomainTooLong)?; - - orig_at = Some(node.len()); - match (node, domain) { - (Cow::Borrowed(_), Cow::Borrowed(_)) => unnormalized.to_string(), - (node, domain) => format!("{node}@{domain}"), - } - } - (None, Some(slash)) => { - let domain = nameprep(&unnormalized[..slash]).map_err(|_| Error::NamePrep)?; - length_check(domain.len(), Error::DomainEmpty, Error::DomainTooLong)?; - - let resource = - resourceprep(&unnormalized[slash + 1..]).map_err(|_| Error::ResourcePrep)?; - length_check(resource.len(), Error::ResourceEmpty, Error::ResourceTooLong)?; - - orig_slash = Some(domain.len()); - match (domain, resource) { - (Cow::Borrowed(_), Cow::Borrowed(_)) => unnormalized.to_string(), - (domain, resource) => format!("{domain}/{resource}"), - } - } - (None, None) => { - let domain = nameprep(unnormalized).map_err(|_| Error::NamePrep)?; - length_check(domain.len(), Error::DomainEmpty, Error::DomainTooLong)?; - - domain.into_owned() - } - }; - - Ok(InnerJid { - normalized, - at: orig_at.and_then(|x| NonZeroU16::new(x as u16)), - slash: orig_slash.and_then(|x| NonZeroU16::new(x as u16)), - }) - } - - pub(crate) fn node(&self) -> Option<&NodeRef> { - self.at.map(|at| { - let at = u16::from(at) as usize; - NodeRef::from_str_unchecked(&self.normalized[..at]) - }) - } - - pub(crate) fn domain(&self) -> &DomainRef { - match (self.at, self.slash) { - (Some(at), Some(slash)) => { - let at = u16::from(at) as usize; - let slash = u16::from(slash) as usize; - DomainRef::from_str_unchecked(&self.normalized[at + 1..slash]) - } - (Some(at), None) => { - let at = u16::from(at) as usize; - DomainRef::from_str_unchecked(&self.normalized[at + 1..]) - } - (None, Some(slash)) => { - let slash = u16::from(slash) as usize; - DomainRef::from_str_unchecked(&self.normalized[..slash]) - } - (None, None) => DomainRef::from_str_unchecked(&self.normalized), - } - } - - pub(crate) fn resource(&self) -> Option<&ResourceRef> { - self.slash.map(|slash| { - let slash = u16::from(slash) as usize; - ResourceRef::from_str_unchecked(&self.normalized[slash + 1..]) - }) - } - - #[inline(always)] - pub(crate) fn as_str(&self) -> &str { - self.normalized.as_str() - } -} - -impl FromStr for InnerJid { - type Err = Error; - - fn from_str(s: &str) -> Result { - InnerJid::new(s) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - macro_rules! assert_size ( - ($t:ty, $sz:expr) => ( - assert_eq!(::std::mem::size_of::<$t>(), $sz); - ); - ); - - #[cfg(target_pointer_width = "32")] - #[test] - fn test_size() { - assert_size!(InnerJid, 16); - } - - #[cfg(target_pointer_width = "64")] - #[test] - fn test_size() { - assert_size!(InnerJid, 32); - } -} diff --git a/jid/src/lib.rs b/jid/src/lib.rs index 2c8de210ecf8fcff272ee0eafdc304e632cb64d3..fde640abf5393caad05dc87ef6e3093702aa1341 100644 --- a/jid/src/lib.rs +++ b/jid/src/lib.rs @@ -31,9 +31,15 @@ //! mixing left-to-write and right-to-left characters use core::num::NonZeroU16; +use std::borrow::Cow; use std::fmt; +use std::ops::Deref; use std::str::FromStr; +use memchr::memchr; + +use stringprep::{nameprep, nodeprep, resourceprep}; + #[cfg(feature = "serde")] use serde::{de, Deserialize, Deserializer, Serialize, Serializer}; @@ -42,53 +48,66 @@ use proc_macro2::TokenStream; #[cfg(feature = "quote")] use quote::{quote, ToTokens}; +#[cfg(feature = "minidom")] +use minidom::{IntoAttributeValue, Node}; + mod error; pub use crate::error::Error; -mod inner; -use inner::InnerJid; - mod parts; pub use parts::{DomainPart, DomainRef, NodePart, NodeRef, ResourcePart, ResourceRef}; -/// An enum representing a Jabber ID. It can be either a `FullJid` or a `BareJid`. -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -#[cfg_attr(feature = "serde", serde(untagged))] -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -pub enum Jid { - /// Contains a [`BareJid`], without a resource part - Bare(BareJid), +fn length_check(len: usize, error_empty: Error, error_too_long: Error) -> Result<(), Error> { + if len == 0 { + Err(error_empty) + } else if len > 1023 { + Err(error_too_long) + } else { + Ok(()) + } +} - /// Contains a [`FullJid`], with a resource part - Full(FullJid), +/// A struct representing a Jabber ID (JID). +/// +/// This JID can either be "bare" (without a `/resource` suffix) or full (with +/// a resource suffix). +/// +/// In many APIs, it is appropriate to use the more specific types +/// ([`BareJid`] or [`FullJid`]) instead, as these two JID types are generally +/// used in different contexts within XMPP. +/// +/// This dynamic type on the other hand can be used in contexts where it is +/// not known, at compile-time, whether a JID is full or bare. +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Jid { + normalized: String, + at: Option, + slash: Option, } impl FromStr for Jid { type Err = Error; - fn from_str(s: &str) -> Result { - Jid::new(s) + fn from_str(s: &str) -> Result { + Self::new(s) } } impl From for Jid { - fn from(bare_jid: BareJid) -> Jid { - Jid::Bare(bare_jid) + fn from(other: BareJid) -> Self { + other.inner } } impl From for Jid { - fn from(full_jid: FullJid) -> Jid { - Jid::Full(full_jid) + fn from(other: FullJid) -> Self { + other.inner } } impl fmt::Display for Jid { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - match self { - Jid::Bare(bare) => bare.fmt(fmt), - Jid::Full(full) => full.fmt(fmt), - } + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str(&self.normalized) } } @@ -112,20 +131,81 @@ impl Jid { /// # Ok(()) /// # } /// ``` - pub fn new(s: &str) -> Result { - let inner = InnerJid::new(s)?; - if inner.slash.is_some() { - Ok(Jid::Full(FullJid { inner })) - } else { - Ok(Jid::Bare(BareJid { inner })) + pub fn new(unnormalized: &str) -> Result { + let bytes = unnormalized.as_bytes(); + let mut orig_at = memchr(b'@', bytes); + let mut orig_slash = memchr(b'/', bytes); + if orig_at.is_some() && orig_slash.is_some() && orig_at > orig_slash { + // This is part of the resource, not a node@domain separator. + orig_at = None; } + + let normalized = match (orig_at, orig_slash) { + (Some(at), Some(slash)) => { + let node = nodeprep(&unnormalized[..at]).map_err(|_| Error::NodePrep)?; + length_check(node.len(), Error::NodeEmpty, Error::NodeTooLong)?; + + let domain = nameprep(&unnormalized[at + 1..slash]).map_err(|_| Error::NamePrep)?; + length_check(domain.len(), Error::DomainEmpty, Error::DomainTooLong)?; + + let resource = + resourceprep(&unnormalized[slash + 1..]).map_err(|_| Error::ResourcePrep)?; + length_check(resource.len(), Error::ResourceEmpty, Error::ResourceTooLong)?; + + orig_at = Some(node.len()); + orig_slash = Some(node.len() + domain.len() + 1); + match (node, domain, resource) { + (Cow::Borrowed(_), Cow::Borrowed(_), Cow::Borrowed(_)) => { + unnormalized.to_string() + } + (node, domain, resource) => format!("{node}@{domain}/{resource}"), + } + } + (Some(at), None) => { + let node = nodeprep(&unnormalized[..at]).map_err(|_| Error::NodePrep)?; + length_check(node.len(), Error::NodeEmpty, Error::NodeTooLong)?; + + let domain = nameprep(&unnormalized[at + 1..]).map_err(|_| Error::NamePrep)?; + length_check(domain.len(), Error::DomainEmpty, Error::DomainTooLong)?; + + orig_at = Some(node.len()); + match (node, domain) { + (Cow::Borrowed(_), Cow::Borrowed(_)) => unnormalized.to_string(), + (node, domain) => format!("{node}@{domain}"), + } + } + (None, Some(slash)) => { + let domain = nameprep(&unnormalized[..slash]).map_err(|_| Error::NamePrep)?; + length_check(domain.len(), Error::DomainEmpty, Error::DomainTooLong)?; + + let resource = + resourceprep(&unnormalized[slash + 1..]).map_err(|_| Error::ResourcePrep)?; + length_check(resource.len(), Error::ResourceEmpty, Error::ResourceTooLong)?; + + orig_slash = Some(domain.len()); + match (domain, resource) { + (Cow::Borrowed(_), Cow::Borrowed(_)) => unnormalized.to_string(), + (domain, resource) => format!("{domain}/{resource}"), + } + } + (None, None) => { + let domain = nameprep(unnormalized).map_err(|_| Error::NamePrep)?; + length_check(domain.len(), Error::DomainEmpty, Error::DomainTooLong)?; + + domain.into_owned() + } + }; + + Ok(Self { + normalized, + at: orig_at.and_then(|x| NonZeroU16::new(x as u16)), + slash: orig_slash.and_then(|x| NonZeroU16::new(x as u16)), + }) } /// Returns the inner String of this JID. pub fn into_inner(self) -> String { - match self { - Jid::Bare(BareJid { inner }) | Jid::Full(FullJid { inner }) => inner.normalized, - } + self.normalized } /// Build a [`Jid`] from typed parts. This method cannot fail because it uses parts that have @@ -138,117 +218,220 @@ impl Jid { node: Option<&NodeRef>, domain: &DomainRef, resource: Option<&ResourceRef>, - ) -> Jid { - if let Some(resource) = resource { - Jid::Full(FullJid::from_parts(node, domain, resource)) - } else { - Jid::Bare(BareJid::from_parts(node, domain)) + ) -> Self { + match resource { + Some(resource) => FullJid::from_parts(node, domain, resource).into(), + None => BareJid::from_parts(node, domain).into(), } } /// The optional node part of the JID as reference. pub fn node(&self) -> Option<&NodeRef> { - match self { - Jid::Bare(BareJid { inner }) | Jid::Full(FullJid { inner }) => inner.node(), - } + self.at.map(|at| { + let at = u16::from(at) as usize; + NodeRef::from_str_unchecked(&self.normalized[..at]) + }) } /// The domain part of the JID as reference pub fn domain(&self) -> &DomainRef { - match self { - Jid::Bare(BareJid { inner }) | Jid::Full(FullJid { inner }) => inner.domain(), + match (self.at, self.slash) { + (Some(at), Some(slash)) => { + let at = u16::from(at) as usize; + let slash = u16::from(slash) as usize; + DomainRef::from_str_unchecked(&self.normalized[at + 1..slash]) + } + (Some(at), None) => { + let at = u16::from(at) as usize; + DomainRef::from_str_unchecked(&self.normalized[at + 1..]) + } + (None, Some(slash)) => { + let slash = u16::from(slash) as usize; + DomainRef::from_str_unchecked(&self.normalized[..slash]) + } + (None, None) => DomainRef::from_str_unchecked(&self.normalized), } } /// The optional resource of the Jabber ID. It is guaranteed to be present when the JID is /// a Full variant, which you can check with [`Jid::is_full`]. pub fn resource(&self) -> Option<&ResourceRef> { - match self { - Jid::Bare(BareJid { inner }) | Jid::Full(FullJid { inner }) => inner.resource(), - } + self.slash.map(|slash| { + let slash = u16::from(slash) as usize; + ResourceRef::from_str_unchecked(&self.normalized[slash + 1..]) + }) } /// Allocate a new [`BareJid`] from this JID, discarding the resource. pub fn to_bare(&self) -> BareJid { - match self { - Jid::Full(jid) => jid.to_bare(), - Jid::Bare(jid) => jid.clone(), - } + BareJid::from_parts(self.node(), self.domain()) } /// Transforms this JID into a [`BareJid`], throwing away the resource. - pub fn into_bare(self) -> BareJid { - match self { - Jid::Full(jid) => jid.into_bare(), - Jid::Bare(jid) => jid, + /// + /// ``` + /// # use jid::{BareJid, Jid}; + /// let jid: Jid = "foo@bar/baz".parse().unwrap(); + /// let bare = jid.into_bare(); + /// assert_eq!(bare.to_string(), "foo@bar"); + /// ``` + pub fn into_bare(mut self) -> BareJid { + if let Some(slash) = self.slash { + // truncate the string + self.normalized.truncate(slash.get() as usize); + self.slash = None; } + BareJid { inner: self } } - /// Checks if the JID contains a [`FullJid`] + /// Checks if the JID is a full JID. pub fn is_full(&self) -> bool { - match self { - Self::Full(_) => true, - Self::Bare(_) => false, - } + self.slash.is_some() } - /// Checks if the JID contains a [`BareJid`] + /// Checks if the JID is a bare JID. pub fn is_bare(&self) -> bool { - !self.is_full() + self.slash.is_none() } /// Return a reference to the canonical string representation of the JID. pub fn as_str(&self) -> &str { - match self { - Jid::Bare(BareJid { inner }) | Jid::Full(FullJid { inner }) => inner.as_str(), + &self.normalized + } + + /// Try to convert this Jid to a [`FullJid`] if it contains a resource + /// and return a [`BareJid`] otherwise. + /// + /// This is useful for match blocks: + /// + /// ``` + /// # use jid::Jid; + /// let jid: Jid = "foo@bar".parse().unwrap(); + /// match jid.try_into_full() { + /// Ok(full) => println!("it is full: {:?}", full), + /// Err(bare) => println!("it is bare: {:?}", bare), + /// } + /// ``` + pub fn try_into_full(self) -> Result { + if self.slash.is_some() { + Ok(FullJid { inner: self }) + } else { + Err(BareJid { inner: self }) + } + } + + /// Try to convert this Jid reference to a [`&FullJid`][`FullJid`] if it + /// contains a resource and return a [`&BareJid`][`BareJid`] otherwise. + /// + /// This is useful for match blocks: + /// + /// ``` + /// # use jid::Jid; + /// let jid: Jid = "foo@bar".parse().unwrap(); + /// match jid.try_as_full() { + /// Ok(full) => println!("it is full: {:?}", full), + /// Err(bare) => println!("it is bare: {:?}", bare), + /// } + /// ``` + pub fn try_as_full(&self) -> Result<&FullJid, &BareJid> { + if self.slash.is_some() { + Ok(unsafe { + // SAFETY: FullJid is #[repr(transparent)] of Jid + // SOUNDNESS: we asserted that self.slash is set above + std::mem::transmute::<&Jid, &FullJid>(self) + }) + } else { + Err(unsafe { + // SAFETY: BareJid is #[repr(transparent)] of Jid + // SOUNDNESS: we asserted that self.slash is unset above + std::mem::transmute::<&Jid, &BareJid>(self) + }) } } + + /// Try to convert this mutable Jid reference to a + /// [`&mut FullJid`][`FullJid`] if it contains a resource and return a + /// [`&mut BareJid`][`BareJid`] otherwise. + pub fn try_as_full_mut(&mut self) -> Result<&mut FullJid, &mut BareJid> { + if self.slash.is_some() { + Ok(unsafe { + // SAFETY: FullJid is #[repr(transparent)] of Jid + // SOUNDNESS: we asserted that self.slash is set above + std::mem::transmute::<&mut Jid, &mut FullJid>(self) + }) + } else { + Err(unsafe { + // SAFETY: BareJid is #[repr(transparent)] of Jid + // SOUNDNESS: we asserted that self.slash is unset above + std::mem::transmute::<&mut Jid, &mut BareJid>(self) + }) + } + } + + #[doc(hidden)] + #[allow(non_snake_case)] + #[deprecated( + since = "0.11.0", + note = "use Jid::from (for construction of Jid values) or Jid::try_into_full/Jid::try_as_full (for match blocks) instead" + )] + pub fn Bare(other: BareJid) -> Self { + Self::from(other) + } + + #[doc(hidden)] + #[allow(non_snake_case)] + #[deprecated( + since = "0.11.0", + note = "use Jid::from (for construction of Jid values) or Jid::try_into_full/Jid::try_as_full (for match blocks) instead" + )] + pub fn Full(other: BareJid) -> Self { + Self::from(other) + } } impl TryFrom for FullJid { type Error = Error; - fn try_from(jid: Jid) -> Result { - match jid { - Jid::Full(full) => Ok(full), - Jid::Bare(_) => Err(Error::ResourceMissingInFullJid), + fn try_from(inner: Jid) -> Result { + if inner.slash.is_none() { + return Err(Error::ResourceMissingInFullJid); } + Ok(Self { inner }) + } +} + +impl TryFrom for BareJid { + type Error = Error; + + fn try_from(inner: Jid) -> Result { + if inner.slash.is_some() { + return Err(Error::ResourceInBareJid); + } + Ok(Self { inner }) } } impl PartialEq for FullJid { fn eq(&self, other: &Jid) -> bool { - match other { - Jid::Full(full) => self == full, - Jid::Bare(_) => false, - } + &self.inner == other } } impl PartialEq for BareJid { fn eq(&self, other: &Jid) -> bool { - match other { - Jid::Full(_) => false, - Jid::Bare(bare) => self == bare, - } + &self.inner == other } } impl PartialEq for Jid { fn eq(&self, other: &FullJid) -> bool { - match self { - Jid::Full(full) => full == other, - Jid::Bare(_) => false, - } + self == &other.inner } } impl PartialEq for Jid { fn eq(&self, other: &BareJid) -> bool { - match self { - Jid::Full(_) => false, - Jid::Bare(bare) => bare == other, - } + self == &other.inner } } @@ -263,9 +446,10 @@ impl PartialEq for Jid { /// Unlike a [`BareJid`], it always contains a resource, and should only be used when you are /// certain there is no case where a resource can be missing. Otherwise, use a [`Jid`] or /// [`BareJid`]. -#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(transparent)] // WARNING: Jid::try_as_* relies on this for safety! pub struct FullJid { - inner: InnerJid, + inner: Jid, } /// A struct representing a bare Jabber ID, without a resource part. @@ -276,32 +460,59 @@ pub struct FullJid { /// /// Unlike a [`FullJid`], it can’t contain a resource, and should only be used when you are certain /// there is no case where a resource can be set. Otherwise, use a [`Jid`] or [`FullJid`]. -#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(transparent)] // WARNING: Jid::try_as_* relies on this for safety! pub struct BareJid { - inner: InnerJid, + inner: Jid, +} + +impl Deref for FullJid { + type Target = Jid; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl Deref for BareJid { + type Target = Jid; + + fn deref(&self) -> &Self::Target { + &self.inner + } } impl fmt::Debug for FullJid { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_tuple("FullJid").field(&self.inner).finish() } } impl fmt::Debug for BareJid { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fmt.debug_tuple("BareJid").field(&self.inner).finish() } } impl fmt::Display for FullJid { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - fmt.write_str(&self.inner.normalized) + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.inner, fmt) } } impl fmt::Display for BareJid { - fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { - fmt.write_str(&self.inner.normalized) + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.inner, fmt) + } +} + +#[cfg(feature = "serde")] +impl Serialize for Jid { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_str(&self.normalized) } } @@ -311,7 +522,7 @@ impl Serialize for FullJid { where S: Serializer, { - serializer.serialize_str(&self.inner.normalized) + self.inner.serialize(serializer) } } @@ -321,26 +532,37 @@ impl Serialize for BareJid { where S: Serializer, { - serializer.serialize_str(&self.inner.normalized) + self.inner.serialize(serializer) } } impl FromStr for FullJid { type Err = Error; - fn from_str(s: &str) -> Result { - FullJid::new(s) + fn from_str(s: &str) -> Result { + Self::new(s) } } #[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for FullJid { +impl<'de> Deserialize<'de> for Jid { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, { let s = String::deserialize(deserializer)?; - FullJid::from_str(&s).map_err(de::Error::custom) + Jid::new(&s).map_err(de::Error::custom) + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for FullJid { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let jid = Jid::deserialize(deserializer)?; + jid.try_into().map_err(de::Error::custom) } } @@ -350,17 +572,17 @@ impl<'de> Deserialize<'de> for BareJid { where D: Deserializer<'de>, { - let s = String::deserialize(deserializer)?; - BareJid::from_str(&s).map_err(de::Error::custom) + let jid = Jid::deserialize(deserializer)?; + jid.try_into().map_err(de::Error::custom) } } #[cfg(feature = "quote")] impl ToTokens for Jid { fn to_tokens(&self, tokens: &mut TokenStream) { - tokens.extend(match self { - Jid::Full(full) => quote! { Jid::Full(#full) }, - Jid::Bare(bare) => quote! { Jid::Bare(#bare) }, + let s = &self.normalized; + tokens.extend(quote! { + ::jid::Jid::new(#s).unwrap() }); } } @@ -368,18 +590,20 @@ impl ToTokens for Jid { #[cfg(feature = "quote")] impl ToTokens for FullJid { fn to_tokens(&self, tokens: &mut TokenStream) { - let inner = &self.inner.normalized; - let t = quote! { FullJid::new(#inner).unwrap() }; - tokens.extend(t); + let s = &self.inner.normalized; + tokens.extend(quote! { + ::jid::FullJid::new(#s).unwrap() + }); } } #[cfg(feature = "quote")] impl ToTokens for BareJid { fn to_tokens(&self, tokens: &mut TokenStream) { - let inner = &self.inner.normalized; - let t = quote! { BareJid::new(#inner).unwrap() }; - tokens.extend(t); + let s = &self.inner.normalized; + tokens.extend(quote! { + ::jid::BareJid::new(#s).unwrap() + }); } } @@ -403,18 +627,8 @@ impl FullJid { /// # Ok(()) /// # } /// ``` - pub fn new(s: &str) -> Result { - let inner = InnerJid::new(s)?; - if inner.slash.is_some() { - Ok(FullJid { inner }) - } else { - Err(Error::ResourceMissingInFullJid) - } - } - - /// Returns the inner String of this JID. - pub fn into_inner(self) -> String { - self.inner.normalized + pub fn new(unnormalized: &str) -> Result { + Jid::new(unnormalized)?.try_into() } /// Build a [`FullJid`] from typed parts. This method cannot fail because it uses parts that have @@ -445,62 +659,26 @@ impl FullJid { ) }; - let inner = InnerJid { + let inner = Jid { normalized, at, slash, }; - FullJid { inner } - } - - /// The optional node part of the JID as reference. - pub fn node(&self) -> Option<&NodeRef> { - self.inner.node() - } - - /// The domain part of the JID as reference - pub fn domain(&self) -> &DomainRef { - self.inner.domain() + Self { inner } } /// The optional resource of the Jabber ID. Since this is a full JID it is always present. pub fn resource(&self) -> &ResourceRef { self.inner.resource().unwrap() } - - /// Allocate a new [`BareJid`] from this full JID, discarding the resource. - pub fn to_bare(&self) -> BareJid { - let slash = self.inner.slash.unwrap().get() as usize; - let normalized = self.inner.normalized[..slash].to_string(); - let inner = InnerJid { - normalized, - at: self.inner.at, - slash: None, - }; - BareJid { inner } - } - - /// Transforms this full JID into a [`BareJid`], discarding the resource. - pub fn into_bare(mut self) -> BareJid { - let slash = self.inner.slash.unwrap().get() as usize; - self.inner.normalized.truncate(slash); - self.inner.normalized.shrink_to_fit(); - self.inner.slash = None; - BareJid { inner: self.inner } - } - - /// Return a reference to the canonical string representation of the JID. - pub fn as_str(&self) -> &str { - self.inner.as_str() - } } impl FromStr for BareJid { type Err = Error; - fn from_str(s: &str) -> Result { - BareJid::new(s) + fn from_str(s: &str) -> Result { + Self::new(s) } } @@ -523,18 +701,8 @@ impl BareJid { /// # Ok(()) /// # } /// ``` - pub fn new(s: &str) -> Result { - let inner = InnerJid::new(s)?; - if inner.slash.is_none() { - Ok(BareJid { inner }) - } else { - Err(Error::ResourceInBareJid) - } - } - - /// Returns the inner String of this JID. - pub fn into_inner(self) -> String { - self.inner.normalized + pub fn new(unnormalized: &str) -> Result { + Jid::new(unnormalized)?.try_into() } /// Build a [`BareJid`] from typed parts. This method cannot fail because it uses parts that have @@ -543,7 +711,7 @@ impl BareJid { /// This method allocates and does not consume the typed parts. To avoid /// allocation if `node` is known to be `None` and `domain` is owned, you /// can use `domain.into()`. - pub fn from_parts(node: Option<&NodeRef>, domain: &DomainRef) -> BareJid { + pub fn from_parts(node: Option<&NodeRef>, domain: &DomainRef) -> Self { let (at, normalized) = if let Some(node) = node { // Parts are never empty so len > 0 for NonZeroU16::new is always Some ( @@ -554,23 +722,13 @@ impl BareJid { (None, domain.to_string()) }; - let inner = InnerJid { + let inner = Jid { normalized, at, slash: None, }; - BareJid { inner } - } - - /// The optional node part of the JID as reference. - pub fn node(&self) -> Option<&NodeRef> { - self.inner.node() - } - - /// The domain part of the JID as reference - pub fn domain(&self) -> &DomainRef { - self.inner.domain() + Self { inner } } /// Constructs a [`BareJid`] from the bare JID, by specifying a [`ResourcePart`]. @@ -592,7 +750,7 @@ impl BareJid { pub fn with_resource(&self, resource: &ResourceRef) -> FullJid { let slash = NonZeroU16::new(self.inner.normalized.len() as u16); let normalized = format!("{}/{resource}", self.inner.normalized); - let inner = InnerJid { + let inner = Jid { normalized, at: self.inner.at, slash, @@ -620,16 +778,8 @@ impl BareJid { let resource = ResourcePart::new(resource)?; Ok(self.with_resource(&resource)) } - - /// Return a reference to the canonical string representation of the JID. - pub fn as_str(&self) -> &str { - self.inner.as_str() - } } -#[cfg(feature = "minidom")] -use minidom::{IntoAttributeValue, Node}; - #[cfg(feature = "minidom")] impl IntoAttributeValue for Jid { fn into_attribute_value(self) -> Option { @@ -639,7 +789,7 @@ impl IntoAttributeValue for Jid { #[cfg(feature = "minidom")] impl From for Node { - fn from(jid: Jid) -> Node { + fn from(jid: Jid) -> Self { Node::Text(jid.to_string()) } } @@ -647,28 +797,28 @@ impl From for Node { #[cfg(feature = "minidom")] impl IntoAttributeValue for FullJid { fn into_attribute_value(self) -> Option { - Some(self.to_string()) + self.inner.into_attribute_value() } } #[cfg(feature = "minidom")] impl From for Node { - fn from(jid: FullJid) -> Node { - Node::Text(jid.to_string()) + fn from(jid: FullJid) -> Self { + jid.inner.into() } } #[cfg(feature = "minidom")] impl IntoAttributeValue for BareJid { fn into_attribute_value(self) -> Option { - Some(self.to_string()) + self.inner.into_attribute_value() } } #[cfg(feature = "minidom")] impl From for Node { - fn from(jid: BareJid) -> Node { - Node::Text(jid.to_string()) + fn from(other: BareJid) -> Self { + other.inner.into() } } @@ -689,7 +839,7 @@ mod tests { fn test_size() { assert_size!(BareJid, 16); assert_size!(FullJid, 16); - assert_size!(Jid, 20); + assert_size!(Jid, 16); } #[cfg(target_pointer_width = "64")] @@ -697,7 +847,7 @@ mod tests { fn test_size() { assert_size!(BareJid, 32); assert_size!(FullJid, 32); - assert_size!(Jid, 40); + assert_size!(Jid, 32); } #[test] @@ -735,8 +885,8 @@ mod tests { let full = FullJid::from_str("a@b.c/d").unwrap(); let bare = BareJid::from_str("e@f.g").unwrap(); - assert_eq!(Jid::from_str("a@b.c/d"), Ok(Jid::Full(full))); - assert_eq!(Jid::from_str("e@f.g"), Ok(Jid::Bare(bare))); + assert_eq!(Jid::from_str("a@b.c/d").unwrap(), full); + assert_eq!(Jid::from_str("e@f.g").unwrap(), bare); } #[test] @@ -792,13 +942,13 @@ mod tests { let full = FullJid::new("a@b.c/d").unwrap(); let bare = BareJid::new("a@b.c").unwrap(); - assert_eq!(FullJid::try_from(Jid::Full(full.clone())), Ok(full.clone())); + assert_eq!(FullJid::try_from(Jid::from(full.clone())), Ok(full.clone())); assert_eq!( - FullJid::try_from(Jid::Bare(bare.clone())), + FullJid::try_from(Jid::from(bare.clone())), Err(Error::ResourceMissingInFullJid), ); - assert_eq!(Jid::Bare(full.clone().to_bare()), bare.clone()); - assert_eq!(Jid::Bare(bare.clone()), bare); + assert_eq!(Jid::from(full.clone().to_bare()), bare.clone()); + assert_eq!(Jid::from(bare.clone()), bare); } #[test] @@ -836,10 +986,10 @@ mod tests { assert_eq!(FullJid::new("a@b/c").unwrap().to_string(), "a@b/c"); assert_eq!(BareJid::new("a@b").unwrap().to_string(), "a@b"); assert_eq!( - Jid::Full(FullJid::new("a@b/c").unwrap()).to_string(), + Jid::from(FullJid::new("a@b/c").unwrap()).to_string(), "a@b/c" ); - assert_eq!(Jid::Bare(BareJid::new("a@b").unwrap()).to_string(), "a@b"); + assert_eq!(Jid::from(BareJid::new("a@b").unwrap()).to_string(), "a@b"); } #[cfg(feature = "minidom")] @@ -847,11 +997,11 @@ mod tests { fn minidom() { let elem: minidom::Element = "".parse().unwrap(); let to: Jid = elem.attr("from").unwrap().parse().unwrap(); - assert_eq!(to, Jid::Full(FullJid::new("a@b/c").unwrap())); + assert_eq!(to, Jid::from(FullJid::new("a@b/c").unwrap())); let elem: minidom::Element = "".parse().unwrap(); let to: Jid = elem.attr("from").unwrap().parse().unwrap(); - assert_eq!(to, Jid::Bare(BareJid::new("a@b").unwrap())); + assert_eq!(to, Jid::from(BareJid::new("a@b").unwrap())); let elem: minidom::Element = "".parse().unwrap(); let to: FullJid = elem.attr("from").unwrap().parse().unwrap(); @@ -877,7 +1027,7 @@ mod tests { .build(); assert_eq!(elem.attr("from"), Some(bare.to_string().as_str())); - let jid = Jid::Bare(bare.clone()); + let jid = Jid::from(bare.clone()); let _elem = minidom::Element::builder("message", "jabber:client") .attr("from", jid) .build(); @@ -939,4 +1089,52 @@ mod tests { assert_eq!(jid1, jid2); assert_eq!(jid2, jid3); } + + #[test] + fn jid_match_replacement_try_as() { + let jid1 = Jid::new("foo@bar").unwrap(); + let jid2 = Jid::new("foo@bar/baz").unwrap(); + + match jid1.try_as_full() { + Err(_) => (), + other => panic!("unexpected result: {:?}", other), + }; + + match jid2.try_as_full() { + Ok(_) => (), + other => panic!("unexpected result: {:?}", other), + }; + } + + #[test] + fn jid_match_replacement_try_as_mut() { + let mut jid1 = Jid::new("foo@bar").unwrap(); + let mut jid2 = Jid::new("foo@bar/baz").unwrap(); + + match jid1.try_as_full_mut() { + Err(_) => (), + other => panic!("unexpected result: {:?}", other), + }; + + match jid2.try_as_full_mut() { + Ok(_) => (), + other => panic!("unexpected result: {:?}", other), + }; + } + + #[test] + fn jid_match_replacement_try_into() { + let jid1 = Jid::new("foo@bar").unwrap(); + let jid2 = Jid::new("foo@bar/baz").unwrap(); + + match jid1.try_as_full() { + Err(_) => (), + other => panic!("unexpected result: {:?}", other), + }; + + match jid2.try_as_full() { + Ok(_) => (), + other => panic!("unexpected result: {:?}", other), + }; + } } diff --git a/jid/src/parts.rs b/jid/src/parts.rs index 2c9a6f342b15531b080ecaaab6ad494ca165395b..c4b5643661c04164a907252631cd0e1b12813648 100644 --- a/jid/src/parts.rs +++ b/jid/src/parts.rs @@ -5,7 +5,7 @@ use std::str::FromStr; use stringprep::{nameprep, nodeprep, resourceprep}; -use crate::{BareJid, Error, InnerJid, Jid}; +use crate::{BareJid, Error, Jid}; fn length_check(len: usize, error_empty: Error, error_too_long: Error) -> Result<(), Error> { if len == 0 { @@ -250,18 +250,18 @@ impl DomainRef { impl From for BareJid { fn from(other: DomainPart) -> Self { BareJid { - inner: InnerJid { - normalized: other.0, - at: None, - slash: None, - }, + inner: other.into(), } } } impl From for Jid { fn from(other: DomainPart) -> Self { - Jid::Bare(other.into()) + Jid { + normalized: other.0, + at: None, + slash: None, + } } } diff --git a/parsers/src/bind.rs b/parsers/src/bind.rs index 6d02b568b7ca5c630298c7f15f409d06623267fe..bc0184c108d59ab164b493b814ec3303ff0f38ec 100644 --- a/parsers/src/bind.rs +++ b/parsers/src/bind.rs @@ -88,7 +88,7 @@ impl From for FullJid { impl From for Jid { fn from(bind: BindResponse) -> Jid { - Jid::Full(bind.jid) + Jid::from(bind.jid) } } diff --git a/parsers/src/carbons.rs b/parsers/src/carbons.rs index f528354382611ebde8f88c66e4e522df00acd46f..9b931ca63ff5fb2797b9a767cd9a708a96fc5504 100644 --- a/parsers/src/carbons.rs +++ b/parsers/src/carbons.rs @@ -71,8 +71,8 @@ mod tests { assert_size!(Enable, 0); assert_size!(Disable, 0); assert_size!(Private, 0); - assert_size!(Received, 152); - assert_size!(Sent, 152); + assert_size!(Received, 140); + assert_size!(Sent, 140); } #[cfg(target_pointer_width = "64")] @@ -81,8 +81,8 @@ mod tests { assert_size!(Enable, 0); assert_size!(Disable, 0); assert_size!(Private, 0); - assert_size!(Received, 288); - assert_size!(Sent, 288); + assert_size!(Received, 264); + assert_size!(Sent, 264); } #[test] diff --git a/parsers/src/delay.rs b/parsers/src/delay.rs index a38f4ec2c73cc02f5de86b820fa444b818f72bf6..3aeeaf367f1ca3afe071596f7282894cd1623fbc 100644 --- a/parsers/src/delay.rs +++ b/parsers/src/delay.rs @@ -40,13 +40,13 @@ mod tests { #[cfg(target_pointer_width = "32")] #[test] fn test_size() { - assert_size!(Delay, 48); + assert_size!(Delay, 44); } #[cfg(target_pointer_width = "64")] #[test] fn test_size() { - assert_size!(Delay, 80); + assert_size!(Delay, 72); } #[test] diff --git a/parsers/src/disco.rs b/parsers/src/disco.rs index 99623a096b69863c4a06ef88b887401178c7c3ee..dc23b6231a2f9525780cbfa833c235f3f4faa402 100644 --- a/parsers/src/disco.rs +++ b/parsers/src/disco.rs @@ -248,7 +248,7 @@ mod tests { assert_size!(DiscoInfoQuery, 12); assert_size!(DiscoInfoResult, 48); - assert_size!(Item, 44); + assert_size!(Item, 40); assert_size!(DiscoItemsQuery, 52); assert_size!(DiscoItemsResult, 64); } @@ -261,7 +261,7 @@ mod tests { assert_size!(DiscoInfoQuery, 24); assert_size!(DiscoInfoResult, 96); - assert_size!(Item, 88); + assert_size!(Item, 80); assert_size!(DiscoItemsQuery, 104); assert_size!(DiscoItemsResult, 128); } diff --git a/parsers/src/forwarding.rs b/parsers/src/forwarding.rs index 28984fa5f4269511a8e88079860373a87b9fd4a1..0bfa1c3a3a3ee136ac368a98c5818295080a6114 100644 --- a/parsers/src/forwarding.rs +++ b/parsers/src/forwarding.rs @@ -32,13 +32,13 @@ mod tests { #[cfg(target_pointer_width = "32")] #[test] fn test_size() { - assert_size!(Forwarded, 152); + assert_size!(Forwarded, 140); } #[cfg(target_pointer_width = "64")] #[test] fn test_size() { - assert_size!(Forwarded, 288); + assert_size!(Forwarded, 264); } #[test] diff --git a/parsers/src/iq.rs b/parsers/src/iq.rs index 2d4451d6e1a2c54de14d6f0963a02ea35194e1b3..ff22b49551f71251d006e14b1e7ed45a8035e882 100644 --- a/parsers/src/iq.rs +++ b/parsers/src/iq.rs @@ -232,15 +232,15 @@ mod tests { #[cfg(target_pointer_width = "32")] #[test] fn test_size() { - assert_size!(IqType, 96); - assert_size!(Iq, 148); + assert_size!(IqType, 92); + assert_size!(Iq, 156); } #[cfg(target_pointer_width = "64")] #[test] fn test_size() { - assert_size!(IqType, 192); - assert_size!(Iq, 296); + assert_size!(IqType, 184); + assert_size!(Iq, 272); } #[test] diff --git a/parsers/src/jid_prep.rs b/parsers/src/jid_prep.rs index 1d26a20c4fed4fb0078d08c5b803beb773f2d6d3..e082a39a8858b6294275e9ede2d40742a431f4f7 100644 --- a/parsers/src/jid_prep.rs +++ b/parsers/src/jid_prep.rs @@ -46,14 +46,14 @@ mod tests { #[test] fn test_size() { assert_size!(JidPrepQuery, 12); - assert_size!(JidPrepResponse, 20); + assert_size!(JidPrepResponse, 16); } #[cfg(target_pointer_width = "64")] #[test] fn test_size() { assert_size!(JidPrepQuery, 24); - assert_size!(JidPrepResponse, 40); + assert_size!(JidPrepResponse, 32); } #[test] diff --git a/parsers/src/jingle.rs b/parsers/src/jingle.rs index f8e8fdc43c366934f89d2f394ea3ecd77c3f3471..a116cc793a1f24aaa81b842bde7f085a6fa26cfc 100644 --- a/parsers/src/jingle.rs +++ b/parsers/src/jingle.rs @@ -692,7 +692,7 @@ mod tests { assert_size!(Reason, 1); assert_size!(ReasonElement, 16); assert_size!(SessionId, 12); - assert_size!(Jingle, 112); + assert_size!(Jingle, 104); } #[cfg(target_pointer_width = "64")] @@ -711,7 +711,7 @@ mod tests { assert_size!(Reason, 1); assert_size!(ReasonElement, 32); assert_size!(SessionId, 24); - assert_size!(Jingle, 224); + assert_size!(Jingle, 208); } #[test] diff --git a/parsers/src/jingle_s5b.rs b/parsers/src/jingle_s5b.rs index a8db30bf8353c3eb816cf946d5e9b5a60c23b8fc..5c9cf3059c958fdf02d4617a1641166fcadd1f64 100644 --- a/parsers/src/jingle_s5b.rs +++ b/parsers/src/jingle_s5b.rs @@ -284,7 +284,7 @@ mod tests { assert_size!(Mode, 1); assert_size!(CandidateId, 12); assert_size!(StreamId, 12); - assert_size!(Candidate, 60); + assert_size!(Candidate, 56); assert_size!(TransportPayload, 16); assert_size!(Transport, 44); } @@ -296,7 +296,7 @@ mod tests { assert_size!(Mode, 1); assert_size!(CandidateId, 24); assert_size!(StreamId, 24); - assert_size!(Candidate, 96); + assert_size!(Candidate, 88); assert_size!(TransportPayload, 32); assert_size!(Transport, 88); } diff --git a/parsers/src/mam.rs b/parsers/src/mam.rs index c1e71610485bf9af215e69a953452248d77290b7..d3fe3bdb86595d3da4744a7507c69dff94d7700e 100644 --- a/parsers/src/mam.rs +++ b/parsers/src/mam.rs @@ -166,7 +166,7 @@ mod tests { fn test_size() { assert_size!(QueryId, 12); assert_size!(Query, 120); - assert_size!(Result_, 176); + assert_size!(Result_, 164); assert_size!(Complete, 1); assert_size!(Fin, 44); } @@ -176,7 +176,7 @@ mod tests { fn test_size() { assert_size!(QueryId, 24); assert_size!(Query, 240); - assert_size!(Result_, 336); + assert_size!(Result_, 312); assert_size!(Complete, 1); assert_size!(Fin, 88); } diff --git a/parsers/src/message.rs b/parsers/src/message.rs index 50fe4213bdfd25a351a48a5285a8859b38955bcf..40c45e426d99341edb4ed3917d7843659e817236 100644 --- a/parsers/src/message.rs +++ b/parsers/src/message.rs @@ -307,7 +307,7 @@ mod tests { assert_size!(Body, 12); assert_size!(Subject, 12); assert_size!(Thread, 12); - assert_size!(Message, 104); + assert_size!(Message, 96); } #[cfg(target_pointer_width = "64")] @@ -317,7 +317,7 @@ mod tests { assert_size!(Body, 24); assert_size!(Subject, 24); assert_size!(Thread, 24); - assert_size!(Message, 208); + assert_size!(Message, 192); } #[test] diff --git a/parsers/src/presence.rs b/parsers/src/presence.rs index de7ea2bbc43d4ab102da9fcc1bfdf710326f50e2..be2d6a40106f21ca760aa6a85e17172607771c4a 100644 --- a/parsers/src/presence.rs +++ b/parsers/src/presence.rs @@ -379,7 +379,7 @@ mod tests { fn test_size() { assert_size!(Show, 1); assert_size!(Type, 1); - assert_size!(Presence, 80); + assert_size!(Presence, 72); } #[cfg(target_pointer_width = "64")] @@ -387,7 +387,7 @@ mod tests { fn test_size() { assert_size!(Show, 1); assert_size!(Type, 1); - assert_size!(Presence, 160); + assert_size!(Presence, 144); } #[test] diff --git a/parsers/src/pubsub/owner.rs b/parsers/src/pubsub/owner.rs index 4ecea7b77cbe929366dda17df34e3a26a1ef2292..43c65077a7f4692b204fb6b7e9403967fa3fd5fb 100644 --- a/parsers/src/pubsub/owner.rs +++ b/parsers/src/pubsub/owner.rs @@ -200,11 +200,11 @@ mod tests { node: NodeName(String::from("foo")), affiliations: vec![ Affiliation { - jid: Jid::Bare(BareJid::from_str("hamlet@denmark.lit").unwrap()), + jid: Jid::from(BareJid::from_str("hamlet@denmark.lit").unwrap()), affiliation: AffiliationAttribute::Owner, }, Affiliation { - jid: Jid::Bare(BareJid::from_str("polonius@denmark.lit").unwrap()), + jid: Jid::from(BareJid::from_str("polonius@denmark.lit").unwrap()), affiliation: AffiliationAttribute::Outcast, }, ], @@ -335,22 +335,22 @@ mod tests { node: NodeName(String::from("foo")), subscriptions: vec![ SubscriptionElem { - jid: Jid::Bare(BareJid::from_str("hamlet@denmark.lit").unwrap()), + jid: Jid::from(BareJid::from_str("hamlet@denmark.lit").unwrap()), subscription: Subscription::Subscribed, subid: None, }, SubscriptionElem { - jid: Jid::Bare(BareJid::from_str("polonius@denmark.lit").unwrap()), + jid: Jid::from(BareJid::from_str("polonius@denmark.lit").unwrap()), subscription: Subscription::Unconfigured, subid: None, }, SubscriptionElem { - jid: Jid::Bare(BareJid::from_str("bernardo@denmark.lit").unwrap()), + jid: Jid::from(BareJid::from_str("bernardo@denmark.lit").unwrap()), subscription: Subscription::Subscribed, subid: Some(String::from("123-abc")), }, SubscriptionElem { - jid: Jid::Bare(BareJid::from_str("bernardo@denmark.lit").unwrap()), + jid: Jid::from(BareJid::from_str("bernardo@denmark.lit").unwrap()), subscription: Subscription::Subscribed, subid: Some(String::from("004-yyy")), }, diff --git a/parsers/src/stanza_error.rs b/parsers/src/stanza_error.rs index 5cd46459f0ba05d60ccf485b0fb6e186bd9136d7..d60be1f286767994046f0c0a0b5d1cfa4ecfcd65 100644 --- a/parsers/src/stanza_error.rs +++ b/parsers/src/stanza_error.rs @@ -319,7 +319,7 @@ mod tests { fn test_size() { assert_size!(ErrorType, 1); assert_size!(DefinedCondition, 1); - assert_size!(StanzaError, 96); + assert_size!(StanzaError, 92); } #[cfg(target_pointer_width = "64")] @@ -327,7 +327,7 @@ mod tests { fn test_size() { assert_size!(ErrorType, 1); assert_size!(DefinedCondition, 1); - assert_size!(StanzaError, 192); + assert_size!(StanzaError, 184); } #[test] diff --git a/parsers/src/stanza_id.rs b/parsers/src/stanza_id.rs index 3d80a6e13e7e145fede85382ce5f202684ffa048..0ee7da95078ce979b1671d607817bfabcf395320 100644 --- a/parsers/src/stanza_id.rs +++ b/parsers/src/stanza_id.rs @@ -44,14 +44,14 @@ mod tests { #[cfg(target_pointer_width = "32")] #[test] fn test_size() { - assert_size!(StanzaId, 32); + assert_size!(StanzaId, 24); assert_size!(OriginId, 12); } #[cfg(target_pointer_width = "64")] #[test] fn test_size() { - assert_size!(StanzaId, 64); + assert_size!(StanzaId, 56); assert_size!(OriginId, 24); } diff --git a/xmpp/examples/hello_bot.rs b/xmpp/examples/hello_bot.rs index dac0ac66857b6650fcda34436c9f6f20ab480b57..a78d4905a5af0e278598c840238b19b8dc350396 100644 --- a/xmpp/examples/hello_bot.rs +++ b/xmpp/examples/hello_bot.rs @@ -75,7 +75,7 @@ async fn main() -> Result<(), Option<()>> { Event::RoomJoined(jid) => { println!("Joined room {}.", jid); client - .send_message(Jid::Bare(jid), MessageType::Groupchat, "en", "Hello world!") + .send_message(Jid::from(jid), MessageType::Groupchat, "en", "Hello world!") .await; } Event::RoomLeft(jid) => { diff --git a/xmpp/src/message/receive/chat.rs b/xmpp/src/message/receive/chat.rs index bca97c86436e400ca0a179a339a790e515a9782b..2c2ffdd7d9a398ca63937e8c7c1d4061c6508304 100644 --- a/xmpp/src/message/receive/chat.rs +++ b/xmpp/src/message/receive/chat.rs @@ -25,8 +25,8 @@ pub async fn handle_message_chat( for payload in &message.payloads { if let Ok(_) = MucUser::try_from(payload.clone()) { - let event = match from.clone() { - Jid::Bare(bare) => { + let event = match from.clone().try_into_full() { + Err(bare) => { // TODO: Can a service message be of type Chat/Normal and not Groupchat? warn!("Received misformed MessageType::Chat in muc#user namespace from a bare JID."); Event::ServiceMessage( @@ -36,7 +36,7 @@ pub async fn handle_message_chat( time_info.clone(), ) } - Jid::Full(full) => Event::RoomPrivateMessage( + Ok(full) => Event::RoomPrivateMessage( message.id.clone(), full.to_bare(), full.resource().to_string(), diff --git a/xmpp/src/message/receive/group_chat.rs b/xmpp/src/message/receive/group_chat.rs index 118039e6154915f23e0a5d1131915ed5385443cb..2e5c90879fc30f31352c56527d5b98bbbb502528 100644 --- a/xmpp/src/message/receive/group_chat.rs +++ b/xmpp/src/message/receive/group_chat.rs @@ -28,17 +28,15 @@ pub async fn handle_message_group_chat( } if let Some((_lang, body)) = message.get_best_body(langs) { - let event = match from.clone() { - Jid::Full(full) => Event::RoomMessage( + let event = match from.clone().try_into_full() { + Ok(full) => Event::RoomMessage( message.id.clone(), from.to_bare(), full.resource().to_string(), body.clone(), time_info, ), - Jid::Bare(bare) => { - Event::ServiceMessage(message.id.clone(), bare, body.clone(), time_info) - } + Err(bare) => Event::ServiceMessage(message.id.clone(), bare, body.clone(), time_info), }; events.push(event) }