Project import generated by Copybara.
PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/core/qpack/qpack_constants.cc b/quic/core/qpack/qpack_constants.cc
new file mode 100644
index 0000000..b9144e0
--- /dev/null
+++ b/quic/core/qpack/qpack_constants.cc
@@ -0,0 +1,200 @@
+// Copyright 2018 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.
+
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
+
+#include <limits>
+
+#include "base/logging.h"
+
+namespace quic {
+
+namespace {
+
+// Validate that
+// * in each instruction, the bits of |value| that are zero in |mask| are zero;
+// * every byte matches exactly one opcode.
+void ValidateLangague(const QpackLanguage* language) {
+#ifndef NDEBUG
+ for (const auto* instruction : *language) {
+ DCHECK_EQ(0, instruction->opcode.value & ~instruction->opcode.mask);
+ }
+
+ for (uint8_t byte = 0; byte < std::numeric_limits<uint8_t>::max(); ++byte) {
+ size_t match_count = 0;
+ for (const auto* instruction : *language) {
+ if ((byte & instruction->opcode.mask) == instruction->opcode.value) {
+ ++match_count;
+ }
+ }
+ DCHECK_EQ(1u, match_count) << static_cast<int>(byte);
+ }
+#endif
+}
+
+} // namespace
+
+bool operator==(const QpackInstructionOpcode& a,
+ const QpackInstructionOpcode& b) {
+ return std::tie(a.value, a.mask) == std::tie(b.value, b.mask);
+}
+
+const QpackInstruction* InsertWithNameReferenceInstruction() {
+ static const QpackInstructionOpcode* const opcode =
+ new QpackInstructionOpcode{0b10000000, 0b10000000};
+ static const QpackInstruction* const instruction =
+ new QpackInstruction{*opcode,
+ {{QpackInstructionFieldType::kSbit, 0b01000000},
+ {QpackInstructionFieldType::kVarint, 6},
+ {QpackInstructionFieldType::kValue, 7}}};
+ return instruction;
+}
+
+const QpackInstruction* InsertWithoutNameReferenceInstruction() {
+ static const QpackInstructionOpcode* const opcode =
+ new QpackInstructionOpcode{0b01000000, 0b11000000};
+ static const QpackInstruction* const instruction =
+ new QpackInstruction{*opcode,
+ {{QpackInstructionFieldType::kName, 5},
+ {QpackInstructionFieldType::kValue, 7}}};
+ return instruction;
+}
+
+const QpackInstruction* DuplicateInstruction() {
+ static const QpackInstructionOpcode* const opcode =
+ new QpackInstructionOpcode{0b00000000, 0b11100000};
+ static const QpackInstruction* const instruction =
+ new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 5}}};
+ return instruction;
+}
+
+const QpackInstruction* SetDynamicTableCapacityInstruction() {
+ static const QpackInstructionOpcode* const opcode =
+ new QpackInstructionOpcode{0b00100000, 0b11100000};
+ static const QpackInstruction* const instruction =
+ new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 5}}};
+ return instruction;
+}
+
+const QpackLanguage* QpackEncoderStreamLanguage() {
+ static const QpackLanguage* const language = new QpackLanguage{
+ InsertWithNameReferenceInstruction(),
+ InsertWithoutNameReferenceInstruction(), DuplicateInstruction(),
+ SetDynamicTableCapacityInstruction()};
+ ValidateLangague(language);
+ return language;
+}
+
+const QpackInstruction* InsertCountIncrementInstruction() {
+ static const QpackInstructionOpcode* const opcode =
+ new QpackInstructionOpcode{0b00000000, 0b11000000};
+ static const QpackInstruction* const instruction =
+ new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 6}}};
+ return instruction;
+}
+
+const QpackInstruction* HeaderAcknowledgementInstruction() {
+ static const QpackInstructionOpcode* const opcode =
+ new QpackInstructionOpcode{0b10000000, 0b10000000};
+ static const QpackInstruction* const instruction =
+ new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 7}}};
+ return instruction;
+}
+
+const QpackInstruction* StreamCancellationInstruction() {
+ static const QpackInstructionOpcode* const opcode =
+ new QpackInstructionOpcode{0b01000000, 0b11000000};
+ static const QpackInstruction* const instruction =
+ new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 6}}};
+ return instruction;
+}
+
+const QpackLanguage* QpackDecoderStreamLanguage() {
+ static const QpackLanguage* const language = new QpackLanguage{
+ InsertCountIncrementInstruction(), HeaderAcknowledgementInstruction(),
+ StreamCancellationInstruction()};
+ ValidateLangague(language);
+ return language;
+}
+
+const QpackInstruction* QpackPrefixInstruction() {
+ // This opcode matches every input.
+ static const QpackInstructionOpcode* const opcode =
+ new QpackInstructionOpcode{0b00000000, 0b00000000};
+ static const QpackInstruction* const instruction =
+ new QpackInstruction{*opcode,
+ {{QpackInstructionFieldType::kVarint, 8},
+ {QpackInstructionFieldType::kSbit, 0b10000000},
+ {QpackInstructionFieldType::kVarint2, 7}}};
+ return instruction;
+}
+
+const QpackLanguage* QpackPrefixLanguage() {
+ static const QpackLanguage* const language =
+ new QpackLanguage{QpackPrefixInstruction()};
+ ValidateLangague(language);
+ return language;
+}
+
+const QpackInstruction* QpackIndexedHeaderFieldInstruction() {
+ static const QpackInstructionOpcode* const opcode =
+ new QpackInstructionOpcode{0b10000000, 0b10000000};
+ static const QpackInstruction* const instruction =
+ new QpackInstruction{*opcode,
+ {{QpackInstructionFieldType::kSbit, 0b01000000},
+ {QpackInstructionFieldType::kVarint, 6}}};
+ return instruction;
+}
+
+const QpackInstruction* QpackIndexedHeaderFieldPostBaseInstruction() {
+ static const QpackInstructionOpcode* const opcode =
+ new QpackInstructionOpcode{0b00010000, 0b11110000};
+ static const QpackInstruction* const instruction =
+ new QpackInstruction{*opcode, {{QpackInstructionFieldType::kVarint, 4}}};
+ return instruction;
+}
+
+const QpackInstruction* QpackLiteralHeaderFieldNameReferenceInstruction() {
+ static const QpackInstructionOpcode* const opcode =
+ new QpackInstructionOpcode{0b01000000, 0b11000000};
+ static const QpackInstruction* const instruction =
+ new QpackInstruction{*opcode,
+ {{QpackInstructionFieldType::kSbit, 0b00010000},
+ {QpackInstructionFieldType::kVarint, 4},
+ {QpackInstructionFieldType::kValue, 7}}};
+ return instruction;
+}
+
+const QpackInstruction* QpackLiteralHeaderFieldPostBaseInstruction() {
+ static const QpackInstructionOpcode* const opcode =
+ new QpackInstructionOpcode{0b00000000, 0b11110000};
+ static const QpackInstruction* const instruction =
+ new QpackInstruction{*opcode,
+ {{QpackInstructionFieldType::kVarint, 3},
+ {QpackInstructionFieldType::kValue, 7}}};
+ return instruction;
+}
+
+const QpackInstruction* QpackLiteralHeaderFieldInstruction() {
+ static const QpackInstructionOpcode* const opcode =
+ new QpackInstructionOpcode{0b00100000, 0b11100000};
+ static const QpackInstruction* const instruction =
+ new QpackInstruction{*opcode,
+ {{QpackInstructionFieldType::kName, 3},
+ {QpackInstructionFieldType::kValue, 7}}};
+ return instruction;
+}
+
+const QpackLanguage* QpackRequestStreamLanguage() {
+ static const QpackLanguage* const language =
+ new QpackLanguage{QpackIndexedHeaderFieldInstruction(),
+ QpackIndexedHeaderFieldPostBaseInstruction(),
+ QpackLiteralHeaderFieldNameReferenceInstruction(),
+ QpackLiteralHeaderFieldPostBaseInstruction(),
+ QpackLiteralHeaderFieldInstruction()};
+ ValidateLangague(language);
+ return language;
+}
+
+} // namespace quic