feat(header): introduce header::Raw (#869)
The Raw type repesents the raw bytes of a header-value. Having a special type allows a couple of benefits: - The exact representation has become private, allowing "uglier" internals. Specifically, since the common case is for a header to only have 1 line of bytes, an enum is used to skip allocating a Vec for only 1 line. Additionally, a Cow<'static, [u8]> is used, so static bytes don't require a copy. Finally, since we can use static bytes, when parsing, we can compare the incoming bytes against a couple of the most common header-values, and possibly remove another copy. - As its own type, the `Headers.set_raw` method can be generic over `Into<Raw>`, which allows for more ergnomic method calls. BREAKING CHANGE: `Header::parse_header` now receives `&Raw`, instead of a `&[Vec<u8>]`. `Raw` provides several methods to ease using it, but may require some changes to existing code.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use std::fmt;
|
||||
|
||||
use header::{Header, parsing};
|
||||
use header::{Header, Raw, parsing};
|
||||
|
||||
/// `Content-Length` header, defined in
|
||||
/// [RFC7230](http://tools.ietf.org/html/rfc7230#section-3.3.2)
|
||||
@@ -40,12 +40,11 @@ impl Header for ContentLength {
|
||||
static NAME: &'static str = "Content-Length";
|
||||
NAME
|
||||
}
|
||||
fn parse_header(raw: &[Vec<u8>]) -> ::Result<ContentLength> {
|
||||
fn parse_header(raw: &Raw) -> ::Result<ContentLength> {
|
||||
// If multiple Content-Length headers were sent, everything can still
|
||||
// be alright if they all contain the same value, and all parse
|
||||
// correctly. If not, then it's an error.
|
||||
raw.iter()
|
||||
.map(::std::ops::Deref::deref)
|
||||
.map(parsing::from_raw_str)
|
||||
.fold(None, |prev, x| {
|
||||
match (prev, x) {
|
||||
@@ -84,8 +83,8 @@ __hyper__tm!(ContentLength, tests {
|
||||
// Can't use the test_header macro because "5, 5" gets cleaned to "5".
|
||||
#[test]
|
||||
fn test_duplicates() {
|
||||
let parsed = HeaderField::parse_header(&[b"5"[..].into(),
|
||||
b"5"[..].into()]).unwrap();
|
||||
let parsed = HeaderField::parse_header(&vec![b"5".to_vec(),
|
||||
b"5".to_vec()].into()).unwrap();
|
||||
assert_eq!(parsed, HeaderField(5));
|
||||
assert_eq!(format!("{}", parsed), "5");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user