|  | // Copyright 2016 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef QUICHE_HTTP2_HPACK_TOOLS_HPACK_BLOCK_BUILDER_H_ | 
|  | #define QUICHE_HTTP2_HPACK_TOOLS_HPACK_BLOCK_BUILDER_H_ | 
|  |  | 
|  | // HpackBlockBuilder builds wire-format HPACK blocks (or fragments thereof) | 
|  | // from components. | 
|  |  | 
|  | // Supports very large varints to enable tests to create HPACK blocks with | 
|  | // values that the decoder should reject. For now, this is only intended for | 
|  | // use in tests, and thus has EXPECT* in the code. If desired to use it in an | 
|  | // encoder, it will need optimization work, especially w.r.t memory mgmt, and | 
|  | // the EXPECT* will need to be removed or replaced with QUICHE_DCHECKs. And of | 
|  | // course the support for very large varints will not be needed in production | 
|  | // code. | 
|  |  | 
|  | #include <stddef.h> | 
|  |  | 
|  | #include <cstdint> | 
|  | #include <string> | 
|  |  | 
|  | #include "absl/strings/string_view.h" | 
|  | #include "http2/hpack/http2_hpack_constants.h" | 
|  | #include "common/platform/api/quiche_test.h" | 
|  |  | 
|  | namespace http2 { | 
|  | namespace test { | 
|  |  | 
|  | class HpackBlockBuilder { | 
|  | public: | 
|  | explicit HpackBlockBuilder(absl::string_view initial_contents) | 
|  | : buffer_(initial_contents.data(), initial_contents.size()) {} | 
|  | HpackBlockBuilder() {} | 
|  | ~HpackBlockBuilder() {} | 
|  |  | 
|  | size_t size() const { return buffer_.size(); } | 
|  | const std::string& buffer() const { return buffer_; } | 
|  |  | 
|  | //---------------------------------------------------------------------------- | 
|  | // Methods for appending a valid HPACK entry. | 
|  |  | 
|  | void AppendIndexedHeader(uint64_t index) { | 
|  | AppendEntryTypeAndVarint(HpackEntryType::kIndexedHeader, index); | 
|  | } | 
|  |  | 
|  | void AppendDynamicTableSizeUpdate(uint64_t size) { | 
|  | AppendEntryTypeAndVarint(HpackEntryType::kDynamicTableSizeUpdate, size); | 
|  | } | 
|  |  | 
|  | void AppendNameIndexAndLiteralValue(HpackEntryType entry_type, | 
|  | uint64_t name_index, | 
|  | bool value_is_huffman_encoded, | 
|  | absl::string_view value) { | 
|  | // name_index==0 would indicate that the entry includes a literal name. | 
|  | // Call AppendLiteralNameAndValue in that case. | 
|  | EXPECT_NE(0u, name_index); | 
|  | AppendEntryTypeAndVarint(entry_type, name_index); | 
|  | AppendString(value_is_huffman_encoded, value); | 
|  | } | 
|  |  | 
|  | void AppendLiteralNameAndValue(HpackEntryType entry_type, | 
|  | bool name_is_huffman_encoded, | 
|  | absl::string_view name, | 
|  | bool value_is_huffman_encoded, | 
|  | absl::string_view value) { | 
|  | AppendEntryTypeAndVarint(entry_type, 0); | 
|  | AppendString(name_is_huffman_encoded, name); | 
|  | AppendString(value_is_huffman_encoded, value); | 
|  | } | 
|  |  | 
|  | //---------------------------------------------------------------------------- | 
|  | // Primitive methods that are not guaranteed to write a valid HPACK entry. | 
|  |  | 
|  | // Appends a varint, with the specified high_bits above the prefix of the | 
|  | // varint. | 
|  | void AppendHighBitsAndVarint(uint8_t high_bits, | 
|  | uint8_t prefix_length, | 
|  | uint64_t varint); | 
|  |  | 
|  | // Append the start of an HPACK entry for the specified type, with the | 
|  | // specified varint. | 
|  | void AppendEntryTypeAndVarint(HpackEntryType entry_type, uint64_t varint); | 
|  |  | 
|  | // Append a header string (i.e. a header name or value) in HPACK format. | 
|  | // Does NOT perform Huffman encoding. | 
|  | void AppendString(bool is_huffman_encoded, absl::string_view str); | 
|  |  | 
|  | private: | 
|  | std::string buffer_; | 
|  | }; | 
|  |  | 
|  | }  // namespace test | 
|  | }  // namespace http2 | 
|  |  | 
|  | #endif  // QUICHE_HTTP2_HPACK_TOOLS_HPACK_BLOCK_BUILDER_H_ |