More work on HPACK decoding
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use super::{huffman, Entry, Key};
|
||||
use util::byte_str::FromUtf8Error;
|
||||
|
||||
use http::{method, header, StatusCode, Method};
|
||||
use http::{method, header, status, StatusCode, Method};
|
||||
use bytes::{Buf, Bytes};
|
||||
|
||||
use std::io::Cursor;
|
||||
@@ -132,10 +132,10 @@ struct Table {
|
||||
|
||||
impl Decoder {
|
||||
/// Creates a new `Decoder` with all settings set to default values.
|
||||
pub fn new() -> Decoder {
|
||||
pub fn new(size: usize) -> Decoder {
|
||||
Decoder {
|
||||
max_size_update: None,
|
||||
table: Table::new(4_096),
|
||||
table: Table::new(size),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,6 +238,7 @@ impl Decoder {
|
||||
if table_idx == 0 {
|
||||
// Read the name as a literal
|
||||
let name = try!(decode_string(buf));
|
||||
|
||||
let value = try!(decode_string(buf));
|
||||
|
||||
Entry::new(name, value)
|
||||
@@ -249,6 +250,12 @@ impl Decoder {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Decoder {
|
||||
fn default() -> Decoder {
|
||||
Decoder::new(4096)
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl Representation =====
|
||||
|
||||
impl Representation {
|
||||
@@ -264,7 +271,7 @@ impl Representation {
|
||||
} else if byte & LITERAL_WITH_INDEXING == LITERAL_WITH_INDEXING {
|
||||
Ok(Representation::LiteralWithIndexing)
|
||||
} else if byte & LITERAL_WITHOUT_INDEXING == 0 {
|
||||
Ok(Representation::LiteralWithIndexing)
|
||||
Ok(Representation::LiteralWithoutIndexing)
|
||||
} else if byte & LITERAL_NEVER_INDEXED == LITERAL_NEVER_INDEXED {
|
||||
Ok(Representation::LiteralNeverIndexed)
|
||||
} else if byte & SIZE_UPDATE == SIZE_UPDATE {
|
||||
@@ -344,10 +351,14 @@ fn decode_string(buf: &mut Cursor<&Bytes>) -> Result<Bytes, DecoderError> {
|
||||
}
|
||||
|
||||
{
|
||||
let raw = &buf.bytes()[..len];
|
||||
if peek_u8(buf) & HUFF_FLAG == HUFF_FLAG {
|
||||
let ret = {
|
||||
let raw = &buf.bytes()[..len];
|
||||
huffman::decode(raw).map(Into::into)
|
||||
};
|
||||
|
||||
if raw[0] & HUFF_FLAG == HUFF_FLAG {
|
||||
return huffman::decode(raw).map(Into::into);
|
||||
buf.advance(len);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -484,6 +495,12 @@ impl From<header::FromBytesError> for DecoderError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<status::FromStrError> for DecoderError {
|
||||
fn from(src: status::FromStrError) -> DecoderError {
|
||||
DecoderError::InvalidUtf8
|
||||
}
|
||||
}
|
||||
|
||||
/// Get an entry from the static table
|
||||
pub fn get_static(idx: usize) -> Entry {
|
||||
use http::{status, method, header};
|
||||
|
||||
@@ -42,13 +42,16 @@ impl Entry {
|
||||
Ok(Entry::Method(method))
|
||||
}
|
||||
b"scheme" => {
|
||||
unimplemented!();
|
||||
let value = try!(ByteStr::from_utf8(value));
|
||||
Ok(Entry::Scheme(value))
|
||||
}
|
||||
b"path" => {
|
||||
unimplemented!();
|
||||
let value = try!(ByteStr::from_utf8(value));
|
||||
Ok(Entry::Path(value))
|
||||
}
|
||||
b"status" => {
|
||||
unimplemented!();
|
||||
let status = try!(StatusCode::from_slice(&value));
|
||||
Ok(Entry::Status(status))
|
||||
}
|
||||
_ => {
|
||||
Err(DecoderError::InvalidPseudoheader)
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
use hpack::Entry;
|
||||
|
||||
use tower::http::{HeaderName, StatusCode, Method, Str};
|
||||
use std::collections::VecDeque;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
pub struct Table {
|
||||
entries: VecDeque<HeaderPair>,
|
||||
max_size: usize,
|
||||
}
|
||||
|
||||
pub enum Entry {
|
||||
Header {
|
||||
name: HeaderName,
|
||||
value: Str,
|
||||
},
|
||||
Authority(Str),
|
||||
Scheme(Str),
|
||||
Path(Str),
|
||||
Status(StatusCode),
|
||||
}
|
||||
impl Table {
|
||||
pub fn new(max_size: usize) -> Table {
|
||||
Table {
|
||||
entries: VecDeque::new(),
|
||||
max_size: max_size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Table {
|
||||
fn default() -> Table {
|
||||
// Default maximum size from the HTTP/2.0 spec.
|
||||
Table::new(4_096)
|
||||
}
|
||||
}
|
||||
*/
|
||||
61
src/util/byte_str.rs
Normal file
61
src/util/byte_str.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
use bytes::Bytes;
|
||||
|
||||
use std::{ops, str};
|
||||
use std::str::Utf8Error;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct ByteStr {
|
||||
bytes: Bytes,
|
||||
}
|
||||
|
||||
pub struct FromUtf8Error {
|
||||
err: Utf8Error,
|
||||
val: Bytes,
|
||||
}
|
||||
|
||||
impl ByteStr {
|
||||
#[inline]
|
||||
pub fn from_static(val: &'static str) -> ByteStr {
|
||||
ByteStr { bytes: Bytes::from_static(val.as_bytes()) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn from_utf8_unchecked(bytes: Bytes) -> ByteStr {
|
||||
ByteStr { bytes: bytes }
|
||||
}
|
||||
|
||||
pub fn from_utf8(bytes: Bytes) -> Result<ByteStr, FromUtf8Error> {
|
||||
if let Err(e) = str::from_utf8(&bytes[..]) {
|
||||
return Err(FromUtf8Error {
|
||||
err: e,
|
||||
val: bytes,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(ByteStr { bytes: bytes })
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Deref for ByteStr {
|
||||
type Target = str;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &str {
|
||||
let b: &[u8] = self.bytes.as_ref();
|
||||
unsafe { str::from_utf8_unchecked(b) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for ByteStr {
|
||||
#[inline]
|
||||
fn from(src: String) -> ByteStr {
|
||||
ByteStr { bytes: Bytes::from(src) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for ByteStr {
|
||||
#[inline]
|
||||
fn from(src: &'a str) -> ByteStr {
|
||||
ByteStr { bytes: Bytes::from(src) }
|
||||
}
|
||||
}
|
||||
1
src/util/mod.rs
Normal file
1
src/util/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub mod byte_str;
|
||||
Reference in New Issue
Block a user