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