More work on HPACK decoding
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
use super::{huffman, Entry, Key};
|
use super::{huffman, Entry, Key};
|
||||||
use util::byte_str::FromUtf8Error;
|
use util::byte_str::FromUtf8Error;
|
||||||
|
|
||||||
use http::{method, header, StatusCode, Method};
|
use http::{method, header, status, StatusCode, Method};
|
||||||
use bytes::{Buf, Bytes};
|
use bytes::{Buf, Bytes};
|
||||||
|
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
@@ -132,10 +132,10 @@ struct Table {
|
|||||||
|
|
||||||
impl Decoder {
|
impl Decoder {
|
||||||
/// Creates a new `Decoder` with all settings set to default values.
|
/// Creates a new `Decoder` with all settings set to default values.
|
||||||
pub fn new() -> Decoder {
|
pub fn new(size: usize) -> Decoder {
|
||||||
Decoder {
|
Decoder {
|
||||||
max_size_update: None,
|
max_size_update: None,
|
||||||
table: Table::new(4_096),
|
table: Table::new(size),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,6 +238,7 @@ impl Decoder {
|
|||||||
if table_idx == 0 {
|
if table_idx == 0 {
|
||||||
// Read the name as a literal
|
// Read the name as a literal
|
||||||
let name = try!(decode_string(buf));
|
let name = try!(decode_string(buf));
|
||||||
|
|
||||||
let value = try!(decode_string(buf));
|
let value = try!(decode_string(buf));
|
||||||
|
|
||||||
Entry::new(name, value)
|
Entry::new(name, value)
|
||||||
@@ -249,6 +250,12 @@ impl Decoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Decoder {
|
||||||
|
fn default() -> Decoder {
|
||||||
|
Decoder::new(4096)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ===== impl Representation =====
|
// ===== impl Representation =====
|
||||||
|
|
||||||
impl Representation {
|
impl Representation {
|
||||||
@@ -264,7 +271,7 @@ impl Representation {
|
|||||||
} else if byte & LITERAL_WITH_INDEXING == LITERAL_WITH_INDEXING {
|
} else if byte & LITERAL_WITH_INDEXING == LITERAL_WITH_INDEXING {
|
||||||
Ok(Representation::LiteralWithIndexing)
|
Ok(Representation::LiteralWithIndexing)
|
||||||
} else if byte & LITERAL_WITHOUT_INDEXING == 0 {
|
} else if byte & LITERAL_WITHOUT_INDEXING == 0 {
|
||||||
Ok(Representation::LiteralWithIndexing)
|
Ok(Representation::LiteralWithoutIndexing)
|
||||||
} else if byte & LITERAL_NEVER_INDEXED == LITERAL_NEVER_INDEXED {
|
} else if byte & LITERAL_NEVER_INDEXED == LITERAL_NEVER_INDEXED {
|
||||||
Ok(Representation::LiteralNeverIndexed)
|
Ok(Representation::LiteralNeverIndexed)
|
||||||
} else if byte & SIZE_UPDATE == SIZE_UPDATE {
|
} 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 {
|
buf.advance(len);
|
||||||
return huffman::decode(raw).map(Into::into);
|
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
|
/// Get an entry from the static table
|
||||||
pub fn get_static(idx: usize) -> Entry {
|
pub fn get_static(idx: usize) -> Entry {
|
||||||
use http::{status, method, header};
|
use http::{status, method, header};
|
||||||
|
|||||||
@@ -42,13 +42,16 @@ impl Entry {
|
|||||||
Ok(Entry::Method(method))
|
Ok(Entry::Method(method))
|
||||||
}
|
}
|
||||||
b"scheme" => {
|
b"scheme" => {
|
||||||
unimplemented!();
|
let value = try!(ByteStr::from_utf8(value));
|
||||||
|
Ok(Entry::Scheme(value))
|
||||||
}
|
}
|
||||||
b"path" => {
|
b"path" => {
|
||||||
unimplemented!();
|
let value = try!(ByteStr::from_utf8(value));
|
||||||
|
Ok(Entry::Path(value))
|
||||||
}
|
}
|
||||||
b"status" => {
|
b"status" => {
|
||||||
unimplemented!();
|
let status = try!(StatusCode::from_slice(&value));
|
||||||
|
Ok(Entry::Status(status))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
Err(DecoderError::InvalidPseudoheader)
|
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