perf(header): Make Uri use MemSlice internally
This commit is contained in:
committed by
Sean McArthur
parent
04f169034a
commit
524f65a9a3
@@ -4,6 +4,7 @@ use std::fmt;
|
||||
use std::io::{self, Read};
|
||||
use std::ops::{Index, Range, RangeFrom, RangeTo, RangeFull};
|
||||
use std::ptr;
|
||||
use std::str;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct MemBuf {
|
||||
@@ -49,8 +50,8 @@ impl MemBuf {
|
||||
}
|
||||
|
||||
pub fn slice(&self, len: usize) -> MemSlice {
|
||||
assert!(self.end - self.start.get() >= len);
|
||||
let start = self.start.get();
|
||||
assert!(!(self.end - start < len));
|
||||
let end = start + len;
|
||||
self.start.set(end);
|
||||
MemSlice {
|
||||
@@ -196,6 +197,19 @@ impl From<Vec<u8>> for MemBuf {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct MemStr(MemSlice);
|
||||
|
||||
impl MemStr {
|
||||
pub unsafe fn from_utf8_unchecked(slice: MemSlice) -> MemStr {
|
||||
MemStr(slice)
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
unsafe { str::from_utf8_unchecked(self.0.as_ref()) }
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MemSlice {
|
||||
buf: Arc<UnsafeCell<Vec<u8>>>,
|
||||
start: usize,
|
||||
|
||||
@@ -577,6 +577,8 @@ mod tests {
|
||||
use super::{Conn, Writing};
|
||||
use ::uri::Uri;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn test_conn_init_read() {
|
||||
let good_message = b"GET / HTTP/1.1\r\n\r\n".to_vec();
|
||||
@@ -587,7 +589,7 @@ mod tests {
|
||||
match conn.poll().unwrap() {
|
||||
Async::Ready(Some(Frame::Message { message, body: false })) => {
|
||||
assert_eq!(message, MessageHead {
|
||||
subject: ::http::RequestLine(::Get, Uri::new("/").unwrap()),
|
||||
subject: ::http::RequestLine(::Get, Uri::from_str("/").unwrap()),
|
||||
.. MessageHead::default()
|
||||
})
|
||||
},
|
||||
|
||||
@@ -6,7 +6,7 @@ use httparse;
|
||||
use header::{self, Headers, ContentLength, TransferEncoding};
|
||||
use http::{MessageHead, RawStatus, Http1Transaction, ParseResult, ServerTransaction, ClientTransaction, RequestLine};
|
||||
use http::h1::{Encoder, Decoder};
|
||||
use http::buf::{MemBuf, MemSlice};
|
||||
use http::buf::{MemBuf, MemSlice, MemStr};
|
||||
use method::Method;
|
||||
use status::StatusCode;
|
||||
use version::HttpVersion::{Http10, Http11};
|
||||
@@ -33,18 +33,26 @@ impl Http1Transaction for ServerTransaction {
|
||||
Ok(match try!(req.parse(buf.bytes())) {
|
||||
httparse::Status::Complete(len) => {
|
||||
trace!("Request.parse Complete({})", len);
|
||||
let mut headers = Headers::with_capacity(req.headers.len());
|
||||
let slice = buf.slice(len);
|
||||
let path = req.path.unwrap();
|
||||
let path_start = path.as_ptr() as usize - slice.as_ref().as_ptr() as usize;
|
||||
let path_end = path_start + path.len();
|
||||
let path = slice.slice(path_start..path_end);
|
||||
// path was found to be utf8 by httparse
|
||||
let path = unsafe { MemStr::from_utf8_unchecked(path) };
|
||||
let subject = RequestLine(
|
||||
try!(req.method.unwrap().parse()),
|
||||
try!(::uri::from_mem_str(path)),
|
||||
);
|
||||
let mut headers = Headers::with_capacity(req.headers.len());
|
||||
headers.extend(HeadersAsMemSliceIter {
|
||||
headers: req.headers.iter(),
|
||||
slice: slice,
|
||||
});
|
||||
|
||||
Some((MessageHead {
|
||||
version: if req.version.unwrap() == 1 { Http11 } else { Http10 },
|
||||
subject: RequestLine(
|
||||
try!(req.method.unwrap().parse()),
|
||||
try!(req.path.unwrap().parse())
|
||||
),
|
||||
subject: subject,
|
||||
headers: headers,
|
||||
}, len))
|
||||
}
|
||||
@@ -143,7 +151,7 @@ impl Http1Transaction for ClientTransaction {
|
||||
headers: headers,
|
||||
}, len))
|
||||
},
|
||||
httparse::Status::Partial => None
|
||||
httparse::Status::Partial => None,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -326,5 +334,4 @@ mod tests {
|
||||
raw.restart();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user