xmpp: RoomNick is newtype wrapper for ResourcePart

xmppftw created

Change summary

xmpp/ChangeLog                         |  3 +
xmpp/src/event.rs                      | 10 +++---
xmpp/src/lib.rs                        | 42 ++++++++++++++++++++++++++-
xmpp/src/message/receive/chat.rs       |  4 +-
xmpp/src/message/receive/group_chat.rs |  6 ++--
xmpp/src/muc/private_message.rs        |  2 
6 files changed, 53 insertions(+), 14 deletions(-)

Detailed changes

xmpp/ChangeLog 🔗

@@ -9,7 +9,8 @@ XXXX-YY-ZZ [ RELEASER <admin@localhost> ]
         any type that implements AsRef<jid::ResourceRef>, such as produced
         by ResourcePart::new (!485)
       - Event::RoomMessage, Event::RoomPrivateMessage, and Event::RoomSubject now
-        use ResourcePart as sender nickname (!485)
+        use RoomNick as sender nickname; previously RoomNick was an alias for String
+        now it's a newtype wrapper around ResourcePart (!485)
     * Added:
       - Agent::send_room_message takes RoomMessageSettings argument (!483)
     * Fixes:

xmpp/src/event.rs 🔗

@@ -4,12 +4,12 @@
 // License, v. 2.0. If a copy of the MPL was not distributed with this
 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+use tokio_xmpp::jid::BareJid;
 #[cfg(feature = "avatars")]
 use tokio_xmpp::jid::Jid;
-use tokio_xmpp::jid::{BareJid, ResourcePart};
 use tokio_xmpp::parsers::{message::Body, roster::Item as RosterItem};
 
-use crate::{delay::StanzaTimeInfo, Error, Id};
+use crate::{delay::StanzaTimeInfo, Error, Id, RoomNick};
 
 #[derive(Debug)]
 pub enum Event {
@@ -28,15 +28,15 @@ pub enum Event {
     ChatMessage(Id, BareJid, Body, StanzaTimeInfo),
     RoomJoined(BareJid),
     RoomLeft(BareJid),
-    RoomMessage(Id, BareJid, ResourcePart, Body, StanzaTimeInfo),
+    RoomMessage(Id, BareJid, RoomNick, Body, StanzaTimeInfo),
     /// The subject of a room was received.
     /// - The BareJid is the room's address.
     /// - The RoomNick is the nickname of the room member who set the subject.
     /// - The String is the new subject.
-    RoomSubject(BareJid, Option<ResourcePart>, String, StanzaTimeInfo),
+    RoomSubject(BareJid, Option<RoomNick>, String, StanzaTimeInfo),
     /// A private message received from a room, containing the message ID, the room's BareJid,
     /// the sender's nickname, and the message body.
-    RoomPrivateMessage(Id, BareJid, ResourcePart, Body, StanzaTimeInfo),
+    RoomPrivateMessage(Id, BareJid, RoomNick, Body, StanzaTimeInfo),
     ServiceMessage(Id, BareJid, Body, StanzaTimeInfo),
     HttpUploadedFile(String),
 }

xmpp/src/lib.rs 🔗

@@ -8,12 +8,14 @@
 #![cfg_attr(docsrs, feature(doc_auto_cfg))]
 
 pub use tokio_xmpp;
-pub use tokio_xmpp::jid;
+pub use tokio_xmpp::jid::{ResourcePart, ResourceRef};
 pub use tokio_xmpp::minidom;
 pub use tokio_xmpp::parsers;
 #[macro_use]
 extern crate log;
 
+use core::fmt;
+
 pub mod agent;
 pub mod builder;
 pub mod delay;
@@ -36,7 +38,43 @@ pub use feature::ClientFeature;
 
 pub type Error = tokio_xmpp::Error;
 pub type Id = Option<String>;
-pub type RoomNick = String;
+
+/// Nickname for a person in a chatroom.
+///
+/// This nickname is not associated with a specific chatroom, or with a certain
+/// user account.
+///
+// TODO: Introduce RoomMember and track by occupant-id
+#[derive(Clone, Debug)]
+pub struct RoomNick(ResourcePart);
+
+impl RoomNick {
+    pub fn new(nick: ResourcePart) -> Self {
+        Self(nick)
+    }
+
+    pub fn from_resource_ref(nick: &ResourceRef) -> Self {
+        Self(nick.to_owned())
+    }
+}
+
+impl AsRef<ResourceRef> for RoomNick {
+    fn as_ref(&self) -> &ResourceRef {
+        self.0.as_ref()
+    }
+}
+
+impl From<RoomNick> for ResourcePart {
+    fn from(room_nick: RoomNick) -> Self {
+        room_nick.0
+    }
+}
+
+impl fmt::Display for RoomNick {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", self.0)
+    }
+}
 
 // The test below is dysfunctional since we have moved to StanzaStream. The
 // StanzaStream will attempt to connect to foo@bar indefinitely.

xmpp/src/message/receive/chat.rs 🔗

@@ -9,7 +9,7 @@ use tokio_xmpp::{
     parsers::{message::Message, muc::user::MucUser},
 };
 
-use crate::{delay::StanzaTimeInfo, Agent, Event};
+use crate::{delay::StanzaTimeInfo, Agent, Event, RoomNick};
 
 pub async fn handle_message_chat(
     agent: &mut Agent,
@@ -38,7 +38,7 @@ pub async fn handle_message_chat(
                     Ok(full) => Event::RoomPrivateMessage(
                         message.id.clone(),
                         full.to_bare(),
-                        full.resource().into(),
+                        RoomNick::from_resource_ref(full.resource()),
                         body.clone(),
                         time_info.clone(),
                     ),

xmpp/src/message/receive/group_chat.rs 🔗

@@ -6,7 +6,7 @@
 
 use tokio_xmpp::{jid::Jid, parsers::message::Message};
 
-use crate::{delay::StanzaTimeInfo, Agent, Event};
+use crate::{delay::StanzaTimeInfo, Agent, Event, RoomNick};
 
 pub async fn handle_message_group_chat(
     agent: &mut Agent,
@@ -20,7 +20,7 @@ pub async fn handle_message_group_chat(
     if let Some((_lang, subject)) = message.get_best_subject(langs.clone()) {
         events.push(Event::RoomSubject(
             from.to_bare(),
-            from.resource().map(Into::into),
+            from.resource().map(RoomNick::from_resource_ref),
             subject.0.clone(),
             time_info.clone(),
         ));
@@ -31,7 +31,7 @@ pub async fn handle_message_group_chat(
             Ok(full) => Event::RoomMessage(
                 message.id.clone(),
                 from.to_bare(),
-                full.resource().into(),
+                RoomNick::from_resource_ref(full.resource()),
                 body.clone(),
                 time_info,
             ),

xmpp/src/muc/private_message.rs 🔗

@@ -21,7 +21,7 @@ pub async fn send_room_private_message(
     lang: &str,
     text: &str,
 ) {
-    let recipient: Jid = room.with_resource_str(&recipient).unwrap().into();
+    let recipient: Jid = room.with_resource(recipient.as_ref()).into();
     let mut message = Message::new(recipient).with_payload(MucUser::new());
     message.type_ = MessageType::Chat;
     message