Use rustfmt to enforce consistent formatting
This change adds a .rustfmt.toml that includes ALL supported settings, 12 of which we have overridden to attempt to cater to our own proclivities. rustfmt is checked in the rust-nightly CI job.
This commit is contained in:
		| @@ -1,15 +1,15 @@ | ||||
| use super::{huffman, Header}; | ||||
| use frame; | ||||
|  | ||||
| use http::{header}; | ||||
| use bytes::{Buf, Bytes, BytesMut}; | ||||
| use http::header; | ||||
| use http::method::{self, Method}; | ||||
| use http::status::{self, StatusCode}; | ||||
| use bytes::{Buf, Bytes, BytesMut}; | ||||
| use string::String; | ||||
|  | ||||
| use std::cmp; | ||||
| use std::io::Cursor; | ||||
| use std::collections::VecDeque; | ||||
| use std::io::Cursor; | ||||
| use std::str::Utf8Error; | ||||
|  | ||||
| /// Decodes headers using HPACK | ||||
| @@ -164,7 +164,8 @@ impl Decoder { | ||||
|  | ||||
|     /// Decodes the headers found in the given buffer. | ||||
|     pub fn decode<F>(&mut self, src: &mut Cursor<Bytes>, mut f: F) -> Result<(), DecoderError> | ||||
|         where F: FnMut(Header) | ||||
|     where | ||||
|         F: FnMut(Header), | ||||
|     { | ||||
|         use self::Representation::*; | ||||
|  | ||||
| @@ -180,16 +181,16 @@ impl Decoder { | ||||
|             // At this point we are always at the beginning of the next block | ||||
|             // within the HPACK data. The type of the block can always be | ||||
|             // determined from the first byte. | ||||
|             match try!(Representation::load(peek_u8(src))) { | ||||
|             match Representation::load(peek_u8(src))? { | ||||
|                 Indexed => { | ||||
|                     trace!("    Indexed; rem={:?}", src.remaining()); | ||||
|                     can_resize = false; | ||||
|                     f(try!(self.decode_indexed(src))); | ||||
|                     f(self.decode_indexed(src)?); | ||||
|                 } | ||||
|                 LiteralWithIndexing => { | ||||
|                     trace!("    LiteralWithIndexing; rem={:?}", src.remaining()); | ||||
|                     can_resize = false; | ||||
|                     let entry = try!(self.decode_literal(src, true)); | ||||
|                     let entry = self.decode_literal(src, true)?; | ||||
|  | ||||
|                     // Insert the header into the table | ||||
|                     self.table.insert(entry.clone()); | ||||
| @@ -199,13 +200,13 @@ impl Decoder { | ||||
|                 LiteralWithoutIndexing => { | ||||
|                     trace!("    LiteralWithoutIndexing; rem={:?}", src.remaining()); | ||||
|                     can_resize = false; | ||||
|                     let entry = try!(self.decode_literal(src, false)); | ||||
|                     let entry = self.decode_literal(src, false)?; | ||||
|                     f(entry); | ||||
|                 } | ||||
|                 LiteralNeverIndexed => { | ||||
|                     trace!("    LiteralNeverIndexed; rem={:?}", src.remaining()); | ||||
|                     can_resize = false; | ||||
|                     let entry = try!(self.decode_literal(src, false)); | ||||
|                     let entry = self.decode_literal(src, false)?; | ||||
|  | ||||
|                     // TODO: Track that this should never be indexed | ||||
|  | ||||
| @@ -218,7 +219,7 @@ impl Decoder { | ||||
|                     } | ||||
|  | ||||
|                     // Handle the dynamic table size update | ||||
|                     try!(self.process_size_update(src)); | ||||
|                     self.process_size_update(src)?; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -226,52 +227,47 @@ impl Decoder { | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     fn process_size_update(&mut self, buf: &mut Cursor<Bytes>) | ||||
|         -> Result<(), DecoderError> | ||||
|     { | ||||
|         let new_size = try!(decode_int(buf, 5)); | ||||
|     fn process_size_update(&mut self, buf: &mut Cursor<Bytes>) -> Result<(), DecoderError> { | ||||
|         let new_size = decode_int(buf, 5)?; | ||||
|  | ||||
|         if new_size > self.last_max_update { | ||||
|             return Err(DecoderError::InvalidMaxDynamicSize); | ||||
|         } | ||||
|  | ||||
|         debug!("Decoder changed max table size from {} to {}", | ||||
|                self.table.size(), new_size); | ||||
|                self.table.size(), | ||||
|                new_size); | ||||
|  | ||||
|         self.table.set_max_size(new_size); | ||||
|  | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     fn decode_indexed(&self, buf: &mut Cursor<Bytes>) | ||||
|         -> Result<Header, DecoderError> | ||||
|     { | ||||
|         let index = try!(decode_int(buf, 7)); | ||||
|     fn decode_indexed(&self, buf: &mut Cursor<Bytes>) -> Result<Header, DecoderError> { | ||||
|         let index = decode_int(buf, 7)?; | ||||
|         self.table.get(index) | ||||
|     } | ||||
|  | ||||
|     fn decode_literal(&mut self, buf: &mut Cursor<Bytes>, index: bool) | ||||
|         -> Result<Header, DecoderError> | ||||
|     { | ||||
|         let prefix = if index { | ||||
|             6 | ||||
|         } else { | ||||
|             4 | ||||
|         }; | ||||
|     fn decode_literal( | ||||
|         &mut self, | ||||
|         buf: &mut Cursor<Bytes>, | ||||
|         index: bool, | ||||
|     ) -> Result<Header, DecoderError> { | ||||
|         let prefix = if index { 6 } else { 4 }; | ||||
|  | ||||
|         // Extract the table index for the name, or 0 if not indexed | ||||
|         let table_idx = try!(decode_int(buf, prefix)); | ||||
|         let table_idx = decode_int(buf, prefix)?; | ||||
|  | ||||
|         // First, read the header name | ||||
|         if table_idx == 0 { | ||||
|             // Read the name as a literal | ||||
|             let name = try!(self.decode_string(buf)); | ||||
|             let value = try!(self.decode_string(buf)); | ||||
|             let name = self.decode_string(buf)?; | ||||
|             let value = self.decode_string(buf)?; | ||||
|  | ||||
|             Header::new(name, value) | ||||
|         } else { | ||||
|             let e = try!(self.table.get(table_idx)); | ||||
|             let value = try!(self.decode_string(buf)); | ||||
|             let e = self.table.get(table_idx)?; | ||||
|             let value = self.decode_string(buf)?; | ||||
|  | ||||
|             e.name().into_entry(value) | ||||
|         } | ||||
| @@ -288,10 +284,12 @@ impl Decoder { | ||||
|         let huff = peek_u8(buf) & HUFF_FLAG == HUFF_FLAG; | ||||
|  | ||||
|         // Decode the string length using 7 bit prefix | ||||
|         let len = try!(decode_int(buf, 7)); | ||||
|         let len = decode_int(buf, 7)?; | ||||
|  | ||||
|         if len > buf.remaining() { | ||||
|             trace!("decode_string underflow; len={}; remaining={}", len, buf.remaining()); | ||||
|             trace!("decode_string underflow; len={}; remaining={}", | ||||
|                    len, | ||||
|                    buf.remaining()); | ||||
|             return Err(DecoderError::StringUnderflow); | ||||
|         } | ||||
|  | ||||
| @@ -319,12 +317,12 @@ impl Default for Decoder { | ||||
|  | ||||
| impl Representation { | ||||
|     pub fn load(byte: u8) -> Result<Representation, DecoderError> { | ||||
|         const INDEXED: u8                  = 0b10000000; | ||||
|         const LITERAL_WITH_INDEXING: u8    = 0b01000000; | ||||
|         const INDEXED: u8 = 0b10000000; | ||||
|         const LITERAL_WITH_INDEXING: u8 = 0b01000000; | ||||
|         const LITERAL_WITHOUT_INDEXING: u8 = 0b11110000; | ||||
|         const LITERAL_NEVER_INDEXED: u8    = 0b00010000; | ||||
|         const SIZE_UPDATE_MASK: u8         = 0b11100000; | ||||
|         const SIZE_UPDATE: u8              = 0b00100000; | ||||
|         const LITERAL_NEVER_INDEXED: u8 = 0b00010000; | ||||
|         const SIZE_UPDATE_MASK: u8 = 0b11100000; | ||||
|         const SIZE_UPDATE: u8 = 0b00100000; | ||||
|  | ||||
|         // TODO: What did I even write here? | ||||
|  | ||||
| @@ -474,7 +472,8 @@ impl Table { | ||||
|         debug_assert!(size <= self.max_size); | ||||
|  | ||||
|         while self.size + size > self.max_size { | ||||
|             let last = self.entries.pop_back() | ||||
|             let last = self.entries | ||||
|                 .pop_back() | ||||
|                 .expect("size of table != 0, but no headers left!"); | ||||
|  | ||||
|             self.size -= last.len(); | ||||
| @@ -564,194 +563,288 @@ pub fn get_static(idx: usize) -> Header { | ||||
|         12 => Header::Status(StatusCode::BAD_REQUEST), | ||||
|         13 => Header::Status(StatusCode::NOT_FOUND), | ||||
|         14 => Header::Status(StatusCode::INTERNAL_SERVER_ERROR), | ||||
|         15 => Header::Field { | ||||
|             name: header::ACCEPT_CHARSET, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         16 => Header::Field { | ||||
|             name: header::ACCEPT_ENCODING, | ||||
|             value: HeaderValue::from_static("gzip, deflate"), | ||||
|         }, | ||||
|         17 => Header::Field { | ||||
|             name: header::ACCEPT_LANGUAGE, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         18 => Header::Field { | ||||
|             name: header::ACCEPT_RANGES, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         19 => Header::Field { | ||||
|             name: header::ACCEPT, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         20 => Header::Field { | ||||
|             name: header::ACCESS_CONTROL_ALLOW_ORIGIN, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         21 => Header::Field { | ||||
|             name: header::AGE, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         22 => Header::Field { | ||||
|             name: header::ALLOW, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         23 => Header::Field { | ||||
|             name: header::AUTHORIZATION, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         24 => Header::Field { | ||||
|             name: header::CACHE_CONTROL, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         25 => Header::Field { | ||||
|             name: header::CONTENT_DISPOSITION, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         26 => Header::Field { | ||||
|             name: header::CONTENT_ENCODING, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         27 => Header::Field { | ||||
|             name: header::CONTENT_LANGUAGE, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         28 => Header::Field { | ||||
|             name: header::CONTENT_LENGTH, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         29 => Header::Field { | ||||
|             name: header::CONTENT_LOCATION, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         30 => Header::Field { | ||||
|             name: header::CONTENT_RANGE, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         31 => Header::Field { | ||||
|             name: header::CONTENT_TYPE, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         32 => Header::Field { | ||||
|             name: header::COOKIE, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         33 => Header::Field { | ||||
|             name: header::DATE, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         34 => Header::Field { | ||||
|             name: header::ETAG, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         35 => Header::Field { | ||||
|             name: header::EXPECT, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         36 => Header::Field { | ||||
|             name: header::EXPIRES, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         37 => Header::Field { | ||||
|             name: header::FROM, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         38 => Header::Field { | ||||
|             name: header::HOST, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         39 => Header::Field { | ||||
|             name: header::IF_MATCH, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         40 => Header::Field { | ||||
|             name: header::IF_MODIFIED_SINCE, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         41 => Header::Field { | ||||
|             name: header::IF_NONE_MATCH, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         42 => Header::Field { | ||||
|             name: header::IF_RANGE, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         43 => Header::Field { | ||||
|             name: header::IF_UNMODIFIED_SINCE, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         44 => Header::Field { | ||||
|             name: header::LAST_MODIFIED, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         45 => Header::Field { | ||||
|             name: header::LINK, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         46 => Header::Field { | ||||
|             name: header::LOCATION, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         47 => Header::Field { | ||||
|             name: header::MAX_FORWARDS, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         48 => Header::Field { | ||||
|             name: header::PROXY_AUTHENTICATE, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         49 => Header::Field { | ||||
|             name: header::PROXY_AUTHORIZATION, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         50 => Header::Field { | ||||
|             name: header::RANGE, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         51 => Header::Field { | ||||
|             name: header::REFERER, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         52 => Header::Field { | ||||
|             name: header::REFRESH, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         53 => Header::Field { | ||||
|             name: header::RETRY_AFTER, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         54 => Header::Field { | ||||
|             name: header::SERVER, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         55 => Header::Field { | ||||
|             name: header::SET_COOKIE, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         56 => Header::Field { | ||||
|             name: header::STRICT_TRANSPORT_SECURITY, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         57 => Header::Field { | ||||
|             name: header::TRANSFER_ENCODING, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         58 => Header::Field { | ||||
|             name: header::USER_AGENT, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         59 => Header::Field { | ||||
|             name: header::VARY, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         60 => Header::Field { | ||||
|             name: header::VIA, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         61 => Header::Field { | ||||
|             name: header::WWW_AUTHENTICATE, | ||||
|             value: HeaderValue::from_static(""), | ||||
|         }, | ||||
|         15 => { | ||||
|             Header::Field { | ||||
|                 name: header::ACCEPT_CHARSET, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         16 => { | ||||
|             Header::Field { | ||||
|                 name: header::ACCEPT_ENCODING, | ||||
|                 value: HeaderValue::from_static("gzip, deflate"), | ||||
|             } | ||||
|         } | ||||
|         17 => { | ||||
|             Header::Field { | ||||
|                 name: header::ACCEPT_LANGUAGE, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         18 => { | ||||
|             Header::Field { | ||||
|                 name: header::ACCEPT_RANGES, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         19 => { | ||||
|             Header::Field { | ||||
|                 name: header::ACCEPT, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         20 => { | ||||
|             Header::Field { | ||||
|                 name: header::ACCESS_CONTROL_ALLOW_ORIGIN, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         21 => { | ||||
|             Header::Field { | ||||
|                 name: header::AGE, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         22 => { | ||||
|             Header::Field { | ||||
|                 name: header::ALLOW, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         23 => { | ||||
|             Header::Field { | ||||
|                 name: header::AUTHORIZATION, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         24 => { | ||||
|             Header::Field { | ||||
|                 name: header::CACHE_CONTROL, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         25 => { | ||||
|             Header::Field { | ||||
|                 name: header::CONTENT_DISPOSITION, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         26 => { | ||||
|             Header::Field { | ||||
|                 name: header::CONTENT_ENCODING, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         27 => { | ||||
|             Header::Field { | ||||
|                 name: header::CONTENT_LANGUAGE, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         28 => { | ||||
|             Header::Field { | ||||
|                 name: header::CONTENT_LENGTH, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         29 => { | ||||
|             Header::Field { | ||||
|                 name: header::CONTENT_LOCATION, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         30 => { | ||||
|             Header::Field { | ||||
|                 name: header::CONTENT_RANGE, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         31 => { | ||||
|             Header::Field { | ||||
|                 name: header::CONTENT_TYPE, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         32 => { | ||||
|             Header::Field { | ||||
|                 name: header::COOKIE, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         33 => { | ||||
|             Header::Field { | ||||
|                 name: header::DATE, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         34 => { | ||||
|             Header::Field { | ||||
|                 name: header::ETAG, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         35 => { | ||||
|             Header::Field { | ||||
|                 name: header::EXPECT, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         36 => { | ||||
|             Header::Field { | ||||
|                 name: header::EXPIRES, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         37 => { | ||||
|             Header::Field { | ||||
|                 name: header::FROM, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         38 => { | ||||
|             Header::Field { | ||||
|                 name: header::HOST, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         39 => { | ||||
|             Header::Field { | ||||
|                 name: header::IF_MATCH, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         40 => { | ||||
|             Header::Field { | ||||
|                 name: header::IF_MODIFIED_SINCE, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         41 => { | ||||
|             Header::Field { | ||||
|                 name: header::IF_NONE_MATCH, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         42 => { | ||||
|             Header::Field { | ||||
|                 name: header::IF_RANGE, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         43 => { | ||||
|             Header::Field { | ||||
|                 name: header::IF_UNMODIFIED_SINCE, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         44 => { | ||||
|             Header::Field { | ||||
|                 name: header::LAST_MODIFIED, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         45 => { | ||||
|             Header::Field { | ||||
|                 name: header::LINK, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         46 => { | ||||
|             Header::Field { | ||||
|                 name: header::LOCATION, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         47 => { | ||||
|             Header::Field { | ||||
|                 name: header::MAX_FORWARDS, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         48 => { | ||||
|             Header::Field { | ||||
|                 name: header::PROXY_AUTHENTICATE, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         49 => { | ||||
|             Header::Field { | ||||
|                 name: header::PROXY_AUTHORIZATION, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         50 => { | ||||
|             Header::Field { | ||||
|                 name: header::RANGE, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         51 => { | ||||
|             Header::Field { | ||||
|                 name: header::REFERER, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         52 => { | ||||
|             Header::Field { | ||||
|                 name: header::REFRESH, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         53 => { | ||||
|             Header::Field { | ||||
|                 name: header::RETRY_AFTER, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         54 => { | ||||
|             Header::Field { | ||||
|                 name: header::SERVER, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         55 => { | ||||
|             Header::Field { | ||||
|                 name: header::SET_COOKIE, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         56 => { | ||||
|             Header::Field { | ||||
|                 name: header::STRICT_TRANSPORT_SECURITY, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         57 => { | ||||
|             Header::Field { | ||||
|                 name: header::TRANSFER_ENCODING, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         58 => { | ||||
|             Header::Field { | ||||
|                 name: header::USER_AGENT, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         59 => { | ||||
|             Header::Field { | ||||
|                 name: header::VARY, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         60 => { | ||||
|             Header::Field { | ||||
|                 name: header::VIA, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         61 => { | ||||
|             Header::Field { | ||||
|                 name: header::WWW_AUTHENTICATE, | ||||
|                 value: HeaderValue::from_static(""), | ||||
|             } | ||||
|         } | ||||
|         _ => unreachable!(), | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| use super::{huffman, Header}; | ||||
| use super::table::{Table, Index}; | ||||
| use super::table::{Index, Table}; | ||||
|  | ||||
| use bytes::{BufMut, BytesMut}; | ||||
| use http::header::{HeaderName, HeaderValue}; | ||||
| use bytes::{BytesMut, BufMut}; | ||||
|  | ||||
| #[derive(Debug)] | ||||
| pub struct Encoder { | ||||
| @@ -76,9 +76,14 @@ impl Encoder { | ||||
|     } | ||||
|  | ||||
|     /// Encode a set of headers into the provide buffer | ||||
|     pub fn encode<I>(&mut self, resume: Option<EncodeState>, headers: &mut I, dst: &mut BytesMut) | ||||
|         -> Encode | ||||
|         where I: Iterator<Item=Header<Option<HeaderName>>>, | ||||
|     pub fn encode<I>( | ||||
|         &mut self, | ||||
|         resume: Option<EncodeState>, | ||||
|         headers: &mut I, | ||||
|         dst: &mut BytesMut, | ||||
|     ) -> Encode | ||||
|     where | ||||
|         I: Iterator<Item = Header<Option<HeaderName>>>, | ||||
|     { | ||||
|         let len = dst.len(); | ||||
|  | ||||
| @@ -94,15 +99,8 @@ impl Encoder { | ||||
|             let len = dst.len(); | ||||
|  | ||||
|             let res = match resume.value { | ||||
|                 Some(ref value) => { | ||||
|                     self.encode_header_without_name( | ||||
|                         &resume.index, | ||||
|                         value, | ||||
|                         dst) | ||||
|                 } | ||||
|                 None => { | ||||
|                     self.encode_header(&resume.index, dst) | ||||
|                 } | ||||
|                 Some(ref value) => self.encode_header_without_name(&resume.index, value, dst), | ||||
|                 None => self.encode_header(&resume.index, dst), | ||||
|             }; | ||||
|  | ||||
|             if res.is_err() { | ||||
| @@ -126,9 +124,9 @@ impl Encoder { | ||||
|                     if res.is_err() { | ||||
|                         dst.truncate(len); | ||||
|                         return Encode::Partial(EncodeState { | ||||
|                             index: index, | ||||
|                             value: None, | ||||
|                         }); | ||||
|                                                    index: index, | ||||
|                                                    value: None, | ||||
|                                                }); | ||||
|                     } | ||||
|  | ||||
|                     last_index = Some(index); | ||||
| @@ -138,17 +136,15 @@ impl Encoder { | ||||
|                 // which case, we skip table lookup and just use the same index | ||||
|                 // as the previous entry. | ||||
|                 Err(value) => { | ||||
|                     let res = self.encode_header_without_name( | ||||
|                         last_index.as_ref().unwrap(), | ||||
|                         &value, | ||||
|                         dst); | ||||
|                     let res = | ||||
|                         self.encode_header_without_name(last_index.as_ref().unwrap(), &value, dst); | ||||
|  | ||||
|                     if res.is_err() { | ||||
|                         dst.truncate(len); | ||||
|                         return Encode::Partial(EncodeState { | ||||
|                             index: last_index.unwrap(), | ||||
|                             value: Some(value), | ||||
|                         }); | ||||
|                                                    index: last_index.unwrap(), | ||||
|                                                    value: Some(value), | ||||
|                                                }); | ||||
|                     } | ||||
|                 } | ||||
|             }; | ||||
| @@ -161,13 +157,13 @@ impl Encoder { | ||||
|         match self.size_update.take() { | ||||
|             Some(SizeUpdate::One(val)) => { | ||||
|                 self.table.resize(val); | ||||
|                 try!(encode_size_update(val, dst)); | ||||
|                 encode_size_update(val, dst)?; | ||||
|             } | ||||
|             Some(SizeUpdate::Two(min, max)) => { | ||||
|                 self.table.resize(min); | ||||
|                 self.table.resize(max); | ||||
|                 try!(encode_size_update(min, dst)); | ||||
|                 try!(encode_size_update(max, dst)); | ||||
|                 encode_size_update(min, dst)?; | ||||
|                 encode_size_update(max, dst)?; | ||||
|             } | ||||
|             None => {} | ||||
|         } | ||||
| @@ -175,21 +171,15 @@ impl Encoder { | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     fn encode_header(&mut self, index: &Index, dst: &mut BytesMut) | ||||
|         -> Result<(), EncoderError> | ||||
|     { | ||||
|     fn encode_header(&mut self, index: &Index, dst: &mut BytesMut) -> Result<(), EncoderError> { | ||||
|         match *index { | ||||
|             Index::Indexed(idx, _) => { | ||||
|                 try!(encode_int(idx, 7, 0x80, dst)); | ||||
|                 encode_int(idx, 7, 0x80, dst)?; | ||||
|             } | ||||
|             Index::Name(idx, _) => { | ||||
|                 let header = self.table.resolve(&index); | ||||
|  | ||||
|                 try!(encode_not_indexed( | ||||
|                         idx, | ||||
|                         header.value_slice(), | ||||
|                         header.is_sensitive(), | ||||
|                         dst)); | ||||
|                 encode_not_indexed(idx, header.value_slice(), header.is_sensitive(), dst)?; | ||||
|             } | ||||
|             Index::Inserted(_) => { | ||||
|                 let header = self.table.resolve(&index); | ||||
| @@ -202,57 +192,52 @@ impl Encoder { | ||||
|  | ||||
|                 dst.put_u8(0b01000000); | ||||
|  | ||||
|                 try!(encode_str(header.name().as_slice(), dst)); | ||||
|                 try!(encode_str(header.value_slice(), dst)); | ||||
|                 encode_str(header.name().as_slice(), dst)?; | ||||
|                 encode_str(header.value_slice(), dst)?; | ||||
|             } | ||||
|             Index::InsertedValue(idx, _) => { | ||||
|                 let header = self.table.resolve(&index); | ||||
|  | ||||
|                 assert!(!header.is_sensitive()); | ||||
|  | ||||
|                 try!(encode_int(idx, 6, 0b01000000, dst)); | ||||
|                 try!(encode_str(header.value_slice(), dst)); | ||||
|                 encode_int(idx, 6, 0b01000000, dst)?; | ||||
|                 encode_str(header.value_slice(), dst)?; | ||||
|             } | ||||
|             Index::NotIndexed(_) => { | ||||
|                 let header = self.table.resolve(&index); | ||||
|  | ||||
|                 try!(encode_not_indexed2( | ||||
|                         header.name().as_slice(), | ||||
|                         header.value_slice(), | ||||
|                         header.is_sensitive(), | ||||
|                         dst)); | ||||
|                 encode_not_indexed2(header.name().as_slice(), | ||||
|                                     header.value_slice(), | ||||
|                                     header.is_sensitive(), | ||||
|                                     dst)?; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     fn encode_header_without_name(&mut self, last: &Index, | ||||
|                                   value: &HeaderValue, dst: &mut BytesMut) | ||||
|         -> Result<(), EncoderError> | ||||
|     { | ||||
|     fn encode_header_without_name( | ||||
|         &mut self, | ||||
|         last: &Index, | ||||
|         value: &HeaderValue, | ||||
|         dst: &mut BytesMut, | ||||
|     ) -> Result<(), EncoderError> { | ||||
|         match *last { | ||||
|             Index::Indexed(..) | | ||||
|                 Index::Name(..) | | ||||
|                 Index::Inserted(..) | | ||||
|                 Index::InsertedValue(..) => | ||||
|             { | ||||
|             Index::Name(..) | | ||||
|             Index::Inserted(..) | | ||||
|             Index::InsertedValue(..) => { | ||||
|                 let idx = self.table.resolve_idx(last); | ||||
|  | ||||
|                 try!(encode_not_indexed( | ||||
|                         idx, | ||||
|                         value.as_ref(), | ||||
|                         value.is_sensitive(), | ||||
|                         dst)); | ||||
|                 encode_not_indexed(idx, value.as_ref(), value.is_sensitive(), dst)?; | ||||
|             } | ||||
|             Index::NotIndexed(_) => { | ||||
|                 let last = self.table.resolve(last); | ||||
|  | ||||
|                 try!(encode_not_indexed2( | ||||
|                         last.name().as_slice(), | ||||
|                         value.as_ref(), | ||||
|                         value.is_sensitive(), | ||||
|                         dst)); | ||||
|                 encode_not_indexed2(last.name().as_slice(), | ||||
|                                     value.as_ref(), | ||||
|                                     value.is_sensitive(), | ||||
|                                     dst)?; | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -270,24 +255,28 @@ fn encode_size_update<B: BufMut>(val: usize, dst: &mut B) -> Result<(), EncoderE | ||||
|     encode_int(val, 5, 0b00100000, dst) | ||||
| } | ||||
|  | ||||
| fn encode_not_indexed(name: usize, value: &[u8], | ||||
|                       sensitive: bool, dst: &mut BytesMut) | ||||
|     -> Result<(), EncoderError> | ||||
| { | ||||
| fn encode_not_indexed( | ||||
|     name: usize, | ||||
|     value: &[u8], | ||||
|     sensitive: bool, | ||||
|     dst: &mut BytesMut, | ||||
| ) -> Result<(), EncoderError> { | ||||
|     if sensitive { | ||||
|         try!(encode_int(name, 4, 0b10000, dst)); | ||||
|         encode_int(name, 4, 0b10000, dst)?; | ||||
|     } else { | ||||
|         try!(encode_int(name, 4, 0, dst)); | ||||
|         encode_int(name, 4, 0, dst)?; | ||||
|     } | ||||
|  | ||||
|     try!(encode_str(value, dst)); | ||||
|     encode_str(value, dst)?; | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| fn encode_not_indexed2(name: &[u8], value: &[u8], | ||||
|                        sensitive: bool, dst: &mut BytesMut) | ||||
|     -> Result<(), EncoderError> | ||||
| { | ||||
| fn encode_not_indexed2( | ||||
|     name: &[u8], | ||||
|     value: &[u8], | ||||
|     sensitive: bool, | ||||
|     dst: &mut BytesMut, | ||||
| ) -> Result<(), EncoderError> { | ||||
|     if !dst.has_remaining_mut() { | ||||
|         return Err(EncoderError::BufferOverflow); | ||||
|     } | ||||
| @@ -298,8 +287,8 @@ fn encode_not_indexed2(name: &[u8], value: &[u8], | ||||
|         dst.put_u8(0); | ||||
|     } | ||||
|  | ||||
|     try!(encode_str(name, dst)); | ||||
|     try!(encode_str(value, dst)); | ||||
|     encode_str(name, dst)?; | ||||
|     encode_str(value, dst)?; | ||||
|     Ok(()) | ||||
| } | ||||
|  | ||||
| @@ -317,7 +306,7 @@ fn encode_str(val: &[u8], dst: &mut BytesMut) -> Result<(), EncoderError> { | ||||
|         dst.put_u8(0); | ||||
|  | ||||
|         // Encode with huffman | ||||
|         try!(huffman::encode(val, dst)); | ||||
|         huffman::encode(val, dst)?; | ||||
|  | ||||
|         let huff_len = dst.len() - (idx + 1); | ||||
|  | ||||
| @@ -330,7 +319,7 @@ fn encode_str(val: &[u8], dst: &mut BytesMut) -> Result<(), EncoderError> { | ||||
|  | ||||
|             let head_len = { | ||||
|                 let mut head_dst = Cursor::new(&mut buf); | ||||
|                 try!(encode_int(huff_len, 7, 0x80, &mut head_dst)); | ||||
|                 encode_int(huff_len, 7, 0x80, &mut head_dst)?; | ||||
|                 head_dst.position() as usize | ||||
|             }; | ||||
|  | ||||
| @@ -343,8 +332,8 @@ fn encode_str(val: &[u8], dst: &mut BytesMut) -> Result<(), EncoderError> { | ||||
|  | ||||
|             // Shift the header forward | ||||
|             for i in 0..huff_len { | ||||
|                 let src_i = idx + 1 + (huff_len - (i+1)); | ||||
|                 let dst_i = idx + head_len + (huff_len - (i+1)); | ||||
|                 let src_i = idx + 1 + (huff_len - (i + 1)); | ||||
|                 let dst_i = idx + head_len + (huff_len - (i + 1)); | ||||
|                 dst[dst_i] = dst[src_i]; | ||||
|             } | ||||
|  | ||||
| @@ -366,9 +355,8 @@ fn encode_int<B: BufMut>( | ||||
|     mut value: usize,   // The integer to encode | ||||
|     prefix_bits: usize, // The number of bits in the prefix | ||||
|     first_byte: u8,     // The base upon which to start encoding the int | ||||
|     dst: &mut B)        // The destination buffer | ||||
|     -> Result<(), EncoderError> | ||||
| { | ||||
|     dst: &mut B, | ||||
| ) -> Result<(), EncoderError> { | ||||
|     let mut rem = dst.remaining_mut(); | ||||
|  | ||||
|     if rem == 0 { | ||||
| @@ -444,7 +432,7 @@ mod test { | ||||
|         let res = encode(&mut encoder, vec![method("PATCH")]); | ||||
|  | ||||
|         assert_eq!(res[0], 0b01000000 | 2); // Incremental indexing w/ name pulled from table | ||||
|         assert_eq!(res[1], 0x80 | 5);       // header value w/ huffman coding | ||||
|         assert_eq!(res[1], 0x80 | 5); // header value w/ huffman coding | ||||
|  | ||||
|         assert_eq!("PATCH", huff_decode(&res[2..7])); | ||||
|         assert_eq!(encoder.table.len(), 1); | ||||
| @@ -522,7 +510,7 @@ mod test { | ||||
|         for i in 1..65 { | ||||
|             let key = format!("x-hello-world-{:02}", i); | ||||
|             let res = encode(&mut encoder, vec![header(&key, &key)]); | ||||
|             assert_eq!(0x80 | (61 + (65-i)), res[0]); | ||||
|             assert_eq!(0x80 | (61 + (65 - i)), res[0]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -547,7 +535,10 @@ mod test { | ||||
|         let mut value = HeaderValue::from_bytes(b"12345").unwrap(); | ||||
|         value.set_sensitive(true); | ||||
|  | ||||
|         let header = Header::Field { name: Some(name), value: value }; | ||||
|         let header = Header::Field { | ||||
|             name: Some(name), | ||||
|             value: value, | ||||
|         }; | ||||
|  | ||||
|         // Now, try to encode the sensitive header | ||||
|  | ||||
| @@ -564,7 +555,10 @@ mod test { | ||||
|         let mut value = HeaderValue::from_bytes(b"12345").unwrap(); | ||||
|         value.set_sensitive(true); | ||||
|  | ||||
|         let header = Header::Field { name: Some(name), value: value }; | ||||
|         let header = Header::Field { | ||||
|             name: Some(name), | ||||
|             value: value, | ||||
|         }; | ||||
|  | ||||
|         let mut encoder = Encoder::default(); | ||||
|         let res = encode(&mut encoder, vec![header]); | ||||
| @@ -576,13 +570,17 @@ mod test { | ||||
|         // Using the name component of a previously indexed header (without | ||||
|         // sensitive flag set) | ||||
|  | ||||
|         let _ = encode(&mut encoder, vec![self::header("my-password", "not-so-secret")]); | ||||
|         let _ = encode(&mut encoder, | ||||
|                        vec![self::header("my-password", "not-so-secret")]); | ||||
|  | ||||
|         let name = "my-password".parse().unwrap(); | ||||
|         let mut value = HeaderValue::from_bytes(b"12345").unwrap(); | ||||
|         value.set_sensitive(true); | ||||
|  | ||||
|         let header = Header::Field { name: Some(name), value: value }; | ||||
|         let header = Header::Field { | ||||
|             name: Some(name), | ||||
|             value: value, | ||||
|         }; | ||||
|         let res = encode(&mut encoder, vec![header]); | ||||
|  | ||||
|         assert_eq!(&[0b11111, 47], &res[..2]); | ||||
| @@ -743,16 +741,19 @@ mod test { | ||||
|     fn test_nameless_header() { | ||||
|         let mut encoder = Encoder::default(); | ||||
|  | ||||
|         let res = encode(&mut encoder, vec![ | ||||
|             Header::Field { | ||||
|                 name: Some("hello".parse().unwrap()), | ||||
|                 value: HeaderValue::from_bytes(b"world").unwrap(), | ||||
|             }, | ||||
|             Header::Field { | ||||
|                 name: None, | ||||
|                 value: HeaderValue::from_bytes(b"zomg").unwrap(), | ||||
|             }, | ||||
|         ]); | ||||
|         let res = encode( | ||||
|             &mut encoder, | ||||
|             vec![ | ||||
|                 Header::Field { | ||||
|                     name: Some("hello".parse().unwrap()), | ||||
|                     value: HeaderValue::from_bytes(b"world").unwrap(), | ||||
|                 }, | ||||
|                 Header::Field { | ||||
|                     name: None, | ||||
|                     value: HeaderValue::from_bytes(b"zomg").unwrap(), | ||||
|                 }, | ||||
|             ], | ||||
|         ); | ||||
|  | ||||
|         assert_eq!(&[0x40, 0x80 | 4], &res[0..2]); | ||||
|         assert_eq!("hello", huff_decode(&res[2..6])); | ||||
| @@ -824,7 +825,10 @@ mod test { | ||||
|         let name = HeaderName::from_bytes(name.as_bytes()).unwrap(); | ||||
|         let value = HeaderValue::from_bytes(val.as_bytes()).unwrap(); | ||||
|  | ||||
|         Header::Field { name: Some(name), value: value } | ||||
|         Header::Field { | ||||
|             name: Some(name), | ||||
|             value: value, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn huff_decode(src: &[u8]) -> BytesMut { | ||||
|   | ||||
| @@ -1,17 +1,14 @@ | ||||
| use super::DecoderError; | ||||
|  | ||||
| use bytes::Bytes; | ||||
| use http::{Method, StatusCode}; | ||||
| use http::header::{HeaderName, HeaderValue}; | ||||
| use bytes::Bytes; | ||||
| use string::{String, TryFrom}; | ||||
|  | ||||
| /// HTTP/2.0 Header | ||||
| #[derive(Debug, Clone, Eq, PartialEq)] | ||||
| pub enum Header<T = HeaderName> { | ||||
|     Field { | ||||
|         name: T, | ||||
|         value: HeaderValue, | ||||
|     }, | ||||
|     Field { name: T, value: HeaderValue }, | ||||
|     // TODO: Change these types to `http::uri` types. | ||||
|     Authority(String<Bytes>), | ||||
|     Method(Method), | ||||
| @@ -41,14 +38,25 @@ impl Header<Option<HeaderName>> { | ||||
|         use self::Header::*; | ||||
|  | ||||
|         Ok(match self { | ||||
|             Field { name: Some(n), value } => Field { name: n, value: value }, | ||||
|             Field { name: None, value } => return Err(value), | ||||
|             Authority(v) => Authority(v), | ||||
|             Method(v) => Method(v), | ||||
|             Scheme(v) => Scheme(v), | ||||
|             Path(v) => Path(v), | ||||
|             Status(v) => Status(v), | ||||
|         }) | ||||
|                Field { | ||||
|                    name: Some(n), | ||||
|                    value, | ||||
|                } => { | ||||
|                    Field { | ||||
|                        name: n, | ||||
|                        value: value, | ||||
|                    } | ||||
|                } | ||||
|                Field { | ||||
|                    name: None, | ||||
|                    value, | ||||
|                } => return Err(value), | ||||
|                Authority(v) => Authority(v), | ||||
|                Method(v) => Method(v), | ||||
|                Scheme(v) => Scheme(v), | ||||
|                Path(v) => Path(v), | ||||
|                Status(v) => Status(v), | ||||
|            }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -57,65 +65,59 @@ impl Header { | ||||
|         if name[0] == b':' { | ||||
|             match &name[1..] { | ||||
|                 b"authority" => { | ||||
|                     let value = try!(String::try_from(value)); | ||||
|                     let value = String::try_from(value)?; | ||||
|                     Ok(Header::Authority(value)) | ||||
|                 } | ||||
|                 b"method" => { | ||||
|                     let method = try!(Method::from_bytes(&value)); | ||||
|                     let method = Method::from_bytes(&value)?; | ||||
|                     Ok(Header::Method(method)) | ||||
|                 } | ||||
|                 b"scheme" => { | ||||
|                     let value = try!(String::try_from(value)); | ||||
|                     let value = String::try_from(value)?; | ||||
|                     Ok(Header::Scheme(value)) | ||||
|                 } | ||||
|                 b"path" => { | ||||
|                     let value = try!(String::try_from(value)); | ||||
|                     let value = String::try_from(value)?; | ||||
|                     Ok(Header::Path(value)) | ||||
|                 } | ||||
|                 b"status" => { | ||||
|                     let status = try!(StatusCode::from_bytes(&value)); | ||||
|                     let status = StatusCode::from_bytes(&value)?; | ||||
|                     Ok(Header::Status(status)) | ||||
|                 } | ||||
|                 _ => { | ||||
|                     Err(DecoderError::InvalidPseudoheader) | ||||
|                 } | ||||
|                 _ => Err(DecoderError::InvalidPseudoheader), | ||||
|             } | ||||
|         } else { | ||||
|             // HTTP/2 requires lower case header names | ||||
|             let name = try!(HeaderName::from_lowercase(&name)); | ||||
|             let value = try!(HeaderValue::from_bytes(&value)); | ||||
|             let name = HeaderName::from_lowercase(&name)?; | ||||
|             let value = HeaderValue::from_bytes(&value)?; | ||||
|  | ||||
|             Ok(Header::Field { name: name, value: value }) | ||||
|             Ok(Header::Field { | ||||
|                    name: name, | ||||
|                    value: value, | ||||
|                }) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     pub fn len(&self) -> usize { | ||||
|         match *self { | ||||
|             Header::Field { ref name, ref value } => { | ||||
|                 len(name, value) | ||||
|             } | ||||
|             Header::Authority(ref v) => { | ||||
|                 32 + 10 + v.len() | ||||
|             } | ||||
|             Header::Method(ref v) => { | ||||
|                 32 + 7 + v.as_ref().len() | ||||
|             } | ||||
|             Header::Scheme(ref v) => { | ||||
|                 32 + 7 + v.len() | ||||
|             } | ||||
|             Header::Path(ref v) => { | ||||
|                 32 + 5 + v.len() | ||||
|             } | ||||
|             Header::Status(_) => { | ||||
|                 32 + 7 + 3 | ||||
|             } | ||||
|             Header::Field { | ||||
|                 ref name, | ||||
|                 ref value, | ||||
|             } => len(name, value), | ||||
|             Header::Authority(ref v) => 32 + 10 + v.len(), | ||||
|             Header::Method(ref v) => 32 + 7 + v.as_ref().len(), | ||||
|             Header::Scheme(ref v) => 32 + 7 + v.len(), | ||||
|             Header::Path(ref v) => 32 + 5 + v.len(), | ||||
|             Header::Status(_) => 32 + 7 + 3, | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /// Returns the header name | ||||
|     pub fn name(&self) -> Name { | ||||
|         match *self { | ||||
|             Header::Field { ref name, .. } => Name::Field(name), | ||||
|             Header::Field { | ||||
|                 ref name, .. | ||||
|             } => Name::Field(name), | ||||
|             Header::Authority(..) => Name::Authority, | ||||
|             Header::Method(..) => Name::Method, | ||||
|             Header::Scheme(..) => Name::Scheme, | ||||
| @@ -126,7 +128,9 @@ impl Header { | ||||
|  | ||||
|     pub fn value_slice(&self) -> &[u8] { | ||||
|         match *self { | ||||
|             Header::Field { ref value, .. } => value.as_ref(), | ||||
|             Header::Field { | ||||
|                 ref value, .. | ||||
|             } => value.as_ref(), | ||||
|             Header::Authority(ref v) => v.as_ref(), | ||||
|             Header::Method(ref v) => v.as_ref().as_ref(), | ||||
|             Header::Scheme(ref v) => v.as_ref(), | ||||
| @@ -137,10 +141,14 @@ impl Header { | ||||
|  | ||||
|     pub fn value_eq(&self, other: &Header) -> bool { | ||||
|         match *self { | ||||
|             Header::Field { ref value, .. } => { | ||||
|             Header::Field { | ||||
|                 ref value, .. | ||||
|             } => { | ||||
|                 let a = value; | ||||
|                 match *other { | ||||
|                     Header::Field { ref value, .. } => a == value, | ||||
|                     Header::Field { | ||||
|                         ref value, .. | ||||
|                     } => a == value, | ||||
|                     _ => false, | ||||
|                 } | ||||
|             } | ||||
| @@ -179,7 +187,9 @@ impl Header { | ||||
|  | ||||
|     pub fn is_sensitive(&self) -> bool { | ||||
|         match *self { | ||||
|             Header::Field { ref value, .. } => value.is_sensitive(), | ||||
|             Header::Field { | ||||
|                 ref value, .. | ||||
|             } => value.is_sensitive(), | ||||
|             // TODO: Technically these other header values can be sensitive too. | ||||
|             _ => false, | ||||
|         } | ||||
| @@ -189,17 +199,19 @@ impl Header { | ||||
|         use http::header; | ||||
|  | ||||
|         match *self { | ||||
|             Header::Field { ref name, .. } => { | ||||
|             Header::Field { | ||||
|                 ref name, .. | ||||
|             } => { | ||||
|                 match *name { | ||||
|                     header::AGE | | ||||
|                         header::AUTHORIZATION | | ||||
|                         header::CONTENT_LENGTH | | ||||
|                         header::ETAG | | ||||
|                         header::IF_MODIFIED_SINCE | | ||||
|                         header::IF_NONE_MATCH | | ||||
|                         header::LOCATION | | ||||
|                         header::COOKIE | | ||||
|                         header::SET_COOKIE => true, | ||||
|                     header::AUTHORIZATION | | ||||
|                     header::CONTENT_LENGTH | | ||||
|                     header::ETAG | | ||||
|                     header::IF_MODIFIED_SINCE | | ||||
|                     header::IF_NONE_MATCH | | ||||
|                     header::LOCATION | | ||||
|                     header::COOKIE | | ||||
|                     header::SET_COOKIE => true, | ||||
|                     _ => false, | ||||
|                 } | ||||
|             } | ||||
| @@ -213,7 +225,15 @@ impl Header { | ||||
| impl From<Header> for Header<Option<HeaderName>> { | ||||
|     fn from(src: Header) -> Self { | ||||
|         match src { | ||||
|             Header::Field { name, value } => Header::Field { name: Some(name), value }, | ||||
|             Header::Field { | ||||
|                 name, | ||||
|                 value, | ||||
|             } => { | ||||
|                 Header::Field { | ||||
|                     name: Some(name), | ||||
|                     value, | ||||
|                 } | ||||
|             } | ||||
|             Header::Authority(v) => Header::Authority(v), | ||||
|             Header::Method(v) => Header::Method(v), | ||||
|             Header::Scheme(v) => Header::Scheme(v), | ||||
| @@ -228,22 +248,14 @@ impl<'a> Name<'a> { | ||||
|         match self { | ||||
|             Name::Field(name) => { | ||||
|                 Ok(Header::Field { | ||||
|                     name: name.clone(), | ||||
|                     value: try!(HeaderValue::from_bytes(&*value)), | ||||
|                 }) | ||||
|             } | ||||
|             Name::Authority => { | ||||
|                 Ok(Header::Authority(try!(String::try_from(value)))) | ||||
|             } | ||||
|             Name::Method => { | ||||
|                 Ok(Header::Method(try!(Method::from_bytes(&*value)))) | ||||
|             } | ||||
|             Name::Scheme => { | ||||
|                 Ok(Header::Scheme(try!(String::try_from(value)))) | ||||
|             } | ||||
|             Name::Path => { | ||||
|                 Ok(Header::Path(try!(String::try_from(value)))) | ||||
|                        name: name.clone(), | ||||
|                        value: HeaderValue::from_bytes(&*value)?, | ||||
|                    }) | ||||
|             } | ||||
|             Name::Authority => Ok(Header::Authority(String::try_from(value)?)), | ||||
|             Name::Method => Ok(Header::Method(Method::from_bytes(&*value)?)), | ||||
|             Name::Scheme => Ok(Header::Scheme(String::try_from(value)?)), | ||||
|             Name::Path => Ok(Header::Path(String::try_from(value)?)), | ||||
|             Name::Status => { | ||||
|                 match StatusCode::from_bytes(&value) { | ||||
|                     Ok(status) => Ok(Header::Status(status)), | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| mod table; | ||||
|  | ||||
| use self::table::{ENCODE_TABLE, DECODE_TABLE}; | ||||
| use self::table::{DECODE_TABLE, ENCODE_TABLE}; | ||||
| use hpack::{DecoderError, EncoderError}; | ||||
|  | ||||
| use bytes::{BytesMut, BufMut}; | ||||
| use bytes::{BufMut, BytesMut}; | ||||
|  | ||||
| // Constructed in the generated `table.rs` file | ||||
| struct Decoder { | ||||
| @@ -24,11 +24,11 @@ pub fn decode(src: &[u8], buf: &mut BytesMut) -> Result<BytesMut, DecoderError> | ||||
|     buf.reserve(src.len() << 1); | ||||
|  | ||||
|     for b in src { | ||||
|         if let Some(b) = try!(decoder.decode4(b >> 4)) { | ||||
|         if let Some(b) = decoder.decode4(b >> 4)? { | ||||
|             buf.put_u8(b); | ||||
|         } | ||||
|  | ||||
|         if let Some(b) = try!(decoder.decode4(b & 0xf)) { | ||||
|         if let Some(b) = decoder.decode4(b & 0xf)? { | ||||
|             buf.put_u8(b); | ||||
|         } | ||||
|     } | ||||
| @@ -161,10 +161,27 @@ mod test { | ||||
|     #[test] | ||||
|     fn encode_decode_str() { | ||||
|         const DATA: &'static [&'static str] = &[ | ||||
|             "hello world", ":method", ":scheme", ":authority", "yahoo.co.jp", "GET", "http", ":path", "/images/top/sp2/cmn/logo-ns-130528.png", | ||||
|             "example.com", "hpack-test", "xxxxxxx1", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0", | ||||
|             "accept", "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "cookie", "B=76j09a189a6h4&b=3&s=0b", | ||||
|             "TE", "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi non bibendum libero. Etiam ultrices lorem ut", | ||||
|             "hello world", | ||||
|             ":method", | ||||
|             ":scheme", | ||||
|             ":authority", | ||||
|             "yahoo.co.jp", | ||||
|             "GET", | ||||
|             "http", | ||||
|             ":path", | ||||
|             "/images/top/sp2/cmn/logo-ns-130528.png", | ||||
|             "example.com", | ||||
|             "hpack-test", | ||||
|             "xxxxxxx1", | ||||
|             "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:16.0) Gecko/20100101 Firefox/16.0", | ||||
|             "accept", | ||||
|             "Accept", | ||||
|             "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", | ||||
|             "cookie", | ||||
|             "B=76j09a189a6h4&b=3&s=0b", | ||||
|             "TE", | ||||
|             "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi non bibendum libero. \ | ||||
|              Etiam ultrices lorem ut.", | ||||
|         ]; | ||||
|  | ||||
|         for s in DATA { | ||||
| @@ -180,9 +197,8 @@ mod test { | ||||
|  | ||||
|     #[test] | ||||
|     fn encode_decode_u8() { | ||||
|         const DATA: &'static [&'static [u8]] = &[ | ||||
|             b"\0", b"\0\0\0", b"\0\x01\x02\x03\x04\x05", b"\xFF\xF8", | ||||
|         ]; | ||||
|         const DATA: &'static [&'static [u8]] = | ||||
|             &[b"\0", b"\0\0\0", b"\0\x01\x02\x03\x04\x05", b"\xFF\xF8"]; | ||||
|  | ||||
|         for s in DATA { | ||||
|             let mut dst = Vec::with_capacity(s.len()); | ||||
|   | ||||
| @@ -7,6 +7,6 @@ mod table; | ||||
| #[cfg(test)] | ||||
| mod test; | ||||
|  | ||||
| pub use self::encoder::{Encoder, Encode, EncoderError, EncodeState}; | ||||
| pub use self::header::Header; | ||||
| pub use self::decoder::{Decoder, DecoderError}; | ||||
| pub use self::encoder::{Encode, EncodeState, Encoder, EncoderError}; | ||||
| pub use self::header::Header; | ||||
|   | ||||
| @@ -83,9 +83,7 @@ impl Table { | ||||
|                 max_size: max_size, | ||||
|             } | ||||
|         } else { | ||||
|             let capacity = cmp::max( | ||||
|                 to_raw_capacity(capacity).next_power_of_two(), | ||||
|                 8); | ||||
|             let capacity = cmp::max(to_raw_capacity(capacity).next_power_of_two(), 8); | ||||
|  | ||||
|             Table { | ||||
|                 mask: capacity.wrapping_sub(1), | ||||
| @@ -203,12 +201,7 @@ impl Table { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     fn index_occupied(&mut self, | ||||
|                       header: Header, | ||||
|                       hash: HashValue, | ||||
|                       mut index: usize) | ||||
|         -> Index | ||||
|     { | ||||
|     fn index_occupied(&mut self, header: Header, hash: HashValue, mut index: usize) -> Index { | ||||
|         debug_assert!(self.assert_valid_state("top")); | ||||
|  | ||||
|         // There already is a match for the given header name. Check if a value | ||||
| @@ -256,14 +249,14 @@ impl Table { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn index_vacant(&mut self, | ||||
|                     header: Header, | ||||
|                     hash: HashValue, | ||||
|                     mut dist: usize, | ||||
|                     mut probe: usize, | ||||
|                     statik: Option<(usize, bool)>) | ||||
|         -> Index | ||||
|     { | ||||
|     fn index_vacant( | ||||
|         &mut self, | ||||
|         header: Header, | ||||
|         hash: HashValue, | ||||
|         mut dist: usize, | ||||
|         mut probe: usize, | ||||
|         statik: Option<(usize, bool)>, | ||||
|     ) -> Index { | ||||
|         if header.is_sensitive() { | ||||
|             return Index::new(statik, header); | ||||
|         } | ||||
| @@ -299,10 +292,11 @@ impl Table { | ||||
|  | ||||
|         let pos_idx = 0usize.wrapping_sub(self.inserted); | ||||
|  | ||||
|         let prev = mem::replace(&mut self.indices[probe], Some(Pos { | ||||
|             index: pos_idx, | ||||
|             hash: hash, | ||||
|         })); | ||||
|         let prev = mem::replace(&mut self.indices[probe], | ||||
|                                 Some(Pos { | ||||
|                                          index: pos_idx, | ||||
|                                          hash: hash, | ||||
|                                      })); | ||||
|  | ||||
|         if let Some(mut prev) = prev { | ||||
|             // Shift forward | ||||
| @@ -331,10 +325,10 @@ impl Table { | ||||
|         self.inserted = self.inserted.wrapping_add(1); | ||||
|  | ||||
|         self.slots.push_front(Slot { | ||||
|             hash: hash, | ||||
|             header: header, | ||||
|             next: None, | ||||
|         }); | ||||
|                                   hash: hash, | ||||
|                                   header: header, | ||||
|                                   next: None, | ||||
|                               }); | ||||
|     } | ||||
|  | ||||
|     pub fn resize(&mut self, size: usize) { | ||||
| @@ -383,11 +377,12 @@ impl Table { | ||||
|         // Update the size | ||||
|         self.size -= slot.header.len(); | ||||
|  | ||||
|         debug_assert_eq!( | ||||
|             self.indices.iter().filter_map(|p| *p) | ||||
|                 .filter(|p| p.index == pos_idx) | ||||
|                 .count(), | ||||
|             1); | ||||
|         debug_assert_eq!(self.indices | ||||
|                              .iter() | ||||
|                              .filter_map(|p| *p) | ||||
|                              .filter(|p| p.index == pos_idx) | ||||
|                              .count(), | ||||
|                          1); | ||||
|  | ||||
|         // Find the associated position | ||||
|         probe_loop!(probe < self.indices.len(), { | ||||
| @@ -500,12 +495,12 @@ impl Table { | ||||
|                 } | ||||
|  | ||||
|                 debug_assert!({ | ||||
|                     let them = self.indices[probe].unwrap(); | ||||
|                     let their_distance = probe_distance(self.mask, them.hash, probe); | ||||
|                     let our_distance = probe_distance(self.mask, pos.hash, probe); | ||||
|                                   let them = self.indices[probe].unwrap(); | ||||
|                                   let their_distance = probe_distance(self.mask, them.hash, probe); | ||||
|                                   let our_distance = probe_distance(self.mask, pos.hash, probe); | ||||
|  | ||||
|                     their_distance >= our_distance | ||||
|                 }); | ||||
|                                   their_distance >= our_distance | ||||
|                               }); | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
| @@ -584,8 +579,10 @@ impl Table { | ||||
|                     } | ||||
|  | ||||
|                     assert!(dist <= their_dist, | ||||
|                             "could not find entry; actual={}; desired={}; probe={}, dist={}; their_dist={}; index={}; msg={}", | ||||
|                             actual, desired, probe, dist, their_dist, index.wrapping_sub(self.inserted), msg); | ||||
|                             "could not find entry; actual={}; desired={};" + | ||||
|                             "probe={}, dist={}; their_dist={}; index={}; msg={}", | ||||
|                             actual, desired, probe, dist, their_dist, | ||||
|                             index.wrapping_sub(self.inserted), msg); | ||||
|  | ||||
|                     dist += 1; | ||||
|                 }); | ||||
| @@ -661,7 +658,10 @@ fn hash_header(header: &Header) -> HashValue { | ||||
| /// boolean representing if the value matched as well. | ||||
| fn index_static(header: &Header) -> Option<(usize, bool)> { | ||||
|     match *header { | ||||
|         Header::Field { ref name, ref value } => { | ||||
|         Header::Field { | ||||
|             ref name, | ||||
|             ref value, | ||||
|         } => { | ||||
|             match *name { | ||||
|                 header::ACCEPT_CHARSET => Some((15, false)), | ||||
|                 header::ACCEPT_ENCODING => { | ||||
|   | ||||
| @@ -2,15 +2,15 @@ extern crate bytes; | ||||
| extern crate hex; | ||||
| extern crate serde_json; | ||||
|  | ||||
| use hpack::{Header, Decoder, Encoder}; | ||||
| use hpack::{Decoder, Encoder, Header}; | ||||
|  | ||||
| use self::bytes::BytesMut; | ||||
| use self::hex::FromHex; | ||||
| use self::serde_json::Value; | ||||
|  | ||||
| use std::fs::File; | ||||
| use std::io::prelude::*; | ||||
| use std::io::Cursor; | ||||
| use std::io::prelude::*; | ||||
| use std::path::Path; | ||||
| use std::str; | ||||
|  | ||||
| @@ -27,7 +27,10 @@ fn test_story(story: Value) { | ||||
|     let story = story.as_object().unwrap(); | ||||
|  | ||||
|     if let Some(cases) = story.get("cases") { | ||||
|         let mut cases: Vec<_> = cases.as_array().unwrap().iter() | ||||
|         let mut cases: Vec<_> = cases | ||||
|             .as_array() | ||||
|             .unwrap() | ||||
|             .iter() | ||||
|             .map(|case| { | ||||
|                 let case = case.as_object().unwrap(); | ||||
|  | ||||
| @@ -37,8 +40,11 @@ fn test_story(story: Value) { | ||||
|                 let wire = case.get("wire").unwrap().as_str().unwrap(); | ||||
|                 let wire: Vec<u8> = FromHex::from_hex(wire.as_bytes()).unwrap(); | ||||
|  | ||||
|                 let expect: Vec<_> = case.get("headers").unwrap() | ||||
|                     .as_array().unwrap().iter() | ||||
|                 let expect: Vec<_> = case.get("headers") | ||||
|                     .unwrap() | ||||
|                     .as_array() | ||||
|                     .unwrap() | ||||
|                     .iter() | ||||
|                     .map(|h| { | ||||
|                         let h = h.as_object().unwrap(); | ||||
|                         let (name, val) = h.iter().next().unwrap(); | ||||
| @@ -67,11 +73,13 @@ fn test_story(story: Value) { | ||||
|                 decoder.queue_size_update(size); | ||||
|             } | ||||
|  | ||||
|             decoder.decode(&mut Cursor::new(case.wire.clone().into()), |e| { | ||||
|                 let (name, value) = expect.remove(0); | ||||
|                 assert_eq!(name, key_str(&e)); | ||||
|                 assert_eq!(value, value_str(&e)); | ||||
|             }).unwrap(); | ||||
|             decoder | ||||
|                 .decode(&mut Cursor::new(case.wire.clone().into()), |e| { | ||||
|                     let (name, value) = expect.remove(0); | ||||
|                     assert_eq!(name, key_str(&e)); | ||||
|                     assert_eq!(value, value_str(&e)); | ||||
|                 }) | ||||
|                 .unwrap(); | ||||
|  | ||||
|             assert_eq!(0, expect.len()); | ||||
|         } | ||||
| @@ -88,15 +96,22 @@ fn test_story(story: Value) { | ||||
|                 decoder.queue_size_update(size); | ||||
|             } | ||||
|  | ||||
|             let mut input: Vec<_> = case.expect.iter().map(|&(ref name, ref value)| { | ||||
|                 Header::new(name.clone().into(), value.clone().into()).unwrap().into() | ||||
|             }).collect(); | ||||
|             let mut input: Vec<_> = case.expect | ||||
|                 .iter() | ||||
|                 .map(|&(ref name, ref value)| { | ||||
|                     Header::new(name.clone().into(), value.clone().into()) | ||||
|                         .unwrap() | ||||
|                         .into() | ||||
|                 }) | ||||
|                 .collect(); | ||||
|  | ||||
|             encoder.encode(None, &mut input.clone().into_iter(), &mut buf); | ||||
|  | ||||
|             decoder.decode(&mut Cursor::new(buf.into()), |e| { | ||||
|                 assert_eq!(e, input.remove(0).reify().unwrap()); | ||||
|             }).unwrap(); | ||||
|             decoder | ||||
|                 .decode(&mut Cursor::new(buf.into()), |e| { | ||||
|                     assert_eq!(e, input.remove(0).reify().unwrap()); | ||||
|                 }) | ||||
|                 .unwrap(); | ||||
|  | ||||
|             assert_eq!(0, input.len()); | ||||
|         } | ||||
| @@ -112,7 +127,9 @@ struct Case { | ||||
|  | ||||
| fn key_str(e: &Header) -> &str { | ||||
|     match *e { | ||||
|         Header::Field { ref name, .. } => name.as_str(), | ||||
|         Header::Field { | ||||
|             ref name, .. | ||||
|         } => name.as_str(), | ||||
|         Header::Authority(..) => ":authority", | ||||
|         Header::Method(..) => ":method", | ||||
|         Header::Scheme(..) => ":scheme", | ||||
| @@ -123,7 +140,9 @@ fn key_str(e: &Header) -> &str { | ||||
|  | ||||
| fn value_str(e: &Header) -> &str { | ||||
|     match *e { | ||||
|         Header::Field { ref value, .. } => value.to_str().unwrap(), | ||||
|         Header::Field { | ||||
|             ref value, .. | ||||
|         } => value.to_str().unwrap(), | ||||
|         Header::Authority(ref v) => &**v, | ||||
|         Header::Method(ref m) => m.as_str(), | ||||
|         Header::Scheme(ref v) => &**v, | ||||
|   | ||||
| @@ -2,13 +2,13 @@ extern crate bytes; | ||||
| extern crate quickcheck; | ||||
| extern crate rand; | ||||
|  | ||||
| use hpack::{Header, Decoder, Encoder, Encode}; | ||||
| use hpack::{Decoder, Encode, Encoder, Header}; | ||||
|  | ||||
| use http::header::{HeaderName, HeaderValue}; | ||||
|  | ||||
| use self::bytes::{BytesMut, Bytes}; | ||||
| use self::quickcheck::{QuickCheck, Arbitrary, Gen, TestResult}; | ||||
| use self::rand::{StdRng, Rng, SeedableRng}; | ||||
| use self::bytes::{Bytes, BytesMut}; | ||||
| use self::quickcheck::{Arbitrary, Gen, QuickCheck, TestResult}; | ||||
| use self::rand::{Rng, SeedableRng, StdRng}; | ||||
|  | ||||
| use std::io::Cursor; | ||||
|  | ||||
| @@ -130,8 +130,7 @@ impl FuzzHpack { | ||||
|             let mut index = None; | ||||
|             let mut input = frame.headers.into_iter(); | ||||
|  | ||||
|             let mut buf = BytesMut::with_capacity( | ||||
|                 chunks.pop().unwrap_or(MAX_CHUNK)); | ||||
|             let mut buf = BytesMut::with_capacity(chunks.pop().unwrap_or(MAX_CHUNK)); | ||||
|  | ||||
|             if let Some(max) = frame.resizes.iter().max() { | ||||
|                 decoder.queue_size_update(*max); | ||||
| @@ -149,20 +148,23 @@ impl FuzzHpack { | ||||
|                         index = Some(i); | ||||
|  | ||||
|                         // Decode the chunk! | ||||
|                         decoder.decode(&mut Cursor::new(buf.into()), |e| { | ||||
|                             assert_eq!(e, expect.remove(0).reify().unwrap()); | ||||
|                         }).unwrap(); | ||||
|                         decoder | ||||
|                             .decode(&mut Cursor::new(buf.into()), |e| { | ||||
|                                 assert_eq!(e, expect.remove(0).reify().unwrap()); | ||||
|                             }) | ||||
|                             .unwrap(); | ||||
|  | ||||
|                         buf = BytesMut::with_capacity( | ||||
|                             chunks.pop().unwrap_or(MAX_CHUNK)); | ||||
|                         buf = BytesMut::with_capacity(chunks.pop().unwrap_or(MAX_CHUNK)); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Decode the chunk! | ||||
|             decoder.decode(&mut Cursor::new(buf.into()), |e| { | ||||
|                 assert_eq!(e, expect.remove(0).reify().unwrap()); | ||||
|             }).unwrap(); | ||||
|             decoder | ||||
|                 .decode(&mut Cursor::new(buf.into()), |e| { | ||||
|                     assert_eq!(e, expect.remove(0).reify().unwrap()); | ||||
|                 }) | ||||
|                 .unwrap(); | ||||
|         } | ||||
|  | ||||
|         assert_eq!(0, expect.len()); | ||||
| @@ -193,9 +195,9 @@ fn gen_header(g: &mut StdRng) -> Header<Option<HeaderName>> { | ||||
|                     4 => Method::DELETE, | ||||
|                     5 => { | ||||
|                         let n: usize = g.gen_range(3, 7); | ||||
|                         let bytes: Vec<u8> = (0..n).map(|_| { | ||||
|                             g.choose(b"ABCDEFGHIJKLMNOPQRSTUVWXYZ").unwrap().clone() | ||||
|                         }).collect(); | ||||
|                         let bytes: Vec<u8> = (0..n) | ||||
|                             .map(|_| g.choose(b"ABCDEFGHIJKLMNOPQRSTUVWXYZ").unwrap().clone()) | ||||
|                             .collect(); | ||||
|  | ||||
|                         Method::from_bytes(&bytes).unwrap() | ||||
|                     } | ||||
| @@ -237,7 +239,10 @@ fn gen_header(g: &mut StdRng) -> Header<Option<HeaderName>> { | ||||
|             value.set_sensitive(true); | ||||
|         } | ||||
|  | ||||
|         Header::Field { name: Some(name), value: value } | ||||
|         Header::Field { | ||||
|             name: Some(name), | ||||
|             value: value, | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -320,7 +325,8 @@ fn gen_header_name(g: &mut StdRng) -> HeaderName { | ||||
|             header::X_DNS_PREFETCH_CONTROL, | ||||
|             header::X_FRAME_OPTIONS, | ||||
|             header::X_XSS_PROTECTION, | ||||
|         ]).unwrap().clone() | ||||
|         ]).unwrap() | ||||
|             .clone() | ||||
|     } else { | ||||
|         let value = gen_string(g, 1, 25); | ||||
|         HeaderName::from_bytes(value.as_bytes()).unwrap() | ||||
| @@ -333,10 +339,14 @@ fn gen_header_value(g: &mut StdRng) -> HeaderValue { | ||||
| } | ||||
|  | ||||
| fn gen_string(g: &mut StdRng, min: usize, max: usize) -> String { | ||||
|     let bytes: Vec<_> = (min..max).map(|_| { | ||||
|         // Chars to pick from | ||||
|         g.choose(b"ABCDEFGHIJKLMNOPQRSTUVabcdefghilpqrstuvwxyz----").unwrap().clone() | ||||
|     }).collect(); | ||||
|     let bytes: Vec<_> = (min..max) | ||||
|         .map(|_| { | ||||
|             // Chars to pick from | ||||
|             g.choose(b"ABCDEFGHIJKLMNOPQRSTUVabcdefghilpqrstuvwxyz----") | ||||
|                 .unwrap() | ||||
|                 .clone() | ||||
|         }) | ||||
|         .collect(); | ||||
|  | ||||
|     String::from_utf8(bytes).unwrap() | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user