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.
This commit is contained in:
parent
fb63ac8e50
commit
2e9c9411a3
21 changed files with 464 additions and 448 deletions
180
jid/src/inner.rs
180
jid/src/inner.rs
|
|
@ -1,180 +0,0 @@
|
||||||
// Copyright (c) 2023 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
|
|
||||||
//
|
|
||||||
// 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<NonZeroU16>,
|
|
||||||
pub(crate) slash: Option<NonZeroU16>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl InnerJid {
|
|
||||||
pub(crate) fn new(unnormalized: &str) -> Result<InnerJid, Error> {
|
|
||||||
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<Self, Self::Err> {
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
628
jid/src/lib.rs
628
jid/src/lib.rs
|
|
@ -31,9 +31,15 @@
|
||||||
//! mixing left-to-write and right-to-left characters
|
//! mixing left-to-write and right-to-left characters
|
||||||
|
|
||||||
use core::num::NonZeroU16;
|
use core::num::NonZeroU16;
|
||||||
|
use std::borrow::Cow;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::ops::Deref;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use memchr::memchr;
|
||||||
|
|
||||||
|
use stringprep::{nameprep, nodeprep, resourceprep};
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
|
||||||
|
|
@ -42,53 +48,66 @@ use proc_macro2::TokenStream;
|
||||||
#[cfg(feature = "quote")]
|
#[cfg(feature = "quote")]
|
||||||
use quote::{quote, ToTokens};
|
use quote::{quote, ToTokens};
|
||||||
|
|
||||||
|
#[cfg(feature = "minidom")]
|
||||||
|
use minidom::{IntoAttributeValue, Node};
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
pub use crate::error::Error;
|
pub use crate::error::Error;
|
||||||
|
|
||||||
mod inner;
|
|
||||||
use inner::InnerJid;
|
|
||||||
|
|
||||||
mod parts;
|
mod parts;
|
||||||
pub use parts::{DomainPart, DomainRef, NodePart, NodeRef, ResourcePart, ResourceRef};
|
pub use parts::{DomainPart, DomainRef, NodePart, NodeRef, ResourcePart, ResourceRef};
|
||||||
|
|
||||||
/// An enum representing a Jabber ID. It can be either a `FullJid` or a `BareJid`.
|
fn length_check(len: usize, error_empty: Error, error_too_long: Error) -> Result<(), Error> {
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
if len == 0 {
|
||||||
#[cfg_attr(feature = "serde", serde(untagged))]
|
Err(error_empty)
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
|
} else if len > 1023 {
|
||||||
pub enum Jid {
|
Err(error_too_long)
|
||||||
/// Contains a [`BareJid`], without a resource part
|
} else {
|
||||||
Bare(BareJid),
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Contains a [`FullJid`], with a resource part
|
/// A struct representing a Jabber ID (JID).
|
||||||
Full(FullJid),
|
///
|
||||||
|
/// 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<NonZeroU16>,
|
||||||
|
slash: Option<NonZeroU16>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for Jid {
|
impl FromStr for Jid {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Jid, Error> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
Jid::new(s)
|
Self::new(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<BareJid> for Jid {
|
impl From<BareJid> for Jid {
|
||||||
fn from(bare_jid: BareJid) -> Jid {
|
fn from(other: BareJid) -> Self {
|
||||||
Jid::Bare(bare_jid)
|
other.inner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<FullJid> for Jid {
|
impl From<FullJid> for Jid {
|
||||||
fn from(full_jid: FullJid) -> Jid {
|
fn from(other: FullJid) -> Self {
|
||||||
Jid::Full(full_jid)
|
other.inner
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Jid {
|
impl fmt::Display for Jid {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
fmt.write_str(&self.normalized)
|
||||||
Jid::Bare(bare) => bare.fmt(fmt),
|
|
||||||
Jid::Full(full) => full.fmt(fmt),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -112,20 +131,81 @@ impl Jid {
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new(s: &str) -> Result<Jid, Error> {
|
pub fn new(unnormalized: &str) -> Result<Jid, Error> {
|
||||||
let inner = InnerJid::new(s)?;
|
let bytes = unnormalized.as_bytes();
|
||||||
if inner.slash.is_some() {
|
let mut orig_at = memchr(b'@', bytes);
|
||||||
Ok(Jid::Full(FullJid { inner }))
|
let mut orig_slash = memchr(b'/', bytes);
|
||||||
} else {
|
if orig_at.is_some() && orig_slash.is_some() && orig_at > orig_slash {
|
||||||
Ok(Jid::Bare(BareJid { inner }))
|
// 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.
|
/// Returns the inner String of this JID.
|
||||||
pub fn into_inner(self) -> String {
|
pub fn into_inner(self) -> String {
|
||||||
match self {
|
self.normalized
|
||||||
Jid::Bare(BareJid { inner }) | Jid::Full(FullJid { inner }) => inner.normalized,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build a [`Jid`] from typed parts. This method cannot fail because it uses parts that have
|
/// 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>,
|
node: Option<&NodeRef>,
|
||||||
domain: &DomainRef,
|
domain: &DomainRef,
|
||||||
resource: Option<&ResourceRef>,
|
resource: Option<&ResourceRef>,
|
||||||
) -> Jid {
|
) -> Self {
|
||||||
if let Some(resource) = resource {
|
match resource {
|
||||||
Jid::Full(FullJid::from_parts(node, domain, resource))
|
Some(resource) => FullJid::from_parts(node, domain, resource).into(),
|
||||||
} else {
|
None => BareJid::from_parts(node, domain).into(),
|
||||||
Jid::Bare(BareJid::from_parts(node, domain))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The optional node part of the JID as reference.
|
/// The optional node part of the JID as reference.
|
||||||
pub fn node(&self) -> Option<&NodeRef> {
|
pub fn node(&self) -> Option<&NodeRef> {
|
||||||
match self {
|
self.at.map(|at| {
|
||||||
Jid::Bare(BareJid { inner }) | Jid::Full(FullJid { inner }) => inner.node(),
|
let at = u16::from(at) as usize;
|
||||||
}
|
NodeRef::from_str_unchecked(&self.normalized[..at])
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The domain part of the JID as reference
|
/// The domain part of the JID as reference
|
||||||
pub fn domain(&self) -> &DomainRef {
|
pub fn domain(&self) -> &DomainRef {
|
||||||
match self {
|
match (self.at, self.slash) {
|
||||||
Jid::Bare(BareJid { inner }) | Jid::Full(FullJid { inner }) => inner.domain(),
|
(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
|
/// 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`].
|
/// a Full variant, which you can check with [`Jid::is_full`].
|
||||||
pub fn resource(&self) -> Option<&ResourceRef> {
|
pub fn resource(&self) -> Option<&ResourceRef> {
|
||||||
match self {
|
self.slash.map(|slash| {
|
||||||
Jid::Bare(BareJid { inner }) | Jid::Full(FullJid { inner }) => inner.resource(),
|
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.
|
/// Allocate a new [`BareJid`] from this JID, discarding the resource.
|
||||||
pub fn to_bare(&self) -> BareJid {
|
pub fn to_bare(&self) -> BareJid {
|
||||||
match self {
|
BareJid::from_parts(self.node(), self.domain())
|
||||||
Jid::Full(jid) => jid.to_bare(),
|
|
||||||
Jid::Bare(jid) => jid.clone(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transforms this JID into a [`BareJid`], throwing away the resource.
|
/// Transforms this JID into a [`BareJid`], throwing away the resource.
|
||||||
pub fn into_bare(self) -> BareJid {
|
///
|
||||||
match self {
|
/// ```
|
||||||
Jid::Full(jid) => jid.into_bare(),
|
/// # use jid::{BareJid, Jid};
|
||||||
Jid::Bare(jid) => 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 {
|
pub fn is_full(&self) -> bool {
|
||||||
match self {
|
self.slash.is_some()
|
||||||
Self::Full(_) => true,
|
|
||||||
Self::Bare(_) => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if the JID contains a [`BareJid`]
|
/// Checks if the JID is a bare JID.
|
||||||
pub fn is_bare(&self) -> bool {
|
pub fn is_bare(&self) -> bool {
|
||||||
!self.is_full()
|
self.slash.is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a reference to the canonical string representation of the JID.
|
/// Return a reference to the canonical string representation of the JID.
|
||||||
pub fn as_str(&self) -> &str {
|
pub fn as_str(&self) -> &str {
|
||||||
match self {
|
&self.normalized
|
||||||
Jid::Bare(BareJid { inner }) | Jid::Full(FullJid { inner }) => inner.as_str(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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<FullJid, BareJid> {
|
||||||
|
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<Jid> for FullJid {
|
impl TryFrom<Jid> for FullJid {
|
||||||
type Error = Error;
|
type Error = Error;
|
||||||
|
|
||||||
fn try_from(jid: Jid) -> Result<Self, Self::Error> {
|
fn try_from(inner: Jid) -> Result<Self, Self::Error> {
|
||||||
match jid {
|
if inner.slash.is_none() {
|
||||||
Jid::Full(full) => Ok(full),
|
return Err(Error::ResourceMissingInFullJid);
|
||||||
Jid::Bare(_) => Err(Error::ResourceMissingInFullJid),
|
|
||||||
}
|
}
|
||||||
|
Ok(Self { inner })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Jid> for BareJid {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn try_from(inner: Jid) -> Result<Self, Self::Error> {
|
||||||
|
if inner.slash.is_some() {
|
||||||
|
return Err(Error::ResourceInBareJid);
|
||||||
|
}
|
||||||
|
Ok(Self { inner })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq<Jid> for FullJid {
|
impl PartialEq<Jid> for FullJid {
|
||||||
fn eq(&self, other: &Jid) -> bool {
|
fn eq(&self, other: &Jid) -> bool {
|
||||||
match other {
|
&self.inner == other
|
||||||
Jid::Full(full) => self == full,
|
|
||||||
Jid::Bare(_) => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq<Jid> for BareJid {
|
impl PartialEq<Jid> for BareJid {
|
||||||
fn eq(&self, other: &Jid) -> bool {
|
fn eq(&self, other: &Jid) -> bool {
|
||||||
match other {
|
&self.inner == other
|
||||||
Jid::Full(_) => false,
|
|
||||||
Jid::Bare(bare) => self == bare,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq<FullJid> for Jid {
|
impl PartialEq<FullJid> for Jid {
|
||||||
fn eq(&self, other: &FullJid) -> bool {
|
fn eq(&self, other: &FullJid) -> bool {
|
||||||
match self {
|
self == &other.inner
|
||||||
Jid::Full(full) => full == other,
|
|
||||||
Jid::Bare(_) => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq<BareJid> for Jid {
|
impl PartialEq<BareJid> for Jid {
|
||||||
fn eq(&self, other: &BareJid) -> bool {
|
fn eq(&self, other: &BareJid) -> bool {
|
||||||
match self {
|
self == &other.inner
|
||||||
Jid::Full(_) => false,
|
|
||||||
Jid::Bare(bare) => bare == other,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -263,9 +446,10 @@ impl PartialEq<BareJid> for Jid {
|
||||||
/// Unlike a [`BareJid`], it always contains a resource, and should only be used when you are
|
/// 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
|
/// certain there is no case where a resource can be missing. Otherwise, use a [`Jid`] or
|
||||||
/// [`BareJid`].
|
/// [`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 {
|
pub struct FullJid {
|
||||||
inner: InnerJid,
|
inner: Jid,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A struct representing a bare Jabber ID, without a resource part.
|
/// 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
|
/// 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`].
|
/// 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 {
|
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 {
|
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()
|
fmt.debug_tuple("FullJid").field(&self.inner).finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for BareJid {
|
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()
|
fmt.debug_tuple("BareJid").field(&self.inner).finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for FullJid {
|
impl fmt::Display for FullJid {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt.write_str(&self.inner.normalized)
|
fmt::Display::fmt(&self.inner, fmt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for BareJid {
|
impl fmt::Display for BareJid {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt.write_str(&self.inner.normalized)
|
fmt::Display::fmt(&self.inner, fmt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
impl Serialize for Jid {
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_str(&self.normalized)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -311,7 +522,7 @@ impl Serialize for FullJid {
|
||||||
where
|
where
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
serializer.serialize_str(&self.inner.normalized)
|
self.inner.serialize(serializer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -321,15 +532,26 @@ impl Serialize for BareJid {
|
||||||
where
|
where
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
serializer.serialize_str(&self.inner.normalized)
|
self.inner.serialize(serializer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for FullJid {
|
impl FromStr for FullJid {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<FullJid, Error> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
FullJid::new(s)
|
Self::new(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
impl<'de> Deserialize<'de> for Jid {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
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
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let s = String::deserialize(deserializer)?;
|
let jid = Jid::deserialize(deserializer)?;
|
||||||
FullJid::from_str(&s).map_err(de::Error::custom)
|
jid.try_into().map_err(de::Error::custom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -350,17 +572,17 @@ impl<'de> Deserialize<'de> for BareJid {
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
{
|
{
|
||||||
let s = String::deserialize(deserializer)?;
|
let jid = Jid::deserialize(deserializer)?;
|
||||||
BareJid::from_str(&s).map_err(de::Error::custom)
|
jid.try_into().map_err(de::Error::custom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "quote")]
|
#[cfg(feature = "quote")]
|
||||||
impl ToTokens for Jid {
|
impl ToTokens for Jid {
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
tokens.extend(match self {
|
let s = &self.normalized;
|
||||||
Jid::Full(full) => quote! { Jid::Full(#full) },
|
tokens.extend(quote! {
|
||||||
Jid::Bare(bare) => quote! { Jid::Bare(#bare) },
|
::jid::Jid::new(#s).unwrap()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -368,18 +590,20 @@ impl ToTokens for Jid {
|
||||||
#[cfg(feature = "quote")]
|
#[cfg(feature = "quote")]
|
||||||
impl ToTokens for FullJid {
|
impl ToTokens for FullJid {
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
let inner = &self.inner.normalized;
|
let s = &self.inner.normalized;
|
||||||
let t = quote! { FullJid::new(#inner).unwrap() };
|
tokens.extend(quote! {
|
||||||
tokens.extend(t);
|
::jid::FullJid::new(#s).unwrap()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "quote")]
|
#[cfg(feature = "quote")]
|
||||||
impl ToTokens for BareJid {
|
impl ToTokens for BareJid {
|
||||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||||
let inner = &self.inner.normalized;
|
let s = &self.inner.normalized;
|
||||||
let t = quote! { BareJid::new(#inner).unwrap() };
|
tokens.extend(quote! {
|
||||||
tokens.extend(t);
|
::jid::BareJid::new(#s).unwrap()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -403,18 +627,8 @@ impl FullJid {
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new(s: &str) -> Result<FullJid, Error> {
|
pub fn new(unnormalized: &str) -> Result<Self, Error> {
|
||||||
let inner = InnerJid::new(s)?;
|
Jid::new(unnormalized)?.try_into()
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build a [`FullJid`] from typed parts. This method cannot fail because it uses parts that have
|
/// 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,
|
normalized,
|
||||||
at,
|
at,
|
||||||
slash,
|
slash,
|
||||||
};
|
};
|
||||||
|
|
||||||
FullJid { inner }
|
Self { 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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The optional resource of the Jabber ID. Since this is a full JID it is always present.
|
/// The optional resource of the Jabber ID. Since this is a full JID it is always present.
|
||||||
pub fn resource(&self) -> &ResourceRef {
|
pub fn resource(&self) -> &ResourceRef {
|
||||||
self.inner.resource().unwrap()
|
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 {
|
impl FromStr for BareJid {
|
||||||
type Err = Error;
|
type Err = Error;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<BareJid, Error> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
BareJid::new(s)
|
Self::new(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -523,18 +701,8 @@ impl BareJid {
|
||||||
/// # Ok(())
|
/// # Ok(())
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn new(s: &str) -> Result<BareJid, Error> {
|
pub fn new(unnormalized: &str) -> Result<Self, Error> {
|
||||||
let inner = InnerJid::new(s)?;
|
Jid::new(unnormalized)?.try_into()
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build a [`BareJid`] from typed parts. This method cannot fail because it uses parts that have
|
/// 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
|
/// 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
|
/// allocation if `node` is known to be `None` and `domain` is owned, you
|
||||||
/// can use `domain.into()`.
|
/// 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 {
|
let (at, normalized) = if let Some(node) = node {
|
||||||
// Parts are never empty so len > 0 for NonZeroU16::new is always Some
|
// Parts are never empty so len > 0 for NonZeroU16::new is always Some
|
||||||
(
|
(
|
||||||
|
|
@ -554,23 +722,13 @@ impl BareJid {
|
||||||
(None, domain.to_string())
|
(None, domain.to_string())
|
||||||
};
|
};
|
||||||
|
|
||||||
let inner = InnerJid {
|
let inner = Jid {
|
||||||
normalized,
|
normalized,
|
||||||
at,
|
at,
|
||||||
slash: None,
|
slash: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
BareJid { inner }
|
Self { 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()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a [`BareJid`] from the bare JID, by specifying a [`ResourcePart`].
|
/// 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 {
|
pub fn with_resource(&self, resource: &ResourceRef) -> FullJid {
|
||||||
let slash = NonZeroU16::new(self.inner.normalized.len() as u16);
|
let slash = NonZeroU16::new(self.inner.normalized.len() as u16);
|
||||||
let normalized = format!("{}/{resource}", self.inner.normalized);
|
let normalized = format!("{}/{resource}", self.inner.normalized);
|
||||||
let inner = InnerJid {
|
let inner = Jid {
|
||||||
normalized,
|
normalized,
|
||||||
at: self.inner.at,
|
at: self.inner.at,
|
||||||
slash,
|
slash,
|
||||||
|
|
@ -620,15 +778,7 @@ impl BareJid {
|
||||||
let resource = ResourcePart::new(resource)?;
|
let resource = ResourcePart::new(resource)?;
|
||||||
Ok(self.with_resource(&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")]
|
#[cfg(feature = "minidom")]
|
||||||
impl IntoAttributeValue for Jid {
|
impl IntoAttributeValue for Jid {
|
||||||
|
|
@ -639,7 +789,7 @@ impl IntoAttributeValue for Jid {
|
||||||
|
|
||||||
#[cfg(feature = "minidom")]
|
#[cfg(feature = "minidom")]
|
||||||
impl From<Jid> for Node {
|
impl From<Jid> for Node {
|
||||||
fn from(jid: Jid) -> Node {
|
fn from(jid: Jid) -> Self {
|
||||||
Node::Text(jid.to_string())
|
Node::Text(jid.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -647,28 +797,28 @@ impl From<Jid> for Node {
|
||||||
#[cfg(feature = "minidom")]
|
#[cfg(feature = "minidom")]
|
||||||
impl IntoAttributeValue for FullJid {
|
impl IntoAttributeValue for FullJid {
|
||||||
fn into_attribute_value(self) -> Option<String> {
|
fn into_attribute_value(self) -> Option<String> {
|
||||||
Some(self.to_string())
|
self.inner.into_attribute_value()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "minidom")]
|
#[cfg(feature = "minidom")]
|
||||||
impl From<FullJid> for Node {
|
impl From<FullJid> for Node {
|
||||||
fn from(jid: FullJid) -> Node {
|
fn from(jid: FullJid) -> Self {
|
||||||
Node::Text(jid.to_string())
|
jid.inner.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "minidom")]
|
#[cfg(feature = "minidom")]
|
||||||
impl IntoAttributeValue for BareJid {
|
impl IntoAttributeValue for BareJid {
|
||||||
fn into_attribute_value(self) -> Option<String> {
|
fn into_attribute_value(self) -> Option<String> {
|
||||||
Some(self.to_string())
|
self.inner.into_attribute_value()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "minidom")]
|
#[cfg(feature = "minidom")]
|
||||||
impl From<BareJid> for Node {
|
impl From<BareJid> for Node {
|
||||||
fn from(jid: BareJid) -> Node {
|
fn from(other: BareJid) -> Self {
|
||||||
Node::Text(jid.to_string())
|
other.inner.into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -689,7 +839,7 @@ mod tests {
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(BareJid, 16);
|
assert_size!(BareJid, 16);
|
||||||
assert_size!(FullJid, 16);
|
assert_size!(FullJid, 16);
|
||||||
assert_size!(Jid, 20);
|
assert_size!(Jid, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
|
|
@ -697,7 +847,7 @@ mod tests {
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(BareJid, 32);
|
assert_size!(BareJid, 32);
|
||||||
assert_size!(FullJid, 32);
|
assert_size!(FullJid, 32);
|
||||||
assert_size!(Jid, 40);
|
assert_size!(Jid, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -735,8 +885,8 @@ mod tests {
|
||||||
let full = FullJid::from_str("a@b.c/d").unwrap();
|
let full = FullJid::from_str("a@b.c/d").unwrap();
|
||||||
let bare = BareJid::from_str("e@f.g").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("a@b.c/d").unwrap(), full);
|
||||||
assert_eq!(Jid::from_str("e@f.g"), Ok(Jid::Bare(bare)));
|
assert_eq!(Jid::from_str("e@f.g").unwrap(), bare);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -792,13 +942,13 @@ mod tests {
|
||||||
let full = FullJid::new("a@b.c/d").unwrap();
|
let full = FullJid::new("a@b.c/d").unwrap();
|
||||||
let bare = BareJid::new("a@b.c").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!(
|
assert_eq!(
|
||||||
FullJid::try_from(Jid::Bare(bare.clone())),
|
FullJid::try_from(Jid::from(bare.clone())),
|
||||||
Err(Error::ResourceMissingInFullJid),
|
Err(Error::ResourceMissingInFullJid),
|
||||||
);
|
);
|
||||||
assert_eq!(Jid::Bare(full.clone().to_bare()), bare.clone());
|
assert_eq!(Jid::from(full.clone().to_bare()), bare.clone());
|
||||||
assert_eq!(Jid::Bare(bare.clone()), bare);
|
assert_eq!(Jid::from(bare.clone()), bare);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -836,10 +986,10 @@ mod tests {
|
||||||
assert_eq!(FullJid::new("a@b/c").unwrap().to_string(), "a@b/c");
|
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!(BareJid::new("a@b").unwrap().to_string(), "a@b");
|
||||||
assert_eq!(
|
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"
|
"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")]
|
#[cfg(feature = "minidom")]
|
||||||
|
|
@ -847,11 +997,11 @@ mod tests {
|
||||||
fn minidom() {
|
fn minidom() {
|
||||||
let elem: minidom::Element = "<message xmlns='ns1' from='a@b/c'/>".parse().unwrap();
|
let elem: minidom::Element = "<message xmlns='ns1' from='a@b/c'/>".parse().unwrap();
|
||||||
let to: Jid = elem.attr("from").unwrap().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 = "<message xmlns='ns1' from='a@b'/>".parse().unwrap();
|
let elem: minidom::Element = "<message xmlns='ns1' from='a@b'/>".parse().unwrap();
|
||||||
let to: Jid = elem.attr("from").unwrap().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 = "<message xmlns='ns1' from='a@b/c'/>".parse().unwrap();
|
let elem: minidom::Element = "<message xmlns='ns1' from='a@b/c'/>".parse().unwrap();
|
||||||
let to: FullJid = elem.attr("from").unwrap().parse().unwrap();
|
let to: FullJid = elem.attr("from").unwrap().parse().unwrap();
|
||||||
|
|
@ -877,7 +1027,7 @@ mod tests {
|
||||||
.build();
|
.build();
|
||||||
assert_eq!(elem.attr("from"), Some(bare.to_string().as_str()));
|
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")
|
let _elem = minidom::Element::builder("message", "jabber:client")
|
||||||
.attr("from", jid)
|
.attr("from", jid)
|
||||||
.build();
|
.build();
|
||||||
|
|
@ -939,4 +1089,52 @@ mod tests {
|
||||||
assert_eq!(jid1, jid2);
|
assert_eq!(jid1, jid2);
|
||||||
assert_eq!(jid2, jid3);
|
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),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use std::str::FromStr;
|
||||||
|
|
||||||
use stringprep::{nameprep, nodeprep, resourceprep};
|
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> {
|
fn length_check(len: usize, error_empty: Error, error_too_long: Error) -> Result<(), Error> {
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
|
|
@ -250,18 +250,18 @@ impl DomainRef {
|
||||||
impl From<DomainPart> for BareJid {
|
impl From<DomainPart> for BareJid {
|
||||||
fn from(other: DomainPart) -> Self {
|
fn from(other: DomainPart) -> Self {
|
||||||
BareJid {
|
BareJid {
|
||||||
inner: InnerJid {
|
inner: other.into(),
|
||||||
normalized: other.0,
|
|
||||||
at: None,
|
|
||||||
slash: None,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<DomainPart> for Jid {
|
impl From<DomainPart> for Jid {
|
||||||
fn from(other: DomainPart) -> Self {
|
fn from(other: DomainPart) -> Self {
|
||||||
Jid::Bare(other.into())
|
Jid {
|
||||||
|
normalized: other.0,
|
||||||
|
at: None,
|
||||||
|
slash: None,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ impl From<BindResponse> for FullJid {
|
||||||
|
|
||||||
impl From<BindResponse> for Jid {
|
impl From<BindResponse> for Jid {
|
||||||
fn from(bind: BindResponse) -> Jid {
|
fn from(bind: BindResponse) -> Jid {
|
||||||
Jid::Full(bind.jid)
|
Jid::from(bind.jid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,8 @@ mod tests {
|
||||||
assert_size!(Enable, 0);
|
assert_size!(Enable, 0);
|
||||||
assert_size!(Disable, 0);
|
assert_size!(Disable, 0);
|
||||||
assert_size!(Private, 0);
|
assert_size!(Private, 0);
|
||||||
assert_size!(Received, 152);
|
assert_size!(Received, 140);
|
||||||
assert_size!(Sent, 152);
|
assert_size!(Sent, 140);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
|
|
@ -81,8 +81,8 @@ mod tests {
|
||||||
assert_size!(Enable, 0);
|
assert_size!(Enable, 0);
|
||||||
assert_size!(Disable, 0);
|
assert_size!(Disable, 0);
|
||||||
assert_size!(Private, 0);
|
assert_size!(Private, 0);
|
||||||
assert_size!(Received, 288);
|
assert_size!(Received, 264);
|
||||||
assert_size!(Sent, 288);
|
assert_size!(Sent, 264);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -40,13 +40,13 @@ mod tests {
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(Delay, 48);
|
assert_size!(Delay, 44);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(Delay, 80);
|
assert_size!(Delay, 72);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -248,7 +248,7 @@ mod tests {
|
||||||
assert_size!(DiscoInfoQuery, 12);
|
assert_size!(DiscoInfoQuery, 12);
|
||||||
assert_size!(DiscoInfoResult, 48);
|
assert_size!(DiscoInfoResult, 48);
|
||||||
|
|
||||||
assert_size!(Item, 44);
|
assert_size!(Item, 40);
|
||||||
assert_size!(DiscoItemsQuery, 52);
|
assert_size!(DiscoItemsQuery, 52);
|
||||||
assert_size!(DiscoItemsResult, 64);
|
assert_size!(DiscoItemsResult, 64);
|
||||||
}
|
}
|
||||||
|
|
@ -261,7 +261,7 @@ mod tests {
|
||||||
assert_size!(DiscoInfoQuery, 24);
|
assert_size!(DiscoInfoQuery, 24);
|
||||||
assert_size!(DiscoInfoResult, 96);
|
assert_size!(DiscoInfoResult, 96);
|
||||||
|
|
||||||
assert_size!(Item, 88);
|
assert_size!(Item, 80);
|
||||||
assert_size!(DiscoItemsQuery, 104);
|
assert_size!(DiscoItemsQuery, 104);
|
||||||
assert_size!(DiscoItemsResult, 128);
|
assert_size!(DiscoItemsResult, 128);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,13 +32,13 @@ mod tests {
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(Forwarded, 152);
|
assert_size!(Forwarded, 140);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(Forwarded, 288);
|
assert_size!(Forwarded, 264);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -232,15 +232,15 @@ mod tests {
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(IqType, 96);
|
assert_size!(IqType, 92);
|
||||||
assert_size!(Iq, 148);
|
assert_size!(Iq, 156);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(IqType, 192);
|
assert_size!(IqType, 184);
|
||||||
assert_size!(Iq, 296);
|
assert_size!(Iq, 272);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -46,14 +46,14 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(JidPrepQuery, 12);
|
assert_size!(JidPrepQuery, 12);
|
||||||
assert_size!(JidPrepResponse, 20);
|
assert_size!(JidPrepResponse, 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(JidPrepQuery, 24);
|
assert_size!(JidPrepQuery, 24);
|
||||||
assert_size!(JidPrepResponse, 40);
|
assert_size!(JidPrepResponse, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -692,7 +692,7 @@ mod tests {
|
||||||
assert_size!(Reason, 1);
|
assert_size!(Reason, 1);
|
||||||
assert_size!(ReasonElement, 16);
|
assert_size!(ReasonElement, 16);
|
||||||
assert_size!(SessionId, 12);
|
assert_size!(SessionId, 12);
|
||||||
assert_size!(Jingle, 112);
|
assert_size!(Jingle, 104);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
|
|
@ -711,7 +711,7 @@ mod tests {
|
||||||
assert_size!(Reason, 1);
|
assert_size!(Reason, 1);
|
||||||
assert_size!(ReasonElement, 32);
|
assert_size!(ReasonElement, 32);
|
||||||
assert_size!(SessionId, 24);
|
assert_size!(SessionId, 24);
|
||||||
assert_size!(Jingle, 224);
|
assert_size!(Jingle, 208);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -284,7 +284,7 @@ mod tests {
|
||||||
assert_size!(Mode, 1);
|
assert_size!(Mode, 1);
|
||||||
assert_size!(CandidateId, 12);
|
assert_size!(CandidateId, 12);
|
||||||
assert_size!(StreamId, 12);
|
assert_size!(StreamId, 12);
|
||||||
assert_size!(Candidate, 60);
|
assert_size!(Candidate, 56);
|
||||||
assert_size!(TransportPayload, 16);
|
assert_size!(TransportPayload, 16);
|
||||||
assert_size!(Transport, 44);
|
assert_size!(Transport, 44);
|
||||||
}
|
}
|
||||||
|
|
@ -296,7 +296,7 @@ mod tests {
|
||||||
assert_size!(Mode, 1);
|
assert_size!(Mode, 1);
|
||||||
assert_size!(CandidateId, 24);
|
assert_size!(CandidateId, 24);
|
||||||
assert_size!(StreamId, 24);
|
assert_size!(StreamId, 24);
|
||||||
assert_size!(Candidate, 96);
|
assert_size!(Candidate, 88);
|
||||||
assert_size!(TransportPayload, 32);
|
assert_size!(TransportPayload, 32);
|
||||||
assert_size!(Transport, 88);
|
assert_size!(Transport, 88);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ mod tests {
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(QueryId, 12);
|
assert_size!(QueryId, 12);
|
||||||
assert_size!(Query, 120);
|
assert_size!(Query, 120);
|
||||||
assert_size!(Result_, 176);
|
assert_size!(Result_, 164);
|
||||||
assert_size!(Complete, 1);
|
assert_size!(Complete, 1);
|
||||||
assert_size!(Fin, 44);
|
assert_size!(Fin, 44);
|
||||||
}
|
}
|
||||||
|
|
@ -176,7 +176,7 @@ mod tests {
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(QueryId, 24);
|
assert_size!(QueryId, 24);
|
||||||
assert_size!(Query, 240);
|
assert_size!(Query, 240);
|
||||||
assert_size!(Result_, 336);
|
assert_size!(Result_, 312);
|
||||||
assert_size!(Complete, 1);
|
assert_size!(Complete, 1);
|
||||||
assert_size!(Fin, 88);
|
assert_size!(Fin, 88);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -307,7 +307,7 @@ mod tests {
|
||||||
assert_size!(Body, 12);
|
assert_size!(Body, 12);
|
||||||
assert_size!(Subject, 12);
|
assert_size!(Subject, 12);
|
||||||
assert_size!(Thread, 12);
|
assert_size!(Thread, 12);
|
||||||
assert_size!(Message, 104);
|
assert_size!(Message, 96);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
|
|
@ -317,7 +317,7 @@ mod tests {
|
||||||
assert_size!(Body, 24);
|
assert_size!(Body, 24);
|
||||||
assert_size!(Subject, 24);
|
assert_size!(Subject, 24);
|
||||||
assert_size!(Thread, 24);
|
assert_size!(Thread, 24);
|
||||||
assert_size!(Message, 208);
|
assert_size!(Message, 192);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -379,7 +379,7 @@ mod tests {
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(Show, 1);
|
assert_size!(Show, 1);
|
||||||
assert_size!(Type, 1);
|
assert_size!(Type, 1);
|
||||||
assert_size!(Presence, 80);
|
assert_size!(Presence, 72);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
|
|
@ -387,7 +387,7 @@ mod tests {
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(Show, 1);
|
assert_size!(Show, 1);
|
||||||
assert_size!(Type, 1);
|
assert_size!(Type, 1);
|
||||||
assert_size!(Presence, 160);
|
assert_size!(Presence, 144);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -200,11 +200,11 @@ mod tests {
|
||||||
node: NodeName(String::from("foo")),
|
node: NodeName(String::from("foo")),
|
||||||
affiliations: vec![
|
affiliations: vec![
|
||||||
Affiliation {
|
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: AffiliationAttribute::Owner,
|
||||||
},
|
},
|
||||||
Affiliation {
|
Affiliation {
|
||||||
jid: Jid::Bare(BareJid::from_str("polonius@denmark.lit").unwrap()),
|
jid: Jid::from(BareJid::from_str("polonius@denmark.lit").unwrap()),
|
||||||
affiliation: AffiliationAttribute::Outcast,
|
affiliation: AffiliationAttribute::Outcast,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -335,22 +335,22 @@ mod tests {
|
||||||
node: NodeName(String::from("foo")),
|
node: NodeName(String::from("foo")),
|
||||||
subscriptions: vec![
|
subscriptions: vec![
|
||||||
SubscriptionElem {
|
SubscriptionElem {
|
||||||
jid: Jid::Bare(BareJid::from_str("hamlet@denmark.lit").unwrap()),
|
jid: Jid::from(BareJid::from_str("hamlet@denmark.lit").unwrap()),
|
||||||
subscription: Subscription::Subscribed,
|
subscription: Subscription::Subscribed,
|
||||||
subid: None,
|
subid: None,
|
||||||
},
|
},
|
||||||
SubscriptionElem {
|
SubscriptionElem {
|
||||||
jid: Jid::Bare(BareJid::from_str("polonius@denmark.lit").unwrap()),
|
jid: Jid::from(BareJid::from_str("polonius@denmark.lit").unwrap()),
|
||||||
subscription: Subscription::Unconfigured,
|
subscription: Subscription::Unconfigured,
|
||||||
subid: None,
|
subid: None,
|
||||||
},
|
},
|
||||||
SubscriptionElem {
|
SubscriptionElem {
|
||||||
jid: Jid::Bare(BareJid::from_str("bernardo@denmark.lit").unwrap()),
|
jid: Jid::from(BareJid::from_str("bernardo@denmark.lit").unwrap()),
|
||||||
subscription: Subscription::Subscribed,
|
subscription: Subscription::Subscribed,
|
||||||
subid: Some(String::from("123-abc")),
|
subid: Some(String::from("123-abc")),
|
||||||
},
|
},
|
||||||
SubscriptionElem {
|
SubscriptionElem {
|
||||||
jid: Jid::Bare(BareJid::from_str("bernardo@denmark.lit").unwrap()),
|
jid: Jid::from(BareJid::from_str("bernardo@denmark.lit").unwrap()),
|
||||||
subscription: Subscription::Subscribed,
|
subscription: Subscription::Subscribed,
|
||||||
subid: Some(String::from("004-yyy")),
|
subid: Some(String::from("004-yyy")),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -319,7 +319,7 @@ mod tests {
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(ErrorType, 1);
|
assert_size!(ErrorType, 1);
|
||||||
assert_size!(DefinedCondition, 1);
|
assert_size!(DefinedCondition, 1);
|
||||||
assert_size!(StanzaError, 96);
|
assert_size!(StanzaError, 92);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
|
|
@ -327,7 +327,7 @@ mod tests {
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(ErrorType, 1);
|
assert_size!(ErrorType, 1);
|
||||||
assert_size!(DefinedCondition, 1);
|
assert_size!(DefinedCondition, 1);
|
||||||
assert_size!(StanzaError, 192);
|
assert_size!(StanzaError, 184);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
|
|
@ -44,14 +44,14 @@ mod tests {
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(StanzaId, 32);
|
assert_size!(StanzaId, 24);
|
||||||
assert_size!(OriginId, 12);
|
assert_size!(OriginId, 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
#[test]
|
#[test]
|
||||||
fn test_size() {
|
fn test_size() {
|
||||||
assert_size!(StanzaId, 64);
|
assert_size!(StanzaId, 56);
|
||||||
assert_size!(OriginId, 24);
|
assert_size!(OriginId, 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ async fn main() -> Result<(), Option<()>> {
|
||||||
Event::RoomJoined(jid) => {
|
Event::RoomJoined(jid) => {
|
||||||
println!("Joined room {}.", jid);
|
println!("Joined room {}.", jid);
|
||||||
client
|
client
|
||||||
.send_message(Jid::Bare(jid), MessageType::Groupchat, "en", "Hello world!")
|
.send_message(Jid::from(jid), MessageType::Groupchat, "en", "Hello world!")
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
Event::RoomLeft(jid) => {
|
Event::RoomLeft(jid) => {
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,8 @@ pub async fn handle_message_chat<C: ServerConnector>(
|
||||||
|
|
||||||
for payload in &message.payloads {
|
for payload in &message.payloads {
|
||||||
if let Ok(_) = MucUser::try_from(payload.clone()) {
|
if let Ok(_) = MucUser::try_from(payload.clone()) {
|
||||||
let event = match from.clone() {
|
let event = match from.clone().try_into_full() {
|
||||||
Jid::Bare(bare) => {
|
Err(bare) => {
|
||||||
// TODO: Can a service message be of type Chat/Normal and not Groupchat?
|
// 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.");
|
warn!("Received misformed MessageType::Chat in muc#user namespace from a bare JID.");
|
||||||
Event::ServiceMessage(
|
Event::ServiceMessage(
|
||||||
|
|
@ -36,7 +36,7 @@ pub async fn handle_message_chat<C: ServerConnector>(
|
||||||
time_info.clone(),
|
time_info.clone(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Jid::Full(full) => Event::RoomPrivateMessage(
|
Ok(full) => Event::RoomPrivateMessage(
|
||||||
message.id.clone(),
|
message.id.clone(),
|
||||||
full.to_bare(),
|
full.to_bare(),
|
||||||
full.resource().to_string(),
|
full.resource().to_string(),
|
||||||
|
|
|
||||||
|
|
@ -28,17 +28,15 @@ pub async fn handle_message_group_chat<C: ServerConnector>(
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((_lang, body)) = message.get_best_body(langs) {
|
if let Some((_lang, body)) = message.get_best_body(langs) {
|
||||||
let event = match from.clone() {
|
let event = match from.clone().try_into_full() {
|
||||||
Jid::Full(full) => Event::RoomMessage(
|
Ok(full) => Event::RoomMessage(
|
||||||
message.id.clone(),
|
message.id.clone(),
|
||||||
from.to_bare(),
|
from.to_bare(),
|
||||||
full.resource().to_string(),
|
full.resource().to_string(),
|
||||||
body.clone(),
|
body.clone(),
|
||||||
time_info,
|
time_info,
|
||||||
),
|
),
|
||||||
Jid::Bare(bare) => {
|
Err(bare) => Event::ServiceMessage(message.id.clone(), bare, body.clone(), time_info),
|
||||||
Event::ServiceMessage(message.id.clone(), bare, body.clone(), time_info)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
events.push(event)
|
events.push(event)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue