1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-11-18 15:41:17 +00:00
actix-web/src/server/helpers.rs

197 lines
6.3 KiB
Rust
Raw Normal View History

2017-12-26 03:42:55 +00:00
use bytes::{BufMut, BytesMut};
2017-12-25 21:40:06 +00:00
use http::Version;
2018-04-13 23:02:01 +00:00
use std::{mem, ptr, slice};
2017-12-14 00:44:35 +00:00
2018-04-13 23:02:01 +00:00
const DEC_DIGITS_LUT: &[u8] = b"0001020304050607080910111213141516171819\
2017-12-14 00:44:35 +00:00
2021222324252627282930313233343536373839\
4041424344454647484950515253545556575859\
6061626364656667686970717273747576777879\
8081828384858687888990919293949596979899";
pub(crate) const STATUS_LINE_BUF_SIZE: usize = 13;
2017-12-25 21:40:06 +00:00
pub(crate) fn write_status_line(version: Version, mut n: u16, bytes: &mut BytesMut) {
let mut buf: [u8; STATUS_LINE_BUF_SIZE] = [
2018-04-29 16:09:08 +00:00
b'H', b'T', b'T', b'P', b'/', b'1', b'.', b'1', b' ', b' ', b' ', b' ', b' ',
];
2017-12-25 21:40:06 +00:00
match version {
Version::HTTP_2 => buf[5] = b'2',
Version::HTTP_10 => buf[7] = b'0',
2018-04-13 23:02:01 +00:00
Version::HTTP_09 => {
buf[5] = b'0';
buf[7] = b'9';
}
2017-12-25 21:40:06 +00:00
_ => (),
}
2017-12-26 03:42:55 +00:00
let mut curr: isize = 12;
2017-12-14 00:44:35 +00:00
let buf_ptr = buf.as_mut_ptr();
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
2017-12-26 03:42:55 +00:00
let four = n > 999;
2017-12-14 00:44:35 +00:00
unsafe {
// decode 2 more chars, if > 2 chars
2017-12-26 03:42:55 +00:00
let d1 = (n % 100) << 1;
n /= 100;
curr -= 2;
ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(curr), 2);
2017-12-14 00:44:35 +00:00
// decode last 1 or 2 chars
if n < 10 {
curr -= 1;
*buf_ptr.offset(curr) = (n as u8) + b'0';
} else {
let d1 = n << 1;
curr -= 2;
2018-04-13 23:02:01 +00:00
ptr::copy_nonoverlapping(
lut_ptr.offset(d1 as isize),
buf_ptr.offset(curr),
2,
);
2017-12-14 00:44:35 +00:00
}
}
2018-03-18 18:05:44 +00:00
bytes.put_slice(&buf);
2017-12-26 03:42:55 +00:00
if four {
bytes.put(b' ');
}
}
/// NOTE: bytes object has to contain enough space
2018-05-21 03:37:19 +00:00
pub fn write_content_length(mut n: usize, bytes: &mut BytesMut) {
2017-12-26 03:42:55 +00:00
if n < 10 {
2018-04-13 23:02:01 +00:00
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',
];
2017-12-26 03:42:55 +00:00
buf[18] = (n as u8) + b'0';
2018-03-18 18:05:44 +00:00
bytes.put_slice(&buf);
2017-12-26 03:42:55 +00:00
} else if n < 100 {
2018-04-13 23:02:01 +00:00
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',
];
2017-12-26 03:42:55 +00:00
let d1 = n << 1;
unsafe {
ptr::copy_nonoverlapping(
2018-04-13 23:02:01 +00:00
DEC_DIGITS_LUT.as_ptr().offset(d1 as isize),
buf.as_mut_ptr().offset(18),
2,
);
2017-12-26 03:42:55 +00:00
}
2018-03-18 18:05:44 +00:00
bytes.put_slice(&buf);
2017-12-26 03:42:55 +00:00
} else if n < 1000 {
2018-04-13 23:02:01 +00:00
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',
];
2017-12-26 03:42:55 +00:00
// decode 2 more chars, if > 2 chars
let d1 = (n % 100) << 1;
n /= 100;
2018-04-13 23:02:01 +00:00
unsafe {
ptr::copy_nonoverlapping(
DEC_DIGITS_LUT.as_ptr().offset(d1 as isize),
buf.as_mut_ptr().offset(19),
2,
)
};
2017-12-26 03:42:55 +00:00
2018-01-02 21:39:32 +00:00
// decode last 1
buf[18] = (n as u8) + b'0';
2017-12-26 03:42:55 +00:00
2018-03-18 18:05:44 +00:00
bytes.put_slice(&buf);
2017-12-26 03:42:55 +00:00
} else {
2018-03-18 18:05:44 +00:00
bytes.put_slice(b"\r\ncontent-length: ");
2017-12-26 03:42:55 +00:00
convert_usize(n, bytes);
}
2017-12-14 00:44:35 +00:00
}
2017-12-16 15:29:15 +00:00
pub(crate) fn convert_usize(mut n: usize, bytes: &mut BytesMut) {
2017-12-14 00:44:35 +00:00
unsafe {
2018-06-19 01:44:01 +00:00
let mut curr: isize = 39;
let mut buf: [u8; 41] = mem::uninitialized();
buf[39] = b'\r';
buf[40] = b'\n';
let buf_ptr = buf.as_mut_ptr();
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
2017-12-25 21:40:06 +00:00
// 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);
2017-12-14 00:44:35 +00:00
}
// 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);
}
// decode last 1 or 2 chars
if n < 10 {
curr -= 1;
*buf_ptr.offset(curr) = (n as u8) + b'0';
} else {
let d1 = n << 1;
curr -= 2;
ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
}
2018-04-13 23:02:01 +00:00
bytes.extend_from_slice(slice::from_raw_parts(
buf_ptr.offset(curr),
41 - curr as usize,
));
2017-12-14 00:44:35 +00:00
}
}
2017-12-26 03:42:55 +00:00
#[cfg(test)]
mod tests {
use super::*;
2018-01-02 21:39:32 +00:00
#[test]
fn test_write_content_length() {
let mut bytes = BytesMut::new();
bytes.reserve(50);
2018-01-02 21:39:32 +00:00
write_content_length(0, &mut bytes);
2018-05-17 19:20:20 +00:00
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 0\r\n"[..]);
bytes.reserve(50);
2018-01-02 21:39:32 +00:00
write_content_length(9, &mut bytes);
2018-05-17 19:20:20 +00:00
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 9\r\n"[..]);
bytes.reserve(50);
2018-01-02 21:39:32 +00:00
write_content_length(10, &mut bytes);
2018-05-17 19:20:20 +00:00
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 10\r\n"[..]);
bytes.reserve(50);
2018-01-02 21:39:32 +00:00
write_content_length(99, &mut bytes);
2018-05-17 19:20:20 +00:00
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 99\r\n"[..]);
bytes.reserve(50);
2018-01-02 21:39:32 +00:00
write_content_length(100, &mut bytes);
2018-05-17 19:20:20 +00:00
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 100\r\n"[..]);
bytes.reserve(50);
2018-01-02 21:39:32 +00:00
write_content_length(101, &mut bytes);
2018-05-17 19:20:20 +00:00
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 101\r\n"[..]);
bytes.reserve(50);
2018-01-02 21:39:32 +00:00
write_content_length(998, &mut bytes);
2018-05-17 19:20:20 +00:00
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 998\r\n"[..]);
bytes.reserve(50);
2018-01-02 21:39:32 +00:00
write_content_length(1000, &mut bytes);
2018-05-17 19:20:20 +00:00
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 1000\r\n"[..]);
bytes.reserve(50);
2018-01-02 21:39:32 +00:00
write_content_length(1001, &mut bytes);
2018-05-17 19:20:20 +00:00
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 1001\r\n"[..]);
bytes.reserve(50);
2018-01-02 21:39:32 +00:00
write_content_length(5909, &mut bytes);
2018-05-17 19:20:20 +00:00
assert_eq!(bytes.take().freeze(), b"\r\ncontent-length: 5909\r\n"[..]);
2018-01-02 21:39:32 +00:00
}
2017-12-14 00:44:35 +00:00
}