diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/rust/h2/src/hpack | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/h2/src/hpack')
-rw-r--r-- | third_party/rust/h2/src/hpack/decoder.rs | 940 | ||||
-rw-r--r-- | third_party/rust/h2/src/hpack/encoder.rs | 721 | ||||
-rw-r--r-- | third_party/rust/h2/src/hpack/header.rs | 308 | ||||
-rw-r--r-- | third_party/rust/h2/src/hpack/huffman/mod.rs | 200 | ||||
-rw-r--r-- | third_party/rust/h2/src/hpack/huffman/table.rs | 5130 | ||||
-rw-r--r-- | third_party/rust/h2/src/hpack/mod.rs | 12 | ||||
-rw-r--r-- | third_party/rust/h2/src/hpack/table.rs | 766 | ||||
-rw-r--r-- | third_party/rust/h2/src/hpack/test/fixture.rs | 615 | ||||
-rw-r--r-- | third_party/rust/h2/src/hpack/test/fuzz.rs | 365 | ||||
-rw-r--r-- | third_party/rust/h2/src/hpack/test/mod.rs | 2 |
10 files changed, 9059 insertions, 0 deletions
diff --git a/third_party/rust/h2/src/hpack/decoder.rs b/third_party/rust/h2/src/hpack/decoder.rs new file mode 100644 index 0000000000..988b48db11 --- /dev/null +++ b/third_party/rust/h2/src/hpack/decoder.rs @@ -0,0 +1,940 @@ +use super::{header::BytesStr, huffman, Header}; +use crate::frame; + +use bytes::{Buf, Bytes, BytesMut}; +use http::header; +use http::method::{self, Method}; +use http::status::{self, StatusCode}; + +use std::cmp; +use std::collections::VecDeque; +use std::io::Cursor; +use std::str::Utf8Error; + +/// Decodes headers using HPACK +#[derive(Debug)] +pub struct Decoder { + // Protocol indicated that the max table size will update + max_size_update: Option<usize>, + last_max_update: usize, + table: Table, + buffer: BytesMut, +} + +/// Represents all errors that can be encountered while performing the decoding +/// of an HPACK header set. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum DecoderError { + InvalidRepresentation, + InvalidIntegerPrefix, + InvalidTableIndex, + InvalidHuffmanCode, + InvalidUtf8, + InvalidStatusCode, + InvalidPseudoheader, + InvalidMaxDynamicSize, + IntegerOverflow, + NeedMore(NeedMore), +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum NeedMore { + UnexpectedEndOfStream, + IntegerUnderflow, + StringUnderflow, +} + +enum Representation { + /// Indexed header field representation + /// + /// An indexed header field representation identifies an entry in either the + /// static table or the dynamic table (see Section 2.3). + /// + /// # Header encoding + /// + /// ```text + /// 0 1 2 3 4 5 6 7 + /// +---+---+---+---+---+---+---+---+ + /// | 1 | Index (7+) | + /// +---+---------------------------+ + /// ``` + Indexed, + + /// Literal Header Field with Incremental Indexing + /// + /// A literal header field with incremental indexing representation results + /// in appending a header field to the decoded header list and inserting it + /// as a new entry into the dynamic table. + /// + /// # Header encoding + /// + /// ```text + /// 0 1 2 3 4 5 6 7 + /// +---+---+---+---+---+---+---+---+ + /// | 0 | 1 | Index (6+) | + /// +---+---+-----------------------+ + /// | H | Value Length (7+) | + /// +---+---------------------------+ + /// | Value String (Length octets) | + /// +-------------------------------+ + /// ``` + LiteralWithIndexing, + + /// Literal Header Field without Indexing + /// + /// A literal header field without indexing representation results in + /// appending a header field to the decoded header list without altering the + /// dynamic table. + /// + /// # Header encoding + /// + /// ```text + /// 0 1 2 3 4 5 6 7 + /// +---+---+---+---+---+---+---+---+ + /// | 0 | 0 | 0 | 0 | Index (4+) | + /// +---+---+-----------------------+ + /// | H | Value Length (7+) | + /// +---+---------------------------+ + /// | Value String (Length octets) | + /// +-------------------------------+ + /// ``` + LiteralWithoutIndexing, + + /// Literal Header Field Never Indexed + /// + /// A literal header field never-indexed representation results in appending + /// a header field to the decoded header list without altering the dynamic + /// table. Intermediaries MUST use the same representation for encoding this + /// header field. + /// + /// ```text + /// 0 1 2 3 4 5 6 7 + /// +---+---+---+---+---+---+---+---+ + /// | 0 | 0 | 0 | 1 | Index (4+) | + /// +---+---+-----------------------+ + /// | H | Value Length (7+) | + /// +---+---------------------------+ + /// | Value String (Length octets) | + /// +-------------------------------+ + /// ``` + LiteralNeverIndexed, + + /// Dynamic Table Size Update + /// + /// A dynamic table size update signals a change to the size of the dynamic + /// table. + /// + /// # Header encoding + /// + /// ```text + /// 0 1 2 3 4 5 6 7 + /// +---+---+---+---+---+---+---+---+ + /// | 0 | 0 | 1 | Max size (5+) | + /// +---+---------------------------+ + /// ``` + SizeUpdate, +} + +#[derive(Debug)] +struct Table { + entries: VecDeque<Header>, + size: usize, + max_size: usize, +} + +struct StringMarker { + offset: usize, + len: usize, + string: Option<Bytes>, +} + +// ===== impl Decoder ===== + +impl Decoder { + /// Creates a new `Decoder` with all settings set to default values. + pub fn new(size: usize) -> Decoder { + Decoder { + max_size_update: None, + last_max_update: size, + table: Table::new(size), + buffer: BytesMut::with_capacity(4096), + } + } + + /// Queues a potential size update + #[allow(dead_code)] + pub fn queue_size_update(&mut self, size: usize) { + let size = match self.max_size_update { + Some(v) => cmp::max(v, size), + None => size, + }; + + self.max_size_update = Some(size); + } + + /// Decodes the headers found in the given buffer. + pub fn decode<F>( + &mut self, + src: &mut Cursor<&mut BytesMut>, + mut f: F, + ) -> Result<(), DecoderError> + where + F: FnMut(Header), + { + use self::Representation::*; + + let mut can_resize = true; + + if let Some(size) = self.max_size_update.take() { + self.last_max_update = size; + } + + let span = tracing::trace_span!("hpack::decode"); + let _e = span.enter(); + + tracing::trace!("decode"); + + while let Some(ty) = peek_u8(src) { + // 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 Representation::load(ty)? { + Indexed => { + tracing::trace!(rem = src.remaining(), kind = %"Indexed"); + can_resize = false; + let entry = self.decode_indexed(src)?; + consume(src); + f(entry); + } + LiteralWithIndexing => { + tracing::trace!(rem = src.remaining(), kind = %"LiteralWithIndexing"); + can_resize = false; + let entry = self.decode_literal(src, true)?; + + // Insert the header into the table + self.table.insert(entry.clone()); + consume(src); + + f(entry); + } + LiteralWithoutIndexing => { + tracing::trace!(rem = src.remaining(), kind = %"LiteralWithoutIndexing"); + can_resize = false; + let entry = self.decode_literal(src, false)?; + consume(src); + f(entry); + } + LiteralNeverIndexed => { + tracing::trace!(rem = src.remaining(), kind = %"LiteralNeverIndexed"); + can_resize = false; + let entry = self.decode_literal(src, false)?; + consume(src); + + // TODO: Track that this should never be indexed + + f(entry); + } + SizeUpdate => { + tracing::trace!(rem = src.remaining(), kind = %"SizeUpdate"); + if !can_resize { + return Err(DecoderError::InvalidMaxDynamicSize); + } + + // Handle the dynamic table size update + self.process_size_update(src)?; + consume(src); + } + } + } + + Ok(()) + } + + fn process_size_update(&mut self, buf: &mut Cursor<&mut BytesMut>) -> Result<(), DecoderError> { + let new_size = decode_int(buf, 5)?; + + if new_size > self.last_max_update { + return Err(DecoderError::InvalidMaxDynamicSize); + } + + tracing::debug!( + from = self.table.size(), + to = new_size, + "Decoder changed max table size" + ); + + self.table.set_max_size(new_size); + + Ok(()) + } + + fn decode_indexed(&self, buf: &mut Cursor<&mut BytesMut>) -> Result<Header, DecoderError> { + let index = decode_int(buf, 7)?; + self.table.get(index) + } + + fn decode_literal( + &mut self, + buf: &mut Cursor<&mut BytesMut>, + 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 = decode_int(buf, prefix)?; + + // First, read the header name + if table_idx == 0 { + let old_pos = buf.position(); + let name_marker = self.try_decode_string(buf)?; + let value_marker = self.try_decode_string(buf)?; + buf.set_position(old_pos); + // Read the name as a literal + let name = name_marker.consume(buf); + let value = value_marker.consume(buf); + Header::new(name, value) + } else { + let e = self.table.get(table_idx)?; + let value = self.decode_string(buf)?; + + e.name().into_entry(value) + } + } + + fn try_decode_string( + &mut self, + buf: &mut Cursor<&mut BytesMut>, + ) -> Result<StringMarker, DecoderError> { + let old_pos = buf.position(); + const HUFF_FLAG: u8 = 0b1000_0000; + + // The first bit in the first byte contains the huffman encoded flag. + let huff = match peek_u8(buf) { + Some(hdr) => (hdr & HUFF_FLAG) == HUFF_FLAG, + None => return Err(DecoderError::NeedMore(NeedMore::UnexpectedEndOfStream)), + }; + + // Decode the string length using 7 bit prefix + let len = decode_int(buf, 7)?; + + if len > buf.remaining() { + tracing::trace!(len, remaining = buf.remaining(), "decode_string underflow",); + return Err(DecoderError::NeedMore(NeedMore::StringUnderflow)); + } + + let offset = (buf.position() - old_pos) as usize; + if huff { + let ret = { + let raw = &buf.chunk()[..len]; + huffman::decode(raw, &mut self.buffer).map(|buf| StringMarker { + offset, + len, + string: Some(BytesMut::freeze(buf)), + }) + }; + + buf.advance(len); + ret + } else { + buf.advance(len); + Ok(StringMarker { + offset, + len, + string: None, + }) + } + } + + fn decode_string(&mut self, buf: &mut Cursor<&mut BytesMut>) -> Result<Bytes, DecoderError> { + let old_pos = buf.position(); + let marker = self.try_decode_string(buf)?; + buf.set_position(old_pos); + Ok(marker.consume(buf)) + } +} + +impl Default for Decoder { + fn default() -> Decoder { + Decoder::new(4096) + } +} + +// ===== impl Representation ===== + +impl Representation { + pub fn load(byte: u8) -> Result<Representation, DecoderError> { + const INDEXED: u8 = 0b1000_0000; + const LITERAL_WITH_INDEXING: u8 = 0b0100_0000; + const LITERAL_WITHOUT_INDEXING: u8 = 0b1111_0000; + const LITERAL_NEVER_INDEXED: u8 = 0b0001_0000; + const SIZE_UPDATE_MASK: u8 = 0b1110_0000; + const SIZE_UPDATE: u8 = 0b0010_0000; + + // TODO: What did I even write here? + + if byte & INDEXED == INDEXED { + Ok(Representation::Indexed) + } else if byte & LITERAL_WITH_INDEXING == LITERAL_WITH_INDEXING { + Ok(Representation::LiteralWithIndexing) + } else if byte & LITERAL_WITHOUT_INDEXING == 0 { + Ok(Representation::LiteralWithoutIndexing) + } else if byte & LITERAL_WITHOUT_INDEXING == LITERAL_NEVER_INDEXED { + Ok(Representation::LiteralNeverIndexed) + } else if byte & SIZE_UPDATE_MASK == SIZE_UPDATE { + Ok(Representation::SizeUpdate) + } else { + Err(DecoderError::InvalidRepresentation) + } + } +} + +fn decode_int<B: Buf>(buf: &mut B, prefix_size: u8) -> Result<usize, DecoderError> { + // The octet limit is chosen such that the maximum allowed *value* can + // never overflow an unsigned 32-bit integer. The maximum value of any + // integer that can be encoded with 5 octets is ~2^28 + const MAX_BYTES: usize = 5; + const VARINT_MASK: u8 = 0b0111_1111; + const VARINT_FLAG: u8 = 0b1000_0000; + + if prefix_size < 1 || prefix_size > 8 { + return Err(DecoderError::InvalidIntegerPrefix); + } + + if !buf.has_remaining() { + return Err(DecoderError::NeedMore(NeedMore::IntegerUnderflow)); + } + + let mask = if prefix_size == 8 { + 0xFF + } else { + (1u8 << prefix_size).wrapping_sub(1) + }; + + let mut ret = (buf.get_u8() & mask) as usize; + + if ret < mask as usize { + // Value fits in the prefix bits + return Ok(ret); + } + + // The int did not fit in the prefix bits, so continue reading. + // + // The total number of bytes used to represent the int. The first byte was + // the prefix, so start at 1. + let mut bytes = 1; + + // The rest of the int is stored as a varint -- 7 bits for the value and 1 + // bit to indicate if it is the last byte. + let mut shift = 0; + + while buf.has_remaining() { + let b = buf.get_u8(); + + bytes += 1; + ret += ((b & VARINT_MASK) as usize) << shift; + shift += 7; + + if b & VARINT_FLAG == 0 { + return Ok(ret); + } + + if bytes == MAX_BYTES { + // The spec requires that this situation is an error + return Err(DecoderError::IntegerOverflow); + } + } + + Err(DecoderError::NeedMore(NeedMore::IntegerUnderflow)) +} + +fn peek_u8<B: Buf>(buf: &mut B) -> Option<u8> { + if buf.has_remaining() { + Some(buf.chunk()[0]) + } else { + None + } +} + +fn take(buf: &mut Cursor<&mut BytesMut>, n: usize) -> Bytes { + let pos = buf.position() as usize; + let mut head = buf.get_mut().split_to(pos + n); + buf.set_position(0); + head.advance(pos); + head.freeze() +} + +impl StringMarker { + fn consume(self, buf: &mut Cursor<&mut BytesMut>) -> Bytes { + buf.advance(self.offset); + match self.string { + Some(string) => { + buf.advance(self.len); + string + } + None => take(buf, self.len), + } + } +} + +fn consume(buf: &mut Cursor<&mut BytesMut>) { + // remove bytes from the internal BytesMut when they have been successfully + // decoded. This is a more permanent cursor position, which will be + // used to resume if decoding was only partial. + take(buf, 0); +} + +// ===== impl Table ===== + +impl Table { + fn new(max_size: usize) -> Table { + Table { + entries: VecDeque::new(), + size: 0, + max_size, + } + } + + fn size(&self) -> usize { + self.size + } + + /// Returns the entry located at the given index. + /// + /// The table is 1-indexed and constructed in such a way that the first + /// entries belong to the static table, followed by entries in the dynamic + /// table. They are merged into a single index address space, though. + /// + /// This is according to the [HPACK spec, section 2.3.3.] + /// (http://http2.github.io/http2-spec/compression.html#index.address.space) + pub fn get(&self, index: usize) -> Result<Header, DecoderError> { + if index == 0 { + return Err(DecoderError::InvalidTableIndex); + } + + if index <= 61 { + return Ok(get_static(index)); + } + + // Convert the index for lookup in the entries structure. + match self.entries.get(index - 62) { + Some(e) => Ok(e.clone()), + None => Err(DecoderError::InvalidTableIndex), + } + } + + fn insert(&mut self, entry: Header) { + let len = entry.len(); + + self.reserve(len); + + if self.size + len <= self.max_size { + self.size += len; + + // Track the entry + self.entries.push_front(entry); + } + } + + fn set_max_size(&mut self, size: usize) { + self.max_size = size; + // Make the table size fit within the new constraints. + self.consolidate(); + } + + fn reserve(&mut self, size: usize) { + while self.size + size > self.max_size { + match self.entries.pop_back() { + Some(last) => { + self.size -= last.len(); + } + None => return, + } + } + } + + fn consolidate(&mut self) { + while self.size > self.max_size { + { + let last = match self.entries.back() { + Some(x) => x, + None => { + // Can never happen as the size of the table must reach + // 0 by the time we've exhausted all elements. + panic!("Size of table != 0, but no headers left!"); + } + }; + + self.size -= last.len(); + } + + self.entries.pop_back(); + } + } +} + +// ===== impl DecoderError ===== + +impl From<Utf8Error> for DecoderError { + fn from(_: Utf8Error) -> DecoderError { + // TODO: Better error? + DecoderError::InvalidUtf8 + } +} + +impl From<header::InvalidHeaderValue> for DecoderError { + fn from(_: header::InvalidHeaderValue) -> DecoderError { + // TODO: Better error? + DecoderError::InvalidUtf8 + } +} + +impl From<header::InvalidHeaderName> for DecoderError { + fn from(_: header::InvalidHeaderName) -> DecoderError { + // TODO: Better error + DecoderError::InvalidUtf8 + } +} + +impl From<method::InvalidMethod> for DecoderError { + fn from(_: method::InvalidMethod) -> DecoderError { + // TODO: Better error + DecoderError::InvalidUtf8 + } +} + +impl From<status::InvalidStatusCode> for DecoderError { + fn from(_: status::InvalidStatusCode) -> DecoderError { + // TODO: Better error + DecoderError::InvalidUtf8 + } +} + +impl From<DecoderError> for frame::Error { + fn from(src: DecoderError) -> Self { + frame::Error::Hpack(src) + } +} + +/// Get an entry from the static table +pub fn get_static(idx: usize) -> Header { + use http::header::HeaderValue; + + match idx { + 1 => Header::Authority(BytesStr::from_static("")), + 2 => Header::Method(Method::GET), + 3 => Header::Method(Method::POST), + 4 => Header::Path(BytesStr::from_static("/")), + 5 => Header::Path(BytesStr::from_static("/index.html")), + 6 => Header::Scheme(BytesStr::from_static("http")), + 7 => Header::Scheme(BytesStr::from_static("https")), + 8 => Header::Status(StatusCode::OK), + 9 => Header::Status(StatusCode::NO_CONTENT), + 10 => Header::Status(StatusCode::PARTIAL_CONTENT), + 11 => Header::Status(StatusCode::NOT_MODIFIED), + 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(""), + }, + _ => unreachable!(), + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::hpack::Header; + + #[test] + fn test_peek_u8() { + let b = 0xff; + let mut buf = Cursor::new(vec![b]); + assert_eq!(peek_u8(&mut buf), Some(b)); + assert_eq!(buf.get_u8(), b); + assert_eq!(peek_u8(&mut buf), None); + } + + #[test] + fn test_decode_string_empty() { + let mut de = Decoder::new(0); + let mut buf = BytesMut::new(); + let err = de.decode_string(&mut Cursor::new(&mut buf)).unwrap_err(); + assert_eq!(err, DecoderError::NeedMore(NeedMore::UnexpectedEndOfStream)); + } + + #[test] + fn test_decode_empty() { + let mut de = Decoder::new(0); + let mut buf = BytesMut::new(); + let empty = de.decode(&mut Cursor::new(&mut buf), |_| {}).unwrap(); + assert_eq!(empty, ()); + } + + #[test] + fn test_decode_indexed_larger_than_table() { + let mut de = Decoder::new(0); + + let mut buf = BytesMut::new(); + buf.extend(&[0b01000000, 0x80 | 2]); + buf.extend(huff_encode(b"foo")); + buf.extend(&[0x80 | 3]); + buf.extend(huff_encode(b"bar")); + + let mut res = vec![]; + let _ = de + .decode(&mut Cursor::new(&mut buf), |h| { + res.push(h); + }) + .unwrap(); + + assert_eq!(res.len(), 1); + assert_eq!(de.table.size(), 0); + + match res[0] { + Header::Field { + ref name, + ref value, + } => { + assert_eq!(name, "foo"); + assert_eq!(value, "bar"); + } + _ => panic!(), + } + } + + fn huff_encode(src: &[u8]) -> BytesMut { + let mut buf = BytesMut::new(); + huffman::encode(src, &mut buf); + buf + } + + #[test] + fn test_decode_continuation_header_with_non_huff_encoded_name() { + let mut de = Decoder::new(0); + let value = huff_encode(b"bar"); + let mut buf = BytesMut::new(); + // header name is non_huff encoded + buf.extend(&[0b01000000, 0x00 | 3]); + buf.extend(b"foo"); + // header value is partial + buf.extend(&[0x80 | 3]); + buf.extend(&value[0..1]); + + let mut res = vec![]; + let e = de + .decode(&mut Cursor::new(&mut buf), |h| { + res.push(h); + }) + .unwrap_err(); + // decode error because the header value is partial + assert_eq!(e, DecoderError::NeedMore(NeedMore::StringUnderflow)); + + // extend buf with the remaining header value + buf.extend(&value[1..]); + let _ = de + .decode(&mut Cursor::new(&mut buf), |h| { + res.push(h); + }) + .unwrap(); + + assert_eq!(res.len(), 1); + assert_eq!(de.table.size(), 0); + + match res[0] { + Header::Field { + ref name, + ref value, + } => { + assert_eq!(name, "foo"); + assert_eq!(value, "bar"); + } + _ => panic!(), + } + } +} diff --git a/third_party/rust/h2/src/hpack/encoder.rs b/third_party/rust/h2/src/hpack/encoder.rs new file mode 100644 index 0000000000..76b373830e --- /dev/null +++ b/third_party/rust/h2/src/hpack/encoder.rs @@ -0,0 +1,721 @@ +use super::table::{Index, Table}; +use super::{huffman, Header}; + +use bytes::{BufMut, BytesMut}; +use http::header::{HeaderName, HeaderValue}; + +#[derive(Debug)] +pub struct Encoder { + table: Table, + size_update: Option<SizeUpdate>, +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +enum SizeUpdate { + One(usize), + Two(usize, usize), // min, max +} + +impl Encoder { + pub fn new(max_size: usize, capacity: usize) -> Encoder { + Encoder { + table: Table::new(max_size, capacity), + size_update: None, + } + } + + /// Queues a max size update. + /// + /// The next call to `encode` will include a dynamic size update frame. + pub fn update_max_size(&mut self, val: usize) { + match self.size_update { + Some(SizeUpdate::One(old)) => { + if val > old { + if old > self.table.max_size() { + self.size_update = Some(SizeUpdate::One(val)); + } else { + self.size_update = Some(SizeUpdate::Two(old, val)); + } + } else { + self.size_update = Some(SizeUpdate::One(val)); + } + } + Some(SizeUpdate::Two(min, _)) => { + if val < min { + self.size_update = Some(SizeUpdate::One(val)); + } else { + self.size_update = Some(SizeUpdate::Two(min, val)); + } + } + None => { + if val != self.table.max_size() { + // Don't bother writing a frame if the value already matches + // the table's max size. + self.size_update = Some(SizeUpdate::One(val)); + } + } + } + } + + /// Encode a set of headers into the provide buffer + pub fn encode<I>(&mut self, headers: I, dst: &mut BytesMut) + where + I: IntoIterator<Item = Header<Option<HeaderName>>>, + { + let span = tracing::trace_span!("hpack::encode"); + let _e = span.enter(); + + self.encode_size_updates(dst); + + let mut last_index = None; + + for header in headers { + match header.reify() { + // The header has an associated name. In which case, try to + // index it in the table. + Ok(header) => { + let index = self.table.index(header); + self.encode_header(&index, dst); + + last_index = Some(index); + } + // The header does not have an associated name. This means that + // the name is the same as the previously yielded header. In + // which case, we skip table lookup and just use the same index + // as the previous entry. + Err(value) => { + self.encode_header_without_name( + last_index.as_ref().unwrap_or_else(|| { + panic!("encoding header without name, but no previous index to use for name"); + }), + &value, + dst, + ); + } + } + } + } + + fn encode_size_updates(&mut self, dst: &mut BytesMut) { + match self.size_update.take() { + Some(SizeUpdate::One(val)) => { + self.table.resize(val); + encode_size_update(val, dst); + } + Some(SizeUpdate::Two(min, max)) => { + self.table.resize(min); + self.table.resize(max); + encode_size_update(min, dst); + encode_size_update(max, dst); + } + None => {} + } + } + + fn encode_header(&mut self, index: &Index, dst: &mut BytesMut) { + match *index { + Index::Indexed(idx, _) => { + encode_int(idx, 7, 0x80, dst); + } + Index::Name(idx, _) => { + let header = self.table.resolve(&index); + + encode_not_indexed(idx, header.value_slice(), header.is_sensitive(), dst); + } + Index::Inserted(_) => { + let header = self.table.resolve(&index); + + assert!(!header.is_sensitive()); + + dst.put_u8(0b0100_0000); + + 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()); + + encode_int(idx, 6, 0b0100_0000, dst); + encode_str(header.value_slice(), dst); + } + Index::NotIndexed(_) => { + let header = self.table.resolve(&index); + + encode_not_indexed2( + header.name().as_slice(), + header.value_slice(), + header.is_sensitive(), + dst, + ); + } + } + } + + fn encode_header_without_name( + &mut self, + last: &Index, + value: &HeaderValue, + dst: &mut BytesMut, + ) { + match *last { + Index::Indexed(..) + | Index::Name(..) + | Index::Inserted(..) + | Index::InsertedValue(..) => { + let idx = self.table.resolve_idx(last); + + encode_not_indexed(idx, value.as_ref(), value.is_sensitive(), dst); + } + Index::NotIndexed(_) => { + let last = self.table.resolve(last); + + encode_not_indexed2( + last.name().as_slice(), + value.as_ref(), + value.is_sensitive(), + dst, + ); + } + } + } +} + +impl Default for Encoder { + fn default() -> Encoder { + Encoder::new(4096, 0) + } +} + +fn encode_size_update(val: usize, dst: &mut BytesMut) { + encode_int(val, 5, 0b0010_0000, dst) +} + +fn encode_not_indexed(name: usize, value: &[u8], sensitive: bool, dst: &mut BytesMut) { + if sensitive { + encode_int(name, 4, 0b10000, dst); + } else { + encode_int(name, 4, 0, dst); + } + + encode_str(value, dst); +} + +fn encode_not_indexed2(name: &[u8], value: &[u8], sensitive: bool, dst: &mut BytesMut) { + if sensitive { + dst.put_u8(0b10000); + } else { + dst.put_u8(0); + } + + encode_str(name, dst); + encode_str(value, dst); +} + +fn encode_str(val: &[u8], dst: &mut BytesMut) { + if !val.is_empty() { + let idx = position(dst); + + // Push a placeholder byte for the length header + dst.put_u8(0); + + // Encode with huffman + huffman::encode(val, dst); + + let huff_len = position(dst) - (idx + 1); + + if encode_int_one_byte(huff_len, 7) { + // Write the string head + dst[idx] = 0x80 | huff_len as u8; + } else { + // Write the head to a placeholder + const PLACEHOLDER_LEN: usize = 8; + let mut buf = [0u8; PLACEHOLDER_LEN]; + + let head_len = { + let mut head_dst = &mut buf[..]; + encode_int(huff_len, 7, 0x80, &mut head_dst); + PLACEHOLDER_LEN - head_dst.remaining_mut() + }; + + // This is just done to reserve space in the destination + dst.put_slice(&buf[1..head_len]); + + // 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)); + dst[dst_i] = dst[src_i]; + } + + // Copy in the head + for i in 0..head_len { + dst[idx + i] = buf[i]; + } + } + } else { + // Write an empty string + dst.put_u8(0); + } +} + +/// Encode an integer into the given destination buffer +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, +) { + if encode_int_one_byte(value, prefix_bits) { + dst.put_u8(first_byte | value as u8); + return; + } + + let low = (1 << prefix_bits) - 1; + + value -= low; + + dst.put_u8(first_byte | low as u8); + + while value >= 128 { + dst.put_u8(0b1000_0000 | value as u8); + + value >>= 7; + } + + dst.put_u8(value as u8); +} + +/// Returns true if the in the int can be fully encoded in the first byte. +fn encode_int_one_byte(value: usize, prefix_bits: usize) -> bool { + value < (1 << prefix_bits) - 1 +} + +fn position(buf: &BytesMut) -> usize { + buf.len() +} + +#[cfg(test)] +mod test { + use super::*; + use crate::hpack::Header; + use http::*; + + #[test] + fn test_encode_method_get() { + let mut encoder = Encoder::default(); + let res = encode(&mut encoder, vec![method("GET")]); + assert_eq!(*res, [0x80 | 2]); + assert_eq!(encoder.table.len(), 0); + } + + #[test] + fn test_encode_method_post() { + let mut encoder = Encoder::default(); + let res = encode(&mut encoder, vec![method("POST")]); + assert_eq!(*res, [0x80 | 3]); + assert_eq!(encoder.table.len(), 0); + } + + #[test] + fn test_encode_method_patch() { + let mut encoder = Encoder::default(); + 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!("PATCH", huff_decode(&res[2..7])); + assert_eq!(encoder.table.len(), 1); + + let res = encode(&mut encoder, vec![method("PATCH")]); + + assert_eq!(1 << 7 | 62, res[0]); + assert_eq!(1, res.len()); + } + + #[test] + fn test_encode_indexed_name_literal_value() { + let mut encoder = Encoder::default(); + let res = encode(&mut encoder, vec![header("content-language", "foo")]); + + assert_eq!(res[0], 0b01000000 | 27); // Indexed name + assert_eq!(res[1], 0x80 | 2); // header value w/ huffman coding + + assert_eq!("foo", huff_decode(&res[2..4])); + + // Same name, new value should still use incremental + let res = encode(&mut encoder, vec![header("content-language", "bar")]); + assert_eq!(res[0], 0b01000000 | 27); // Indexed name + assert_eq!(res[1], 0x80 | 3); // header value w/ huffman coding + assert_eq!("bar", huff_decode(&res[2..5])); + } + + #[test] + fn test_repeated_headers_are_indexed() { + let mut encoder = Encoder::default(); + let res = encode(&mut encoder, vec![header("foo", "hello")]); + + assert_eq!(&[0b01000000, 0x80 | 2], &res[0..2]); + assert_eq!("foo", huff_decode(&res[2..4])); + assert_eq!(0x80 | 4, res[4]); + assert_eq!("hello", huff_decode(&res[5..])); + assert_eq!(9, res.len()); + + assert_eq!(1, encoder.table.len()); + + let res = encode(&mut encoder, vec![header("foo", "hello")]); + assert_eq!([0x80 | 62], *res); + + assert_eq!(encoder.table.len(), 1); + } + + #[test] + fn test_evicting_headers() { + let mut encoder = Encoder::default(); + + // Fill the table + for i in 0..64 { + let key = format!("x-hello-world-{:02}", i); + let res = encode(&mut encoder, vec![header(&key, &key)]); + + assert_eq!(&[0b01000000, 0x80 | 12], &res[0..2]); + assert_eq!(key, huff_decode(&res[2..14])); + assert_eq!(0x80 | 12, res[14]); + assert_eq!(key, huff_decode(&res[15..])); + assert_eq!(27, res.len()); + + // Make sure the header can be found... + let res = encode(&mut encoder, vec![header(&key, &key)]); + + // Only check that it is found + assert_eq!(0x80, res[0] & 0x80); + } + + assert_eq!(4096, encoder.table.size()); + assert_eq!(64, encoder.table.len()); + + // Find existing headers + for i in 0..64 { + let key = format!("x-hello-world-{:02}", i); + let res = encode(&mut encoder, vec![header(&key, &key)]); + assert_eq!(0x80, res[0] & 0x80); + } + + // Insert a new header + let key = "x-hello-world-64"; + let res = encode(&mut encoder, vec![header(key, key)]); + + assert_eq!(&[0b01000000, 0x80 | 12], &res[0..2]); + assert_eq!(key, huff_decode(&res[2..14])); + assert_eq!(0x80 | 12, res[14]); + assert_eq!(key, huff_decode(&res[15..])); + assert_eq!(27, res.len()); + + assert_eq!(64, encoder.table.len()); + + // Now try encoding entries that should exist in the table + 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]); + } + } + + #[test] + fn test_large_headers_are_not_indexed() { + let mut encoder = Encoder::new(128, 0); + let key = "hello-world-hello-world-HELLO-zzz"; + + let res = encode(&mut encoder, vec![header(key, key)]); + + assert_eq!(&[0, 0x80 | 25], &res[..2]); + + assert_eq!(0, encoder.table.len()); + assert_eq!(0, encoder.table.size()); + } + + #[test] + fn test_sensitive_headers_are_never_indexed() { + use http::header::HeaderValue; + + 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, + }; + + // Now, try to encode the sensitive header + + let mut encoder = Encoder::default(); + let res = encode(&mut encoder, vec![header]); + + assert_eq!(&[0b10000, 0x80 | 8], &res[..2]); + assert_eq!("my-password", huff_decode(&res[2..10])); + assert_eq!(0x80 | 4, res[10]); + assert_eq!("12345", huff_decode(&res[11..])); + + // Now, try to encode a sensitive header w/ a name in the static table + let name = "authorization".parse().unwrap(); + let mut value = HeaderValue::from_bytes(b"12345").unwrap(); + value.set_sensitive(true); + + let header = Header::Field { + name: Some(name), + value, + }; + + let mut encoder = Encoder::default(); + let res = encode(&mut encoder, vec![header]); + + assert_eq!(&[0b11111, 8], &res[..2]); + assert_eq!(0x80 | 4, res[2]); + assert_eq!("12345", huff_decode(&res[3..])); + + // 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 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, + }; + let res = encode(&mut encoder, vec![header]); + + assert_eq!(&[0b11111, 47], &res[..2]); + assert_eq!(0x80 | 4, res[2]); + assert_eq!("12345", huff_decode(&res[3..])); + } + + #[test] + fn test_content_length_value_not_indexed() { + let mut encoder = Encoder::default(); + let res = encode(&mut encoder, vec![header("content-length", "1234")]); + + assert_eq!(&[15, 13, 0x80 | 3], &res[0..3]); + assert_eq!("1234", huff_decode(&res[3..])); + assert_eq!(6, res.len()); + } + + #[test] + fn test_encoding_headers_with_same_name() { + let mut encoder = Encoder::default(); + let name = "hello"; + + // Encode first one + let _ = encode(&mut encoder, vec![header(name, "one")]); + + // Encode second one + let res = encode(&mut encoder, vec![header(name, "two")]); + assert_eq!(&[0x40 | 62, 0x80 | 3], &res[0..2]); + assert_eq!("two", huff_decode(&res[2..])); + assert_eq!(5, res.len()); + + // Encode the first one again + let res = encode(&mut encoder, vec![header(name, "one")]); + assert_eq!(&[0x80 | 63], &res[..]); + + // Now the second one + let res = encode(&mut encoder, vec![header(name, "two")]); + assert_eq!(&[0x80 | 62], &res[..]); + } + + #[test] + fn test_evicting_headers_when_multiple_of_same_name_are_in_table() { + // The encoder only has space for 2 headers + let mut encoder = Encoder::new(76, 0); + + let _ = encode(&mut encoder, vec![header("foo", "bar")]); + assert_eq!(1, encoder.table.len()); + + let _ = encode(&mut encoder, vec![header("bar", "foo")]); + assert_eq!(2, encoder.table.len()); + + // This will evict the first header, while still referencing the header + // name + let res = encode(&mut encoder, vec![header("foo", "baz")]); + assert_eq!(&[0x40 | 63, 0, 0x80 | 3], &res[..3]); + assert_eq!(2, encoder.table.len()); + + // Try adding the same header again + let res = encode(&mut encoder, vec![header("foo", "baz")]); + assert_eq!(&[0x80 | 62], &res[..]); + assert_eq!(2, encoder.table.len()); + } + + #[test] + fn test_max_size_zero() { + // Static table only + let mut encoder = Encoder::new(0, 0); + let res = encode(&mut encoder, vec![method("GET")]); + assert_eq!(*res, [0x80 | 2]); + assert_eq!(encoder.table.len(), 0); + + let res = encode(&mut encoder, vec![header("foo", "bar")]); + assert_eq!(&[0, 0x80 | 2], &res[..2]); + assert_eq!("foo", huff_decode(&res[2..4])); + assert_eq!(0x80 | 3, res[4]); + assert_eq!("bar", huff_decode(&res[5..8])); + assert_eq!(0, encoder.table.len()); + + // Encode a custom value + let res = encode(&mut encoder, vec![header("transfer-encoding", "chunked")]); + assert_eq!(&[15, 42, 0x80 | 6], &res[..3]); + assert_eq!("chunked", huff_decode(&res[3..])); + } + + #[test] + fn test_update_max_size_combos() { + let mut encoder = Encoder::default(); + assert!(encoder.size_update.is_none()); + assert_eq!(4096, encoder.table.max_size()); + + encoder.update_max_size(4096); // Default size + assert!(encoder.size_update.is_none()); + + encoder.update_max_size(0); + assert_eq!(Some(SizeUpdate::One(0)), encoder.size_update); + + encoder.update_max_size(100); + assert_eq!(Some(SizeUpdate::Two(0, 100)), encoder.size_update); + + let mut encoder = Encoder::default(); + encoder.update_max_size(8000); + assert_eq!(Some(SizeUpdate::One(8000)), encoder.size_update); + + encoder.update_max_size(100); + assert_eq!(Some(SizeUpdate::One(100)), encoder.size_update); + + encoder.update_max_size(8000); + assert_eq!(Some(SizeUpdate::Two(100, 8000)), encoder.size_update); + + encoder.update_max_size(4000); + assert_eq!(Some(SizeUpdate::Two(100, 4000)), encoder.size_update); + + encoder.update_max_size(50); + assert_eq!(Some(SizeUpdate::One(50)), encoder.size_update); + } + + #[test] + fn test_resizing_table() { + let mut encoder = Encoder::default(); + + // Add a header + let _ = encode(&mut encoder, vec![header("foo", "bar")]); + + encoder.update_max_size(1); + assert_eq!(1, encoder.table.len()); + + let res = encode(&mut encoder, vec![method("GET")]); + assert_eq!(&[32 | 1, 0x80 | 2], &res[..]); + assert_eq!(0, encoder.table.len()); + + let res = encode(&mut encoder, vec![header("foo", "bar")]); + assert_eq!(0, res[0]); + + encoder.update_max_size(100); + let res = encode(&mut encoder, vec![header("foo", "bar")]); + assert_eq!(&[32 | 31, 69, 64], &res[..3]); + + encoder.update_max_size(0); + let res = encode(&mut encoder, vec![header("foo", "bar")]); + assert_eq!(&[32, 0], &res[..2]); + } + + #[test] + fn test_decreasing_table_size_without_eviction() { + let mut encoder = Encoder::default(); + + // Add a header + let _ = encode(&mut encoder, vec![header("foo", "bar")]); + + encoder.update_max_size(100); + assert_eq!(1, encoder.table.len()); + + let res = encode(&mut encoder, vec![header("foo", "bar")]); + assert_eq!(&[32 | 31, 69, 0x80 | 62], &res[..]); + } + + #[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(), + }, + ], + ); + + assert_eq!(&[0x40, 0x80 | 4], &res[0..2]); + assert_eq!("hello", huff_decode(&res[2..6])); + assert_eq!(0x80 | 4, res[6]); + assert_eq!("world", huff_decode(&res[7..11])); + + // Next is not indexed + assert_eq!(&[15, 47, 0x80 | 3], &res[11..14]); + assert_eq!("zomg", huff_decode(&res[14..])); + } + + #[test] + fn test_large_size_update() { + let mut encoder = Encoder::default(); + + encoder.update_max_size(1912930560); + assert_eq!(Some(SizeUpdate::One(1912930560)), encoder.size_update); + + let mut dst = BytesMut::with_capacity(6); + encoder.encode_size_updates(&mut dst); + assert_eq!([63, 225, 129, 148, 144, 7], &dst[..]); + } + + #[test] + #[ignore] + fn test_evicted_overflow() { + // Not sure what the best way to do this is. + } + + fn encode(e: &mut Encoder, hdrs: Vec<Header<Option<HeaderName>>>) -> BytesMut { + let mut dst = BytesMut::with_capacity(1024); + e.encode(&mut hdrs.into_iter(), &mut dst); + dst + } + + fn method(s: &str) -> Header<Option<HeaderName>> { + Header::Method(Method::from_bytes(s.as_bytes()).unwrap()) + } + + fn header(name: &str, val: &str) -> Header<Option<HeaderName>> { + let name = HeaderName::from_bytes(name.as_bytes()).unwrap(); + let value = HeaderValue::from_bytes(val.as_bytes()).unwrap(); + + Header::Field { + name: Some(name), + value, + } + } + + fn huff_decode(src: &[u8]) -> BytesMut { + let mut buf = BytesMut::new(); + huffman::decode(src, &mut buf).unwrap() + } +} diff --git a/third_party/rust/h2/src/hpack/header.rs b/third_party/rust/h2/src/hpack/header.rs new file mode 100644 index 0000000000..e6df555abf --- /dev/null +++ b/third_party/rust/h2/src/hpack/header.rs @@ -0,0 +1,308 @@ +use super::{DecoderError, NeedMore}; +use crate::ext::Protocol; + +use bytes::Bytes; +use http::header::{HeaderName, HeaderValue}; +use http::{Method, StatusCode}; +use std::fmt; + +/// HTTP/2 Header +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum Header<T = HeaderName> { + Field { name: T, value: HeaderValue }, + // TODO: Change these types to `http::uri` types. + Authority(BytesStr), + Method(Method), + Scheme(BytesStr), + Path(BytesStr), + Protocol(Protocol), + Status(StatusCode), +} + +/// The header field name +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +pub enum Name<'a> { + Field(&'a HeaderName), + Authority, + Method, + Scheme, + Path, + Protocol, + Status, +} + +#[doc(hidden)] +#[derive(Clone, Eq, PartialEq, Default)] +pub struct BytesStr(Bytes); + +pub fn len(name: &HeaderName, value: &HeaderValue) -> usize { + let n: &str = name.as_ref(); + 32 + n.len() + value.len() +} + +impl Header<Option<HeaderName>> { + pub fn reify(self) -> Result<Header, HeaderValue> { + use self::Header::*; + + Ok(match self { + Field { + name: Some(n), + value, + } => Field { name: n, value }, + Field { name: None, value } => return Err(value), + Authority(v) => Authority(v), + Method(v) => Method(v), + Scheme(v) => Scheme(v), + Path(v) => Path(v), + Protocol(v) => Protocol(v), + Status(v) => Status(v), + }) + } +} + +impl Header { + pub fn new(name: Bytes, value: Bytes) -> Result<Header, DecoderError> { + if name.is_empty() { + return Err(DecoderError::NeedMore(NeedMore::UnexpectedEndOfStream)); + } + if name[0] == b':' { + match &name[1..] { + b"authority" => { + let value = BytesStr::try_from(value)?; + Ok(Header::Authority(value)) + } + b"method" => { + let method = Method::from_bytes(&value)?; + Ok(Header::Method(method)) + } + b"scheme" => { + let value = BytesStr::try_from(value)?; + Ok(Header::Scheme(value)) + } + b"path" => { + let value = BytesStr::try_from(value)?; + Ok(Header::Path(value)) + } + b"protocol" => { + let value = Protocol::try_from(value)?; + Ok(Header::Protocol(value)) + } + b"status" => { + let status = StatusCode::from_bytes(&value)?; + Ok(Header::Status(status)) + } + _ => Err(DecoderError::InvalidPseudoheader), + } + } else { + // HTTP/2 requires lower case header names + let name = HeaderName::from_lowercase(&name)?; + let value = HeaderValue::from_bytes(&value)?; + + Ok(Header::Field { name, 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::Protocol(ref v) => 32 + 9 + v.as_str().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::Authority(..) => Name::Authority, + Header::Method(..) => Name::Method, + Header::Scheme(..) => Name::Scheme, + Header::Path(..) => Name::Path, + Header::Protocol(..) => Name::Protocol, + Header::Status(..) => Name::Status, + } + } + + pub fn value_slice(&self) -> &[u8] { + match *self { + 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(), + Header::Path(ref v) => v.as_ref(), + Header::Protocol(ref v) => v.as_ref(), + Header::Status(ref v) => v.as_str().as_ref(), + } + } + + pub fn value_eq(&self, other: &Header) -> bool { + match *self { + Header::Field { ref value, .. } => { + let a = value; + match *other { + Header::Field { ref value, .. } => a == value, + _ => false, + } + } + Header::Authority(ref a) => match *other { + Header::Authority(ref b) => a == b, + _ => false, + }, + Header::Method(ref a) => match *other { + Header::Method(ref b) => a == b, + _ => false, + }, + Header::Scheme(ref a) => match *other { + Header::Scheme(ref b) => a == b, + _ => false, + }, + Header::Path(ref a) => match *other { + Header::Path(ref b) => a == b, + _ => false, + }, + Header::Protocol(ref a) => match *other { + Header::Protocol(ref b) => a == b, + _ => false, + }, + Header::Status(ref a) => match *other { + Header::Status(ref b) => a == b, + _ => false, + }, + } + } + + pub fn is_sensitive(&self) -> bool { + match *self { + Header::Field { ref value, .. } => value.is_sensitive(), + // TODO: Technically these other header values can be sensitive too. + _ => false, + } + } + + pub fn skip_value_index(&self) -> bool { + use http::header; + + match *self { + 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, + _ => false, + }, + Header::Path(..) => true, + _ => false, + } + } +} + +// Mostly for tests +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::Authority(v) => Header::Authority(v), + Header::Method(v) => Header::Method(v), + Header::Scheme(v) => Header::Scheme(v), + Header::Path(v) => Header::Path(v), + Header::Protocol(v) => Header::Protocol(v), + Header::Status(v) => Header::Status(v), + } + } +} + +impl<'a> Name<'a> { + pub fn into_entry(self, value: Bytes) -> Result<Header, DecoderError> { + match self { + Name::Field(name) => Ok(Header::Field { + name: name.clone(), + value: HeaderValue::from_bytes(&*value)?, + }), + Name::Authority => Ok(Header::Authority(BytesStr::try_from(value)?)), + Name::Method => Ok(Header::Method(Method::from_bytes(&*value)?)), + Name::Scheme => Ok(Header::Scheme(BytesStr::try_from(value)?)), + Name::Path => Ok(Header::Path(BytesStr::try_from(value)?)), + Name::Protocol => Ok(Header::Protocol(Protocol::try_from(value)?)), + Name::Status => { + match StatusCode::from_bytes(&value) { + Ok(status) => Ok(Header::Status(status)), + // TODO: better error handling + Err(_) => Err(DecoderError::InvalidStatusCode), + } + } + } + } + + pub fn as_slice(&self) -> &[u8] { + match *self { + Name::Field(ref name) => name.as_ref(), + Name::Authority => b":authority", + Name::Method => b":method", + Name::Scheme => b":scheme", + Name::Path => b":path", + Name::Protocol => b":protocol", + Name::Status => b":status", + } + } +} + +// ===== impl BytesStr ===== + +impl BytesStr { + pub(crate) const fn from_static(value: &'static str) -> Self { + BytesStr(Bytes::from_static(value.as_bytes())) + } + + pub(crate) fn from(value: &str) -> Self { + BytesStr(Bytes::copy_from_slice(value.as_bytes())) + } + + #[doc(hidden)] + pub fn try_from(bytes: Bytes) -> Result<Self, std::str::Utf8Error> { + std::str::from_utf8(bytes.as_ref())?; + Ok(BytesStr(bytes)) + } + + pub(crate) fn as_str(&self) -> &str { + // Safety: check valid utf-8 in constructor + unsafe { std::str::from_utf8_unchecked(self.0.as_ref()) } + } + + pub(crate) fn into_inner(self) -> Bytes { + self.0 + } +} + +impl std::ops::Deref for BytesStr { + type Target = str; + fn deref(&self) -> &str { + self.as_str() + } +} + +impl AsRef<[u8]> for BytesStr { + fn as_ref(&self) -> &[u8] { + self.0.as_ref() + } +} + +impl fmt::Debug for BytesStr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} diff --git a/third_party/rust/h2/src/hpack/huffman/mod.rs b/third_party/rust/h2/src/hpack/huffman/mod.rs new file mode 100644 index 0000000000..07b3fd925b --- /dev/null +++ b/third_party/rust/h2/src/hpack/huffman/mod.rs @@ -0,0 +1,200 @@ +mod table; + +use self::table::{DECODE_TABLE, ENCODE_TABLE}; +use crate::hpack::DecoderError; + +use bytes::{BufMut, BytesMut}; + +// Constructed in the generated `table.rs` file +struct Decoder { + state: usize, + maybe_eos: bool, +} + +// These flags must match the ones in genhuff.rs + +const MAYBE_EOS: u8 = 1; +const DECODED: u8 = 2; +const ERROR: u8 = 4; + +pub fn decode(src: &[u8], buf: &mut BytesMut) -> Result<BytesMut, DecoderError> { + let mut decoder = Decoder::new(); + + // Max compression ratio is >= 0.5 + buf.reserve(src.len() << 1); + + for b in src { + if let Some(b) = decoder.decode4(b >> 4)? { + buf.put_u8(b); + } + + if let Some(b) = decoder.decode4(b & 0xf)? { + buf.put_u8(b); + } + } + + if !decoder.is_final() { + return Err(DecoderError::InvalidHuffmanCode); + } + + Ok(buf.split()) +} + +pub fn encode(src: &[u8], dst: &mut BytesMut) { + let mut bits: u64 = 0; + let mut bits_left = 40; + + for &b in src { + let (nbits, code) = ENCODE_TABLE[b as usize]; + + bits |= code << (bits_left - nbits); + bits_left -= nbits; + + while bits_left <= 32 { + dst.put_u8((bits >> 32) as u8); + + bits <<= 8; + bits_left += 8; + } + } + + if bits_left != 40 { + // This writes the EOS token + bits |= (1 << bits_left) - 1; + dst.put_u8((bits >> 32) as u8); + } +} + +impl Decoder { + fn new() -> Decoder { + Decoder { + state: 0, + maybe_eos: false, + } + } + + // Decodes 4 bits + fn decode4(&mut self, input: u8) -> Result<Option<u8>, DecoderError> { + // (next-state, byte, flags) + let (next, byte, flags) = DECODE_TABLE[self.state][input as usize]; + + if flags & ERROR == ERROR { + // Data followed the EOS marker + return Err(DecoderError::InvalidHuffmanCode); + } + + let mut ret = None; + + if flags & DECODED == DECODED { + ret = Some(byte); + } + + self.state = next; + self.maybe_eos = flags & MAYBE_EOS == MAYBE_EOS; + + Ok(ret) + } + + fn is_final(&self) -> bool { + self.state == 0 || self.maybe_eos + } +} + +#[cfg(test)] +mod test { + use super::*; + + fn decode(src: &[u8]) -> Result<BytesMut, DecoderError> { + let mut buf = BytesMut::new(); + super::decode(src, &mut buf) + } + + #[test] + fn decode_single_byte() { + assert_eq!("o", decode(&[0b00111111]).unwrap()); + assert_eq!("0", decode(&[0x0 + 7]).unwrap()); + assert_eq!("A", decode(&[(0x21 << 2) + 3]).unwrap()); + } + + #[test] + fn single_char_multi_byte() { + assert_eq!("#", decode(&[255, 160 + 15]).unwrap()); + assert_eq!("$", decode(&[255, 200 + 7]).unwrap()); + assert_eq!("\x0a", decode(&[255, 255, 255, 240 + 3]).unwrap()); + } + + #[test] + fn multi_char() { + assert_eq!("!0", decode(&[254, 1]).unwrap()); + assert_eq!(" !", decode(&[0b01010011, 0b11111000]).unwrap()); + } + + #[test] + fn encode_single_byte() { + let mut dst = BytesMut::with_capacity(1); + + encode(b"o", &mut dst); + assert_eq!(&dst[..], &[0b00111111]); + + dst.clear(); + encode(b"0", &mut dst); + assert_eq!(&dst[..], &[0x0 + 7]); + + dst.clear(); + encode(b"A", &mut dst); + assert_eq!(&dst[..], &[(0x21 << 2) + 3]); + } + + #[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.", + ]; + + for s in DATA { + let mut dst = BytesMut::with_capacity(s.len()); + + encode(s.as_bytes(), &mut dst); + + let decoded = decode(&dst).unwrap(); + + assert_eq!(&decoded[..], s.as_bytes()); + } + } + + #[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"]; + + for s in DATA { + let mut dst = BytesMut::with_capacity(s.len()); + + encode(s, &mut dst); + + let decoded = decode(&dst).unwrap(); + + assert_eq!(&decoded[..], &s[..]); + } + } +} diff --git a/third_party/rust/h2/src/hpack/huffman/table.rs b/third_party/rust/h2/src/hpack/huffman/table.rs new file mode 100644 index 0000000000..560cfaf7be --- /dev/null +++ b/third_party/rust/h2/src/hpack/huffman/table.rs @@ -0,0 +1,5130 @@ +// !!! DO NOT EDIT !!! Generated by util/genhuff/src/main.rs + +// (num-bits, bits) +pub const ENCODE_TABLE: [(usize, u64); 257] = [ + (13, 0x1ff8), + (23, 0x007f_ffd8), + (28, 0x0fff_ffe2), + (28, 0x0fff_ffe3), + (28, 0x0fff_ffe4), + (28, 0x0fff_ffe5), + (28, 0x0fff_ffe6), + (28, 0x0fff_ffe7), + (28, 0x0fff_ffe8), + (24, 0x00ff_ffea), + (30, 0x3fff_fffc), + (28, 0x0fff_ffe9), + (28, 0x0fff_ffea), + (30, 0x3fff_fffd), + (28, 0x0fff_ffeb), + (28, 0x0fff_ffec), + (28, 0x0fff_ffed), + (28, 0x0fff_ffee), + (28, 0x0fff_ffef), + (28, 0x0fff_fff0), + (28, 0x0fff_fff1), + (28, 0x0fff_fff2), + (30, 0x3fff_fffe), + (28, 0x0fff_fff3), + (28, 0x0fff_fff4), + (28, 0x0fff_fff5), + (28, 0x0fff_fff6), + (28, 0x0fff_fff7), + (28, 0x0fff_fff8), + (28, 0x0fff_fff9), + (28, 0x0fff_fffa), + (28, 0x0fff_fffb), + (6, 0x14), + (10, 0x3f8), + (10, 0x3f9), + (12, 0xffa), + (13, 0x1ff9), + (6, 0x15), + (8, 0xf8), + (11, 0x7fa), + (10, 0x3fa), + (10, 0x3fb), + (8, 0xf9), + (11, 0x7fb), + (8, 0xfa), + (6, 0x16), + (6, 0x17), + (6, 0x18), + (5, 0x0), + (5, 0x1), + (5, 0x2), + (6, 0x19), + (6, 0x1a), + (6, 0x1b), + (6, 0x1c), + (6, 0x1d), + (6, 0x1e), + (6, 0x1f), + (7, 0x5c), + (8, 0xfb), + (15, 0x7ffc), + (6, 0x20), + (12, 0xffb), + (10, 0x3fc), + (13, 0x1ffa), + (6, 0x21), + (7, 0x5d), + (7, 0x5e), + (7, 0x5f), + (7, 0x60), + (7, 0x61), + (7, 0x62), + (7, 0x63), + (7, 0x64), + (7, 0x65), + (7, 0x66), + (7, 0x67), + (7, 0x68), + (7, 0x69), + (7, 0x6a), + (7, 0x6b), + (7, 0x6c), + (7, 0x6d), + (7, 0x6e), + (7, 0x6f), + (7, 0x70), + (7, 0x71), + (7, 0x72), + (8, 0xfc), + (7, 0x73), + (8, 0xfd), + (13, 0x1ffb), + (19, 0x7fff0), + (13, 0x1ffc), + (14, 0x3ffc), + (6, 0x22), + (15, 0x7ffd), + (5, 0x3), + (6, 0x23), + (5, 0x4), + (6, 0x24), + (5, 0x5), + (6, 0x25), + (6, 0x26), + (6, 0x27), + (5, 0x6), + (7, 0x74), + (7, 0x75), + (6, 0x28), + (6, 0x29), + (6, 0x2a), + (5, 0x7), + (6, 0x2b), + (7, 0x76), + (6, 0x2c), + (5, 0x8), + (5, 0x9), + (6, 0x2d), + (7, 0x77), + (7, 0x78), + (7, 0x79), + (7, 0x7a), + (7, 0x7b), + (15, 0x7ffe), + (11, 0x7fc), + (14, 0x3ffd), + (13, 0x1ffd), + (28, 0x0fff_fffc), + (20, 0xfffe6), + (22, 0x003f_ffd2), + (20, 0xfffe7), + (20, 0xfffe8), + (22, 0x003f_ffd3), + (22, 0x003f_ffd4), + (22, 0x003f_ffd5), + (23, 0x007f_ffd9), + (22, 0x003f_ffd6), + (23, 0x007f_ffda), + (23, 0x007f_ffdb), + (23, 0x007f_ffdc), + (23, 0x007f_ffdd), + (23, 0x007f_ffde), + (24, 0x00ff_ffeb), + (23, 0x007f_ffdf), + (24, 0x00ff_ffec), + (24, 0x00ff_ffed), + (22, 0x003f_ffd7), + (23, 0x007f_ffe0), + (24, 0x00ff_ffee), + (23, 0x007f_ffe1), + (23, 0x007f_ffe2), + (23, 0x007f_ffe3), + (23, 0x007f_ffe4), + (21, 0x001f_ffdc), + (22, 0x003f_ffd8), + (23, 0x007f_ffe5), + (22, 0x003f_ffd9), + (23, 0x007f_ffe6), + (23, 0x007f_ffe7), + (24, 0x00ff_ffef), + (22, 0x003f_ffda), + (21, 0x001f_ffdd), + (20, 0xfffe9), + (22, 0x003f_ffdb), + (22, 0x003f_ffdc), + (23, 0x007f_ffe8), + (23, 0x007f_ffe9), + (21, 0x001f_ffde), + (23, 0x007f_ffea), + (22, 0x003f_ffdd), + (22, 0x003f_ffde), + (24, 0x00ff_fff0), + (21, 0x001f_ffdf), + (22, 0x003f_ffdf), + (23, 0x007f_ffeb), + (23, 0x007f_ffec), + (21, 0x001f_ffe0), + (21, 0x001f_ffe1), + (22, 0x003f_ffe0), + (21, 0x001f_ffe2), + (23, 0x007f_ffed), + (22, 0x003f_ffe1), + (23, 0x007f_ffee), + (23, 0x007f_ffef), + (20, 0xfffea), + (22, 0x003f_ffe2), + (22, 0x003f_ffe3), + (22, 0x003f_ffe4), + (23, 0x007f_fff0), + (22, 0x003f_ffe5), + (22, 0x003f_ffe6), + (23, 0x007f_fff1), + (26, 0x03ff_ffe0), + (26, 0x03ff_ffe1), + (20, 0xfffeb), + (19, 0x7fff1), + (22, 0x003f_ffe7), + (23, 0x007f_fff2), + (22, 0x003f_ffe8), + (25, 0x01ff_ffec), + (26, 0x03ff_ffe2), + (26, 0x03ff_ffe3), + (26, 0x03ff_ffe4), + (27, 0x07ff_ffde), + (27, 0x07ff_ffdf), + (26, 0x03ff_ffe5), + (24, 0x00ff_fff1), + (25, 0x01ff_ffed), + (19, 0x7fff2), + (21, 0x001f_ffe3), + (26, 0x03ff_ffe6), + (27, 0x07ff_ffe0), + (27, 0x07ff_ffe1), + (26, 0x03ff_ffe7), + (27, 0x07ff_ffe2), + (24, 0x00ff_fff2), + (21, 0x001f_ffe4), + (21, 0x001f_ffe5), + (26, 0x03ff_ffe8), + (26, 0x03ff_ffe9), + (28, 0x0fff_fffd), + (27, 0x07ff_ffe3), + (27, 0x07ff_ffe4), + (27, 0x07ff_ffe5), + (20, 0xfffec), + (24, 0x00ff_fff3), + (20, 0xfffed), + (21, 0x001f_ffe6), + (22, 0x003f_ffe9), + (21, 0x001f_ffe7), + (21, 0x001f_ffe8), + (23, 0x007f_fff3), + (22, 0x003f_ffea), + (22, 0x003f_ffeb), + (25, 0x01ff_ffee), + (25, 0x01ff_ffef), + (24, 0x00ff_fff4), + (24, 0x00ff_fff5), + (26, 0x03ff_ffea), + (23, 0x007f_fff4), + (26, 0x03ff_ffeb), + (27, 0x07ff_ffe6), + (26, 0x03ff_ffec), + (26, 0x03ff_ffed), + (27, 0x07ff_ffe7), + (27, 0x07ff_ffe8), + (27, 0x07ff_ffe9), + (27, 0x07ff_ffea), + (27, 0x07ff_ffeb), + (28, 0x0fff_fffe), + (27, 0x07ff_ffec), + (27, 0x07ff_ffed), + (27, 0x07ff_ffee), + (27, 0x07ff_ffef), + (27, 0x07ff_fff0), + (26, 0x03ff_ffee), + (30, 0x3fff_ffff), +]; + +// (next-state, byte, flags) +pub const DECODE_TABLE: [[(usize, u8, u8); 16]; 256] = [ + // 0 + [ + (4, 0, 0x00), + (5, 0, 0x00), + (7, 0, 0x00), + (8, 0, 0x00), + (11, 0, 0x00), + (12, 0, 0x00), + (16, 0, 0x00), + (19, 0, 0x00), + (25, 0, 0x00), + (28, 0, 0x00), + (32, 0, 0x00), + (35, 0, 0x00), + (42, 0, 0x00), + (49, 0, 0x00), + (57, 0, 0x00), + (64, 0, 0x01), + ], + // 1 + [ + (0, 48, 0x02), + (0, 49, 0x02), + (0, 50, 0x02), + (0, 97, 0x02), + (0, 99, 0x02), + (0, 101, 0x02), + (0, 105, 0x02), + (0, 111, 0x02), + (0, 115, 0x02), + (0, 116, 0x02), + (13, 0, 0x00), + (14, 0, 0x00), + (17, 0, 0x00), + (18, 0, 0x00), + (20, 0, 0x00), + (21, 0, 0x00), + ], + // 2 + [ + (1, 48, 0x02), + (22, 48, 0x03), + (1, 49, 0x02), + (22, 49, 0x03), + (1, 50, 0x02), + (22, 50, 0x03), + (1, 97, 0x02), + (22, 97, 0x03), + (1, 99, 0x02), + (22, 99, 0x03), + (1, 101, 0x02), + (22, 101, 0x03), + (1, 105, 0x02), + (22, 105, 0x03), + (1, 111, 0x02), + (22, 111, 0x03), + ], + // 3 + [ + (2, 48, 0x02), + (9, 48, 0x02), + (23, 48, 0x02), + (40, 48, 0x03), + (2, 49, 0x02), + (9, 49, 0x02), + (23, 49, 0x02), + (40, 49, 0x03), + (2, 50, 0x02), + (9, 50, 0x02), + (23, 50, 0x02), + (40, 50, 0x03), + (2, 97, 0x02), + (9, 97, 0x02), + (23, 97, 0x02), + (40, 97, 0x03), + ], + // 4 + [ + (3, 48, 0x02), + (6, 48, 0x02), + (10, 48, 0x02), + (15, 48, 0x02), + (24, 48, 0x02), + (31, 48, 0x02), + (41, 48, 0x02), + (56, 48, 0x03), + (3, 49, 0x02), + (6, 49, 0x02), + (10, 49, 0x02), + (15, 49, 0x02), + (24, 49, 0x02), + (31, 49, 0x02), + (41, 49, 0x02), + (56, 49, 0x03), + ], + // 5 + [ + (3, 50, 0x02), + (6, 50, 0x02), + (10, 50, 0x02), + (15, 50, 0x02), + (24, 50, 0x02), + (31, 50, 0x02), + (41, 50, 0x02), + (56, 50, 0x03), + (3, 97, 0x02), + (6, 97, 0x02), + (10, 97, 0x02), + (15, 97, 0x02), + (24, 97, 0x02), + (31, 97, 0x02), + (41, 97, 0x02), + (56, 97, 0x03), + ], + // 6 + [ + (2, 99, 0x02), + (9, 99, 0x02), + (23, 99, 0x02), + (40, 99, 0x03), + (2, 101, 0x02), + (9, 101, 0x02), + (23, 101, 0x02), + (40, 101, 0x03), + (2, 105, 0x02), + (9, 105, 0x02), + (23, 105, 0x02), + (40, 105, 0x03), + (2, 111, 0x02), + (9, 111, 0x02), + (23, 111, 0x02), + (40, 111, 0x03), + ], + // 7 + [ + (3, 99, 0x02), + (6, 99, 0x02), + (10, 99, 0x02), + (15, 99, 0x02), + (24, 99, 0x02), + (31, 99, 0x02), + (41, 99, 0x02), + (56, 99, 0x03), + (3, 101, 0x02), + (6, 101, 0x02), + (10, 101, 0x02), + (15, 101, 0x02), + (24, 101, 0x02), + (31, 101, 0x02), + (41, 101, 0x02), + (56, 101, 0x03), + ], + // 8 + [ + (3, 105, 0x02), + (6, 105, 0x02), + (10, 105, 0x02), + (15, 105, 0x02), + (24, 105, 0x02), + (31, 105, 0x02), + (41, 105, 0x02), + (56, 105, 0x03), + (3, 111, 0x02), + (6, 111, 0x02), + (10, 111, 0x02), + (15, 111, 0x02), + (24, 111, 0x02), + (31, 111, 0x02), + (41, 111, 0x02), + (56, 111, 0x03), + ], + // 9 + [ + (1, 115, 0x02), + (22, 115, 0x03), + (1, 116, 0x02), + (22, 116, 0x03), + (0, 32, 0x02), + (0, 37, 0x02), + (0, 45, 0x02), + (0, 46, 0x02), + (0, 47, 0x02), + (0, 51, 0x02), + (0, 52, 0x02), + (0, 53, 0x02), + (0, 54, 0x02), + (0, 55, 0x02), + (0, 56, 0x02), + (0, 57, 0x02), + ], + // 10 + [ + (2, 115, 0x02), + (9, 115, 0x02), + (23, 115, 0x02), + (40, 115, 0x03), + (2, 116, 0x02), + (9, 116, 0x02), + (23, 116, 0x02), + (40, 116, 0x03), + (1, 32, 0x02), + (22, 32, 0x03), + (1, 37, 0x02), + (22, 37, 0x03), + (1, 45, 0x02), + (22, 45, 0x03), + (1, 46, 0x02), + (22, 46, 0x03), + ], + // 11 + [ + (3, 115, 0x02), + (6, 115, 0x02), + (10, 115, 0x02), + (15, 115, 0x02), + (24, 115, 0x02), + (31, 115, 0x02), + (41, 115, 0x02), + (56, 115, 0x03), + (3, 116, 0x02), + (6, 116, 0x02), + (10, 116, 0x02), + (15, 116, 0x02), + (24, 116, 0x02), + (31, 116, 0x02), + (41, 116, 0x02), + (56, 116, 0x03), + ], + // 12 + [ + (2, 32, 0x02), + (9, 32, 0x02), + (23, 32, 0x02), + (40, 32, 0x03), + (2, 37, 0x02), + (9, 37, 0x02), + (23, 37, 0x02), + (40, 37, 0x03), + (2, 45, 0x02), + (9, 45, 0x02), + (23, 45, 0x02), + (40, 45, 0x03), + (2, 46, 0x02), + (9, 46, 0x02), + (23, 46, 0x02), + (40, 46, 0x03), + ], + // 13 + [ + (3, 32, 0x02), + (6, 32, 0x02), + (10, 32, 0x02), + (15, 32, 0x02), + (24, 32, 0x02), + (31, 32, 0x02), + (41, 32, 0x02), + (56, 32, 0x03), + (3, 37, 0x02), + (6, 37, 0x02), + (10, 37, 0x02), + (15, 37, 0x02), + (24, 37, 0x02), + (31, 37, 0x02), + (41, 37, 0x02), + (56, 37, 0x03), + ], + // 14 + [ + (3, 45, 0x02), + (6, 45, 0x02), + (10, 45, 0x02), + (15, 45, 0x02), + (24, 45, 0x02), + (31, 45, 0x02), + (41, 45, 0x02), + (56, 45, 0x03), + (3, 46, 0x02), + (6, 46, 0x02), + (10, 46, 0x02), + (15, 46, 0x02), + (24, 46, 0x02), + (31, 46, 0x02), + (41, 46, 0x02), + (56, 46, 0x03), + ], + // 15 + [ + (1, 47, 0x02), + (22, 47, 0x03), + (1, 51, 0x02), + (22, 51, 0x03), + (1, 52, 0x02), + (22, 52, 0x03), + (1, 53, 0x02), + (22, 53, 0x03), + (1, 54, 0x02), + (22, 54, 0x03), + (1, 55, 0x02), + (22, 55, 0x03), + (1, 56, 0x02), + (22, 56, 0x03), + (1, 57, 0x02), + (22, 57, 0x03), + ], + // 16 + [ + (2, 47, 0x02), + (9, 47, 0x02), + (23, 47, 0x02), + (40, 47, 0x03), + (2, 51, 0x02), + (9, 51, 0x02), + (23, 51, 0x02), + (40, 51, 0x03), + (2, 52, 0x02), + (9, 52, 0x02), + (23, 52, 0x02), + (40, 52, 0x03), + (2, 53, 0x02), + (9, 53, 0x02), + (23, 53, 0x02), + (40, 53, 0x03), + ], + // 17 + [ + (3, 47, 0x02), + (6, 47, 0x02), + (10, 47, 0x02), + (15, 47, 0x02), + (24, 47, 0x02), + (31, 47, 0x02), + (41, 47, 0x02), + (56, 47, 0x03), + (3, 51, 0x02), + (6, 51, 0x02), + (10, 51, 0x02), + (15, 51, 0x02), + (24, 51, 0x02), + (31, 51, 0x02), + (41, 51, 0x02), + (56, 51, 0x03), + ], + // 18 + [ + (3, 52, 0x02), + (6, 52, 0x02), + (10, 52, 0x02), + (15, 52, 0x02), + (24, 52, 0x02), + (31, 52, 0x02), + (41, 52, 0x02), + (56, 52, 0x03), + (3, 53, 0x02), + (6, 53, 0x02), + (10, 53, 0x02), + (15, 53, 0x02), + (24, 53, 0x02), + (31, 53, 0x02), + (41, 53, 0x02), + (56, 53, 0x03), + ], + // 19 + [ + (2, 54, 0x02), + (9, 54, 0x02), + (23, 54, 0x02), + (40, 54, 0x03), + (2, 55, 0x02), + (9, 55, 0x02), + (23, 55, 0x02), + (40, 55, 0x03), + (2, 56, 0x02), + (9, 56, 0x02), + (23, 56, 0x02), + (40, 56, 0x03), + (2, 57, 0x02), + (9, 57, 0x02), + (23, 57, 0x02), + (40, 57, 0x03), + ], + // 20 + [ + (3, 54, 0x02), + (6, 54, 0x02), + (10, 54, 0x02), + (15, 54, 0x02), + (24, 54, 0x02), + (31, 54, 0x02), + (41, 54, 0x02), + (56, 54, 0x03), + (3, 55, 0x02), + (6, 55, 0x02), + (10, 55, 0x02), + (15, 55, 0x02), + (24, 55, 0x02), + (31, 55, 0x02), + (41, 55, 0x02), + (56, 55, 0x03), + ], + // 21 + [ + (3, 56, 0x02), + (6, 56, 0x02), + (10, 56, 0x02), + (15, 56, 0x02), + (24, 56, 0x02), + (31, 56, 0x02), + (41, 56, 0x02), + (56, 56, 0x03), + (3, 57, 0x02), + (6, 57, 0x02), + (10, 57, 0x02), + (15, 57, 0x02), + (24, 57, 0x02), + (31, 57, 0x02), + (41, 57, 0x02), + (56, 57, 0x03), + ], + // 22 + [ + (26, 0, 0x00), + (27, 0, 0x00), + (29, 0, 0x00), + (30, 0, 0x00), + (33, 0, 0x00), + (34, 0, 0x00), + (36, 0, 0x00), + (37, 0, 0x00), + (43, 0, 0x00), + (46, 0, 0x00), + (50, 0, 0x00), + (53, 0, 0x00), + (58, 0, 0x00), + (61, 0, 0x00), + (65, 0, 0x00), + (68, 0, 0x01), + ], + // 23 + [ + (0, 61, 0x02), + (0, 65, 0x02), + (0, 95, 0x02), + (0, 98, 0x02), + (0, 100, 0x02), + (0, 102, 0x02), + (0, 103, 0x02), + (0, 104, 0x02), + (0, 108, 0x02), + (0, 109, 0x02), + (0, 110, 0x02), + (0, 112, 0x02), + (0, 114, 0x02), + (0, 117, 0x02), + (38, 0, 0x00), + (39, 0, 0x00), + ], + // 24 + [ + (1, 61, 0x02), + (22, 61, 0x03), + (1, 65, 0x02), + (22, 65, 0x03), + (1, 95, 0x02), + (22, 95, 0x03), + (1, 98, 0x02), + (22, 98, 0x03), + (1, 100, 0x02), + (22, 100, 0x03), + (1, 102, 0x02), + (22, 102, 0x03), + (1, 103, 0x02), + (22, 103, 0x03), + (1, 104, 0x02), + (22, 104, 0x03), + ], + // 25 + [ + (2, 61, 0x02), + (9, 61, 0x02), + (23, 61, 0x02), + (40, 61, 0x03), + (2, 65, 0x02), + (9, 65, 0x02), + (23, 65, 0x02), + (40, 65, 0x03), + (2, 95, 0x02), + (9, 95, 0x02), + (23, 95, 0x02), + (40, 95, 0x03), + (2, 98, 0x02), + (9, 98, 0x02), + (23, 98, 0x02), + (40, 98, 0x03), + ], + // 26 + [ + (3, 61, 0x02), + (6, 61, 0x02), + (10, 61, 0x02), + (15, 61, 0x02), + (24, 61, 0x02), + (31, 61, 0x02), + (41, 61, 0x02), + (56, 61, 0x03), + (3, 65, 0x02), + (6, 65, 0x02), + (10, 65, 0x02), + (15, 65, 0x02), + (24, 65, 0x02), + (31, 65, 0x02), + (41, 65, 0x02), + (56, 65, 0x03), + ], + // 27 + [ + (3, 95, 0x02), + (6, 95, 0x02), + (10, 95, 0x02), + (15, 95, 0x02), + (24, 95, 0x02), + (31, 95, 0x02), + (41, 95, 0x02), + (56, 95, 0x03), + (3, 98, 0x02), + (6, 98, 0x02), + (10, 98, 0x02), + (15, 98, 0x02), + (24, 98, 0x02), + (31, 98, 0x02), + (41, 98, 0x02), + (56, 98, 0x03), + ], + // 28 + [ + (2, 100, 0x02), + (9, 100, 0x02), + (23, 100, 0x02), + (40, 100, 0x03), + (2, 102, 0x02), + (9, 102, 0x02), + (23, 102, 0x02), + (40, 102, 0x03), + (2, 103, 0x02), + (9, 103, 0x02), + (23, 103, 0x02), + (40, 103, 0x03), + (2, 104, 0x02), + (9, 104, 0x02), + (23, 104, 0x02), + (40, 104, 0x03), + ], + // 29 + [ + (3, 100, 0x02), + (6, 100, 0x02), + (10, 100, 0x02), + (15, 100, 0x02), + (24, 100, 0x02), + (31, 100, 0x02), + (41, 100, 0x02), + (56, 100, 0x03), + (3, 102, 0x02), + (6, 102, 0x02), + (10, 102, 0x02), + (15, 102, 0x02), + (24, 102, 0x02), + (31, 102, 0x02), + (41, 102, 0x02), + (56, 102, 0x03), + ], + // 30 + [ + (3, 103, 0x02), + (6, 103, 0x02), + (10, 103, 0x02), + (15, 103, 0x02), + (24, 103, 0x02), + (31, 103, 0x02), + (41, 103, 0x02), + (56, 103, 0x03), + (3, 104, 0x02), + (6, 104, 0x02), + (10, 104, 0x02), + (15, 104, 0x02), + (24, 104, 0x02), + (31, 104, 0x02), + (41, 104, 0x02), + (56, 104, 0x03), + ], + // 31 + [ + (1, 108, 0x02), + (22, 108, 0x03), + (1, 109, 0x02), + (22, 109, 0x03), + (1, 110, 0x02), + (22, 110, 0x03), + (1, 112, 0x02), + (22, 112, 0x03), + (1, 114, 0x02), + (22, 114, 0x03), + (1, 117, 0x02), + (22, 117, 0x03), + (0, 58, 0x02), + (0, 66, 0x02), + (0, 67, 0x02), + (0, 68, 0x02), + ], + // 32 + [ + (2, 108, 0x02), + (9, 108, 0x02), + (23, 108, 0x02), + (40, 108, 0x03), + (2, 109, 0x02), + (9, 109, 0x02), + (23, 109, 0x02), + (40, 109, 0x03), + (2, 110, 0x02), + (9, 110, 0x02), + (23, 110, 0x02), + (40, 110, 0x03), + (2, 112, 0x02), + (9, 112, 0x02), + (23, 112, 0x02), + (40, 112, 0x03), + ], + // 33 + [ + (3, 108, 0x02), + (6, 108, 0x02), + (10, 108, 0x02), + (15, 108, 0x02), + (24, 108, 0x02), + (31, 108, 0x02), + (41, 108, 0x02), + (56, 108, 0x03), + (3, 109, 0x02), + (6, 109, 0x02), + (10, 109, 0x02), + (15, 109, 0x02), + (24, 109, 0x02), + (31, 109, 0x02), + (41, 109, 0x02), + (56, 109, 0x03), + ], + // 34 + [ + (3, 110, 0x02), + (6, 110, 0x02), + (10, 110, 0x02), + (15, 110, 0x02), + (24, 110, 0x02), + (31, 110, 0x02), + (41, 110, 0x02), + (56, 110, 0x03), + (3, 112, 0x02), + (6, 112, 0x02), + (10, 112, 0x02), + (15, 112, 0x02), + (24, 112, 0x02), + (31, 112, 0x02), + (41, 112, 0x02), + (56, 112, 0x03), + ], + // 35 + [ + (2, 114, 0x02), + (9, 114, 0x02), + (23, 114, 0x02), + (40, 114, 0x03), + (2, 117, 0x02), + (9, 117, 0x02), + (23, 117, 0x02), + (40, 117, 0x03), + (1, 58, 0x02), + (22, 58, 0x03), + (1, 66, 0x02), + (22, 66, 0x03), + (1, 67, 0x02), + (22, 67, 0x03), + (1, 68, 0x02), + (22, 68, 0x03), + ], + // 36 + [ + (3, 114, 0x02), + (6, 114, 0x02), + (10, 114, 0x02), + (15, 114, 0x02), + (24, 114, 0x02), + (31, 114, 0x02), + (41, 114, 0x02), + (56, 114, 0x03), + (3, 117, 0x02), + (6, 117, 0x02), + (10, 117, 0x02), + (15, 117, 0x02), + (24, 117, 0x02), + (31, 117, 0x02), + (41, 117, 0x02), + (56, 117, 0x03), + ], + // 37 + [ + (2, 58, 0x02), + (9, 58, 0x02), + (23, 58, 0x02), + (40, 58, 0x03), + (2, 66, 0x02), + (9, 66, 0x02), + (23, 66, 0x02), + (40, 66, 0x03), + (2, 67, 0x02), + (9, 67, 0x02), + (23, 67, 0x02), + (40, 67, 0x03), + (2, 68, 0x02), + (9, 68, 0x02), + (23, 68, 0x02), + (40, 68, 0x03), + ], + // 38 + [ + (3, 58, 0x02), + (6, 58, 0x02), + (10, 58, 0x02), + (15, 58, 0x02), + (24, 58, 0x02), + (31, 58, 0x02), + (41, 58, 0x02), + (56, 58, 0x03), + (3, 66, 0x02), + (6, 66, 0x02), + (10, 66, 0x02), + (15, 66, 0x02), + (24, 66, 0x02), + (31, 66, 0x02), + (41, 66, 0x02), + (56, 66, 0x03), + ], + // 39 + [ + (3, 67, 0x02), + (6, 67, 0x02), + (10, 67, 0x02), + (15, 67, 0x02), + (24, 67, 0x02), + (31, 67, 0x02), + (41, 67, 0x02), + (56, 67, 0x03), + (3, 68, 0x02), + (6, 68, 0x02), + (10, 68, 0x02), + (15, 68, 0x02), + (24, 68, 0x02), + (31, 68, 0x02), + (41, 68, 0x02), + (56, 68, 0x03), + ], + // 40 + [ + (44, 0, 0x00), + (45, 0, 0x00), + (47, 0, 0x00), + (48, 0, 0x00), + (51, 0, 0x00), + (52, 0, 0x00), + (54, 0, 0x00), + (55, 0, 0x00), + (59, 0, 0x00), + (60, 0, 0x00), + (62, 0, 0x00), + (63, 0, 0x00), + (66, 0, 0x00), + (67, 0, 0x00), + (69, 0, 0x00), + (72, 0, 0x01), + ], + // 41 + [ + (0, 69, 0x02), + (0, 70, 0x02), + (0, 71, 0x02), + (0, 72, 0x02), + (0, 73, 0x02), + (0, 74, 0x02), + (0, 75, 0x02), + (0, 76, 0x02), + (0, 77, 0x02), + (0, 78, 0x02), + (0, 79, 0x02), + (0, 80, 0x02), + (0, 81, 0x02), + (0, 82, 0x02), + (0, 83, 0x02), + (0, 84, 0x02), + ], + // 42 + [ + (1, 69, 0x02), + (22, 69, 0x03), + (1, 70, 0x02), + (22, 70, 0x03), + (1, 71, 0x02), + (22, 71, 0x03), + (1, 72, 0x02), + (22, 72, 0x03), + (1, 73, 0x02), + (22, 73, 0x03), + (1, 74, 0x02), + (22, 74, 0x03), + (1, 75, 0x02), + (22, 75, 0x03), + (1, 76, 0x02), + (22, 76, 0x03), + ], + // 43 + [ + (2, 69, 0x02), + (9, 69, 0x02), + (23, 69, 0x02), + (40, 69, 0x03), + (2, 70, 0x02), + (9, 70, 0x02), + (23, 70, 0x02), + (40, 70, 0x03), + (2, 71, 0x02), + (9, 71, 0x02), + (23, 71, 0x02), + (40, 71, 0x03), + (2, 72, 0x02), + (9, 72, 0x02), + (23, 72, 0x02), + (40, 72, 0x03), + ], + // 44 + [ + (3, 69, 0x02), + (6, 69, 0x02), + (10, 69, 0x02), + (15, 69, 0x02), + (24, 69, 0x02), + (31, 69, 0x02), + (41, 69, 0x02), + (56, 69, 0x03), + (3, 70, 0x02), + (6, 70, 0x02), + (10, 70, 0x02), + (15, 70, 0x02), + (24, 70, 0x02), + (31, 70, 0x02), + (41, 70, 0x02), + (56, 70, 0x03), + ], + // 45 + [ + (3, 71, 0x02), + (6, 71, 0x02), + (10, 71, 0x02), + (15, 71, 0x02), + (24, 71, 0x02), + (31, 71, 0x02), + (41, 71, 0x02), + (56, 71, 0x03), + (3, 72, 0x02), + (6, 72, 0x02), + (10, 72, 0x02), + (15, 72, 0x02), + (24, 72, 0x02), + (31, 72, 0x02), + (41, 72, 0x02), + (56, 72, 0x03), + ], + // 46 + [ + (2, 73, 0x02), + (9, 73, 0x02), + (23, 73, 0x02), + (40, 73, 0x03), + (2, 74, 0x02), + (9, 74, 0x02), + (23, 74, 0x02), + (40, 74, 0x03), + (2, 75, 0x02), + (9, 75, 0x02), + (23, 75, 0x02), + (40, 75, 0x03), + (2, 76, 0x02), + (9, 76, 0x02), + (23, 76, 0x02), + (40, 76, 0x03), + ], + // 47 + [ + (3, 73, 0x02), + (6, 73, 0x02), + (10, 73, 0x02), + (15, 73, 0x02), + (24, 73, 0x02), + (31, 73, 0x02), + (41, 73, 0x02), + (56, 73, 0x03), + (3, 74, 0x02), + (6, 74, 0x02), + (10, 74, 0x02), + (15, 74, 0x02), + (24, 74, 0x02), + (31, 74, 0x02), + (41, 74, 0x02), + (56, 74, 0x03), + ], + // 48 + [ + (3, 75, 0x02), + (6, 75, 0x02), + (10, 75, 0x02), + (15, 75, 0x02), + (24, 75, 0x02), + (31, 75, 0x02), + (41, 75, 0x02), + (56, 75, 0x03), + (3, 76, 0x02), + (6, 76, 0x02), + (10, 76, 0x02), + (15, 76, 0x02), + (24, 76, 0x02), + (31, 76, 0x02), + (41, 76, 0x02), + (56, 76, 0x03), + ], + // 49 + [ + (1, 77, 0x02), + (22, 77, 0x03), + (1, 78, 0x02), + (22, 78, 0x03), + (1, 79, 0x02), + (22, 79, 0x03), + (1, 80, 0x02), + (22, 80, 0x03), + (1, 81, 0x02), + (22, 81, 0x03), + (1, 82, 0x02), + (22, 82, 0x03), + (1, 83, 0x02), + (22, 83, 0x03), + (1, 84, 0x02), + (22, 84, 0x03), + ], + // 50 + [ + (2, 77, 0x02), + (9, 77, 0x02), + (23, 77, 0x02), + (40, 77, 0x03), + (2, 78, 0x02), + (9, 78, 0x02), + (23, 78, 0x02), + (40, 78, 0x03), + (2, 79, 0x02), + (9, 79, 0x02), + (23, 79, 0x02), + (40, 79, 0x03), + (2, 80, 0x02), + (9, 80, 0x02), + (23, 80, 0x02), + (40, 80, 0x03), + ], + // 51 + [ + (3, 77, 0x02), + (6, 77, 0x02), + (10, 77, 0x02), + (15, 77, 0x02), + (24, 77, 0x02), + (31, 77, 0x02), + (41, 77, 0x02), + (56, 77, 0x03), + (3, 78, 0x02), + (6, 78, 0x02), + (10, 78, 0x02), + (15, 78, 0x02), + (24, 78, 0x02), + (31, 78, 0x02), + (41, 78, 0x02), + (56, 78, 0x03), + ], + // 52 + [ + (3, 79, 0x02), + (6, 79, 0x02), + (10, 79, 0x02), + (15, 79, 0x02), + (24, 79, 0x02), + (31, 79, 0x02), + (41, 79, 0x02), + (56, 79, 0x03), + (3, 80, 0x02), + (6, 80, 0x02), + (10, 80, 0x02), + (15, 80, 0x02), + (24, 80, 0x02), + (31, 80, 0x02), + (41, 80, 0x02), + (56, 80, 0x03), + ], + // 53 + [ + (2, 81, 0x02), + (9, 81, 0x02), + (23, 81, 0x02), + (40, 81, 0x03), + (2, 82, 0x02), + (9, 82, 0x02), + (23, 82, 0x02), + (40, 82, 0x03), + (2, 83, 0x02), + (9, 83, 0x02), + (23, 83, 0x02), + (40, 83, 0x03), + (2, 84, 0x02), + (9, 84, 0x02), + (23, 84, 0x02), + (40, 84, 0x03), + ], + // 54 + [ + (3, 81, 0x02), + (6, 81, 0x02), + (10, 81, 0x02), + (15, 81, 0x02), + (24, 81, 0x02), + (31, 81, 0x02), + (41, 81, 0x02), + (56, 81, 0x03), + (3, 82, 0x02), + (6, 82, 0x02), + (10, 82, 0x02), + (15, 82, 0x02), + (24, 82, 0x02), + (31, 82, 0x02), + (41, 82, 0x02), + (56, 82, 0x03), + ], + // 55 + [ + (3, 83, 0x02), + (6, 83, 0x02), + (10, 83, 0x02), + (15, 83, 0x02), + (24, 83, 0x02), + (31, 83, 0x02), + (41, 83, 0x02), + (56, 83, 0x03), + (3, 84, 0x02), + (6, 84, 0x02), + (10, 84, 0x02), + (15, 84, 0x02), + (24, 84, 0x02), + (31, 84, 0x02), + (41, 84, 0x02), + (56, 84, 0x03), + ], + // 56 + [ + (0, 85, 0x02), + (0, 86, 0x02), + (0, 87, 0x02), + (0, 89, 0x02), + (0, 106, 0x02), + (0, 107, 0x02), + (0, 113, 0x02), + (0, 118, 0x02), + (0, 119, 0x02), + (0, 120, 0x02), + (0, 121, 0x02), + (0, 122, 0x02), + (70, 0, 0x00), + (71, 0, 0x00), + (73, 0, 0x00), + (74, 0, 0x01), + ], + // 57 + [ + (1, 85, 0x02), + (22, 85, 0x03), + (1, 86, 0x02), + (22, 86, 0x03), + (1, 87, 0x02), + (22, 87, 0x03), + (1, 89, 0x02), + (22, 89, 0x03), + (1, 106, 0x02), + (22, 106, 0x03), + (1, 107, 0x02), + (22, 107, 0x03), + (1, 113, 0x02), + (22, 113, 0x03), + (1, 118, 0x02), + (22, 118, 0x03), + ], + // 58 + [ + (2, 85, 0x02), + (9, 85, 0x02), + (23, 85, 0x02), + (40, 85, 0x03), + (2, 86, 0x02), + (9, 86, 0x02), + (23, 86, 0x02), + (40, 86, 0x03), + (2, 87, 0x02), + (9, 87, 0x02), + (23, 87, 0x02), + (40, 87, 0x03), + (2, 89, 0x02), + (9, 89, 0x02), + (23, 89, 0x02), + (40, 89, 0x03), + ], + // 59 + [ + (3, 85, 0x02), + (6, 85, 0x02), + (10, 85, 0x02), + (15, 85, 0x02), + (24, 85, 0x02), + (31, 85, 0x02), + (41, 85, 0x02), + (56, 85, 0x03), + (3, 86, 0x02), + (6, 86, 0x02), + (10, 86, 0x02), + (15, 86, 0x02), + (24, 86, 0x02), + (31, 86, 0x02), + (41, 86, 0x02), + (56, 86, 0x03), + ], + // 60 + [ + (3, 87, 0x02), + (6, 87, 0x02), + (10, 87, 0x02), + (15, 87, 0x02), + (24, 87, 0x02), + (31, 87, 0x02), + (41, 87, 0x02), + (56, 87, 0x03), + (3, 89, 0x02), + (6, 89, 0x02), + (10, 89, 0x02), + (15, 89, 0x02), + (24, 89, 0x02), + (31, 89, 0x02), + (41, 89, 0x02), + (56, 89, 0x03), + ], + // 61 + [ + (2, 106, 0x02), + (9, 106, 0x02), + (23, 106, 0x02), + (40, 106, 0x03), + (2, 107, 0x02), + (9, 107, 0x02), + (23, 107, 0x02), + (40, 107, 0x03), + (2, 113, 0x02), + (9, 113, 0x02), + (23, 113, 0x02), + (40, 113, 0x03), + (2, 118, 0x02), + (9, 118, 0x02), + (23, 118, 0x02), + (40, 118, 0x03), + ], + // 62 + [ + (3, 106, 0x02), + (6, 106, 0x02), + (10, 106, 0x02), + (15, 106, 0x02), + (24, 106, 0x02), + (31, 106, 0x02), + (41, 106, 0x02), + (56, 106, 0x03), + (3, 107, 0x02), + (6, 107, 0x02), + (10, 107, 0x02), + (15, 107, 0x02), + (24, 107, 0x02), + (31, 107, 0x02), + (41, 107, 0x02), + (56, 107, 0x03), + ], + // 63 + [ + (3, 113, 0x02), + (6, 113, 0x02), + (10, 113, 0x02), + (15, 113, 0x02), + (24, 113, 0x02), + (31, 113, 0x02), + (41, 113, 0x02), + (56, 113, 0x03), + (3, 118, 0x02), + (6, 118, 0x02), + (10, 118, 0x02), + (15, 118, 0x02), + (24, 118, 0x02), + (31, 118, 0x02), + (41, 118, 0x02), + (56, 118, 0x03), + ], + // 64 + [ + (1, 119, 0x02), + (22, 119, 0x03), + (1, 120, 0x02), + (22, 120, 0x03), + (1, 121, 0x02), + (22, 121, 0x03), + (1, 122, 0x02), + (22, 122, 0x03), + (0, 38, 0x02), + (0, 42, 0x02), + (0, 44, 0x02), + (0, 59, 0x02), + (0, 88, 0x02), + (0, 90, 0x02), + (75, 0, 0x00), + (78, 0, 0x00), + ], + // 65 + [ + (2, 119, 0x02), + (9, 119, 0x02), + (23, 119, 0x02), + (40, 119, 0x03), + (2, 120, 0x02), + (9, 120, 0x02), + (23, 120, 0x02), + (40, 120, 0x03), + (2, 121, 0x02), + (9, 121, 0x02), + (23, 121, 0x02), + (40, 121, 0x03), + (2, 122, 0x02), + (9, 122, 0x02), + (23, 122, 0x02), + (40, 122, 0x03), + ], + // 66 + [ + (3, 119, 0x02), + (6, 119, 0x02), + (10, 119, 0x02), + (15, 119, 0x02), + (24, 119, 0x02), + (31, 119, 0x02), + (41, 119, 0x02), + (56, 119, 0x03), + (3, 120, 0x02), + (6, 120, 0x02), + (10, 120, 0x02), + (15, 120, 0x02), + (24, 120, 0x02), + (31, 120, 0x02), + (41, 120, 0x02), + (56, 120, 0x03), + ], + // 67 + [ + (3, 121, 0x02), + (6, 121, 0x02), + (10, 121, 0x02), + (15, 121, 0x02), + (24, 121, 0x02), + (31, 121, 0x02), + (41, 121, 0x02), + (56, 121, 0x03), + (3, 122, 0x02), + (6, 122, 0x02), + (10, 122, 0x02), + (15, 122, 0x02), + (24, 122, 0x02), + (31, 122, 0x02), + (41, 122, 0x02), + (56, 122, 0x03), + ], + // 68 + [ + (1, 38, 0x02), + (22, 38, 0x03), + (1, 42, 0x02), + (22, 42, 0x03), + (1, 44, 0x02), + (22, 44, 0x03), + (1, 59, 0x02), + (22, 59, 0x03), + (1, 88, 0x02), + (22, 88, 0x03), + (1, 90, 0x02), + (22, 90, 0x03), + (76, 0, 0x00), + (77, 0, 0x00), + (79, 0, 0x00), + (81, 0, 0x00), + ], + // 69 + [ + (2, 38, 0x02), + (9, 38, 0x02), + (23, 38, 0x02), + (40, 38, 0x03), + (2, 42, 0x02), + (9, 42, 0x02), + (23, 42, 0x02), + (40, 42, 0x03), + (2, 44, 0x02), + (9, 44, 0x02), + (23, 44, 0x02), + (40, 44, 0x03), + (2, 59, 0x02), + (9, 59, 0x02), + (23, 59, 0x02), + (40, 59, 0x03), + ], + // 70 + [ + (3, 38, 0x02), + (6, 38, 0x02), + (10, 38, 0x02), + (15, 38, 0x02), + (24, 38, 0x02), + (31, 38, 0x02), + (41, 38, 0x02), + (56, 38, 0x03), + (3, 42, 0x02), + (6, 42, 0x02), + (10, 42, 0x02), + (15, 42, 0x02), + (24, 42, 0x02), + (31, 42, 0x02), + (41, 42, 0x02), + (56, 42, 0x03), + ], + // 71 + [ + (3, 44, 0x02), + (6, 44, 0x02), + (10, 44, 0x02), + (15, 44, 0x02), + (24, 44, 0x02), + (31, 44, 0x02), + (41, 44, 0x02), + (56, 44, 0x03), + (3, 59, 0x02), + (6, 59, 0x02), + (10, 59, 0x02), + (15, 59, 0x02), + (24, 59, 0x02), + (31, 59, 0x02), + (41, 59, 0x02), + (56, 59, 0x03), + ], + // 72 + [ + (2, 88, 0x02), + (9, 88, 0x02), + (23, 88, 0x02), + (40, 88, 0x03), + (2, 90, 0x02), + (9, 90, 0x02), + (23, 90, 0x02), + (40, 90, 0x03), + (0, 33, 0x02), + (0, 34, 0x02), + (0, 40, 0x02), + (0, 41, 0x02), + (0, 63, 0x02), + (80, 0, 0x00), + (82, 0, 0x00), + (84, 0, 0x00), + ], + // 73 + [ + (3, 88, 0x02), + (6, 88, 0x02), + (10, 88, 0x02), + (15, 88, 0x02), + (24, 88, 0x02), + (31, 88, 0x02), + (41, 88, 0x02), + (56, 88, 0x03), + (3, 90, 0x02), + (6, 90, 0x02), + (10, 90, 0x02), + (15, 90, 0x02), + (24, 90, 0x02), + (31, 90, 0x02), + (41, 90, 0x02), + (56, 90, 0x03), + ], + // 74 + [ + (1, 33, 0x02), + (22, 33, 0x03), + (1, 34, 0x02), + (22, 34, 0x03), + (1, 40, 0x02), + (22, 40, 0x03), + (1, 41, 0x02), + (22, 41, 0x03), + (1, 63, 0x02), + (22, 63, 0x03), + (0, 39, 0x02), + (0, 43, 0x02), + (0, 124, 0x02), + (83, 0, 0x00), + (85, 0, 0x00), + (88, 0, 0x00), + ], + // 75 + [ + (2, 33, 0x02), + (9, 33, 0x02), + (23, 33, 0x02), + (40, 33, 0x03), + (2, 34, 0x02), + (9, 34, 0x02), + (23, 34, 0x02), + (40, 34, 0x03), + (2, 40, 0x02), + (9, 40, 0x02), + (23, 40, 0x02), + (40, 40, 0x03), + (2, 41, 0x02), + (9, 41, 0x02), + (23, 41, 0x02), + (40, 41, 0x03), + ], + // 76 + [ + (3, 33, 0x02), + (6, 33, 0x02), + (10, 33, 0x02), + (15, 33, 0x02), + (24, 33, 0x02), + (31, 33, 0x02), + (41, 33, 0x02), + (56, 33, 0x03), + (3, 34, 0x02), + (6, 34, 0x02), + (10, 34, 0x02), + (15, 34, 0x02), + (24, 34, 0x02), + (31, 34, 0x02), + (41, 34, 0x02), + (56, 34, 0x03), + ], + // 77 + [ + (3, 40, 0x02), + (6, 40, 0x02), + (10, 40, 0x02), + (15, 40, 0x02), + (24, 40, 0x02), + (31, 40, 0x02), + (41, 40, 0x02), + (56, 40, 0x03), + (3, 41, 0x02), + (6, 41, 0x02), + (10, 41, 0x02), + (15, 41, 0x02), + (24, 41, 0x02), + (31, 41, 0x02), + (41, 41, 0x02), + (56, 41, 0x03), + ], + // 78 + [ + (2, 63, 0x02), + (9, 63, 0x02), + (23, 63, 0x02), + (40, 63, 0x03), + (1, 39, 0x02), + (22, 39, 0x03), + (1, 43, 0x02), + (22, 43, 0x03), + (1, 124, 0x02), + (22, 124, 0x03), + (0, 35, 0x02), + (0, 62, 0x02), + (86, 0, 0x00), + (87, 0, 0x00), + (89, 0, 0x00), + (90, 0, 0x00), + ], + // 79 + [ + (3, 63, 0x02), + (6, 63, 0x02), + (10, 63, 0x02), + (15, 63, 0x02), + (24, 63, 0x02), + (31, 63, 0x02), + (41, 63, 0x02), + (56, 63, 0x03), + (2, 39, 0x02), + (9, 39, 0x02), + (23, 39, 0x02), + (40, 39, 0x03), + (2, 43, 0x02), + (9, 43, 0x02), + (23, 43, 0x02), + (40, 43, 0x03), + ], + // 80 + [ + (3, 39, 0x02), + (6, 39, 0x02), + (10, 39, 0x02), + (15, 39, 0x02), + (24, 39, 0x02), + (31, 39, 0x02), + (41, 39, 0x02), + (56, 39, 0x03), + (3, 43, 0x02), + (6, 43, 0x02), + (10, 43, 0x02), + (15, 43, 0x02), + (24, 43, 0x02), + (31, 43, 0x02), + (41, 43, 0x02), + (56, 43, 0x03), + ], + // 81 + [ + (2, 124, 0x02), + (9, 124, 0x02), + (23, 124, 0x02), + (40, 124, 0x03), + (1, 35, 0x02), + (22, 35, 0x03), + (1, 62, 0x02), + (22, 62, 0x03), + (0, 0, 0x02), + (0, 36, 0x02), + (0, 64, 0x02), + (0, 91, 0x02), + (0, 93, 0x02), + (0, 126, 0x02), + (91, 0, 0x00), + (92, 0, 0x00), + ], + // 82 + [ + (3, 124, 0x02), + (6, 124, 0x02), + (10, 124, 0x02), + (15, 124, 0x02), + (24, 124, 0x02), + (31, 124, 0x02), + (41, 124, 0x02), + (56, 124, 0x03), + (2, 35, 0x02), + (9, 35, 0x02), + (23, 35, 0x02), + (40, 35, 0x03), + (2, 62, 0x02), + (9, 62, 0x02), + (23, 62, 0x02), + (40, 62, 0x03), + ], + // 83 + [ + (3, 35, 0x02), + (6, 35, 0x02), + (10, 35, 0x02), + (15, 35, 0x02), + (24, 35, 0x02), + (31, 35, 0x02), + (41, 35, 0x02), + (56, 35, 0x03), + (3, 62, 0x02), + (6, 62, 0x02), + (10, 62, 0x02), + (15, 62, 0x02), + (24, 62, 0x02), + (31, 62, 0x02), + (41, 62, 0x02), + (56, 62, 0x03), + ], + // 84 + [ + (1, 0, 0x02), + (22, 0, 0x03), + (1, 36, 0x02), + (22, 36, 0x03), + (1, 64, 0x02), + (22, 64, 0x03), + (1, 91, 0x02), + (22, 91, 0x03), + (1, 93, 0x02), + (22, 93, 0x03), + (1, 126, 0x02), + (22, 126, 0x03), + (0, 94, 0x02), + (0, 125, 0x02), + (93, 0, 0x00), + (94, 0, 0x00), + ], + // 85 + [ + (2, 0, 0x02), + (9, 0, 0x02), + (23, 0, 0x02), + (40, 0, 0x03), + (2, 36, 0x02), + (9, 36, 0x02), + (23, 36, 0x02), + (40, 36, 0x03), + (2, 64, 0x02), + (9, 64, 0x02), + (23, 64, 0x02), + (40, 64, 0x03), + (2, 91, 0x02), + (9, 91, 0x02), + (23, 91, 0x02), + (40, 91, 0x03), + ], + // 86 + [ + (3, 0, 0x02), + (6, 0, 0x02), + (10, 0, 0x02), + (15, 0, 0x02), + (24, 0, 0x02), + (31, 0, 0x02), + (41, 0, 0x02), + (56, 0, 0x03), + (3, 36, 0x02), + (6, 36, 0x02), + (10, 36, 0x02), + (15, 36, 0x02), + (24, 36, 0x02), + (31, 36, 0x02), + (41, 36, 0x02), + (56, 36, 0x03), + ], + // 87 + [ + (3, 64, 0x02), + (6, 64, 0x02), + (10, 64, 0x02), + (15, 64, 0x02), + (24, 64, 0x02), + (31, 64, 0x02), + (41, 64, 0x02), + (56, 64, 0x03), + (3, 91, 0x02), + (6, 91, 0x02), + (10, 91, 0x02), + (15, 91, 0x02), + (24, 91, 0x02), + (31, 91, 0x02), + (41, 91, 0x02), + (56, 91, 0x03), + ], + // 88 + [ + (2, 93, 0x02), + (9, 93, 0x02), + (23, 93, 0x02), + (40, 93, 0x03), + (2, 126, 0x02), + (9, 126, 0x02), + (23, 126, 0x02), + (40, 126, 0x03), + (1, 94, 0x02), + (22, 94, 0x03), + (1, 125, 0x02), + (22, 125, 0x03), + (0, 60, 0x02), + (0, 96, 0x02), + (0, 123, 0x02), + (95, 0, 0x00), + ], + // 89 + [ + (3, 93, 0x02), + (6, 93, 0x02), + (10, 93, 0x02), + (15, 93, 0x02), + (24, 93, 0x02), + (31, 93, 0x02), + (41, 93, 0x02), + (56, 93, 0x03), + (3, 126, 0x02), + (6, 126, 0x02), + (10, 126, 0x02), + (15, 126, 0x02), + (24, 126, 0x02), + (31, 126, 0x02), + (41, 126, 0x02), + (56, 126, 0x03), + ], + // 90 + [ + (2, 94, 0x02), + (9, 94, 0x02), + (23, 94, 0x02), + (40, 94, 0x03), + (2, 125, 0x02), + (9, 125, 0x02), + (23, 125, 0x02), + (40, 125, 0x03), + (1, 60, 0x02), + (22, 60, 0x03), + (1, 96, 0x02), + (22, 96, 0x03), + (1, 123, 0x02), + (22, 123, 0x03), + (96, 0, 0x00), + (110, 0, 0x00), + ], + // 91 + [ + (3, 94, 0x02), + (6, 94, 0x02), + (10, 94, 0x02), + (15, 94, 0x02), + (24, 94, 0x02), + (31, 94, 0x02), + (41, 94, 0x02), + (56, 94, 0x03), + (3, 125, 0x02), + (6, 125, 0x02), + (10, 125, 0x02), + (15, 125, 0x02), + (24, 125, 0x02), + (31, 125, 0x02), + (41, 125, 0x02), + (56, 125, 0x03), + ], + // 92 + [ + (2, 60, 0x02), + (9, 60, 0x02), + (23, 60, 0x02), + (40, 60, 0x03), + (2, 96, 0x02), + (9, 96, 0x02), + (23, 96, 0x02), + (40, 96, 0x03), + (2, 123, 0x02), + (9, 123, 0x02), + (23, 123, 0x02), + (40, 123, 0x03), + (97, 0, 0x00), + (101, 0, 0x00), + (111, 0, 0x00), + (133, 0, 0x00), + ], + // 93 + [ + (3, 60, 0x02), + (6, 60, 0x02), + (10, 60, 0x02), + (15, 60, 0x02), + (24, 60, 0x02), + (31, 60, 0x02), + (41, 60, 0x02), + (56, 60, 0x03), + (3, 96, 0x02), + (6, 96, 0x02), + (10, 96, 0x02), + (15, 96, 0x02), + (24, 96, 0x02), + (31, 96, 0x02), + (41, 96, 0x02), + (56, 96, 0x03), + ], + // 94 + [ + (3, 123, 0x02), + (6, 123, 0x02), + (10, 123, 0x02), + (15, 123, 0x02), + (24, 123, 0x02), + (31, 123, 0x02), + (41, 123, 0x02), + (56, 123, 0x03), + (98, 0, 0x00), + (99, 0, 0x00), + (102, 0, 0x00), + (105, 0, 0x00), + (112, 0, 0x00), + (119, 0, 0x00), + (134, 0, 0x00), + (153, 0, 0x00), + ], + // 95 + [ + (0, 92, 0x02), + (0, 195, 0x02), + (0, 208, 0x02), + (100, 0, 0x00), + (103, 0, 0x00), + (104, 0, 0x00), + (106, 0, 0x00), + (107, 0, 0x00), + (113, 0, 0x00), + (116, 0, 0x00), + (120, 0, 0x00), + (126, 0, 0x00), + (135, 0, 0x00), + (142, 0, 0x00), + (154, 0, 0x00), + (169, 0, 0x00), + ], + // 96 + [ + (1, 92, 0x02), + (22, 92, 0x03), + (1, 195, 0x02), + (22, 195, 0x03), + (1, 208, 0x02), + (22, 208, 0x03), + (0, 128, 0x02), + (0, 130, 0x02), + (0, 131, 0x02), + (0, 162, 0x02), + (0, 184, 0x02), + (0, 194, 0x02), + (0, 224, 0x02), + (0, 226, 0x02), + (108, 0, 0x00), + (109, 0, 0x00), + ], + // 97 + [ + (2, 92, 0x02), + (9, 92, 0x02), + (23, 92, 0x02), + (40, 92, 0x03), + (2, 195, 0x02), + (9, 195, 0x02), + (23, 195, 0x02), + (40, 195, 0x03), + (2, 208, 0x02), + (9, 208, 0x02), + (23, 208, 0x02), + (40, 208, 0x03), + (1, 128, 0x02), + (22, 128, 0x03), + (1, 130, 0x02), + (22, 130, 0x03), + ], + // 98 + [ + (3, 92, 0x02), + (6, 92, 0x02), + (10, 92, 0x02), + (15, 92, 0x02), + (24, 92, 0x02), + (31, 92, 0x02), + (41, 92, 0x02), + (56, 92, 0x03), + (3, 195, 0x02), + (6, 195, 0x02), + (10, 195, 0x02), + (15, 195, 0x02), + (24, 195, 0x02), + (31, 195, 0x02), + (41, 195, 0x02), + (56, 195, 0x03), + ], + // 99 + [ + (3, 208, 0x02), + (6, 208, 0x02), + (10, 208, 0x02), + (15, 208, 0x02), + (24, 208, 0x02), + (31, 208, 0x02), + (41, 208, 0x02), + (56, 208, 0x03), + (2, 128, 0x02), + (9, 128, 0x02), + (23, 128, 0x02), + (40, 128, 0x03), + (2, 130, 0x02), + (9, 130, 0x02), + (23, 130, 0x02), + (40, 130, 0x03), + ], + // 100 + [ + (3, 128, 0x02), + (6, 128, 0x02), + (10, 128, 0x02), + (15, 128, 0x02), + (24, 128, 0x02), + (31, 128, 0x02), + (41, 128, 0x02), + (56, 128, 0x03), + (3, 130, 0x02), + (6, 130, 0x02), + (10, 130, 0x02), + (15, 130, 0x02), + (24, 130, 0x02), + (31, 130, 0x02), + (41, 130, 0x02), + (56, 130, 0x03), + ], + // 101 + [ + (1, 131, 0x02), + (22, 131, 0x03), + (1, 162, 0x02), + (22, 162, 0x03), + (1, 184, 0x02), + (22, 184, 0x03), + (1, 194, 0x02), + (22, 194, 0x03), + (1, 224, 0x02), + (22, 224, 0x03), + (1, 226, 0x02), + (22, 226, 0x03), + (0, 153, 0x02), + (0, 161, 0x02), + (0, 167, 0x02), + (0, 172, 0x02), + ], + // 102 + [ + (2, 131, 0x02), + (9, 131, 0x02), + (23, 131, 0x02), + (40, 131, 0x03), + (2, 162, 0x02), + (9, 162, 0x02), + (23, 162, 0x02), + (40, 162, 0x03), + (2, 184, 0x02), + (9, 184, 0x02), + (23, 184, 0x02), + (40, 184, 0x03), + (2, 194, 0x02), + (9, 194, 0x02), + (23, 194, 0x02), + (40, 194, 0x03), + ], + // 103 + [ + (3, 131, 0x02), + (6, 131, 0x02), + (10, 131, 0x02), + (15, 131, 0x02), + (24, 131, 0x02), + (31, 131, 0x02), + (41, 131, 0x02), + (56, 131, 0x03), + (3, 162, 0x02), + (6, 162, 0x02), + (10, 162, 0x02), + (15, 162, 0x02), + (24, 162, 0x02), + (31, 162, 0x02), + (41, 162, 0x02), + (56, 162, 0x03), + ], + // 104 + [ + (3, 184, 0x02), + (6, 184, 0x02), + (10, 184, 0x02), + (15, 184, 0x02), + (24, 184, 0x02), + (31, 184, 0x02), + (41, 184, 0x02), + (56, 184, 0x03), + (3, 194, 0x02), + (6, 194, 0x02), + (10, 194, 0x02), + (15, 194, 0x02), + (24, 194, 0x02), + (31, 194, 0x02), + (41, 194, 0x02), + (56, 194, 0x03), + ], + // 105 + [ + (2, 224, 0x02), + (9, 224, 0x02), + (23, 224, 0x02), + (40, 224, 0x03), + (2, 226, 0x02), + (9, 226, 0x02), + (23, 226, 0x02), + (40, 226, 0x03), + (1, 153, 0x02), + (22, 153, 0x03), + (1, 161, 0x02), + (22, 161, 0x03), + (1, 167, 0x02), + (22, 167, 0x03), + (1, 172, 0x02), + (22, 172, 0x03), + ], + // 106 + [ + (3, 224, 0x02), + (6, 224, 0x02), + (10, 224, 0x02), + (15, 224, 0x02), + (24, 224, 0x02), + (31, 224, 0x02), + (41, 224, 0x02), + (56, 224, 0x03), + (3, 226, 0x02), + (6, 226, 0x02), + (10, 226, 0x02), + (15, 226, 0x02), + (24, 226, 0x02), + (31, 226, 0x02), + (41, 226, 0x02), + (56, 226, 0x03), + ], + // 107 + [ + (2, 153, 0x02), + (9, 153, 0x02), + (23, 153, 0x02), + (40, 153, 0x03), + (2, 161, 0x02), + (9, 161, 0x02), + (23, 161, 0x02), + (40, 161, 0x03), + (2, 167, 0x02), + (9, 167, 0x02), + (23, 167, 0x02), + (40, 167, 0x03), + (2, 172, 0x02), + (9, 172, 0x02), + (23, 172, 0x02), + (40, 172, 0x03), + ], + // 108 + [ + (3, 153, 0x02), + (6, 153, 0x02), + (10, 153, 0x02), + (15, 153, 0x02), + (24, 153, 0x02), + (31, 153, 0x02), + (41, 153, 0x02), + (56, 153, 0x03), + (3, 161, 0x02), + (6, 161, 0x02), + (10, 161, 0x02), + (15, 161, 0x02), + (24, 161, 0x02), + (31, 161, 0x02), + (41, 161, 0x02), + (56, 161, 0x03), + ], + // 109 + [ + (3, 167, 0x02), + (6, 167, 0x02), + (10, 167, 0x02), + (15, 167, 0x02), + (24, 167, 0x02), + (31, 167, 0x02), + (41, 167, 0x02), + (56, 167, 0x03), + (3, 172, 0x02), + (6, 172, 0x02), + (10, 172, 0x02), + (15, 172, 0x02), + (24, 172, 0x02), + (31, 172, 0x02), + (41, 172, 0x02), + (56, 172, 0x03), + ], + // 110 + [ + (114, 0, 0x00), + (115, 0, 0x00), + (117, 0, 0x00), + (118, 0, 0x00), + (121, 0, 0x00), + (123, 0, 0x00), + (127, 0, 0x00), + (130, 0, 0x00), + (136, 0, 0x00), + (139, 0, 0x00), + (143, 0, 0x00), + (146, 0, 0x00), + (155, 0, 0x00), + (162, 0, 0x00), + (170, 0, 0x00), + (180, 0, 0x00), + ], + // 111 + [ + (0, 176, 0x02), + (0, 177, 0x02), + (0, 179, 0x02), + (0, 209, 0x02), + (0, 216, 0x02), + (0, 217, 0x02), + (0, 227, 0x02), + (0, 229, 0x02), + (0, 230, 0x02), + (122, 0, 0x00), + (124, 0, 0x00), + (125, 0, 0x00), + (128, 0, 0x00), + (129, 0, 0x00), + (131, 0, 0x00), + (132, 0, 0x00), + ], + // 112 + [ + (1, 176, 0x02), + (22, 176, 0x03), + (1, 177, 0x02), + (22, 177, 0x03), + (1, 179, 0x02), + (22, 179, 0x03), + (1, 209, 0x02), + (22, 209, 0x03), + (1, 216, 0x02), + (22, 216, 0x03), + (1, 217, 0x02), + (22, 217, 0x03), + (1, 227, 0x02), + (22, 227, 0x03), + (1, 229, 0x02), + (22, 229, 0x03), + ], + // 113 + [ + (2, 176, 0x02), + (9, 176, 0x02), + (23, 176, 0x02), + (40, 176, 0x03), + (2, 177, 0x02), + (9, 177, 0x02), + (23, 177, 0x02), + (40, 177, 0x03), + (2, 179, 0x02), + (9, 179, 0x02), + (23, 179, 0x02), + (40, 179, 0x03), + (2, 209, 0x02), + (9, 209, 0x02), + (23, 209, 0x02), + (40, 209, 0x03), + ], + // 114 + [ + (3, 176, 0x02), + (6, 176, 0x02), + (10, 176, 0x02), + (15, 176, 0x02), + (24, 176, 0x02), + (31, 176, 0x02), + (41, 176, 0x02), + (56, 176, 0x03), + (3, 177, 0x02), + (6, 177, 0x02), + (10, 177, 0x02), + (15, 177, 0x02), + (24, 177, 0x02), + (31, 177, 0x02), + (41, 177, 0x02), + (56, 177, 0x03), + ], + // 115 + [ + (3, 179, 0x02), + (6, 179, 0x02), + (10, 179, 0x02), + (15, 179, 0x02), + (24, 179, 0x02), + (31, 179, 0x02), + (41, 179, 0x02), + (56, 179, 0x03), + (3, 209, 0x02), + (6, 209, 0x02), + (10, 209, 0x02), + (15, 209, 0x02), + (24, 209, 0x02), + (31, 209, 0x02), + (41, 209, 0x02), + (56, 209, 0x03), + ], + // 116 + [ + (2, 216, 0x02), + (9, 216, 0x02), + (23, 216, 0x02), + (40, 216, 0x03), + (2, 217, 0x02), + (9, 217, 0x02), + (23, 217, 0x02), + (40, 217, 0x03), + (2, 227, 0x02), + (9, 227, 0x02), + (23, 227, 0x02), + (40, 227, 0x03), + (2, 229, 0x02), + (9, 229, 0x02), + (23, 229, 0x02), + (40, 229, 0x03), + ], + // 117 + [ + (3, 216, 0x02), + (6, 216, 0x02), + (10, 216, 0x02), + (15, 216, 0x02), + (24, 216, 0x02), + (31, 216, 0x02), + (41, 216, 0x02), + (56, 216, 0x03), + (3, 217, 0x02), + (6, 217, 0x02), + (10, 217, 0x02), + (15, 217, 0x02), + (24, 217, 0x02), + (31, 217, 0x02), + (41, 217, 0x02), + (56, 217, 0x03), + ], + // 118 + [ + (3, 227, 0x02), + (6, 227, 0x02), + (10, 227, 0x02), + (15, 227, 0x02), + (24, 227, 0x02), + (31, 227, 0x02), + (41, 227, 0x02), + (56, 227, 0x03), + (3, 229, 0x02), + (6, 229, 0x02), + (10, 229, 0x02), + (15, 229, 0x02), + (24, 229, 0x02), + (31, 229, 0x02), + (41, 229, 0x02), + (56, 229, 0x03), + ], + // 119 + [ + (1, 230, 0x02), + (22, 230, 0x03), + (0, 129, 0x02), + (0, 132, 0x02), + (0, 133, 0x02), + (0, 134, 0x02), + (0, 136, 0x02), + (0, 146, 0x02), + (0, 154, 0x02), + (0, 156, 0x02), + (0, 160, 0x02), + (0, 163, 0x02), + (0, 164, 0x02), + (0, 169, 0x02), + (0, 170, 0x02), + (0, 173, 0x02), + ], + // 120 + [ + (2, 230, 0x02), + (9, 230, 0x02), + (23, 230, 0x02), + (40, 230, 0x03), + (1, 129, 0x02), + (22, 129, 0x03), + (1, 132, 0x02), + (22, 132, 0x03), + (1, 133, 0x02), + (22, 133, 0x03), + (1, 134, 0x02), + (22, 134, 0x03), + (1, 136, 0x02), + (22, 136, 0x03), + (1, 146, 0x02), + (22, 146, 0x03), + ], + // 121 + [ + (3, 230, 0x02), + (6, 230, 0x02), + (10, 230, 0x02), + (15, 230, 0x02), + (24, 230, 0x02), + (31, 230, 0x02), + (41, 230, 0x02), + (56, 230, 0x03), + (2, 129, 0x02), + (9, 129, 0x02), + (23, 129, 0x02), + (40, 129, 0x03), + (2, 132, 0x02), + (9, 132, 0x02), + (23, 132, 0x02), + (40, 132, 0x03), + ], + // 122 + [ + (3, 129, 0x02), + (6, 129, 0x02), + (10, 129, 0x02), + (15, 129, 0x02), + (24, 129, 0x02), + (31, 129, 0x02), + (41, 129, 0x02), + (56, 129, 0x03), + (3, 132, 0x02), + (6, 132, 0x02), + (10, 132, 0x02), + (15, 132, 0x02), + (24, 132, 0x02), + (31, 132, 0x02), + (41, 132, 0x02), + (56, 132, 0x03), + ], + // 123 + [ + (2, 133, 0x02), + (9, 133, 0x02), + (23, 133, 0x02), + (40, 133, 0x03), + (2, 134, 0x02), + (9, 134, 0x02), + (23, 134, 0x02), + (40, 134, 0x03), + (2, 136, 0x02), + (9, 136, 0x02), + (23, 136, 0x02), + (40, 136, 0x03), + (2, 146, 0x02), + (9, 146, 0x02), + (23, 146, 0x02), + (40, 146, 0x03), + ], + // 124 + [ + (3, 133, 0x02), + (6, 133, 0x02), + (10, 133, 0x02), + (15, 133, 0x02), + (24, 133, 0x02), + (31, 133, 0x02), + (41, 133, 0x02), + (56, 133, 0x03), + (3, 134, 0x02), + (6, 134, 0x02), + (10, 134, 0x02), + (15, 134, 0x02), + (24, 134, 0x02), + (31, 134, 0x02), + (41, 134, 0x02), + (56, 134, 0x03), + ], + // 125 + [ + (3, 136, 0x02), + (6, 136, 0x02), + (10, 136, 0x02), + (15, 136, 0x02), + (24, 136, 0x02), + (31, 136, 0x02), + (41, 136, 0x02), + (56, 136, 0x03), + (3, 146, 0x02), + (6, 146, 0x02), + (10, 146, 0x02), + (15, 146, 0x02), + (24, 146, 0x02), + (31, 146, 0x02), + (41, 146, 0x02), + (56, 146, 0x03), + ], + // 126 + [ + (1, 154, 0x02), + (22, 154, 0x03), + (1, 156, 0x02), + (22, 156, 0x03), + (1, 160, 0x02), + (22, 160, 0x03), + (1, 163, 0x02), + (22, 163, 0x03), + (1, 164, 0x02), + (22, 164, 0x03), + (1, 169, 0x02), + (22, 169, 0x03), + (1, 170, 0x02), + (22, 170, 0x03), + (1, 173, 0x02), + (22, 173, 0x03), + ], + // 127 + [ + (2, 154, 0x02), + (9, 154, 0x02), + (23, 154, 0x02), + (40, 154, 0x03), + (2, 156, 0x02), + (9, 156, 0x02), + (23, 156, 0x02), + (40, 156, 0x03), + (2, 160, 0x02), + (9, 160, 0x02), + (23, 160, 0x02), + (40, 160, 0x03), + (2, 163, 0x02), + (9, 163, 0x02), + (23, 163, 0x02), + (40, 163, 0x03), + ], + // 128 + [ + (3, 154, 0x02), + (6, 154, 0x02), + (10, 154, 0x02), + (15, 154, 0x02), + (24, 154, 0x02), + (31, 154, 0x02), + (41, 154, 0x02), + (56, 154, 0x03), + (3, 156, 0x02), + (6, 156, 0x02), + (10, 156, 0x02), + (15, 156, 0x02), + (24, 156, 0x02), + (31, 156, 0x02), + (41, 156, 0x02), + (56, 156, 0x03), + ], + // 129 + [ + (3, 160, 0x02), + (6, 160, 0x02), + (10, 160, 0x02), + (15, 160, 0x02), + (24, 160, 0x02), + (31, 160, 0x02), + (41, 160, 0x02), + (56, 160, 0x03), + (3, 163, 0x02), + (6, 163, 0x02), + (10, 163, 0x02), + (15, 163, 0x02), + (24, 163, 0x02), + (31, 163, 0x02), + (41, 163, 0x02), + (56, 163, 0x03), + ], + // 130 + [ + (2, 164, 0x02), + (9, 164, 0x02), + (23, 164, 0x02), + (40, 164, 0x03), + (2, 169, 0x02), + (9, 169, 0x02), + (23, 169, 0x02), + (40, 169, 0x03), + (2, 170, 0x02), + (9, 170, 0x02), + (23, 170, 0x02), + (40, 170, 0x03), + (2, 173, 0x02), + (9, 173, 0x02), + (23, 173, 0x02), + (40, 173, 0x03), + ], + // 131 + [ + (3, 164, 0x02), + (6, 164, 0x02), + (10, 164, 0x02), + (15, 164, 0x02), + (24, 164, 0x02), + (31, 164, 0x02), + (41, 164, 0x02), + (56, 164, 0x03), + (3, 169, 0x02), + (6, 169, 0x02), + (10, 169, 0x02), + (15, 169, 0x02), + (24, 169, 0x02), + (31, 169, 0x02), + (41, 169, 0x02), + (56, 169, 0x03), + ], + // 132 + [ + (3, 170, 0x02), + (6, 170, 0x02), + (10, 170, 0x02), + (15, 170, 0x02), + (24, 170, 0x02), + (31, 170, 0x02), + (41, 170, 0x02), + (56, 170, 0x03), + (3, 173, 0x02), + (6, 173, 0x02), + (10, 173, 0x02), + (15, 173, 0x02), + (24, 173, 0x02), + (31, 173, 0x02), + (41, 173, 0x02), + (56, 173, 0x03), + ], + // 133 + [ + (137, 0, 0x00), + (138, 0, 0x00), + (140, 0, 0x00), + (141, 0, 0x00), + (144, 0, 0x00), + (145, 0, 0x00), + (147, 0, 0x00), + (150, 0, 0x00), + (156, 0, 0x00), + (159, 0, 0x00), + (163, 0, 0x00), + (166, 0, 0x00), + (171, 0, 0x00), + (174, 0, 0x00), + (181, 0, 0x00), + (190, 0, 0x00), + ], + // 134 + [ + (0, 178, 0x02), + (0, 181, 0x02), + (0, 185, 0x02), + (0, 186, 0x02), + (0, 187, 0x02), + (0, 189, 0x02), + (0, 190, 0x02), + (0, 196, 0x02), + (0, 198, 0x02), + (0, 228, 0x02), + (0, 232, 0x02), + (0, 233, 0x02), + (148, 0, 0x00), + (149, 0, 0x00), + (151, 0, 0x00), + (152, 0, 0x00), + ], + // 135 + [ + (1, 178, 0x02), + (22, 178, 0x03), + (1, 181, 0x02), + (22, 181, 0x03), + (1, 185, 0x02), + (22, 185, 0x03), + (1, 186, 0x02), + (22, 186, 0x03), + (1, 187, 0x02), + (22, 187, 0x03), + (1, 189, 0x02), + (22, 189, 0x03), + (1, 190, 0x02), + (22, 190, 0x03), + (1, 196, 0x02), + (22, 196, 0x03), + ], + // 136 + [ + (2, 178, 0x02), + (9, 178, 0x02), + (23, 178, 0x02), + (40, 178, 0x03), + (2, 181, 0x02), + (9, 181, 0x02), + (23, 181, 0x02), + (40, 181, 0x03), + (2, 185, 0x02), + (9, 185, 0x02), + (23, 185, 0x02), + (40, 185, 0x03), + (2, 186, 0x02), + (9, 186, 0x02), + (23, 186, 0x02), + (40, 186, 0x03), + ], + // 137 + [ + (3, 178, 0x02), + (6, 178, 0x02), + (10, 178, 0x02), + (15, 178, 0x02), + (24, 178, 0x02), + (31, 178, 0x02), + (41, 178, 0x02), + (56, 178, 0x03), + (3, 181, 0x02), + (6, 181, 0x02), + (10, 181, 0x02), + (15, 181, 0x02), + (24, 181, 0x02), + (31, 181, 0x02), + (41, 181, 0x02), + (56, 181, 0x03), + ], + // 138 + [ + (3, 185, 0x02), + (6, 185, 0x02), + (10, 185, 0x02), + (15, 185, 0x02), + (24, 185, 0x02), + (31, 185, 0x02), + (41, 185, 0x02), + (56, 185, 0x03), + (3, 186, 0x02), + (6, 186, 0x02), + (10, 186, 0x02), + (15, 186, 0x02), + (24, 186, 0x02), + (31, 186, 0x02), + (41, 186, 0x02), + (56, 186, 0x03), + ], + // 139 + [ + (2, 187, 0x02), + (9, 187, 0x02), + (23, 187, 0x02), + (40, 187, 0x03), + (2, 189, 0x02), + (9, 189, 0x02), + (23, 189, 0x02), + (40, 189, 0x03), + (2, 190, 0x02), + (9, 190, 0x02), + (23, 190, 0x02), + (40, 190, 0x03), + (2, 196, 0x02), + (9, 196, 0x02), + (23, 196, 0x02), + (40, 196, 0x03), + ], + // 140 + [ + (3, 187, 0x02), + (6, 187, 0x02), + (10, 187, 0x02), + (15, 187, 0x02), + (24, 187, 0x02), + (31, 187, 0x02), + (41, 187, 0x02), + (56, 187, 0x03), + (3, 189, 0x02), + (6, 189, 0x02), + (10, 189, 0x02), + (15, 189, 0x02), + (24, 189, 0x02), + (31, 189, 0x02), + (41, 189, 0x02), + (56, 189, 0x03), + ], + // 141 + [ + (3, 190, 0x02), + (6, 190, 0x02), + (10, 190, 0x02), + (15, 190, 0x02), + (24, 190, 0x02), + (31, 190, 0x02), + (41, 190, 0x02), + (56, 190, 0x03), + (3, 196, 0x02), + (6, 196, 0x02), + (10, 196, 0x02), + (15, 196, 0x02), + (24, 196, 0x02), + (31, 196, 0x02), + (41, 196, 0x02), + (56, 196, 0x03), + ], + // 142 + [ + (1, 198, 0x02), + (22, 198, 0x03), + (1, 228, 0x02), + (22, 228, 0x03), + (1, 232, 0x02), + (22, 232, 0x03), + (1, 233, 0x02), + (22, 233, 0x03), + (0, 1, 0x02), + (0, 135, 0x02), + (0, 137, 0x02), + (0, 138, 0x02), + (0, 139, 0x02), + (0, 140, 0x02), + (0, 141, 0x02), + (0, 143, 0x02), + ], + // 143 + [ + (2, 198, 0x02), + (9, 198, 0x02), + (23, 198, 0x02), + (40, 198, 0x03), + (2, 228, 0x02), + (9, 228, 0x02), + (23, 228, 0x02), + (40, 228, 0x03), + (2, 232, 0x02), + (9, 232, 0x02), + (23, 232, 0x02), + (40, 232, 0x03), + (2, 233, 0x02), + (9, 233, 0x02), + (23, 233, 0x02), + (40, 233, 0x03), + ], + // 144 + [ + (3, 198, 0x02), + (6, 198, 0x02), + (10, 198, 0x02), + (15, 198, 0x02), + (24, 198, 0x02), + (31, 198, 0x02), + (41, 198, 0x02), + (56, 198, 0x03), + (3, 228, 0x02), + (6, 228, 0x02), + (10, 228, 0x02), + (15, 228, 0x02), + (24, 228, 0x02), + (31, 228, 0x02), + (41, 228, 0x02), + (56, 228, 0x03), + ], + // 145 + [ + (3, 232, 0x02), + (6, 232, 0x02), + (10, 232, 0x02), + (15, 232, 0x02), + (24, 232, 0x02), + (31, 232, 0x02), + (41, 232, 0x02), + (56, 232, 0x03), + (3, 233, 0x02), + (6, 233, 0x02), + (10, 233, 0x02), + (15, 233, 0x02), + (24, 233, 0x02), + (31, 233, 0x02), + (41, 233, 0x02), + (56, 233, 0x03), + ], + // 146 + [ + (1, 1, 0x02), + (22, 1, 0x03), + (1, 135, 0x02), + (22, 135, 0x03), + (1, 137, 0x02), + (22, 137, 0x03), + (1, 138, 0x02), + (22, 138, 0x03), + (1, 139, 0x02), + (22, 139, 0x03), + (1, 140, 0x02), + (22, 140, 0x03), + (1, 141, 0x02), + (22, 141, 0x03), + (1, 143, 0x02), + (22, 143, 0x03), + ], + // 147 + [ + (2, 1, 0x02), + (9, 1, 0x02), + (23, 1, 0x02), + (40, 1, 0x03), + (2, 135, 0x02), + (9, 135, 0x02), + (23, 135, 0x02), + (40, 135, 0x03), + (2, 137, 0x02), + (9, 137, 0x02), + (23, 137, 0x02), + (40, 137, 0x03), + (2, 138, 0x02), + (9, 138, 0x02), + (23, 138, 0x02), + (40, 138, 0x03), + ], + // 148 + [ + (3, 1, 0x02), + (6, 1, 0x02), + (10, 1, 0x02), + (15, 1, 0x02), + (24, 1, 0x02), + (31, 1, 0x02), + (41, 1, 0x02), + (56, 1, 0x03), + (3, 135, 0x02), + (6, 135, 0x02), + (10, 135, 0x02), + (15, 135, 0x02), + (24, 135, 0x02), + (31, 135, 0x02), + (41, 135, 0x02), + (56, 135, 0x03), + ], + // 149 + [ + (3, 137, 0x02), + (6, 137, 0x02), + (10, 137, 0x02), + (15, 137, 0x02), + (24, 137, 0x02), + (31, 137, 0x02), + (41, 137, 0x02), + (56, 137, 0x03), + (3, 138, 0x02), + (6, 138, 0x02), + (10, 138, 0x02), + (15, 138, 0x02), + (24, 138, 0x02), + (31, 138, 0x02), + (41, 138, 0x02), + (56, 138, 0x03), + ], + // 150 + [ + (2, 139, 0x02), + (9, 139, 0x02), + (23, 139, 0x02), + (40, 139, 0x03), + (2, 140, 0x02), + (9, 140, 0x02), + (23, 140, 0x02), + (40, 140, 0x03), + (2, 141, 0x02), + (9, 141, 0x02), + (23, 141, 0x02), + (40, 141, 0x03), + (2, 143, 0x02), + (9, 143, 0x02), + (23, 143, 0x02), + (40, 143, 0x03), + ], + // 151 + [ + (3, 139, 0x02), + (6, 139, 0x02), + (10, 139, 0x02), + (15, 139, 0x02), + (24, 139, 0x02), + (31, 139, 0x02), + (41, 139, 0x02), + (56, 139, 0x03), + (3, 140, 0x02), + (6, 140, 0x02), + (10, 140, 0x02), + (15, 140, 0x02), + (24, 140, 0x02), + (31, 140, 0x02), + (41, 140, 0x02), + (56, 140, 0x03), + ], + // 152 + [ + (3, 141, 0x02), + (6, 141, 0x02), + (10, 141, 0x02), + (15, 141, 0x02), + (24, 141, 0x02), + (31, 141, 0x02), + (41, 141, 0x02), + (56, 141, 0x03), + (3, 143, 0x02), + (6, 143, 0x02), + (10, 143, 0x02), + (15, 143, 0x02), + (24, 143, 0x02), + (31, 143, 0x02), + (41, 143, 0x02), + (56, 143, 0x03), + ], + // 153 + [ + (157, 0, 0x00), + (158, 0, 0x00), + (160, 0, 0x00), + (161, 0, 0x00), + (164, 0, 0x00), + (165, 0, 0x00), + (167, 0, 0x00), + (168, 0, 0x00), + (172, 0, 0x00), + (173, 0, 0x00), + (175, 0, 0x00), + (177, 0, 0x00), + (182, 0, 0x00), + (185, 0, 0x00), + (191, 0, 0x00), + (207, 0, 0x00), + ], + // 154 + [ + (0, 147, 0x02), + (0, 149, 0x02), + (0, 150, 0x02), + (0, 151, 0x02), + (0, 152, 0x02), + (0, 155, 0x02), + (0, 157, 0x02), + (0, 158, 0x02), + (0, 165, 0x02), + (0, 166, 0x02), + (0, 168, 0x02), + (0, 174, 0x02), + (0, 175, 0x02), + (0, 180, 0x02), + (0, 182, 0x02), + (0, 183, 0x02), + ], + // 155 + [ + (1, 147, 0x02), + (22, 147, 0x03), + (1, 149, 0x02), + (22, 149, 0x03), + (1, 150, 0x02), + (22, 150, 0x03), + (1, 151, 0x02), + (22, 151, 0x03), + (1, 152, 0x02), + (22, 152, 0x03), + (1, 155, 0x02), + (22, 155, 0x03), + (1, 157, 0x02), + (22, 157, 0x03), + (1, 158, 0x02), + (22, 158, 0x03), + ], + // 156 + [ + (2, 147, 0x02), + (9, 147, 0x02), + (23, 147, 0x02), + (40, 147, 0x03), + (2, 149, 0x02), + (9, 149, 0x02), + (23, 149, 0x02), + (40, 149, 0x03), + (2, 150, 0x02), + (9, 150, 0x02), + (23, 150, 0x02), + (40, 150, 0x03), + (2, 151, 0x02), + (9, 151, 0x02), + (23, 151, 0x02), + (40, 151, 0x03), + ], + // 157 + [ + (3, 147, 0x02), + (6, 147, 0x02), + (10, 147, 0x02), + (15, 147, 0x02), + (24, 147, 0x02), + (31, 147, 0x02), + (41, 147, 0x02), + (56, 147, 0x03), + (3, 149, 0x02), + (6, 149, 0x02), + (10, 149, 0x02), + (15, 149, 0x02), + (24, 149, 0x02), + (31, 149, 0x02), + (41, 149, 0x02), + (56, 149, 0x03), + ], + // 158 + [ + (3, 150, 0x02), + (6, 150, 0x02), + (10, 150, 0x02), + (15, 150, 0x02), + (24, 150, 0x02), + (31, 150, 0x02), + (41, 150, 0x02), + (56, 150, 0x03), + (3, 151, 0x02), + (6, 151, 0x02), + (10, 151, 0x02), + (15, 151, 0x02), + (24, 151, 0x02), + (31, 151, 0x02), + (41, 151, 0x02), + (56, 151, 0x03), + ], + // 159 + [ + (2, 152, 0x02), + (9, 152, 0x02), + (23, 152, 0x02), + (40, 152, 0x03), + (2, 155, 0x02), + (9, 155, 0x02), + (23, 155, 0x02), + (40, 155, 0x03), + (2, 157, 0x02), + (9, 157, 0x02), + (23, 157, 0x02), + (40, 157, 0x03), + (2, 158, 0x02), + (9, 158, 0x02), + (23, 158, 0x02), + (40, 158, 0x03), + ], + // 160 + [ + (3, 152, 0x02), + (6, 152, 0x02), + (10, 152, 0x02), + (15, 152, 0x02), + (24, 152, 0x02), + (31, 152, 0x02), + (41, 152, 0x02), + (56, 152, 0x03), + (3, 155, 0x02), + (6, 155, 0x02), + (10, 155, 0x02), + (15, 155, 0x02), + (24, 155, 0x02), + (31, 155, 0x02), + (41, 155, 0x02), + (56, 155, 0x03), + ], + // 161 + [ + (3, 157, 0x02), + (6, 157, 0x02), + (10, 157, 0x02), + (15, 157, 0x02), + (24, 157, 0x02), + (31, 157, 0x02), + (41, 157, 0x02), + (56, 157, 0x03), + (3, 158, 0x02), + (6, 158, 0x02), + (10, 158, 0x02), + (15, 158, 0x02), + (24, 158, 0x02), + (31, 158, 0x02), + (41, 158, 0x02), + (56, 158, 0x03), + ], + // 162 + [ + (1, 165, 0x02), + (22, 165, 0x03), + (1, 166, 0x02), + (22, 166, 0x03), + (1, 168, 0x02), + (22, 168, 0x03), + (1, 174, 0x02), + (22, 174, 0x03), + (1, 175, 0x02), + (22, 175, 0x03), + (1, 180, 0x02), + (22, 180, 0x03), + (1, 182, 0x02), + (22, 182, 0x03), + (1, 183, 0x02), + (22, 183, 0x03), + ], + // 163 + [ + (2, 165, 0x02), + (9, 165, 0x02), + (23, 165, 0x02), + (40, 165, 0x03), + (2, 166, 0x02), + (9, 166, 0x02), + (23, 166, 0x02), + (40, 166, 0x03), + (2, 168, 0x02), + (9, 168, 0x02), + (23, 168, 0x02), + (40, 168, 0x03), + (2, 174, 0x02), + (9, 174, 0x02), + (23, 174, 0x02), + (40, 174, 0x03), + ], + // 164 + [ + (3, 165, 0x02), + (6, 165, 0x02), + (10, 165, 0x02), + (15, 165, 0x02), + (24, 165, 0x02), + (31, 165, 0x02), + (41, 165, 0x02), + (56, 165, 0x03), + (3, 166, 0x02), + (6, 166, 0x02), + (10, 166, 0x02), + (15, 166, 0x02), + (24, 166, 0x02), + (31, 166, 0x02), + (41, 166, 0x02), + (56, 166, 0x03), + ], + // 165 + [ + (3, 168, 0x02), + (6, 168, 0x02), + (10, 168, 0x02), + (15, 168, 0x02), + (24, 168, 0x02), + (31, 168, 0x02), + (41, 168, 0x02), + (56, 168, 0x03), + (3, 174, 0x02), + (6, 174, 0x02), + (10, 174, 0x02), + (15, 174, 0x02), + (24, 174, 0x02), + (31, 174, 0x02), + (41, 174, 0x02), + (56, 174, 0x03), + ], + // 166 + [ + (2, 175, 0x02), + (9, 175, 0x02), + (23, 175, 0x02), + (40, 175, 0x03), + (2, 180, 0x02), + (9, 180, 0x02), + (23, 180, 0x02), + (40, 180, 0x03), + (2, 182, 0x02), + (9, 182, 0x02), + (23, 182, 0x02), + (40, 182, 0x03), + (2, 183, 0x02), + (9, 183, 0x02), + (23, 183, 0x02), + (40, 183, 0x03), + ], + // 167 + [ + (3, 175, 0x02), + (6, 175, 0x02), + (10, 175, 0x02), + (15, 175, 0x02), + (24, 175, 0x02), + (31, 175, 0x02), + (41, 175, 0x02), + (56, 175, 0x03), + (3, 180, 0x02), + (6, 180, 0x02), + (10, 180, 0x02), + (15, 180, 0x02), + (24, 180, 0x02), + (31, 180, 0x02), + (41, 180, 0x02), + (56, 180, 0x03), + ], + // 168 + [ + (3, 182, 0x02), + (6, 182, 0x02), + (10, 182, 0x02), + (15, 182, 0x02), + (24, 182, 0x02), + (31, 182, 0x02), + (41, 182, 0x02), + (56, 182, 0x03), + (3, 183, 0x02), + (6, 183, 0x02), + (10, 183, 0x02), + (15, 183, 0x02), + (24, 183, 0x02), + (31, 183, 0x02), + (41, 183, 0x02), + (56, 183, 0x03), + ], + // 169 + [ + (0, 188, 0x02), + (0, 191, 0x02), + (0, 197, 0x02), + (0, 231, 0x02), + (0, 239, 0x02), + (176, 0, 0x00), + (178, 0, 0x00), + (179, 0, 0x00), + (183, 0, 0x00), + (184, 0, 0x00), + (186, 0, 0x00), + (187, 0, 0x00), + (192, 0, 0x00), + (199, 0, 0x00), + (208, 0, 0x00), + (223, 0, 0x00), + ], + // 170 + [ + (1, 188, 0x02), + (22, 188, 0x03), + (1, 191, 0x02), + (22, 191, 0x03), + (1, 197, 0x02), + (22, 197, 0x03), + (1, 231, 0x02), + (22, 231, 0x03), + (1, 239, 0x02), + (22, 239, 0x03), + (0, 9, 0x02), + (0, 142, 0x02), + (0, 144, 0x02), + (0, 145, 0x02), + (0, 148, 0x02), + (0, 159, 0x02), + ], + // 171 + [ + (2, 188, 0x02), + (9, 188, 0x02), + (23, 188, 0x02), + (40, 188, 0x03), + (2, 191, 0x02), + (9, 191, 0x02), + (23, 191, 0x02), + (40, 191, 0x03), + (2, 197, 0x02), + (9, 197, 0x02), + (23, 197, 0x02), + (40, 197, 0x03), + (2, 231, 0x02), + (9, 231, 0x02), + (23, 231, 0x02), + (40, 231, 0x03), + ], + // 172 + [ + (3, 188, 0x02), + (6, 188, 0x02), + (10, 188, 0x02), + (15, 188, 0x02), + (24, 188, 0x02), + (31, 188, 0x02), + (41, 188, 0x02), + (56, 188, 0x03), + (3, 191, 0x02), + (6, 191, 0x02), + (10, 191, 0x02), + (15, 191, 0x02), + (24, 191, 0x02), + (31, 191, 0x02), + (41, 191, 0x02), + (56, 191, 0x03), + ], + // 173 + [ + (3, 197, 0x02), + (6, 197, 0x02), + (10, 197, 0x02), + (15, 197, 0x02), + (24, 197, 0x02), + (31, 197, 0x02), + (41, 197, 0x02), + (56, 197, 0x03), + (3, 231, 0x02), + (6, 231, 0x02), + (10, 231, 0x02), + (15, 231, 0x02), + (24, 231, 0x02), + (31, 231, 0x02), + (41, 231, 0x02), + (56, 231, 0x03), + ], + // 174 + [ + (2, 239, 0x02), + (9, 239, 0x02), + (23, 239, 0x02), + (40, 239, 0x03), + (1, 9, 0x02), + (22, 9, 0x03), + (1, 142, 0x02), + (22, 142, 0x03), + (1, 144, 0x02), + (22, 144, 0x03), + (1, 145, 0x02), + (22, 145, 0x03), + (1, 148, 0x02), + (22, 148, 0x03), + (1, 159, 0x02), + (22, 159, 0x03), + ], + // 175 + [ + (3, 239, 0x02), + (6, 239, 0x02), + (10, 239, 0x02), + (15, 239, 0x02), + (24, 239, 0x02), + (31, 239, 0x02), + (41, 239, 0x02), + (56, 239, 0x03), + (2, 9, 0x02), + (9, 9, 0x02), + (23, 9, 0x02), + (40, 9, 0x03), + (2, 142, 0x02), + (9, 142, 0x02), + (23, 142, 0x02), + (40, 142, 0x03), + ], + // 176 + [ + (3, 9, 0x02), + (6, 9, 0x02), + (10, 9, 0x02), + (15, 9, 0x02), + (24, 9, 0x02), + (31, 9, 0x02), + (41, 9, 0x02), + (56, 9, 0x03), + (3, 142, 0x02), + (6, 142, 0x02), + (10, 142, 0x02), + (15, 142, 0x02), + (24, 142, 0x02), + (31, 142, 0x02), + (41, 142, 0x02), + (56, 142, 0x03), + ], + // 177 + [ + (2, 144, 0x02), + (9, 144, 0x02), + (23, 144, 0x02), + (40, 144, 0x03), + (2, 145, 0x02), + (9, 145, 0x02), + (23, 145, 0x02), + (40, 145, 0x03), + (2, 148, 0x02), + (9, 148, 0x02), + (23, 148, 0x02), + (40, 148, 0x03), + (2, 159, 0x02), + (9, 159, 0x02), + (23, 159, 0x02), + (40, 159, 0x03), + ], + // 178 + [ + (3, 144, 0x02), + (6, 144, 0x02), + (10, 144, 0x02), + (15, 144, 0x02), + (24, 144, 0x02), + (31, 144, 0x02), + (41, 144, 0x02), + (56, 144, 0x03), + (3, 145, 0x02), + (6, 145, 0x02), + (10, 145, 0x02), + (15, 145, 0x02), + (24, 145, 0x02), + (31, 145, 0x02), + (41, 145, 0x02), + (56, 145, 0x03), + ], + // 179 + [ + (3, 148, 0x02), + (6, 148, 0x02), + (10, 148, 0x02), + (15, 148, 0x02), + (24, 148, 0x02), + (31, 148, 0x02), + (41, 148, 0x02), + (56, 148, 0x03), + (3, 159, 0x02), + (6, 159, 0x02), + (10, 159, 0x02), + (15, 159, 0x02), + (24, 159, 0x02), + (31, 159, 0x02), + (41, 159, 0x02), + (56, 159, 0x03), + ], + // 180 + [ + (0, 171, 0x02), + (0, 206, 0x02), + (0, 215, 0x02), + (0, 225, 0x02), + (0, 236, 0x02), + (0, 237, 0x02), + (188, 0, 0x00), + (189, 0, 0x00), + (193, 0, 0x00), + (196, 0, 0x00), + (200, 0, 0x00), + (203, 0, 0x00), + (209, 0, 0x00), + (216, 0, 0x00), + (224, 0, 0x00), + (238, 0, 0x00), + ], + // 181 + [ + (1, 171, 0x02), + (22, 171, 0x03), + (1, 206, 0x02), + (22, 206, 0x03), + (1, 215, 0x02), + (22, 215, 0x03), + (1, 225, 0x02), + (22, 225, 0x03), + (1, 236, 0x02), + (22, 236, 0x03), + (1, 237, 0x02), + (22, 237, 0x03), + (0, 199, 0x02), + (0, 207, 0x02), + (0, 234, 0x02), + (0, 235, 0x02), + ], + // 182 + [ + (2, 171, 0x02), + (9, 171, 0x02), + (23, 171, 0x02), + (40, 171, 0x03), + (2, 206, 0x02), + (9, 206, 0x02), + (23, 206, 0x02), + (40, 206, 0x03), + (2, 215, 0x02), + (9, 215, 0x02), + (23, 215, 0x02), + (40, 215, 0x03), + (2, 225, 0x02), + (9, 225, 0x02), + (23, 225, 0x02), + (40, 225, 0x03), + ], + // 183 + [ + (3, 171, 0x02), + (6, 171, 0x02), + (10, 171, 0x02), + (15, 171, 0x02), + (24, 171, 0x02), + (31, 171, 0x02), + (41, 171, 0x02), + (56, 171, 0x03), + (3, 206, 0x02), + (6, 206, 0x02), + (10, 206, 0x02), + (15, 206, 0x02), + (24, 206, 0x02), + (31, 206, 0x02), + (41, 206, 0x02), + (56, 206, 0x03), + ], + // 184 + [ + (3, 215, 0x02), + (6, 215, 0x02), + (10, 215, 0x02), + (15, 215, 0x02), + (24, 215, 0x02), + (31, 215, 0x02), + (41, 215, 0x02), + (56, 215, 0x03), + (3, 225, 0x02), + (6, 225, 0x02), + (10, 225, 0x02), + (15, 225, 0x02), + (24, 225, 0x02), + (31, 225, 0x02), + (41, 225, 0x02), + (56, 225, 0x03), + ], + // 185 + [ + (2, 236, 0x02), + (9, 236, 0x02), + (23, 236, 0x02), + (40, 236, 0x03), + (2, 237, 0x02), + (9, 237, 0x02), + (23, 237, 0x02), + (40, 237, 0x03), + (1, 199, 0x02), + (22, 199, 0x03), + (1, 207, 0x02), + (22, 207, 0x03), + (1, 234, 0x02), + (22, 234, 0x03), + (1, 235, 0x02), + (22, 235, 0x03), + ], + // 186 + [ + (3, 236, 0x02), + (6, 236, 0x02), + (10, 236, 0x02), + (15, 236, 0x02), + (24, 236, 0x02), + (31, 236, 0x02), + (41, 236, 0x02), + (56, 236, 0x03), + (3, 237, 0x02), + (6, 237, 0x02), + (10, 237, 0x02), + (15, 237, 0x02), + (24, 237, 0x02), + (31, 237, 0x02), + (41, 237, 0x02), + (56, 237, 0x03), + ], + // 187 + [ + (2, 199, 0x02), + (9, 199, 0x02), + (23, 199, 0x02), + (40, 199, 0x03), + (2, 207, 0x02), + (9, 207, 0x02), + (23, 207, 0x02), + (40, 207, 0x03), + (2, 234, 0x02), + (9, 234, 0x02), + (23, 234, 0x02), + (40, 234, 0x03), + (2, 235, 0x02), + (9, 235, 0x02), + (23, 235, 0x02), + (40, 235, 0x03), + ], + // 188 + [ + (3, 199, 0x02), + (6, 199, 0x02), + (10, 199, 0x02), + (15, 199, 0x02), + (24, 199, 0x02), + (31, 199, 0x02), + (41, 199, 0x02), + (56, 199, 0x03), + (3, 207, 0x02), + (6, 207, 0x02), + (10, 207, 0x02), + (15, 207, 0x02), + (24, 207, 0x02), + (31, 207, 0x02), + (41, 207, 0x02), + (56, 207, 0x03), + ], + // 189 + [ + (3, 234, 0x02), + (6, 234, 0x02), + (10, 234, 0x02), + (15, 234, 0x02), + (24, 234, 0x02), + (31, 234, 0x02), + (41, 234, 0x02), + (56, 234, 0x03), + (3, 235, 0x02), + (6, 235, 0x02), + (10, 235, 0x02), + (15, 235, 0x02), + (24, 235, 0x02), + (31, 235, 0x02), + (41, 235, 0x02), + (56, 235, 0x03), + ], + // 190 + [ + (194, 0, 0x00), + (195, 0, 0x00), + (197, 0, 0x00), + (198, 0, 0x00), + (201, 0, 0x00), + (202, 0, 0x00), + (204, 0, 0x00), + (205, 0, 0x00), + (210, 0, 0x00), + (213, 0, 0x00), + (217, 0, 0x00), + (220, 0, 0x00), + (225, 0, 0x00), + (231, 0, 0x00), + (239, 0, 0x00), + (246, 0, 0x00), + ], + // 191 + [ + (0, 192, 0x02), + (0, 193, 0x02), + (0, 200, 0x02), + (0, 201, 0x02), + (0, 202, 0x02), + (0, 205, 0x02), + (0, 210, 0x02), + (0, 213, 0x02), + (0, 218, 0x02), + (0, 219, 0x02), + (0, 238, 0x02), + (0, 240, 0x02), + (0, 242, 0x02), + (0, 243, 0x02), + (0, 255, 0x02), + (206, 0, 0x00), + ], + // 192 + [ + (1, 192, 0x02), + (22, 192, 0x03), + (1, 193, 0x02), + (22, 193, 0x03), + (1, 200, 0x02), + (22, 200, 0x03), + (1, 201, 0x02), + (22, 201, 0x03), + (1, 202, 0x02), + (22, 202, 0x03), + (1, 205, 0x02), + (22, 205, 0x03), + (1, 210, 0x02), + (22, 210, 0x03), + (1, 213, 0x02), + (22, 213, 0x03), + ], + // 193 + [ + (2, 192, 0x02), + (9, 192, 0x02), + (23, 192, 0x02), + (40, 192, 0x03), + (2, 193, 0x02), + (9, 193, 0x02), + (23, 193, 0x02), + (40, 193, 0x03), + (2, 200, 0x02), + (9, 200, 0x02), + (23, 200, 0x02), + (40, 200, 0x03), + (2, 201, 0x02), + (9, 201, 0x02), + (23, 201, 0x02), + (40, 201, 0x03), + ], + // 194 + [ + (3, 192, 0x02), + (6, 192, 0x02), + (10, 192, 0x02), + (15, 192, 0x02), + (24, 192, 0x02), + (31, 192, 0x02), + (41, 192, 0x02), + (56, 192, 0x03), + (3, 193, 0x02), + (6, 193, 0x02), + (10, 193, 0x02), + (15, 193, 0x02), + (24, 193, 0x02), + (31, 193, 0x02), + (41, 193, 0x02), + (56, 193, 0x03), + ], + // 195 + [ + (3, 200, 0x02), + (6, 200, 0x02), + (10, 200, 0x02), + (15, 200, 0x02), + (24, 200, 0x02), + (31, 200, 0x02), + (41, 200, 0x02), + (56, 200, 0x03), + (3, 201, 0x02), + (6, 201, 0x02), + (10, 201, 0x02), + (15, 201, 0x02), + (24, 201, 0x02), + (31, 201, 0x02), + (41, 201, 0x02), + (56, 201, 0x03), + ], + // 196 + [ + (2, 202, 0x02), + (9, 202, 0x02), + (23, 202, 0x02), + (40, 202, 0x03), + (2, 205, 0x02), + (9, 205, 0x02), + (23, 205, 0x02), + (40, 205, 0x03), + (2, 210, 0x02), + (9, 210, 0x02), + (23, 210, 0x02), + (40, 210, 0x03), + (2, 213, 0x02), + (9, 213, 0x02), + (23, 213, 0x02), + (40, 213, 0x03), + ], + // 197 + [ + (3, 202, 0x02), + (6, 202, 0x02), + (10, 202, 0x02), + (15, 202, 0x02), + (24, 202, 0x02), + (31, 202, 0x02), + (41, 202, 0x02), + (56, 202, 0x03), + (3, 205, 0x02), + (6, 205, 0x02), + (10, 205, 0x02), + (15, 205, 0x02), + (24, 205, 0x02), + (31, 205, 0x02), + (41, 205, 0x02), + (56, 205, 0x03), + ], + // 198 + [ + (3, 210, 0x02), + (6, 210, 0x02), + (10, 210, 0x02), + (15, 210, 0x02), + (24, 210, 0x02), + (31, 210, 0x02), + (41, 210, 0x02), + (56, 210, 0x03), + (3, 213, 0x02), + (6, 213, 0x02), + (10, 213, 0x02), + (15, 213, 0x02), + (24, 213, 0x02), + (31, 213, 0x02), + (41, 213, 0x02), + (56, 213, 0x03), + ], + // 199 + [ + (1, 218, 0x02), + (22, 218, 0x03), + (1, 219, 0x02), + (22, 219, 0x03), + (1, 238, 0x02), + (22, 238, 0x03), + (1, 240, 0x02), + (22, 240, 0x03), + (1, 242, 0x02), + (22, 242, 0x03), + (1, 243, 0x02), + (22, 243, 0x03), + (1, 255, 0x02), + (22, 255, 0x03), + (0, 203, 0x02), + (0, 204, 0x02), + ], + // 200 + [ + (2, 218, 0x02), + (9, 218, 0x02), + (23, 218, 0x02), + (40, 218, 0x03), + (2, 219, 0x02), + (9, 219, 0x02), + (23, 219, 0x02), + (40, 219, 0x03), + (2, 238, 0x02), + (9, 238, 0x02), + (23, 238, 0x02), + (40, 238, 0x03), + (2, 240, 0x02), + (9, 240, 0x02), + (23, 240, 0x02), + (40, 240, 0x03), + ], + // 201 + [ + (3, 218, 0x02), + (6, 218, 0x02), + (10, 218, 0x02), + (15, 218, 0x02), + (24, 218, 0x02), + (31, 218, 0x02), + (41, 218, 0x02), + (56, 218, 0x03), + (3, 219, 0x02), + (6, 219, 0x02), + (10, 219, 0x02), + (15, 219, 0x02), + (24, 219, 0x02), + (31, 219, 0x02), + (41, 219, 0x02), + (56, 219, 0x03), + ], + // 202 + [ + (3, 238, 0x02), + (6, 238, 0x02), + (10, 238, 0x02), + (15, 238, 0x02), + (24, 238, 0x02), + (31, 238, 0x02), + (41, 238, 0x02), + (56, 238, 0x03), + (3, 240, 0x02), + (6, 240, 0x02), + (10, 240, 0x02), + (15, 240, 0x02), + (24, 240, 0x02), + (31, 240, 0x02), + (41, 240, 0x02), + (56, 240, 0x03), + ], + // 203 + [ + (2, 242, 0x02), + (9, 242, 0x02), + (23, 242, 0x02), + (40, 242, 0x03), + (2, 243, 0x02), + (9, 243, 0x02), + (23, 243, 0x02), + (40, 243, 0x03), + (2, 255, 0x02), + (9, 255, 0x02), + (23, 255, 0x02), + (40, 255, 0x03), + (1, 203, 0x02), + (22, 203, 0x03), + (1, 204, 0x02), + (22, 204, 0x03), + ], + // 204 + [ + (3, 242, 0x02), + (6, 242, 0x02), + (10, 242, 0x02), + (15, 242, 0x02), + (24, 242, 0x02), + (31, 242, 0x02), + (41, 242, 0x02), + (56, 242, 0x03), + (3, 243, 0x02), + (6, 243, 0x02), + (10, 243, 0x02), + (15, 243, 0x02), + (24, 243, 0x02), + (31, 243, 0x02), + (41, 243, 0x02), + (56, 243, 0x03), + ], + // 205 + [ + (3, 255, 0x02), + (6, 255, 0x02), + (10, 255, 0x02), + (15, 255, 0x02), + (24, 255, 0x02), + (31, 255, 0x02), + (41, 255, 0x02), + (56, 255, 0x03), + (2, 203, 0x02), + (9, 203, 0x02), + (23, 203, 0x02), + (40, 203, 0x03), + (2, 204, 0x02), + (9, 204, 0x02), + (23, 204, 0x02), + (40, 204, 0x03), + ], + // 206 + [ + (3, 203, 0x02), + (6, 203, 0x02), + (10, 203, 0x02), + (15, 203, 0x02), + (24, 203, 0x02), + (31, 203, 0x02), + (41, 203, 0x02), + (56, 203, 0x03), + (3, 204, 0x02), + (6, 204, 0x02), + (10, 204, 0x02), + (15, 204, 0x02), + (24, 204, 0x02), + (31, 204, 0x02), + (41, 204, 0x02), + (56, 204, 0x03), + ], + // 207 + [ + (211, 0, 0x00), + (212, 0, 0x00), + (214, 0, 0x00), + (215, 0, 0x00), + (218, 0, 0x00), + (219, 0, 0x00), + (221, 0, 0x00), + (222, 0, 0x00), + (226, 0, 0x00), + (228, 0, 0x00), + (232, 0, 0x00), + (235, 0, 0x00), + (240, 0, 0x00), + (243, 0, 0x00), + (247, 0, 0x00), + (250, 0, 0x00), + ], + // 208 + [ + (0, 211, 0x02), + (0, 212, 0x02), + (0, 214, 0x02), + (0, 221, 0x02), + (0, 222, 0x02), + (0, 223, 0x02), + (0, 241, 0x02), + (0, 244, 0x02), + (0, 245, 0x02), + (0, 246, 0x02), + (0, 247, 0x02), + (0, 248, 0x02), + (0, 250, 0x02), + (0, 251, 0x02), + (0, 252, 0x02), + (0, 253, 0x02), + ], + // 209 + [ + (1, 211, 0x02), + (22, 211, 0x03), + (1, 212, 0x02), + (22, 212, 0x03), + (1, 214, 0x02), + (22, 214, 0x03), + (1, 221, 0x02), + (22, 221, 0x03), + (1, 222, 0x02), + (22, 222, 0x03), + (1, 223, 0x02), + (22, 223, 0x03), + (1, 241, 0x02), + (22, 241, 0x03), + (1, 244, 0x02), + (22, 244, 0x03), + ], + // 210 + [ + (2, 211, 0x02), + (9, 211, 0x02), + (23, 211, 0x02), + (40, 211, 0x03), + (2, 212, 0x02), + (9, 212, 0x02), + (23, 212, 0x02), + (40, 212, 0x03), + (2, 214, 0x02), + (9, 214, 0x02), + (23, 214, 0x02), + (40, 214, 0x03), + (2, 221, 0x02), + (9, 221, 0x02), + (23, 221, 0x02), + (40, 221, 0x03), + ], + // 211 + [ + (3, 211, 0x02), + (6, 211, 0x02), + (10, 211, 0x02), + (15, 211, 0x02), + (24, 211, 0x02), + (31, 211, 0x02), + (41, 211, 0x02), + (56, 211, 0x03), + (3, 212, 0x02), + (6, 212, 0x02), + (10, 212, 0x02), + (15, 212, 0x02), + (24, 212, 0x02), + (31, 212, 0x02), + (41, 212, 0x02), + (56, 212, 0x03), + ], + // 212 + [ + (3, 214, 0x02), + (6, 214, 0x02), + (10, 214, 0x02), + (15, 214, 0x02), + (24, 214, 0x02), + (31, 214, 0x02), + (41, 214, 0x02), + (56, 214, 0x03), + (3, 221, 0x02), + (6, 221, 0x02), + (10, 221, 0x02), + (15, 221, 0x02), + (24, 221, 0x02), + (31, 221, 0x02), + (41, 221, 0x02), + (56, 221, 0x03), + ], + // 213 + [ + (2, 222, 0x02), + (9, 222, 0x02), + (23, 222, 0x02), + (40, 222, 0x03), + (2, 223, 0x02), + (9, 223, 0x02), + (23, 223, 0x02), + (40, 223, 0x03), + (2, 241, 0x02), + (9, 241, 0x02), + (23, 241, 0x02), + (40, 241, 0x03), + (2, 244, 0x02), + (9, 244, 0x02), + (23, 244, 0x02), + (40, 244, 0x03), + ], + // 214 + [ + (3, 222, 0x02), + (6, 222, 0x02), + (10, 222, 0x02), + (15, 222, 0x02), + (24, 222, 0x02), + (31, 222, 0x02), + (41, 222, 0x02), + (56, 222, 0x03), + (3, 223, 0x02), + (6, 223, 0x02), + (10, 223, 0x02), + (15, 223, 0x02), + (24, 223, 0x02), + (31, 223, 0x02), + (41, 223, 0x02), + (56, 223, 0x03), + ], + // 215 + [ + (3, 241, 0x02), + (6, 241, 0x02), + (10, 241, 0x02), + (15, 241, 0x02), + (24, 241, 0x02), + (31, 241, 0x02), + (41, 241, 0x02), + (56, 241, 0x03), + (3, 244, 0x02), + (6, 244, 0x02), + (10, 244, 0x02), + (15, 244, 0x02), + (24, 244, 0x02), + (31, 244, 0x02), + (41, 244, 0x02), + (56, 244, 0x03), + ], + // 216 + [ + (1, 245, 0x02), + (22, 245, 0x03), + (1, 246, 0x02), + (22, 246, 0x03), + (1, 247, 0x02), + (22, 247, 0x03), + (1, 248, 0x02), + (22, 248, 0x03), + (1, 250, 0x02), + (22, 250, 0x03), + (1, 251, 0x02), + (22, 251, 0x03), + (1, 252, 0x02), + (22, 252, 0x03), + (1, 253, 0x02), + (22, 253, 0x03), + ], + // 217 + [ + (2, 245, 0x02), + (9, 245, 0x02), + (23, 245, 0x02), + (40, 245, 0x03), + (2, 246, 0x02), + (9, 246, 0x02), + (23, 246, 0x02), + (40, 246, 0x03), + (2, 247, 0x02), + (9, 247, 0x02), + (23, 247, 0x02), + (40, 247, 0x03), + (2, 248, 0x02), + (9, 248, 0x02), + (23, 248, 0x02), + (40, 248, 0x03), + ], + // 218 + [ + (3, 245, 0x02), + (6, 245, 0x02), + (10, 245, 0x02), + (15, 245, 0x02), + (24, 245, 0x02), + (31, 245, 0x02), + (41, 245, 0x02), + (56, 245, 0x03), + (3, 246, 0x02), + (6, 246, 0x02), + (10, 246, 0x02), + (15, 246, 0x02), + (24, 246, 0x02), + (31, 246, 0x02), + (41, 246, 0x02), + (56, 246, 0x03), + ], + // 219 + [ + (3, 247, 0x02), + (6, 247, 0x02), + (10, 247, 0x02), + (15, 247, 0x02), + (24, 247, 0x02), + (31, 247, 0x02), + (41, 247, 0x02), + (56, 247, 0x03), + (3, 248, 0x02), + (6, 248, 0x02), + (10, 248, 0x02), + (15, 248, 0x02), + (24, 248, 0x02), + (31, 248, 0x02), + (41, 248, 0x02), + (56, 248, 0x03), + ], + // 220 + [ + (2, 250, 0x02), + (9, 250, 0x02), + (23, 250, 0x02), + (40, 250, 0x03), + (2, 251, 0x02), + (9, 251, 0x02), + (23, 251, 0x02), + (40, 251, 0x03), + (2, 252, 0x02), + (9, 252, 0x02), + (23, 252, 0x02), + (40, 252, 0x03), + (2, 253, 0x02), + (9, 253, 0x02), + (23, 253, 0x02), + (40, 253, 0x03), + ], + // 221 + [ + (3, 250, 0x02), + (6, 250, 0x02), + (10, 250, 0x02), + (15, 250, 0x02), + (24, 250, 0x02), + (31, 250, 0x02), + (41, 250, 0x02), + (56, 250, 0x03), + (3, 251, 0x02), + (6, 251, 0x02), + (10, 251, 0x02), + (15, 251, 0x02), + (24, 251, 0x02), + (31, 251, 0x02), + (41, 251, 0x02), + (56, 251, 0x03), + ], + // 222 + [ + (3, 252, 0x02), + (6, 252, 0x02), + (10, 252, 0x02), + (15, 252, 0x02), + (24, 252, 0x02), + (31, 252, 0x02), + (41, 252, 0x02), + (56, 252, 0x03), + (3, 253, 0x02), + (6, 253, 0x02), + (10, 253, 0x02), + (15, 253, 0x02), + (24, 253, 0x02), + (31, 253, 0x02), + (41, 253, 0x02), + (56, 253, 0x03), + ], + // 223 + [ + (0, 254, 0x02), + (227, 0, 0x00), + (229, 0, 0x00), + (230, 0, 0x00), + (233, 0, 0x00), + (234, 0, 0x00), + (236, 0, 0x00), + (237, 0, 0x00), + (241, 0, 0x00), + (242, 0, 0x00), + (244, 0, 0x00), + (245, 0, 0x00), + (248, 0, 0x00), + (249, 0, 0x00), + (251, 0, 0x00), + (252, 0, 0x00), + ], + // 224 + [ + (1, 254, 0x02), + (22, 254, 0x03), + (0, 2, 0x02), + (0, 3, 0x02), + (0, 4, 0x02), + (0, 5, 0x02), + (0, 6, 0x02), + (0, 7, 0x02), + (0, 8, 0x02), + (0, 11, 0x02), + (0, 12, 0x02), + (0, 14, 0x02), + (0, 15, 0x02), + (0, 16, 0x02), + (0, 17, 0x02), + (0, 18, 0x02), + ], + // 225 + [ + (2, 254, 0x02), + (9, 254, 0x02), + (23, 254, 0x02), + (40, 254, 0x03), + (1, 2, 0x02), + (22, 2, 0x03), + (1, 3, 0x02), + (22, 3, 0x03), + (1, 4, 0x02), + (22, 4, 0x03), + (1, 5, 0x02), + (22, 5, 0x03), + (1, 6, 0x02), + (22, 6, 0x03), + (1, 7, 0x02), + (22, 7, 0x03), + ], + // 226 + [ + (3, 254, 0x02), + (6, 254, 0x02), + (10, 254, 0x02), + (15, 254, 0x02), + (24, 254, 0x02), + (31, 254, 0x02), + (41, 254, 0x02), + (56, 254, 0x03), + (2, 2, 0x02), + (9, 2, 0x02), + (23, 2, 0x02), + (40, 2, 0x03), + (2, 3, 0x02), + (9, 3, 0x02), + (23, 3, 0x02), + (40, 3, 0x03), + ], + // 227 + [ + (3, 2, 0x02), + (6, 2, 0x02), + (10, 2, 0x02), + (15, 2, 0x02), + (24, 2, 0x02), + (31, 2, 0x02), + (41, 2, 0x02), + (56, 2, 0x03), + (3, 3, 0x02), + (6, 3, 0x02), + (10, 3, 0x02), + (15, 3, 0x02), + (24, 3, 0x02), + (31, 3, 0x02), + (41, 3, 0x02), + (56, 3, 0x03), + ], + // 228 + [ + (2, 4, 0x02), + (9, 4, 0x02), + (23, 4, 0x02), + (40, 4, 0x03), + (2, 5, 0x02), + (9, 5, 0x02), + (23, 5, 0x02), + (40, 5, 0x03), + (2, 6, 0x02), + (9, 6, 0x02), + (23, 6, 0x02), + (40, 6, 0x03), + (2, 7, 0x02), + (9, 7, 0x02), + (23, 7, 0x02), + (40, 7, 0x03), + ], + // 229 + [ + (3, 4, 0x02), + (6, 4, 0x02), + (10, 4, 0x02), + (15, 4, 0x02), + (24, 4, 0x02), + (31, 4, 0x02), + (41, 4, 0x02), + (56, 4, 0x03), + (3, 5, 0x02), + (6, 5, 0x02), + (10, 5, 0x02), + (15, 5, 0x02), + (24, 5, 0x02), + (31, 5, 0x02), + (41, 5, 0x02), + (56, 5, 0x03), + ], + // 230 + [ + (3, 6, 0x02), + (6, 6, 0x02), + (10, 6, 0x02), + (15, 6, 0x02), + (24, 6, 0x02), + (31, 6, 0x02), + (41, 6, 0x02), + (56, 6, 0x03), + (3, 7, 0x02), + (6, 7, 0x02), + (10, 7, 0x02), + (15, 7, 0x02), + (24, 7, 0x02), + (31, 7, 0x02), + (41, 7, 0x02), + (56, 7, 0x03), + ], + // 231 + [ + (1, 8, 0x02), + (22, 8, 0x03), + (1, 11, 0x02), + (22, 11, 0x03), + (1, 12, 0x02), + (22, 12, 0x03), + (1, 14, 0x02), + (22, 14, 0x03), + (1, 15, 0x02), + (22, 15, 0x03), + (1, 16, 0x02), + (22, 16, 0x03), + (1, 17, 0x02), + (22, 17, 0x03), + (1, 18, 0x02), + (22, 18, 0x03), + ], + // 232 + [ + (2, 8, 0x02), + (9, 8, 0x02), + (23, 8, 0x02), + (40, 8, 0x03), + (2, 11, 0x02), + (9, 11, 0x02), + (23, 11, 0x02), + (40, 11, 0x03), + (2, 12, 0x02), + (9, 12, 0x02), + (23, 12, 0x02), + (40, 12, 0x03), + (2, 14, 0x02), + (9, 14, 0x02), + (23, 14, 0x02), + (40, 14, 0x03), + ], + // 233 + [ + (3, 8, 0x02), + (6, 8, 0x02), + (10, 8, 0x02), + (15, 8, 0x02), + (24, 8, 0x02), + (31, 8, 0x02), + (41, 8, 0x02), + (56, 8, 0x03), + (3, 11, 0x02), + (6, 11, 0x02), + (10, 11, 0x02), + (15, 11, 0x02), + (24, 11, 0x02), + (31, 11, 0x02), + (41, 11, 0x02), + (56, 11, 0x03), + ], + // 234 + [ + (3, 12, 0x02), + (6, 12, 0x02), + (10, 12, 0x02), + (15, 12, 0x02), + (24, 12, 0x02), + (31, 12, 0x02), + (41, 12, 0x02), + (56, 12, 0x03), + (3, 14, 0x02), + (6, 14, 0x02), + (10, 14, 0x02), + (15, 14, 0x02), + (24, 14, 0x02), + (31, 14, 0x02), + (41, 14, 0x02), + (56, 14, 0x03), + ], + // 235 + [ + (2, 15, 0x02), + (9, 15, 0x02), + (23, 15, 0x02), + (40, 15, 0x03), + (2, 16, 0x02), + (9, 16, 0x02), + (23, 16, 0x02), + (40, 16, 0x03), + (2, 17, 0x02), + (9, 17, 0x02), + (23, 17, 0x02), + (40, 17, 0x03), + (2, 18, 0x02), + (9, 18, 0x02), + (23, 18, 0x02), + (40, 18, 0x03), + ], + // 236 + [ + (3, 15, 0x02), + (6, 15, 0x02), + (10, 15, 0x02), + (15, 15, 0x02), + (24, 15, 0x02), + (31, 15, 0x02), + (41, 15, 0x02), + (56, 15, 0x03), + (3, 16, 0x02), + (6, 16, 0x02), + (10, 16, 0x02), + (15, 16, 0x02), + (24, 16, 0x02), + (31, 16, 0x02), + (41, 16, 0x02), + (56, 16, 0x03), + ], + // 237 + [ + (3, 17, 0x02), + (6, 17, 0x02), + (10, 17, 0x02), + (15, 17, 0x02), + (24, 17, 0x02), + (31, 17, 0x02), + (41, 17, 0x02), + (56, 17, 0x03), + (3, 18, 0x02), + (6, 18, 0x02), + (10, 18, 0x02), + (15, 18, 0x02), + (24, 18, 0x02), + (31, 18, 0x02), + (41, 18, 0x02), + (56, 18, 0x03), + ], + // 238 + [ + (0, 19, 0x02), + (0, 20, 0x02), + (0, 21, 0x02), + (0, 23, 0x02), + (0, 24, 0x02), + (0, 25, 0x02), + (0, 26, 0x02), + (0, 27, 0x02), + (0, 28, 0x02), + (0, 29, 0x02), + (0, 30, 0x02), + (0, 31, 0x02), + (0, 127, 0x02), + (0, 220, 0x02), + (0, 249, 0x02), + (253, 0, 0x00), + ], + // 239 + [ + (1, 19, 0x02), + (22, 19, 0x03), + (1, 20, 0x02), + (22, 20, 0x03), + (1, 21, 0x02), + (22, 21, 0x03), + (1, 23, 0x02), + (22, 23, 0x03), + (1, 24, 0x02), + (22, 24, 0x03), + (1, 25, 0x02), + (22, 25, 0x03), + (1, 26, 0x02), + (22, 26, 0x03), + (1, 27, 0x02), + (22, 27, 0x03), + ], + // 240 + [ + (2, 19, 0x02), + (9, 19, 0x02), + (23, 19, 0x02), + (40, 19, 0x03), + (2, 20, 0x02), + (9, 20, 0x02), + (23, 20, 0x02), + (40, 20, 0x03), + (2, 21, 0x02), + (9, 21, 0x02), + (23, 21, 0x02), + (40, 21, 0x03), + (2, 23, 0x02), + (9, 23, 0x02), + (23, 23, 0x02), + (40, 23, 0x03), + ], + // 241 + [ + (3, 19, 0x02), + (6, 19, 0x02), + (10, 19, 0x02), + (15, 19, 0x02), + (24, 19, 0x02), + (31, 19, 0x02), + (41, 19, 0x02), + (56, 19, 0x03), + (3, 20, 0x02), + (6, 20, 0x02), + (10, 20, 0x02), + (15, 20, 0x02), + (24, 20, 0x02), + (31, 20, 0x02), + (41, 20, 0x02), + (56, 20, 0x03), + ], + // 242 + [ + (3, 21, 0x02), + (6, 21, 0x02), + (10, 21, 0x02), + (15, 21, 0x02), + (24, 21, 0x02), + (31, 21, 0x02), + (41, 21, 0x02), + (56, 21, 0x03), + (3, 23, 0x02), + (6, 23, 0x02), + (10, 23, 0x02), + (15, 23, 0x02), + (24, 23, 0x02), + (31, 23, 0x02), + (41, 23, 0x02), + (56, 23, 0x03), + ], + // 243 + [ + (2, 24, 0x02), + (9, 24, 0x02), + (23, 24, 0x02), + (40, 24, 0x03), + (2, 25, 0x02), + (9, 25, 0x02), + (23, 25, 0x02), + (40, 25, 0x03), + (2, 26, 0x02), + (9, 26, 0x02), + (23, 26, 0x02), + (40, 26, 0x03), + (2, 27, 0x02), + (9, 27, 0x02), + (23, 27, 0x02), + (40, 27, 0x03), + ], + // 244 + [ + (3, 24, 0x02), + (6, 24, 0x02), + (10, 24, 0x02), + (15, 24, 0x02), + (24, 24, 0x02), + (31, 24, 0x02), + (41, 24, 0x02), + (56, 24, 0x03), + (3, 25, 0x02), + (6, 25, 0x02), + (10, 25, 0x02), + (15, 25, 0x02), + (24, 25, 0x02), + (31, 25, 0x02), + (41, 25, 0x02), + (56, 25, 0x03), + ], + // 245 + [ + (3, 26, 0x02), + (6, 26, 0x02), + (10, 26, 0x02), + (15, 26, 0x02), + (24, 26, 0x02), + (31, 26, 0x02), + (41, 26, 0x02), + (56, 26, 0x03), + (3, 27, 0x02), + (6, 27, 0x02), + (10, 27, 0x02), + (15, 27, 0x02), + (24, 27, 0x02), + (31, 27, 0x02), + (41, 27, 0x02), + (56, 27, 0x03), + ], + // 246 + [ + (1, 28, 0x02), + (22, 28, 0x03), + (1, 29, 0x02), + (22, 29, 0x03), + (1, 30, 0x02), + (22, 30, 0x03), + (1, 31, 0x02), + (22, 31, 0x03), + (1, 127, 0x02), + (22, 127, 0x03), + (1, 220, 0x02), + (22, 220, 0x03), + (1, 249, 0x02), + (22, 249, 0x03), + (254, 0, 0x00), + (255, 0, 0x00), + ], + // 247 + [ + (2, 28, 0x02), + (9, 28, 0x02), + (23, 28, 0x02), + (40, 28, 0x03), + (2, 29, 0x02), + (9, 29, 0x02), + (23, 29, 0x02), + (40, 29, 0x03), + (2, 30, 0x02), + (9, 30, 0x02), + (23, 30, 0x02), + (40, 30, 0x03), + (2, 31, 0x02), + (9, 31, 0x02), + (23, 31, 0x02), + (40, 31, 0x03), + ], + // 248 + [ + (3, 28, 0x02), + (6, 28, 0x02), + (10, 28, 0x02), + (15, 28, 0x02), + (24, 28, 0x02), + (31, 28, 0x02), + (41, 28, 0x02), + (56, 28, 0x03), + (3, 29, 0x02), + (6, 29, 0x02), + (10, 29, 0x02), + (15, 29, 0x02), + (24, 29, 0x02), + (31, 29, 0x02), + (41, 29, 0x02), + (56, 29, 0x03), + ], + // 249 + [ + (3, 30, 0x02), + (6, 30, 0x02), + (10, 30, 0x02), + (15, 30, 0x02), + (24, 30, 0x02), + (31, 30, 0x02), + (41, 30, 0x02), + (56, 30, 0x03), + (3, 31, 0x02), + (6, 31, 0x02), + (10, 31, 0x02), + (15, 31, 0x02), + (24, 31, 0x02), + (31, 31, 0x02), + (41, 31, 0x02), + (56, 31, 0x03), + ], + // 250 + [ + (2, 127, 0x02), + (9, 127, 0x02), + (23, 127, 0x02), + (40, 127, 0x03), + (2, 220, 0x02), + (9, 220, 0x02), + (23, 220, 0x02), + (40, 220, 0x03), + (2, 249, 0x02), + (9, 249, 0x02), + (23, 249, 0x02), + (40, 249, 0x03), + (0, 10, 0x02), + (0, 13, 0x02), + (0, 22, 0x02), + (0, 0, 0x04), + ], + // 251 + [ + (3, 127, 0x02), + (6, 127, 0x02), + (10, 127, 0x02), + (15, 127, 0x02), + (24, 127, 0x02), + (31, 127, 0x02), + (41, 127, 0x02), + (56, 127, 0x03), + (3, 220, 0x02), + (6, 220, 0x02), + (10, 220, 0x02), + (15, 220, 0x02), + (24, 220, 0x02), + (31, 220, 0x02), + (41, 220, 0x02), + (56, 220, 0x03), + ], + // 252 + [ + (3, 249, 0x02), + (6, 249, 0x02), + (10, 249, 0x02), + (15, 249, 0x02), + (24, 249, 0x02), + (31, 249, 0x02), + (41, 249, 0x02), + (56, 249, 0x03), + (1, 10, 0x02), + (22, 10, 0x03), + (1, 13, 0x02), + (22, 13, 0x03), + (1, 22, 0x02), + (22, 22, 0x03), + (0, 0, 0x04), + (0, 0, 0x05), + ], + // 253 + [ + (2, 10, 0x02), + (9, 10, 0x02), + (23, 10, 0x02), + (40, 10, 0x03), + (2, 13, 0x02), + (9, 13, 0x02), + (23, 13, 0x02), + (40, 13, 0x03), + (2, 22, 0x02), + (9, 22, 0x02), + (23, 22, 0x02), + (40, 22, 0x03), + (0, 0, 0x04), + (0, 0, 0x04), + (0, 0, 0x04), + (0, 0, 0x05), + ], + // 254 + [ + (3, 10, 0x02), + (6, 10, 0x02), + (10, 10, 0x02), + (15, 10, 0x02), + (24, 10, 0x02), + (31, 10, 0x02), + (41, 10, 0x02), + (56, 10, 0x03), + (3, 13, 0x02), + (6, 13, 0x02), + (10, 13, 0x02), + (15, 13, 0x02), + (24, 13, 0x02), + (31, 13, 0x02), + (41, 13, 0x02), + (56, 13, 0x03), + ], + // 255 + [ + (3, 22, 0x02), + (6, 22, 0x02), + (10, 22, 0x02), + (15, 22, 0x02), + (24, 22, 0x02), + (31, 22, 0x02), + (41, 22, 0x02), + (56, 22, 0x03), + (0, 0, 0x04), + (0, 0, 0x04), + (0, 0, 0x04), + (0, 0, 0x04), + (0, 0, 0x04), + (0, 0, 0x04), + (0, 0, 0x04), + (0, 0, 0x05), + ], +]; diff --git a/third_party/rust/h2/src/hpack/mod.rs b/third_party/rust/h2/src/hpack/mod.rs new file mode 100644 index 0000000000..12c75d5535 --- /dev/null +++ b/third_party/rust/h2/src/hpack/mod.rs @@ -0,0 +1,12 @@ +mod decoder; +mod encoder; +pub(crate) mod header; +pub(crate) mod huffman; +mod table; + +#[cfg(test)] +mod test; + +pub use self::decoder::{Decoder, DecoderError, NeedMore}; +pub use self::encoder::Encoder; +pub use self::header::{BytesStr, Header}; diff --git a/third_party/rust/h2/src/hpack/table.rs b/third_party/rust/h2/src/hpack/table.rs new file mode 100644 index 0000000000..0124f216d5 --- /dev/null +++ b/third_party/rust/h2/src/hpack/table.rs @@ -0,0 +1,766 @@ +use super::Header; + +use fnv::FnvHasher; +use http::header; +use http::method::Method; + +use std::collections::VecDeque; +use std::hash::{Hash, Hasher}; +use std::{cmp, mem, usize}; + +/// HPACK encoder table +#[derive(Debug)] +pub struct Table { + mask: usize, + indices: Vec<Option<Pos>>, + slots: VecDeque<Slot>, + inserted: usize, + // Size is in bytes + size: usize, + max_size: usize, +} + +#[derive(Debug)] +pub enum Index { + // The header is already fully indexed + Indexed(usize, Header), + + // The name is indexed, but not the value + Name(usize, Header), + + // The full header has been inserted into the table. + Inserted(usize), + + // Only the value has been inserted (hpack table idx, slots idx) + InsertedValue(usize, usize), + + // The header is not indexed by this table + NotIndexed(Header), +} + +#[derive(Debug)] +struct Slot { + hash: HashValue, + header: Header, + next: Option<usize>, +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +struct Pos { + index: usize, + hash: HashValue, +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +struct HashValue(usize); + +const MAX_SIZE: usize = 1 << 16; +const DYN_OFFSET: usize = 62; + +macro_rules! probe_loop { + ($probe_var: ident < $len: expr, $body: expr) => { + debug_assert!($len > 0); + loop { + if $probe_var < $len { + $body + $probe_var += 1; + } else { + $probe_var = 0; + } + } + }; +} + +impl Table { + pub fn new(max_size: usize, capacity: usize) -> Table { + if capacity == 0 { + Table { + mask: 0, + indices: vec![], + slots: VecDeque::new(), + inserted: 0, + size: 0, + max_size, + } + } else { + let capacity = cmp::max(to_raw_capacity(capacity).next_power_of_two(), 8); + + Table { + mask: capacity.wrapping_sub(1), + indices: vec![None; capacity], + slots: VecDeque::with_capacity(usable_capacity(capacity)), + inserted: 0, + size: 0, + max_size, + } + } + } + + #[inline] + pub fn capacity(&self) -> usize { + usable_capacity(self.indices.len()) + } + + pub fn max_size(&self) -> usize { + self.max_size + } + + /// Gets the header stored in the table + pub fn resolve<'a>(&'a self, index: &'a Index) -> &'a Header { + use self::Index::*; + + match *index { + Indexed(_, ref h) => h, + Name(_, ref h) => h, + Inserted(idx) => &self.slots[idx].header, + InsertedValue(_, idx) => &self.slots[idx].header, + NotIndexed(ref h) => h, + } + } + + pub fn resolve_idx(&self, index: &Index) -> usize { + use self::Index::*; + + match *index { + Indexed(idx, ..) => idx, + Name(idx, ..) => idx, + Inserted(idx) => idx + DYN_OFFSET, + InsertedValue(_name_idx, slot_idx) => slot_idx + DYN_OFFSET, + NotIndexed(_) => panic!("cannot resolve index"), + } + } + + /// Index the header in the HPACK table. + pub fn index(&mut self, header: Header) -> Index { + // Check the static table + let statik = index_static(&header); + + // Don't index certain headers. This logic is borrowed from nghttp2. + if header.skip_value_index() { + // Right now, if this is true, the header name is always in the + // static table. At some point in the future, this might not be true + // and this logic will need to be updated. + debug_assert!(statik.is_some(), "skip_value_index requires a static name",); + return Index::new(statik, header); + } + + // If the header is already indexed by the static table, return that + if let Some((n, true)) = statik { + return Index::Indexed(n, header); + } + + // Don't index large headers + if header.len() * 4 > self.max_size * 3 { + return Index::new(statik, header); + } + + self.index_dynamic(header, statik) + } + + fn index_dynamic(&mut self, header: Header, statik: Option<(usize, bool)>) -> Index { + debug_assert!(self.assert_valid_state("one")); + + if header.len() + self.size < self.max_size || !header.is_sensitive() { + // Only grow internal storage if needed + self.reserve_one(); + } + + if self.indices.is_empty() { + // If `indices` is not empty, then it is impossible for all + // `indices` entries to be `Some`. So, we only need to check for the + // empty case. + return Index::new(statik, header); + } + + let hash = hash_header(&header); + + let desired_pos = desired_pos(self.mask, hash); + let mut probe = desired_pos; + let mut dist = 0; + + // Start at the ideal position, checking all slots + probe_loop!(probe < self.indices.len(), { + if let Some(pos) = self.indices[probe] { + // The slot is already occupied, but check if it has a lower + // displacement. + let their_dist = probe_distance(self.mask, pos.hash, probe); + + let slot_idx = pos.index.wrapping_add(self.inserted); + + if their_dist < dist { + // Index robinhood + return self.index_vacant(header, hash, dist, probe, statik); + } else if pos.hash == hash && self.slots[slot_idx].header.name() == header.name() { + // Matching name, check values + return self.index_occupied(header, hash, pos.index, statik.map(|(n, _)| n)); + } + } else { + return self.index_vacant(header, hash, dist, probe, statik); + } + + dist += 1; + }); + } + + fn index_occupied( + &mut self, + header: Header, + hash: HashValue, + mut index: usize, + statik: Option<usize>, + ) -> Index { + debug_assert!(self.assert_valid_state("top")); + + // There already is a match for the given header name. Check if a value + // matches. The header will also only be inserted if the table is not at + // capacity. + loop { + // Compute the real index into the VecDeque + let real_idx = index.wrapping_add(self.inserted); + + if self.slots[real_idx].header.value_eq(&header) { + // We have a full match! + return Index::Indexed(real_idx + DYN_OFFSET, header); + } + + if let Some(next) = self.slots[real_idx].next { + index = next; + continue; + } + + if header.is_sensitive() { + // Should we assert this? + // debug_assert!(statik.is_none()); + return Index::Name(real_idx + DYN_OFFSET, header); + } + + self.update_size(header.len(), Some(index)); + + // Insert the new header + self.insert(header, hash); + + // Recompute real_idx as it just changed. + let new_real_idx = index.wrapping_add(self.inserted); + + // The previous node in the linked list may have gotten evicted + // while making room for this header. + if new_real_idx < self.slots.len() { + let idx = 0usize.wrapping_sub(self.inserted); + + self.slots[new_real_idx].next = Some(idx); + } + + debug_assert!(self.assert_valid_state("bottom")); + + // Even if the previous header was evicted, we can still reference + // it when inserting the new one... + return if let Some(n) = statik { + // If name is in static table, use it instead + Index::InsertedValue(n, 0) + } else { + Index::InsertedValue(real_idx + DYN_OFFSET, 0) + }; + } + } + + 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); + } + + debug_assert!(self.assert_valid_state("top")); + debug_assert!(dist == 0 || self.indices[probe.wrapping_sub(1) & self.mask].is_some()); + + // Passing in `usize::MAX` for prev_idx since there is no previous + // header in this case. + if self.update_size(header.len(), None) { + while dist != 0 { + let back = probe.wrapping_sub(1) & self.mask; + + if let Some(pos) = self.indices[back] { + let their_dist = probe_distance(self.mask, pos.hash, back); + + if their_dist < (dist - 1) { + probe = back; + dist -= 1; + } else { + break; + } + } else { + probe = back; + dist -= 1; + } + } + } + + debug_assert!(self.assert_valid_state("after update")); + + self.insert(header, hash); + + let pos_idx = 0usize.wrapping_sub(self.inserted); + + let prev = mem::replace( + &mut self.indices[probe], + Some(Pos { + index: pos_idx, + hash, + }), + ); + + if let Some(mut prev) = prev { + // Shift forward + let mut probe = probe + 1; + + probe_loop!(probe < self.indices.len(), { + let pos = &mut self.indices[probe as usize]; + + prev = match mem::replace(pos, Some(prev)) { + Some(p) => p, + None => break, + }; + }); + } + + debug_assert!(self.assert_valid_state("bottom")); + + if let Some((n, _)) = statik { + Index::InsertedValue(n, 0) + } else { + Index::Inserted(0) + } + } + + fn insert(&mut self, header: Header, hash: HashValue) { + self.inserted = self.inserted.wrapping_add(1); + + self.slots.push_front(Slot { + hash, + header, + next: None, + }); + } + + pub fn resize(&mut self, size: usize) { + self.max_size = size; + + if size == 0 { + self.size = 0; + + for i in &mut self.indices { + *i = None; + } + + self.slots.clear(); + self.inserted = 0; + } else { + self.converge(None); + } + } + + fn update_size(&mut self, len: usize, prev_idx: Option<usize>) -> bool { + self.size += len; + self.converge(prev_idx) + } + + fn converge(&mut self, prev_idx: Option<usize>) -> bool { + let mut ret = false; + + while self.size > self.max_size { + ret = true; + self.evict(prev_idx); + } + + ret + } + + fn evict(&mut self, prev_idx: Option<usize>) { + let pos_idx = (self.slots.len() - 1).wrapping_sub(self.inserted); + + debug_assert!(!self.slots.is_empty()); + debug_assert!(self.assert_valid_state("one")); + + // Remove the header + let slot = self.slots.pop_back().unwrap(); + let mut probe = desired_pos(self.mask, slot.hash); + + // 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 + ); + + // Find the associated position + probe_loop!(probe < self.indices.len(), { + debug_assert!(!self.indices[probe].is_none()); + + let mut pos = self.indices[probe].unwrap(); + + if pos.index == pos_idx { + if let Some(idx) = slot.next { + pos.index = idx; + self.indices[probe] = Some(pos); + } else if Some(pos.index) == prev_idx { + pos.index = 0usize.wrapping_sub(self.inserted + 1); + self.indices[probe] = Some(pos); + } else { + self.indices[probe] = None; + self.remove_phase_two(probe); + } + + break; + } + }); + + debug_assert!(self.assert_valid_state("two")); + } + + // Shifts all indices that were displaced by the header that has just been + // removed. + fn remove_phase_two(&mut self, probe: usize) { + let mut last_probe = probe; + let mut probe = probe + 1; + + probe_loop!(probe < self.indices.len(), { + if let Some(pos) = self.indices[probe] { + if probe_distance(self.mask, pos.hash, probe) > 0 { + self.indices[last_probe] = self.indices[probe].take(); + } else { + break; + } + } else { + break; + } + + last_probe = probe; + }); + + debug_assert!(self.assert_valid_state("two")); + } + + fn reserve_one(&mut self) { + let len = self.slots.len(); + + if len == self.capacity() { + if len == 0 { + let new_raw_cap = 8; + self.mask = 8 - 1; + self.indices = vec![None; new_raw_cap]; + } else { + let raw_cap = self.indices.len(); + self.grow(raw_cap << 1); + } + } + } + + #[inline] + fn grow(&mut self, new_raw_cap: usize) { + // This path can never be reached when handling the first allocation in + // the map. + + debug_assert!(self.assert_valid_state("top")); + + // find first ideally placed element -- start of cluster + let mut first_ideal = 0; + + for (i, pos) in self.indices.iter().enumerate() { + if let Some(pos) = *pos { + if 0 == probe_distance(self.mask, pos.hash, i) { + first_ideal = i; + break; + } + } + } + + // visit the entries in an order where we can simply reinsert them + // into self.indices without any bucket stealing. + let old_indices = mem::replace(&mut self.indices, vec![None; new_raw_cap]); + self.mask = new_raw_cap.wrapping_sub(1); + + for &pos in &old_indices[first_ideal..] { + self.reinsert_entry_in_order(pos); + } + + for &pos in &old_indices[..first_ideal] { + self.reinsert_entry_in_order(pos); + } + + debug_assert!(self.assert_valid_state("bottom")); + } + + fn reinsert_entry_in_order(&mut self, pos: Option<Pos>) { + if let Some(pos) = pos { + // Find first empty bucket and insert there + let mut probe = desired_pos(self.mask, pos.hash); + + probe_loop!(probe < self.indices.len(), { + if self.indices[probe].is_none() { + // empty bucket, insert here + self.indices[probe] = Some(pos); + return; + } + + 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); + + their_distance >= our_distance + }); + }); + } + } + + #[cfg(not(test))] + fn assert_valid_state(&self, _: &'static str) -> bool { + true + } + + #[cfg(test)] + fn assert_valid_state(&self, _msg: &'static str) -> bool { + /* + // Checks that the internal map structure is valid + // + // Ensure all hash codes in indices match the associated slot + for pos in &self.indices { + if let Some(pos) = *pos { + let real_idx = pos.index.wrapping_add(self.inserted); + + if real_idx.wrapping_add(1) != 0 { + assert!(real_idx < self.slots.len(), + "out of index; real={}; len={}, msg={}", + real_idx, self.slots.len(), msg); + + assert_eq!(pos.hash, self.slots[real_idx].hash, + "index hash does not match slot; msg={}", msg); + } + } + } + + // Every index is only available once + for i in 0..self.indices.len() { + if self.indices[i].is_none() { + continue; + } + + for j in i+1..self.indices.len() { + assert_ne!(self.indices[i], self.indices[j], + "duplicate indices; msg={}", msg); + } + } + + for (index, slot) in self.slots.iter().enumerate() { + let mut indexed = None; + + // First, see if the slot is indexed + for (i, pos) in self.indices.iter().enumerate() { + if let Some(pos) = *pos { + let real_idx = pos.index.wrapping_add(self.inserted); + if real_idx == index { + indexed = Some(i); + // Already know that there is no dup, so break + break; + } + } + } + + if let Some(actual) = indexed { + // Ensure that it is accessible.. + let desired = desired_pos(self.mask, slot.hash); + let mut probe = desired; + let mut dist = 0; + + probe_loop!(probe < self.indices.len(), { + assert!(self.indices[probe].is_some(), + "unexpected empty slot; probe={}; hash={:?}; msg={}", + probe, slot.hash, msg); + + let pos = self.indices[probe].unwrap(); + + let their_dist = probe_distance(self.mask, pos.hash, probe); + let real_idx = pos.index.wrapping_add(self.inserted); + + if real_idx == index { + break; + } + + 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); + + dist += 1; + }); + } else { + // There is exactly one next link + let cnt = self.slots.iter().map(|s| s.next) + .filter(|n| *n == Some(index.wrapping_sub(self.inserted))) + .count(); + + assert_eq!(1, cnt, "more than one node pointing here; msg={}", msg); + } + } + */ + + // TODO: Ensure linked lists are correct: no cycles, etc... + + true + } +} + +#[cfg(test)] +impl Table { + /// Returns the number of headers in the table + pub fn len(&self) -> usize { + self.slots.len() + } + + /// Returns the table size + pub fn size(&self) -> usize { + self.size + } +} + +impl Index { + fn new(v: Option<(usize, bool)>, e: Header) -> Index { + match v { + None => Index::NotIndexed(e), + Some((n, true)) => Index::Indexed(n, e), + Some((n, false)) => Index::Name(n, e), + } + } +} + +#[inline] +fn usable_capacity(cap: usize) -> usize { + cap - cap / 4 +} + +#[inline] +fn to_raw_capacity(n: usize) -> usize { + n + n / 3 +} + +#[inline] +fn desired_pos(mask: usize, hash: HashValue) -> usize { + (hash.0 & mask) as usize +} + +#[inline] +fn probe_distance(mask: usize, hash: HashValue, current: usize) -> usize { + current.wrapping_sub(desired_pos(mask, hash)) & mask as usize +} + +fn hash_header(header: &Header) -> HashValue { + const MASK: u64 = (MAX_SIZE as u64) - 1; + + let mut h = FnvHasher::default(); + header.name().hash(&mut h); + HashValue((h.finish() & MASK) as usize) +} + +/// Checks the static table for the header. If found, returns the index and a +/// boolean representing if the value matched as well. +fn index_static(header: &Header) -> Option<(usize, bool)> { + match *header { + Header::Field { + ref name, + ref value, + } => match *name { + header::ACCEPT_CHARSET => Some((15, false)), + header::ACCEPT_ENCODING => { + if value == "gzip, deflate" { + Some((16, true)) + } else { + Some((16, false)) + } + } + header::ACCEPT_LANGUAGE => Some((17, false)), + header::ACCEPT_RANGES => Some((18, false)), + header::ACCEPT => Some((19, false)), + header::ACCESS_CONTROL_ALLOW_ORIGIN => Some((20, false)), + header::AGE => Some((21, false)), + header::ALLOW => Some((22, false)), + header::AUTHORIZATION => Some((23, false)), + header::CACHE_CONTROL => Some((24, false)), + header::CONTENT_DISPOSITION => Some((25, false)), + header::CONTENT_ENCODING => Some((26, false)), + header::CONTENT_LANGUAGE => Some((27, false)), + header::CONTENT_LENGTH => Some((28, false)), + header::CONTENT_LOCATION => Some((29, false)), + header::CONTENT_RANGE => Some((30, false)), + header::CONTENT_TYPE => Some((31, false)), + header::COOKIE => Some((32, false)), + header::DATE => Some((33, false)), + header::ETAG => Some((34, false)), + header::EXPECT => Some((35, false)), + header::EXPIRES => Some((36, false)), + header::FROM => Some((37, false)), + header::HOST => Some((38, false)), + header::IF_MATCH => Some((39, false)), + header::IF_MODIFIED_SINCE => Some((40, false)), + header::IF_NONE_MATCH => Some((41, false)), + header::IF_RANGE => Some((42, false)), + header::IF_UNMODIFIED_SINCE => Some((43, false)), + header::LAST_MODIFIED => Some((44, false)), + header::LINK => Some((45, false)), + header::LOCATION => Some((46, false)), + header::MAX_FORWARDS => Some((47, false)), + header::PROXY_AUTHENTICATE => Some((48, false)), + header::PROXY_AUTHORIZATION => Some((49, false)), + header::RANGE => Some((50, false)), + header::REFERER => Some((51, false)), + header::REFRESH => Some((52, false)), + header::RETRY_AFTER => Some((53, false)), + header::SERVER => Some((54, false)), + header::SET_COOKIE => Some((55, false)), + header::STRICT_TRANSPORT_SECURITY => Some((56, false)), + header::TRANSFER_ENCODING => Some((57, false)), + header::USER_AGENT => Some((58, false)), + header::VARY => Some((59, false)), + header::VIA => Some((60, false)), + header::WWW_AUTHENTICATE => Some((61, false)), + _ => None, + }, + Header::Authority(_) => Some((1, false)), + Header::Method(ref v) => match *v { + Method::GET => Some((2, true)), + Method::POST => Some((3, true)), + _ => Some((2, false)), + }, + Header::Scheme(ref v) => match &**v { + "http" => Some((6, true)), + "https" => Some((7, true)), + _ => Some((6, false)), + }, + Header::Path(ref v) => match &**v { + "/" => Some((4, true)), + "/index.html" => Some((5, true)), + _ => Some((4, false)), + }, + Header::Protocol(..) => None, + Header::Status(ref v) => match u16::from(*v) { + 200 => Some((8, true)), + 204 => Some((9, true)), + 206 => Some((10, true)), + 304 => Some((11, true)), + 400 => Some((12, true)), + 404 => Some((13, true)), + 500 => Some((14, true)), + _ => Some((8, false)), + }, + } +} diff --git a/third_party/rust/h2/src/hpack/test/fixture.rs b/third_party/rust/h2/src/hpack/test/fixture.rs new file mode 100644 index 0000000000..3428c39583 --- /dev/null +++ b/third_party/rust/h2/src/hpack/test/fixture.rs @@ -0,0 +1,615 @@ +use crate::hpack::{Decoder, Encoder, Header}; + +use bytes::BytesMut; +use hex::FromHex; +use serde_json::Value; + +use std::fs::File; +use std::io::prelude::*; +use std::io::Cursor; +use std::path::Path; +use std::str; + +fn test_fixture(path: &Path) { + let mut file = File::open(path).unwrap(); + let mut data = String::new(); + file.read_to_string(&mut data).unwrap(); + + let story: Value = serde_json::from_str(&data).unwrap(); + test_story(story); +} + +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() + .map(|case| { + let case = case.as_object().unwrap(); + + let size = case + .get("header_table_size") + .map(|v| v.as_u64().unwrap() as usize); + + 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() + .map(|h| { + let h = h.as_object().unwrap(); + let (name, val) = h.iter().next().unwrap(); + (name.clone(), val.as_str().unwrap().to_string()) + }) + .collect(); + + Case { + seqno: case.get("seqno").unwrap().as_u64().unwrap(), + wire: wire, + expect: expect, + header_table_size: size, + } + }) + .collect(); + + cases.sort_by_key(|c| c.seqno); + + let mut decoder = Decoder::default(); + + // First, check decoding against the fixtures + for case in &cases { + let mut expect = case.expect.clone(); + + if let Some(size) = case.header_table_size { + decoder.queue_size_update(size); + } + + let mut buf = BytesMut::with_capacity(case.wire.len()); + buf.extend_from_slice(&case.wire); + decoder + .decode(&mut Cursor::new(&mut buf), |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()); + } + + let mut encoder = Encoder::default(); + let mut decoder = Decoder::default(); + + // Now, encode the headers + for case in &cases { + let limit = 64 * 1024; + let mut buf = BytesMut::with_capacity(limit); + + if let Some(size) = case.header_table_size { + encoder.update_max_size(size); + 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(); + + encoder.encode(&mut input.clone().into_iter(), &mut buf); + + decoder + .decode(&mut Cursor::new(&mut buf), |e| { + assert_eq!(e, input.remove(0).reify().unwrap()); + }) + .unwrap(); + + assert_eq!(0, input.len()); + } + } +} + +struct Case { + seqno: u64, + wire: Vec<u8>, + expect: Vec<(String, String)>, + header_table_size: Option<usize>, +} + +fn key_str(e: &Header) -> &str { + match *e { + Header::Field { ref name, .. } => name.as_str(), + Header::Authority(..) => ":authority", + Header::Method(..) => ":method", + Header::Scheme(..) => ":scheme", + Header::Path(..) => ":path", + Header::Protocol(..) => ":protocol", + Header::Status(..) => ":status", + } +} + +fn value_str(e: &Header) -> &str { + match *e { + 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, + Header::Path(ref v) => &**v, + Header::Protocol(ref v) => v.as_str(), + Header::Status(ref v) => v.as_str(), + } +} + +macro_rules! fixture_mod { + ($module:ident => { + $( + ($fn:ident, $path:expr); + )+ + }) => { + mod $module { + $( + #[test] + fn $fn() { + let path = ::std::path::Path::new(env!("CARGO_MANIFEST_DIR")) + .join("fixtures/hpack") + .join($path); + + super::test_fixture(path.as_ref()); + } + )+ + } + } +} + +fixture_mod!( + haskell_http2_linear_huffman => { + (story_00, "haskell-http2-linear-huffman/story_00.json"); + (story_01, "haskell-http2-linear-huffman/story_01.json"); + (story_02, "haskell-http2-linear-huffman/story_02.json"); + (story_03, "haskell-http2-linear-huffman/story_03.json"); + (story_04, "haskell-http2-linear-huffman/story_04.json"); + (story_05, "haskell-http2-linear-huffman/story_05.json"); + (story_06, "haskell-http2-linear-huffman/story_06.json"); + (story_07, "haskell-http2-linear-huffman/story_07.json"); + (story_08, "haskell-http2-linear-huffman/story_08.json"); + (story_09, "haskell-http2-linear-huffman/story_09.json"); + (story_10, "haskell-http2-linear-huffman/story_10.json"); + (story_11, "haskell-http2-linear-huffman/story_11.json"); + (story_12, "haskell-http2-linear-huffman/story_12.json"); + (story_13, "haskell-http2-linear-huffman/story_13.json"); + (story_14, "haskell-http2-linear-huffman/story_14.json"); + (story_15, "haskell-http2-linear-huffman/story_15.json"); + (story_16, "haskell-http2-linear-huffman/story_16.json"); + (story_17, "haskell-http2-linear-huffman/story_17.json"); + (story_18, "haskell-http2-linear-huffman/story_18.json"); + (story_19, "haskell-http2-linear-huffman/story_19.json"); + (story_20, "haskell-http2-linear-huffman/story_20.json"); + (story_21, "haskell-http2-linear-huffman/story_21.json"); + (story_22, "haskell-http2-linear-huffman/story_22.json"); + (story_23, "haskell-http2-linear-huffman/story_23.json"); + (story_24, "haskell-http2-linear-huffman/story_24.json"); + (story_25, "haskell-http2-linear-huffman/story_25.json"); + (story_26, "haskell-http2-linear-huffman/story_26.json"); + (story_27, "haskell-http2-linear-huffman/story_27.json"); + (story_28, "haskell-http2-linear-huffman/story_28.json"); + (story_29, "haskell-http2-linear-huffman/story_29.json"); + (story_30, "haskell-http2-linear-huffman/story_30.json"); + (story_31, "haskell-http2-linear-huffman/story_31.json"); + } +); + +fixture_mod!( + python_hpack => { + (story_00, "python-hpack/story_00.json"); + (story_01, "python-hpack/story_01.json"); + (story_02, "python-hpack/story_02.json"); + (story_03, "python-hpack/story_03.json"); + (story_04, "python-hpack/story_04.json"); + (story_05, "python-hpack/story_05.json"); + (story_06, "python-hpack/story_06.json"); + (story_07, "python-hpack/story_07.json"); + (story_08, "python-hpack/story_08.json"); + (story_09, "python-hpack/story_09.json"); + (story_10, "python-hpack/story_10.json"); + (story_11, "python-hpack/story_11.json"); + (story_12, "python-hpack/story_12.json"); + (story_13, "python-hpack/story_13.json"); + (story_14, "python-hpack/story_14.json"); + (story_15, "python-hpack/story_15.json"); + (story_16, "python-hpack/story_16.json"); + (story_17, "python-hpack/story_17.json"); + (story_18, "python-hpack/story_18.json"); + (story_19, "python-hpack/story_19.json"); + (story_20, "python-hpack/story_20.json"); + (story_21, "python-hpack/story_21.json"); + (story_22, "python-hpack/story_22.json"); + (story_23, "python-hpack/story_23.json"); + (story_24, "python-hpack/story_24.json"); + (story_25, "python-hpack/story_25.json"); + (story_26, "python-hpack/story_26.json"); + (story_27, "python-hpack/story_27.json"); + (story_28, "python-hpack/story_28.json"); + (story_29, "python-hpack/story_29.json"); + (story_30, "python-hpack/story_30.json"); + (story_31, "python-hpack/story_31.json"); + } +); + +fixture_mod!( + nghttp2_16384_4096 => { + (story_00, "nghttp2-16384-4096/story_00.json"); + (story_01, "nghttp2-16384-4096/story_01.json"); + (story_02, "nghttp2-16384-4096/story_02.json"); + (story_03, "nghttp2-16384-4096/story_03.json"); + (story_04, "nghttp2-16384-4096/story_04.json"); + (story_05, "nghttp2-16384-4096/story_05.json"); + (story_06, "nghttp2-16384-4096/story_06.json"); + (story_07, "nghttp2-16384-4096/story_07.json"); + (story_08, "nghttp2-16384-4096/story_08.json"); + (story_09, "nghttp2-16384-4096/story_09.json"); + (story_10, "nghttp2-16384-4096/story_10.json"); + (story_11, "nghttp2-16384-4096/story_11.json"); + (story_12, "nghttp2-16384-4096/story_12.json"); + (story_13, "nghttp2-16384-4096/story_13.json"); + (story_14, "nghttp2-16384-4096/story_14.json"); + (story_15, "nghttp2-16384-4096/story_15.json"); + (story_16, "nghttp2-16384-4096/story_16.json"); + (story_17, "nghttp2-16384-4096/story_17.json"); + (story_18, "nghttp2-16384-4096/story_18.json"); + (story_19, "nghttp2-16384-4096/story_19.json"); + (story_20, "nghttp2-16384-4096/story_20.json"); + (story_21, "nghttp2-16384-4096/story_21.json"); + (story_22, "nghttp2-16384-4096/story_22.json"); + (story_23, "nghttp2-16384-4096/story_23.json"); + (story_24, "nghttp2-16384-4096/story_24.json"); + (story_25, "nghttp2-16384-4096/story_25.json"); + (story_26, "nghttp2-16384-4096/story_26.json"); + (story_27, "nghttp2-16384-4096/story_27.json"); + (story_28, "nghttp2-16384-4096/story_28.json"); + (story_29, "nghttp2-16384-4096/story_29.json"); + (story_30, "nghttp2-16384-4096/story_30.json"); + } +); + +fixture_mod!( + node_http2_hpack => { + (story_00, "node-http2-hpack/story_00.json"); + (story_01, "node-http2-hpack/story_01.json"); + (story_02, "node-http2-hpack/story_02.json"); + (story_03, "node-http2-hpack/story_03.json"); + (story_04, "node-http2-hpack/story_04.json"); + (story_05, "node-http2-hpack/story_05.json"); + (story_06, "node-http2-hpack/story_06.json"); + (story_07, "node-http2-hpack/story_07.json"); + (story_08, "node-http2-hpack/story_08.json"); + (story_09, "node-http2-hpack/story_09.json"); + (story_10, "node-http2-hpack/story_10.json"); + (story_11, "node-http2-hpack/story_11.json"); + (story_12, "node-http2-hpack/story_12.json"); + (story_13, "node-http2-hpack/story_13.json"); + (story_14, "node-http2-hpack/story_14.json"); + (story_15, "node-http2-hpack/story_15.json"); + (story_16, "node-http2-hpack/story_16.json"); + (story_17, "node-http2-hpack/story_17.json"); + (story_18, "node-http2-hpack/story_18.json"); + (story_19, "node-http2-hpack/story_19.json"); + (story_20, "node-http2-hpack/story_20.json"); + (story_21, "node-http2-hpack/story_21.json"); + (story_22, "node-http2-hpack/story_22.json"); + (story_23, "node-http2-hpack/story_23.json"); + (story_24, "node-http2-hpack/story_24.json"); + (story_25, "node-http2-hpack/story_25.json"); + (story_26, "node-http2-hpack/story_26.json"); + (story_27, "node-http2-hpack/story_27.json"); + (story_28, "node-http2-hpack/story_28.json"); + (story_29, "node-http2-hpack/story_29.json"); + (story_30, "node-http2-hpack/story_30.json"); + (story_31, "node-http2-hpack/story_31.json"); + } +); + +fixture_mod!( + nghttp2_change_table_size => { + (story_00, "nghttp2-change-table-size/story_00.json"); + (story_01, "nghttp2-change-table-size/story_01.json"); + (story_02, "nghttp2-change-table-size/story_02.json"); + (story_03, "nghttp2-change-table-size/story_03.json"); + (story_04, "nghttp2-change-table-size/story_04.json"); + (story_05, "nghttp2-change-table-size/story_05.json"); + (story_06, "nghttp2-change-table-size/story_06.json"); + (story_07, "nghttp2-change-table-size/story_07.json"); + (story_08, "nghttp2-change-table-size/story_08.json"); + (story_09, "nghttp2-change-table-size/story_09.json"); + (story_10, "nghttp2-change-table-size/story_10.json"); + (story_11, "nghttp2-change-table-size/story_11.json"); + (story_12, "nghttp2-change-table-size/story_12.json"); + (story_13, "nghttp2-change-table-size/story_13.json"); + (story_14, "nghttp2-change-table-size/story_14.json"); + (story_15, "nghttp2-change-table-size/story_15.json"); + (story_16, "nghttp2-change-table-size/story_16.json"); + (story_17, "nghttp2-change-table-size/story_17.json"); + (story_18, "nghttp2-change-table-size/story_18.json"); + (story_19, "nghttp2-change-table-size/story_19.json"); + (story_20, "nghttp2-change-table-size/story_20.json"); + (story_21, "nghttp2-change-table-size/story_21.json"); + (story_22, "nghttp2-change-table-size/story_22.json"); + (story_23, "nghttp2-change-table-size/story_23.json"); + (story_24, "nghttp2-change-table-size/story_24.json"); + (story_25, "nghttp2-change-table-size/story_25.json"); + (story_26, "nghttp2-change-table-size/story_26.json"); + (story_27, "nghttp2-change-table-size/story_27.json"); + (story_28, "nghttp2-change-table-size/story_28.json"); + (story_29, "nghttp2-change-table-size/story_29.json"); + (story_30, "nghttp2-change-table-size/story_30.json"); + } +); + +fixture_mod!( + haskell_http2_static_huffman => { + (story_00, "haskell-http2-static-huffman/story_00.json"); + (story_01, "haskell-http2-static-huffman/story_01.json"); + (story_02, "haskell-http2-static-huffman/story_02.json"); + (story_03, "haskell-http2-static-huffman/story_03.json"); + (story_04, "haskell-http2-static-huffman/story_04.json"); + (story_05, "haskell-http2-static-huffman/story_05.json"); + (story_06, "haskell-http2-static-huffman/story_06.json"); + (story_07, "haskell-http2-static-huffman/story_07.json"); + (story_08, "haskell-http2-static-huffman/story_08.json"); + (story_09, "haskell-http2-static-huffman/story_09.json"); + (story_10, "haskell-http2-static-huffman/story_10.json"); + (story_11, "haskell-http2-static-huffman/story_11.json"); + (story_12, "haskell-http2-static-huffman/story_12.json"); + (story_13, "haskell-http2-static-huffman/story_13.json"); + (story_14, "haskell-http2-static-huffman/story_14.json"); + (story_15, "haskell-http2-static-huffman/story_15.json"); + (story_16, "haskell-http2-static-huffman/story_16.json"); + (story_17, "haskell-http2-static-huffman/story_17.json"); + (story_18, "haskell-http2-static-huffman/story_18.json"); + (story_19, "haskell-http2-static-huffman/story_19.json"); + (story_20, "haskell-http2-static-huffman/story_20.json"); + (story_21, "haskell-http2-static-huffman/story_21.json"); + (story_22, "haskell-http2-static-huffman/story_22.json"); + (story_23, "haskell-http2-static-huffman/story_23.json"); + (story_24, "haskell-http2-static-huffman/story_24.json"); + (story_25, "haskell-http2-static-huffman/story_25.json"); + (story_26, "haskell-http2-static-huffman/story_26.json"); + (story_27, "haskell-http2-static-huffman/story_27.json"); + (story_28, "haskell-http2-static-huffman/story_28.json"); + (story_29, "haskell-http2-static-huffman/story_29.json"); + (story_30, "haskell-http2-static-huffman/story_30.json"); + (story_31, "haskell-http2-static-huffman/story_31.json"); + } +); + +fixture_mod!( + haskell_http2_naive_huffman => { + (story_00, "haskell-http2-naive-huffman/story_00.json"); + (story_01, "haskell-http2-naive-huffman/story_01.json"); + (story_02, "haskell-http2-naive-huffman/story_02.json"); + (story_03, "haskell-http2-naive-huffman/story_03.json"); + (story_04, "haskell-http2-naive-huffman/story_04.json"); + (story_05, "haskell-http2-naive-huffman/story_05.json"); + (story_06, "haskell-http2-naive-huffman/story_06.json"); + (story_07, "haskell-http2-naive-huffman/story_07.json"); + (story_08, "haskell-http2-naive-huffman/story_08.json"); + (story_09, "haskell-http2-naive-huffman/story_09.json"); + (story_10, "haskell-http2-naive-huffman/story_10.json"); + (story_11, "haskell-http2-naive-huffman/story_11.json"); + (story_12, "haskell-http2-naive-huffman/story_12.json"); + (story_13, "haskell-http2-naive-huffman/story_13.json"); + (story_14, "haskell-http2-naive-huffman/story_14.json"); + (story_15, "haskell-http2-naive-huffman/story_15.json"); + (story_16, "haskell-http2-naive-huffman/story_16.json"); + (story_17, "haskell-http2-naive-huffman/story_17.json"); + (story_18, "haskell-http2-naive-huffman/story_18.json"); + (story_19, "haskell-http2-naive-huffman/story_19.json"); + (story_20, "haskell-http2-naive-huffman/story_20.json"); + (story_21, "haskell-http2-naive-huffman/story_21.json"); + (story_22, "haskell-http2-naive-huffman/story_22.json"); + (story_23, "haskell-http2-naive-huffman/story_23.json"); + (story_24, "haskell-http2-naive-huffman/story_24.json"); + (story_25, "haskell-http2-naive-huffman/story_25.json"); + (story_26, "haskell-http2-naive-huffman/story_26.json"); + (story_27, "haskell-http2-naive-huffman/story_27.json"); + (story_28, "haskell-http2-naive-huffman/story_28.json"); + (story_29, "haskell-http2-naive-huffman/story_29.json"); + (story_30, "haskell-http2-naive-huffman/story_30.json"); + (story_31, "haskell-http2-naive-huffman/story_31.json"); + } +); + +fixture_mod!( + haskell_http2_naive => { + (story_00, "haskell-http2-naive/story_00.json"); + (story_01, "haskell-http2-naive/story_01.json"); + (story_02, "haskell-http2-naive/story_02.json"); + (story_03, "haskell-http2-naive/story_03.json"); + (story_04, "haskell-http2-naive/story_04.json"); + (story_05, "haskell-http2-naive/story_05.json"); + (story_06, "haskell-http2-naive/story_06.json"); + (story_07, "haskell-http2-naive/story_07.json"); + (story_08, "haskell-http2-naive/story_08.json"); + (story_09, "haskell-http2-naive/story_09.json"); + (story_10, "haskell-http2-naive/story_10.json"); + (story_11, "haskell-http2-naive/story_11.json"); + (story_12, "haskell-http2-naive/story_12.json"); + (story_13, "haskell-http2-naive/story_13.json"); + (story_14, "haskell-http2-naive/story_14.json"); + (story_15, "haskell-http2-naive/story_15.json"); + (story_16, "haskell-http2-naive/story_16.json"); + (story_17, "haskell-http2-naive/story_17.json"); + (story_18, "haskell-http2-naive/story_18.json"); + (story_19, "haskell-http2-naive/story_19.json"); + (story_20, "haskell-http2-naive/story_20.json"); + (story_21, "haskell-http2-naive/story_21.json"); + (story_22, "haskell-http2-naive/story_22.json"); + (story_23, "haskell-http2-naive/story_23.json"); + (story_24, "haskell-http2-naive/story_24.json"); + (story_25, "haskell-http2-naive/story_25.json"); + (story_26, "haskell-http2-naive/story_26.json"); + (story_27, "haskell-http2-naive/story_27.json"); + (story_28, "haskell-http2-naive/story_28.json"); + (story_29, "haskell-http2-naive/story_29.json"); + (story_30, "haskell-http2-naive/story_30.json"); + (story_31, "haskell-http2-naive/story_31.json"); + } +); + +fixture_mod!( + haskell_http2_static => { + (story_00, "haskell-http2-static/story_00.json"); + (story_01, "haskell-http2-static/story_01.json"); + (story_02, "haskell-http2-static/story_02.json"); + (story_03, "haskell-http2-static/story_03.json"); + (story_04, "haskell-http2-static/story_04.json"); + (story_05, "haskell-http2-static/story_05.json"); + (story_06, "haskell-http2-static/story_06.json"); + (story_07, "haskell-http2-static/story_07.json"); + (story_08, "haskell-http2-static/story_08.json"); + (story_09, "haskell-http2-static/story_09.json"); + (story_10, "haskell-http2-static/story_10.json"); + (story_11, "haskell-http2-static/story_11.json"); + (story_12, "haskell-http2-static/story_12.json"); + (story_13, "haskell-http2-static/story_13.json"); + (story_14, "haskell-http2-static/story_14.json"); + (story_15, "haskell-http2-static/story_15.json"); + (story_16, "haskell-http2-static/story_16.json"); + (story_17, "haskell-http2-static/story_17.json"); + (story_18, "haskell-http2-static/story_18.json"); + (story_19, "haskell-http2-static/story_19.json"); + (story_20, "haskell-http2-static/story_20.json"); + (story_21, "haskell-http2-static/story_21.json"); + (story_22, "haskell-http2-static/story_22.json"); + (story_23, "haskell-http2-static/story_23.json"); + (story_24, "haskell-http2-static/story_24.json"); + (story_25, "haskell-http2-static/story_25.json"); + (story_26, "haskell-http2-static/story_26.json"); + (story_27, "haskell-http2-static/story_27.json"); + (story_28, "haskell-http2-static/story_28.json"); + (story_29, "haskell-http2-static/story_29.json"); + (story_30, "haskell-http2-static/story_30.json"); + (story_31, "haskell-http2-static/story_31.json"); + } +); + +fixture_mod!( + nghttp2 => { + (story_00, "nghttp2/story_00.json"); + (story_01, "nghttp2/story_01.json"); + (story_02, "nghttp2/story_02.json"); + (story_03, "nghttp2/story_03.json"); + (story_04, "nghttp2/story_04.json"); + (story_05, "nghttp2/story_05.json"); + (story_06, "nghttp2/story_06.json"); + (story_07, "nghttp2/story_07.json"); + (story_08, "nghttp2/story_08.json"); + (story_09, "nghttp2/story_09.json"); + (story_10, "nghttp2/story_10.json"); + (story_11, "nghttp2/story_11.json"); + (story_12, "nghttp2/story_12.json"); + (story_13, "nghttp2/story_13.json"); + (story_14, "nghttp2/story_14.json"); + (story_15, "nghttp2/story_15.json"); + (story_16, "nghttp2/story_16.json"); + (story_17, "nghttp2/story_17.json"); + (story_18, "nghttp2/story_18.json"); + (story_19, "nghttp2/story_19.json"); + (story_20, "nghttp2/story_20.json"); + (story_21, "nghttp2/story_21.json"); + (story_22, "nghttp2/story_22.json"); + (story_23, "nghttp2/story_23.json"); + (story_24, "nghttp2/story_24.json"); + (story_25, "nghttp2/story_25.json"); + (story_26, "nghttp2/story_26.json"); + (story_27, "nghttp2/story_27.json"); + (story_28, "nghttp2/story_28.json"); + (story_29, "nghttp2/story_29.json"); + (story_30, "nghttp2/story_30.json"); + (story_31, "nghttp2/story_31.json"); + } +); + +fixture_mod!( + haskell_http2_linear => { + (story_00, "haskell-http2-linear/story_00.json"); + (story_01, "haskell-http2-linear/story_01.json"); + (story_02, "haskell-http2-linear/story_02.json"); + (story_03, "haskell-http2-linear/story_03.json"); + (story_04, "haskell-http2-linear/story_04.json"); + (story_05, "haskell-http2-linear/story_05.json"); + (story_06, "haskell-http2-linear/story_06.json"); + (story_07, "haskell-http2-linear/story_07.json"); + (story_08, "haskell-http2-linear/story_08.json"); + (story_09, "haskell-http2-linear/story_09.json"); + (story_10, "haskell-http2-linear/story_10.json"); + (story_11, "haskell-http2-linear/story_11.json"); + (story_12, "haskell-http2-linear/story_12.json"); + (story_13, "haskell-http2-linear/story_13.json"); + (story_14, "haskell-http2-linear/story_14.json"); + (story_15, "haskell-http2-linear/story_15.json"); + (story_16, "haskell-http2-linear/story_16.json"); + (story_17, "haskell-http2-linear/story_17.json"); + (story_18, "haskell-http2-linear/story_18.json"); + (story_19, "haskell-http2-linear/story_19.json"); + (story_20, "haskell-http2-linear/story_20.json"); + (story_21, "haskell-http2-linear/story_21.json"); + (story_22, "haskell-http2-linear/story_22.json"); + (story_23, "haskell-http2-linear/story_23.json"); + (story_24, "haskell-http2-linear/story_24.json"); + (story_25, "haskell-http2-linear/story_25.json"); + (story_26, "haskell-http2-linear/story_26.json"); + (story_27, "haskell-http2-linear/story_27.json"); + (story_28, "haskell-http2-linear/story_28.json"); + (story_29, "haskell-http2-linear/story_29.json"); + (story_30, "haskell-http2-linear/story_30.json"); + (story_31, "haskell-http2-linear/story_31.json"); + } +); + +fixture_mod!( + go_hpack => { + (story_00, "go-hpack/story_00.json"); + (story_01, "go-hpack/story_01.json"); + (story_02, "go-hpack/story_02.json"); + (story_03, "go-hpack/story_03.json"); + (story_04, "go-hpack/story_04.json"); + (story_05, "go-hpack/story_05.json"); + (story_06, "go-hpack/story_06.json"); + (story_07, "go-hpack/story_07.json"); + (story_08, "go-hpack/story_08.json"); + (story_09, "go-hpack/story_09.json"); + (story_10, "go-hpack/story_10.json"); + (story_11, "go-hpack/story_11.json"); + (story_12, "go-hpack/story_12.json"); + (story_13, "go-hpack/story_13.json"); + (story_14, "go-hpack/story_14.json"); + (story_15, "go-hpack/story_15.json"); + (story_16, "go-hpack/story_16.json"); + (story_17, "go-hpack/story_17.json"); + (story_18, "go-hpack/story_18.json"); + (story_19, "go-hpack/story_19.json"); + (story_20, "go-hpack/story_20.json"); + (story_21, "go-hpack/story_21.json"); + (story_22, "go-hpack/story_22.json"); + (story_23, "go-hpack/story_23.json"); + (story_24, "go-hpack/story_24.json"); + (story_25, "go-hpack/story_25.json"); + (story_26, "go-hpack/story_26.json"); + (story_27, "go-hpack/story_27.json"); + (story_28, "go-hpack/story_28.json"); + (story_29, "go-hpack/story_29.json"); + (story_30, "go-hpack/story_30.json"); + (story_31, "go-hpack/story_31.json"); + } +); diff --git a/third_party/rust/h2/src/hpack/test/fuzz.rs b/third_party/rust/h2/src/hpack/test/fuzz.rs new file mode 100644 index 0000000000..ad0d47b6b1 --- /dev/null +++ b/third_party/rust/h2/src/hpack/test/fuzz.rs @@ -0,0 +1,365 @@ +use crate::hpack::{Decoder, Encoder, Header}; + +use http::header::{HeaderName, HeaderValue}; + +use bytes::BytesMut; +use quickcheck::{Arbitrary, Gen, QuickCheck, TestResult}; +use rand::distributions::Slice; +use rand::rngs::StdRng; +use rand::{thread_rng, Rng, SeedableRng}; + +use std::io::Cursor; + +const MAX_CHUNK: usize = 2 * 1024; + +#[test] +fn hpack_fuzz() { + let _ = env_logger::try_init(); + fn prop(fuzz: FuzzHpack) -> TestResult { + fuzz.run(); + TestResult::from_bool(true) + } + + QuickCheck::new() + .tests(100) + .quickcheck(prop as fn(FuzzHpack) -> TestResult) +} + +/* +// If wanting to test with a specific feed, uncomment and fill in the seed. +#[test] +fn hpack_fuzz_seeded() { + let _ = env_logger::try_init(); + let seed = [/* fill me in*/]; + FuzzHpack::new(seed).run(); +} +*/ + +#[derive(Debug, Clone)] +struct FuzzHpack { + // The set of headers to encode / decode + frames: Vec<HeaderFrame>, +} + +#[derive(Debug, Clone)] +struct HeaderFrame { + resizes: Vec<usize>, + headers: Vec<Header<Option<HeaderName>>>, +} + +impl FuzzHpack { + fn new(seed: [u8; 32]) -> FuzzHpack { + // Seed the RNG + let mut rng = StdRng::from_seed(seed); + + // Generates a bunch of source headers + let mut source: Vec<Header<Option<HeaderName>>> = vec![]; + + for _ in 0..2000 { + source.push(gen_header(&mut rng)); + } + + // Actual test run headers + let num: usize = rng.gen_range(40..500); + + let mut frames: Vec<HeaderFrame> = vec![]; + let mut added = 0; + + let skew: i32 = rng.gen_range(1..5); + + // Rough number of headers to add + while added < num { + let mut frame = HeaderFrame { + resizes: vec![], + headers: vec![], + }; + + match rng.gen_range(0..20) { + 0 => { + // Two resizes + let high = rng.gen_range(128..MAX_CHUNK * 2); + let low = rng.gen_range(0..high); + + frame.resizes.extend(&[low, high]); + } + 1..=3 => { + frame.resizes.push(rng.gen_range(128..MAX_CHUNK * 2)); + } + _ => {} + } + + let mut is_name_required = true; + + for _ in 0..rng.gen_range(1..(num - added) + 1) { + let x: f64 = rng.gen_range(0.0..1.0); + let x = x.powi(skew); + + let i = (x * source.len() as f64) as usize; + + let header = &source[i]; + match header { + Header::Field { name: None, .. } => { + if is_name_required { + continue; + } + } + Header::Field { .. } => { + is_name_required = false; + } + _ => { + // pseudos can't be followed by a header with no name + is_name_required = true; + } + } + + frame.headers.push(header.clone()); + + added += 1; + } + + frames.push(frame); + } + + FuzzHpack { frames } + } + + fn run(self) { + let frames = self.frames; + let mut expect = vec![]; + + let mut encoder = Encoder::default(); + let mut decoder = Decoder::default(); + + for frame in frames { + // build "expected" frames, such that decoding headers always + // includes a name + let mut prev_name = None; + for header in &frame.headers { + match header.clone().reify() { + Ok(h) => { + prev_name = match h { + Header::Field { ref name, .. } => Some(name.clone()), + _ => None, + }; + expect.push(h); + } + Err(value) => { + expect.push(Header::Field { + name: prev_name.as_ref().cloned().expect("previous header name"), + value, + }); + } + } + } + + let mut buf = BytesMut::new(); + + if let Some(max) = frame.resizes.iter().max() { + decoder.queue_size_update(*max); + } + + // Apply resizes + for resize in &frame.resizes { + encoder.update_max_size(*resize); + } + + encoder.encode(frame.headers, &mut buf); + + // Decode the chunk! + decoder + .decode(&mut Cursor::new(&mut buf), |h| { + let e = expect.remove(0); + assert_eq!(h, e); + }) + .expect("full decode"); + } + + assert_eq!(0, expect.len()); + } +} + +impl Arbitrary for FuzzHpack { + fn arbitrary(_: &mut Gen) -> Self { + FuzzHpack::new(thread_rng().gen()) + } +} + +fn gen_header(g: &mut StdRng) -> Header<Option<HeaderName>> { + use http::{Method, StatusCode}; + + if g.gen_ratio(1, 10) { + match g.gen_range(0u32..5) { + 0 => { + let value = gen_string(g, 4, 20); + Header::Authority(to_shared(value)) + } + 1 => { + let method = match g.gen_range(0u32..6) { + 0 => Method::GET, + 1 => Method::POST, + 2 => Method::PUT, + 3 => Method::PATCH, + 4 => Method::DELETE, + 5 => { + let n: usize = g.gen_range(3..7); + let bytes: Vec<u8> = (0..n) + .map(|_| *g.sample(Slice::new(b"ABCDEFGHIJKLMNOPQRSTUVWXYZ").unwrap())) + .collect(); + + Method::from_bytes(&bytes).unwrap() + } + _ => unreachable!(), + }; + + Header::Method(method) + } + 2 => { + let value = match g.gen_range(0u32..2) { + 0 => "http", + 1 => "https", + _ => unreachable!(), + }; + + Header::Scheme(to_shared(value.to_string())) + } + 3 => { + let value = match g.gen_range(0u32..100) { + 0 => "/".to_string(), + 1 => "/index.html".to_string(), + _ => gen_string(g, 2, 20), + }; + + Header::Path(to_shared(value)) + } + 4 => { + let status = (g.gen::<u16>() % 500) + 100; + + Header::Status(StatusCode::from_u16(status).unwrap()) + } + _ => unreachable!(), + } + } else { + let name = if g.gen_ratio(1, 10) { + None + } else { + Some(gen_header_name(g)) + }; + let mut value = gen_header_value(g); + + if g.gen_ratio(1, 30) { + value.set_sensitive(true); + } + + Header::Field { name, value } + } +} + +fn gen_header_name(g: &mut StdRng) -> HeaderName { + use http::header; + + if g.gen_ratio(1, 2) { + g.sample( + Slice::new(&[ + header::ACCEPT, + header::ACCEPT_CHARSET, + header::ACCEPT_ENCODING, + header::ACCEPT_LANGUAGE, + header::ACCEPT_RANGES, + header::ACCESS_CONTROL_ALLOW_CREDENTIALS, + header::ACCESS_CONTROL_ALLOW_HEADERS, + header::ACCESS_CONTROL_ALLOW_METHODS, + header::ACCESS_CONTROL_ALLOW_ORIGIN, + header::ACCESS_CONTROL_EXPOSE_HEADERS, + header::ACCESS_CONTROL_MAX_AGE, + header::ACCESS_CONTROL_REQUEST_HEADERS, + header::ACCESS_CONTROL_REQUEST_METHOD, + header::AGE, + header::ALLOW, + header::ALT_SVC, + header::AUTHORIZATION, + header::CACHE_CONTROL, + header::CONNECTION, + header::CONTENT_DISPOSITION, + header::CONTENT_ENCODING, + header::CONTENT_LANGUAGE, + header::CONTENT_LENGTH, + header::CONTENT_LOCATION, + header::CONTENT_RANGE, + header::CONTENT_SECURITY_POLICY, + header::CONTENT_SECURITY_POLICY_REPORT_ONLY, + header::CONTENT_TYPE, + header::COOKIE, + header::DNT, + header::DATE, + header::ETAG, + header::EXPECT, + header::EXPIRES, + header::FORWARDED, + header::FROM, + header::HOST, + header::IF_MATCH, + header::IF_MODIFIED_SINCE, + header::IF_NONE_MATCH, + header::IF_RANGE, + header::IF_UNMODIFIED_SINCE, + header::LAST_MODIFIED, + header::LINK, + header::LOCATION, + header::MAX_FORWARDS, + header::ORIGIN, + header::PRAGMA, + header::PROXY_AUTHENTICATE, + header::PROXY_AUTHORIZATION, + header::PUBLIC_KEY_PINS, + header::PUBLIC_KEY_PINS_REPORT_ONLY, + header::RANGE, + header::REFERER, + header::REFERRER_POLICY, + header::REFRESH, + header::RETRY_AFTER, + header::SERVER, + header::SET_COOKIE, + header::STRICT_TRANSPORT_SECURITY, + header::TE, + header::TRAILER, + header::TRANSFER_ENCODING, + header::USER_AGENT, + header::UPGRADE, + header::UPGRADE_INSECURE_REQUESTS, + header::VARY, + header::VIA, + header::WARNING, + header::WWW_AUTHENTICATE, + header::X_CONTENT_TYPE_OPTIONS, + header::X_DNS_PREFETCH_CONTROL, + header::X_FRAME_OPTIONS, + header::X_XSS_PROTECTION, + ]) + .unwrap(), + ) + .clone() + } else { + let value = gen_string(g, 1, 25); + HeaderName::from_bytes(value.as_bytes()).unwrap() + } +} + +fn gen_header_value(g: &mut StdRng) -> HeaderValue { + let value = gen_string(g, 0, 70); + HeaderValue::from_bytes(value.as_bytes()).unwrap() +} + +fn gen_string(g: &mut StdRng, min: usize, max: usize) -> String { + let bytes: Vec<_> = (min..max) + .map(|_| { + // Chars to pick from + *g.sample(Slice::new(b"ABCDEFGHIJKLMNOPQRSTUVabcdefghilpqrstuvwxyz----").unwrap()) + }) + .collect(); + + String::from_utf8(bytes).unwrap() +} + +fn to_shared(src: String) -> crate::hpack::BytesStr { + crate::hpack::BytesStr::from(src.as_str()) +} diff --git a/third_party/rust/h2/src/hpack/test/mod.rs b/third_party/rust/h2/src/hpack/test/mod.rs new file mode 100644 index 0000000000..9b1f27169d --- /dev/null +++ b/third_party/rust/h2/src/hpack/test/mod.rs @@ -0,0 +1,2 @@ +mod fixture; +mod fuzz; |