xmpp-parsers: Reduce component handshake allocations

Emmanuel Gil Peyrot created

This function always appends to an existing string, so by passing it a
String directly we can avoid superfluous allocations.

Also tokio-xmpp was doing a bunch of &str to String for no reason around
there, let’s remove that too.

Change summary

parsers/ChangeLog                 |  4 ++++
parsers/src/component.rs          |  8 +++++---
tokio-xmpp/src/component/login.rs | 11 +++++------
tokio-xmpp/src/component/mod.rs   |  1 -
4 files changed, 14 insertions(+), 10 deletions(-)

Detailed changes

parsers/ChangeLog πŸ”—

@@ -54,6 +54,10 @@ XXXX-YY-ZZ RELEASER <admin@example.com>
       - pubsub::Event is now the wrapper for the pubsub::event::Payload enum,
         and the PublishedItems and RetractedItems have been merged into the
         Items sub-struct.  These replace the previous PubSubEvent enum (!531)
+      - Handshake::from_password_and_stream_id() became
+        Handshake::from_stream_id_and_password(), with the two parameters
+        having been exchanged, and the stream_id is now a String instead of
+        &str.
     * New parsers/serialisers:
       - Stream Features (RFC 6120) (!400)
       - Spam Reporting (XEP-0377) (!506)

parsers/src/component.rs πŸ”—

@@ -31,8 +31,8 @@ impl Handshake {
     }
 
     /// Creates an authentication request from the component.
-    pub fn from_password_and_stream_id(password: &str, stream_id: &str) -> Handshake {
-        let input = String::from(stream_id) + password;
+    pub fn from_stream_id_and_password(stream_id: String, password: &str) -> Handshake {
+        let input = stream_id + password;
         let hash = Sha1::digest(input.as_bytes());
         Handshake {
             data: Some(hash.into()),
@@ -76,7 +76,9 @@ mod tests {
         let handshake = Handshake::new();
         assert_eq!(handshake.data, None);
 
-        let handshake = Handshake::from_password_and_stream_id("123456", "sid");
+        let stream_id = String::from("sid");
+        let password = "123456";
+        let handshake = Handshake::from_stream_id_and_password(stream_id, password);
         assert_eq!(
             handshake.data,
             Some([

tokio-xmpp/src/component/login.rs πŸ”—

@@ -12,15 +12,14 @@ use crate::xmlstream::{ReadError, Timeouts, XmppStream, XmppStreamElement};
 pub async fn component_login<C: ServerConnector>(
     connector: C,
     jid: Jid,
-    password: String,
+    password: &str,
     timeouts: Timeouts,
 ) -> Result<XmppStream<C::Stream>, Error> {
-    let password = password;
     let (mut stream, _) = connector.connect(&jid, ns::COMPONENT, timeouts).await?;
     let header = stream.take_header();
     let mut stream = stream.skip_features();
     let stream_id = match header.id {
-        Some(ref v) => &**v,
+        Some(id) => id.into_owned(),
         None => {
             return Err(io::Error::new(
                 io::ErrorKind::InvalidData,
@@ -29,16 +28,16 @@ pub async fn component_login<C: ServerConnector>(
             .into())
         }
     };
-    auth(&mut stream, stream_id, &password).await?;
+    auth(&mut stream, stream_id, password).await?;
     Ok(stream)
 }
 
 pub async fn auth<S: AsyncBufRead + AsyncWrite + Unpin>(
     stream: &mut XmppStream<S>,
-    stream_id: &str,
+    stream_id: String,
     password: &str,
 ) -> Result<(), Error> {
-    let nonza = Handshake::from_password_and_stream_id(password, stream_id);
+    let nonza = Handshake::from_stream_id_and_password(stream_id, password);
     stream
         .send(&XmppStreamElement::ComponentHandshake(nonza))
         .await?;

tokio-xmpp/src/component/mod.rs πŸ”—

@@ -87,7 +87,6 @@ impl<C: ServerConnector> Component<C> {
         timeouts: Timeouts,
     ) -> Result<Self, Error> {
         let jid = Jid::from_str(jid)?;
-        let password = password.to_owned();
         let stream = component_login(connector, jid.clone(), password, timeouts).await?;
         Ok(Component { jid, stream })
     }