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:
Sean McArthur
2016-07-23 12:54:16 -07:00
committed by GitHub
parent d67dbc6028
commit 50ccdaa7e7
27 changed files with 489 additions and 245 deletions

View File

@@ -4,18 +4,18 @@ use std::fmt;
use std::str::from_utf8;
use super::cell::{OptCell, PtrMapCell};
use header::{Header};
use header::{Header, Raw};
#[derive(Clone)]
pub struct Item {
raw: OptCell<Vec<Vec<u8>>>,
raw: OptCell<Raw>,
typed: PtrMapCell<Header + Send + Sync>
}
impl Item {
#[inline]
pub fn new_raw(data: Vec<Vec<u8>>) -> Item {
pub fn new_raw(data: Raw) -> Item {
Item {
raw: OptCell::new(Some(data)),
typed: PtrMapCell::new(),
@@ -33,23 +33,22 @@ impl Item {
}
#[inline]
pub fn mut_raw(&mut self) -> &mut Vec<Vec<u8>> {
pub fn mut_raw(&mut self) -> &mut Raw {
self.typed = PtrMapCell::new();
unsafe {
self.raw.get_mut()
}
}
pub fn raw(&self) -> &[Vec<u8>] {
pub fn raw(&self) -> &Raw {
if let Some(ref raw) = *self.raw {
return &raw[..];
return raw;
}
let raw = vec![unsafe { self.typed.one() }.to_string().into_bytes()];
let raw = unsafe { self.typed.one() }.to_string().into_bytes().into();
self.raw.set(raw);
let raw = self.raw.as_ref().unwrap();
&raw[..]
self.raw.as_ref().unwrap()
}
pub fn typed<H: Header + Any>(&self) -> Option<&H> {
@@ -86,10 +85,8 @@ impl Item {
}
#[inline]
fn parse<H: Header>(raw: &Vec<Vec<u8>>) ->
::Result<Box<Header + Send + Sync>> {
Header::parse_header(&raw[..]).map(|h: H| {
// FIXME: Use Type ascription
fn parse<H: Header>(raw: &Raw) -> ::Result<Box<Header + Send + Sync>> {
H::parse_header(raw).map(|h| {
let h: Box<Header + Send + Sync> = Box::new(h);
h
})