From ffb5742b7138dd81ebec2eadd468b4c8baace7cd Mon Sep 17 00:00:00 2001
From: Nikolay Kim <fafhrd91@gmail.com>
Date: Mon, 25 Dec 2017 19:42:55 -0800
Subject: [PATCH] fix tests

---
 src/h1writer.rs |  14 +++---
 src/helpers.rs  | 110 ++++++++++++++++++++++++++++++++----------------
 2 files changed, 79 insertions(+), 45 deletions(-)

diff --git a/src/h1writer.rs b/src/h1writer.rs
index e33020fb..2deca9d1 100644
--- a/src/h1writer.rs
+++ b/src/h1writer.rs
@@ -161,14 +161,12 @@ impl<T: AsyncWrite> Writer for H1Writer<T> {
             buffer.extend_from_slice(msg.reason().as_bytes());
 
             match body {
-                Body::Empty => {
-                    buffer.extend_from_slice(b"\r\ncontent-length: 0\r\n");
-                }
-                Body::Binary(ref bytes) => {
-                    buffer.extend_from_slice(b"\r\ncontent-length: ");
-                    helpers::convert_usize(bytes.len(), &mut buffer);
-                }
-                _ => buffer.extend_from_slice(b"\r\n"),
+                Body::Empty =>
+                    buffer.extend_from_slice(b"\r\ncontent-length: 0\r\n"),
+                Body::Binary(ref bytes) =>
+                    helpers::write_content_length(bytes.len(), &mut buffer),
+                _ =>
+                    buffer.extend_from_slice(b"\r\n"),
             }
 
             // write headers
diff --git a/src/helpers.rs b/src/helpers.rs
index 147ab457..8211b03d 100644
--- a/src/helpers.rs
+++ b/src/helpers.rs
@@ -5,7 +5,7 @@ use std::rc::Rc;
 use std::ops::{Deref, DerefMut};
 use std::collections::VecDeque;
 use time;
-use bytes::BytesMut;
+use bytes::{BufMut, BytesMut};
 use http::Version;
 
 use httprequest::HttpMessage;
@@ -240,8 +240,8 @@ const DEC_DIGITS_LUT: &[u8] =
       8081828384858687888990919293949596979899";
 
 pub(crate) fn write_status_line(version: Version, mut n: u16, bytes: &mut BytesMut) {
-    let mut buf: [u8; 14] = [b'H', b'T', b'T', b'P', b'/', b'1', b'.', b'1',
-                             b' ', b' ', b' ', b' ', b' ', b' '];
+    let mut buf: [u8; 13] = [b'H', b'T', b'T', b'P', b'/', b'1', b'.', b'1',
+                             b' ', b' ', b' ', b' ', b' '];
     match version {
         Version::HTTP_2 => buf[5] = b'2',
         Version::HTTP_10 => buf[7] = b'0',
@@ -249,33 +249,17 @@ pub(crate) fn write_status_line(version: Version, mut n: u16, bytes: &mut BytesM
         _ => (),
     }
 
-    let mut curr: isize = 13;
+    let mut curr: isize = 12;
     let buf_ptr = buf.as_mut_ptr();
     let lut_ptr = DEC_DIGITS_LUT.as_ptr();
+    let four = n > 999;
 
     unsafe {
-        // eagerly decode 4 characters at a time
-        while n >= 10_000 {
-            let rem = (n % 10_000) as isize;
-            n /= 10_000;
-
-            let d1 = (rem / 100) << 1;
-            let d2 = (rem % 100) << 1;
-            curr -= 4;
-            ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
-            ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
-        }
-
-        // if we reach here numbers are <= 9999, so at most 4 chars long
-        let mut n = n as isize; // possibly reduce 64bit math
-
         // decode 2 more chars, if > 2 chars
-        if n >= 100 {
-            let d1 = (n % 100) << 1;
-            n /= 100;
-            curr -= 2;
-            ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
-        }
+        let d1 = (n % 100) << 1;
+        n /= 100;
+        curr -= 2;
+        ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(curr), 2);
 
         // decode last 1 or 2 chars
         if n < 10 {
@@ -284,11 +268,57 @@ pub(crate) fn write_status_line(version: Version, mut n: u16, bytes: &mut BytesM
         } else {
             let d1 = n << 1;
             curr -= 2;
-            ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
+            ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(curr), 2);
         }
     }
 
     bytes.extend_from_slice(&buf);
+    if four {
+        bytes.put(b' ');
+    }
+}
+
+pub(crate) fn write_content_length(mut n: usize, bytes: &mut BytesMut) {
+    if n < 10 {
+        let mut buf: [u8; 21] = [b'\r',b'\n',b'c',b'o',b'n',b't',b'e',
+                                 b'n',b't',b'-',b'l',b'e',b'n',b'g',
+                                 b't',b'h',b':',b' ',b'0',b'\r',b'\n'];
+        buf[18] = (n as u8) + b'0';
+        bytes.extend_from_slice(&buf);
+    } else if n < 100 {
+        let mut buf: [u8; 22] = [b'\r',b'\n',b'c',b'o',b'n',b't',b'e',
+                                 b'n',b't',b'-',b'l',b'e',b'n',b'g',
+                                 b't',b'h',b':',b' ',b'0',b'0',b'\r',b'\n'];
+        let d1 = n << 1;
+        unsafe {
+            ptr::copy_nonoverlapping(
+                DEC_DIGITS_LUT.as_ptr().offset(d1 as isize), buf.as_mut_ptr().offset(18), 2);
+        }
+        bytes.extend_from_slice(&buf);
+    } else if n < 1000 {
+        let mut buf: [u8; 23] = [b'\r',b'\n',b'c',b'o',b'n',b't',b'e',
+                                 b'n',b't',b'-',b'l',b'e',b'n',b'g',
+                                 b't',b'h',b':',b' ',b'0',b'0',b'0',b'\r',b'\n'];
+        // decode 2 more chars, if > 2 chars
+        let d1 = (n % 100) << 1;
+        n /= 100;
+        unsafe {ptr::copy_nonoverlapping(
+            DEC_DIGITS_LUT.as_ptr().offset(d1 as isize), buf.as_mut_ptr().offset(18), 2)};
+
+        // decode last 1 or 2 chars
+        if n < 10 {
+            buf[20] = (n as u8) + b'0';
+        } else {
+            let d1 = n << 1;
+            unsafe {ptr::copy_nonoverlapping(
+                DEC_DIGITS_LUT.as_ptr().offset(d1 as isize), buf.as_mut_ptr().offset(17), 2)};
+        }
+
+        bytes.extend_from_slice(&buf);
+    } else {
+        bytes.extend_from_slice(b"\r\ncontent-length: ");
+        convert_usize(n, bytes);
+    }
 }
 
 pub(crate) fn convert_usize(mut n: usize, bytes: &mut BytesMut) {
@@ -340,16 +370,22 @@ pub(crate) fn convert_usize(mut n: usize, bytes: &mut BytesMut) {
     }
 }
 
-#[test]
-fn test_date_len() {
-    assert_eq!(DATE_VALUE_LENGTH, "Sun, 06 Nov 1994 08:49:37 GMT".len());
-}
 
-#[test]
-fn test_date() {
-    let mut buf1 = BytesMut::new();
-    date(&mut buf1);
-    let mut buf2 = BytesMut::new();
-    date(&mut buf2);
-    assert_eq!(buf1, buf2);
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_date_len() {
+        assert_eq!(DATE_VALUE_LENGTH, "Sun, 06 Nov 1994 08:49:37 GMT".len());
+    }
+
+    #[test]
+    fn test_date() {
+        let mut buf1 = BytesMut::new();
+        date(&mut buf1);
+        let mut buf2 = BytesMut::new();
+        date(&mut buf2);
+        assert_eq!(buf1, buf2);
+    }
 }