avoid allocation in hash comparison
authoralfadur
Sun, 16 Jun 2019 19:16:26 +0300
changeset 15168 bcb98009ad39
parent 15167 7416f6319de9
child 15169 2ad1f0bdc1f3
avoid allocation in hash comparison
rust/hedgewars-server/src/handlers.rs
rust/hedgewars-server/src/server/database.rs
--- a/rust/hedgewars-server/src/handlers.rs	Sun Jun 16 13:27:14 2019 +0200
+++ b/rust/hedgewars-server/src/handlers.rs	Sun Jun 16 19:16:26 2019 +0300
@@ -1,5 +1,10 @@
 use mio;
-use std::{collections::HashMap, io, io::Write};
+use std::{
+    cmp::PartialEq,
+    collections::HashMap,
+    fmt::{Formatter, LowerHex},
+    iter::Iterator,
+};
 
 use self::{
     actions::{Destination, DestinationGroup, PendingMessage},
@@ -28,8 +33,6 @@
 mod inlobby;
 mod inroom;
 
-use std::fmt::{Formatter, LowerHex};
-
 #[derive(PartialEq, Debug)]
 pub struct Sha1Digest([u8; 20]);
 
@@ -48,6 +51,35 @@
     }
 }
 
+impl PartialEq<&str> for Sha1Digest {
+    fn eq(&self, other: &&str) -> bool {
+        if other.len() != self.0.len() * 2 {
+            false
+        } else {
+            #[inline]
+            fn convert(c: u8) -> u8 {
+                if c > b'9' {
+                    c.overflowing_sub(b'a').0.saturating_add(10)
+                } else {
+                    c.overflowing_sub(b'0').0
+                }
+            }
+
+            other
+                .as_bytes()
+                .chunks_exact(2)
+                .zip(&self.0)
+                .all(|(chars, byte)| {
+                    if let [hi, lo] = chars {
+                        convert(*lo) == byte & 0x0f && convert(*hi) == (byte & 0xf0) >> 4
+                    } else {
+                        unreachable!()
+                    }
+                })
+        }
+    }
+}
+
 #[derive(Debug)]
 pub struct AccountInfo {
     pub is_registered: bool,
@@ -411,3 +443,18 @@
         }
     }
 }
+
+#[cfg(test)]
+mod test {
+    use super::Sha1Digest;
+
+    #[test]
+    fn hash_cmp_test() {
+        let hash = Sha1Digest([
+            0x37, 0xC4, 0x9F, 0x5C, 0xC3, 0xC9, 0xDB, 0xFC, 0x54, 0xAC, 0x22, 0x04, 0xF6, 0x12,
+            0x9A, 0xED, 0x69, 0xB1, 0xC4, 0x5C,
+        ]);
+
+        assert_eq!(hash, &format!("{:x}", hash)[..]);
+    }
+}
--- a/rust/hedgewars-server/src/server/database.rs	Sun Jun 16 13:27:14 2019 +0200
+++ b/rust/hedgewars-server/src/server/database.rs	Sun Jun 16 19:16:26 2019 +0300
@@ -69,7 +69,7 @@
                 let server_hash = get_hash(protocol, &password, &server_salt, &client_salt);
                 password.replace_range(.., "🦔🦔🦔🦔🦔🦔🦔🦔");
 
-                if password_hash == format!("{:x}", client_hash) {
+                if client_hash == password_hash {
                     Ok(Some(AccountInfo {
                         is_registered: true,
                         is_admin: is_admin == 1,