Project import generated by Copybara.
PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/core/qpack/qpack_instruction_decoder.h b/quic/core/qpack/qpack_instruction_decoder.h
new file mode 100644
index 0000000..9d674c3
--- /dev/null
+++ b/quic/core/qpack/qpack_instruction_decoder.h
@@ -0,0 +1,146 @@
+// 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.
+
+#ifndef QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTION_DECODER_H_
+#define QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTION_DECODER_H_
+
+#include <cstddef>
+#include <cstdint>
+
+#include "net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder.h"
+#include "net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
+
+namespace quic {
+
+// Generic instruction decoder class. Takes a QpackLanguage that describes a
+// language, that is, a set of instruction opcodes together with a list of
+// fields that follow each instruction.
+class QUIC_EXPORT_PRIVATE QpackInstructionDecoder {
+ public:
+ // Delegate is notified each time an instruction is decoded or when an error
+ // occurs.
+ class QUIC_EXPORT_PRIVATE Delegate {
+ public:
+ virtual ~Delegate() = default;
+
+ // Called when an instruction (including all its fields) is decoded.
+ // |instruction| points to an entry in |language|.
+ // Returns true if decoded fields are valid.
+ // Returns false otherwise, in which case QpackInstructionDecoder stops
+ // decoding: Delegate methods will not be called, and Decode() must not be
+ // called.
+ virtual bool OnInstructionDecoded(const QpackInstruction* instruction) = 0;
+
+ // Called by QpackInstructionDecoder if an error has occurred.
+ // No more data is processed afterwards.
+ virtual void OnError(QuicStringPiece error_message) = 0;
+ };
+
+ // Both |*language| and |*delegate| must outlive this object.
+ QpackInstructionDecoder(const QpackLanguage* language, Delegate* delegate);
+ QpackInstructionDecoder() = delete;
+ QpackInstructionDecoder(const QpackInstructionDecoder&) = delete;
+ QpackInstructionDecoder& operator=(const QpackInstructionDecoder&) = delete;
+
+ // Provide a data fragment to decode. Must not be called after an error has
+ // occurred. Must not be called with empty |data|.
+ void Decode(QuicStringPiece data);
+
+ // Returns true if no decoding has taken place yet or if the last instruction
+ // has been entirely parsed.
+ bool AtInstructionBoundary() const;
+
+ // Accessors for decoded values. Should only be called for fields that are
+ // part of the most recently decoded instruction, and only after |this| calls
+ // Delegate::OnInstructionDecoded() but before Decode() is called again.
+ bool s_bit() const { return s_bit_; }
+ uint64_t varint() const { return varint_; }
+ uint64_t varint2() const { return varint2_; }
+ const QuicString& name() const { return name_; }
+ const QuicString& value() const { return value_; }
+
+ private:
+ enum class State {
+ // Identify instruction.
+ kStartInstruction,
+ // Start decoding next field.
+ kStartField,
+ // Read a single bit.
+ kReadBit,
+ // Start reading integer.
+ kVarintStart,
+ // Resume reading integer.
+ kVarintResume,
+ // Done reading integer.
+ kVarintDone,
+ // Read string.
+ kReadString,
+ // Done reading string.
+ kReadStringDone
+ };
+
+ // One method for each state. Some take input data and return the number of
+ // octets processed. Some take input data but do have void return type
+ // because they not consume any bytes. Some do not take any arguments because
+ // they only change internal state.
+ void DoStartInstruction(QuicStringPiece data);
+ void DoStartField();
+ void DoReadBit(QuicStringPiece data);
+ size_t DoVarintStart(QuicStringPiece data);
+ size_t DoVarintResume(QuicStringPiece data);
+ void DoVarintDone();
+ size_t DoReadString(QuicStringPiece data);
+ void DoReadStringDone();
+
+ // Identify instruction based on opcode encoded in |byte|.
+ // Returns a pointer to an element of |*language_|.
+ const QpackInstruction* LookupOpcode(uint8_t byte) const;
+
+ // Stops decoding and calls Delegate::OnError().
+ void OnError(QuicStringPiece error_message);
+
+ // Describes the language used for decoding.
+ const QpackLanguage* const language_;
+
+ // The Delegate to notify of decoded instructions and errors.
+ Delegate* const delegate_;
+
+ // Storage for decoded field values.
+ bool s_bit_;
+ uint64_t varint_;
+ uint64_t varint2_;
+ QuicString name_;
+ QuicString value_;
+ // Whether the currently decoded header name or value is Huffman encoded.
+ bool is_huffman_encoded_;
+ // Length of string being read into |name_| or |value_|.
+ size_t string_length_;
+
+ // Decoder instance for decoding integers.
+ http2::HpackVarintDecoder varint_decoder_;
+
+ // Decoder instance for decoding Huffman encoded strings.
+ http2::HpackHuffmanDecoder huffman_decoder_;
+
+ // True if a decoding error has been detected either by
+ // QpackInstructionDecoder or by Delegate.
+ bool error_detected_;
+
+ // Decoding state.
+ State state_;
+
+ // Instruction currently being decoded.
+ const QpackInstruction* instruction_;
+
+ // Field currently being decoded.
+ QpackInstructionFields::const_iterator field_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QPACK_QPACK_INSTRUCTION_DECODER_H_