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 781c940..0000000 --- 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 2c8de21..fde640a 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,15 +532,26 @@ 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 Jid { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let s = String::deserialize(deserializer)?; + Jid::new(&s).map_err(de::Error::custom) } } @@ -339,8 +561,8 @@ impl<'de> Deserialize<'de> for FullJid { where D: Deserializer<'de>, { - let s = String::deserialize(deserializer)?; - FullJid::from_str(&s).map_err(de::Error::custom) + 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 2c9a6f3..c4b5643 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 6d02b56..bc0184c 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 f528354..9b931ca 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 a38f4ec..3aeeaf3 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 99623a0..dc23b62 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 28984fa..0bfa1c3 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 2d4451d..ff22b49 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 1d26a20..e082a39 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 f8e8fdc..a116cc7 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 a8db30b..5c9cf30 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 c1e7161..d3fe3bd 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 50fe421..40c45e4 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 de7ea2b..be2d6a4 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 4ecea7b..43c6507 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 5cd4645..d60be1f 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 3d80a6e..0ee7da9 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 dac0ac6..a78d490 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 bca97c8..2c2ffdd 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 118039e..2e5c908 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) }