Project import generated by Copybara.

PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/core/qpack/qpack_progressive_decoder.h b/quic/core/qpack/qpack_progressive_decoder.h
new file mode 100644
index 0000000..7988861
--- /dev/null
+++ b/quic/core/qpack/qpack_progressive_decoder.h
@@ -0,0 +1,140 @@
+// Copyright (c) 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_PROGRESSIVE_DECODER_H_
+#define QUICHE_QUIC_CORE_QPACK_QPACK_PROGRESSIVE_DECODER_H_
+
+#include <cstdint>
+#include <memory>
+
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_decoder_stream_sender.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_encoder_stream_receiver.h"
+#include "net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.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 {
+
+class QpackHeaderTable;
+
+// Class to decode a single header block.
+class QUIC_EXPORT_PRIVATE QpackProgressiveDecoder
+    : public QpackInstructionDecoder::Delegate {
+ public:
+  // Interface for receiving decoded header block from the decoder.
+  class QUIC_EXPORT_PRIVATE HeadersHandlerInterface {
+   public:
+    virtual ~HeadersHandlerInterface() {}
+
+    // Called when a new header name-value pair is decoded.  Multiple values for
+    // a given name will be emitted as multiple calls to OnHeader.
+    virtual void OnHeaderDecoded(QuicStringPiece name,
+                                 QuicStringPiece value) = 0;
+
+    // Called when the header block is completely decoded.
+    // Indicates the total number of bytes in this block.
+    // The decoder will not access the handler after this call.
+    // Note that this method might not be called synchronously when the header
+    // block is received on the wire, in case decoding is blocked on receiving
+    // entries on the encoder stream.  TODO(bnc): Implement blocked decoding.
+    virtual void OnDecodingCompleted() = 0;
+
+    // Called when a decoding error has occurred.  No other methods will be
+    // called afterwards.
+    virtual void OnDecodingErrorDetected(QuicStringPiece error_message) = 0;
+  };
+
+  QpackProgressiveDecoder() = delete;
+  QpackProgressiveDecoder(QuicStreamId stream_id,
+                          QpackHeaderTable* header_table,
+                          QpackDecoderStreamSender* decoder_stream_sender,
+                          HeadersHandlerInterface* handler);
+  QpackProgressiveDecoder(const QpackProgressiveDecoder&) = delete;
+  QpackProgressiveDecoder& operator=(const QpackProgressiveDecoder&) = delete;
+  ~QpackProgressiveDecoder() override = default;
+
+  // Calculate Required Insert Count from Encoded Required Insert Count,
+  // MaxEntries, and total number of dynamic table insertions according to
+  // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#ric.
+  // Returns true on success, false on invalid input or overflow/underflow.
+  static bool DecodeRequiredInsertCount(uint64_t encoded_required_insert_count,
+                                        uint64_t max_entries,
+                                        uint64_t total_number_of_inserts,
+                                        uint64_t* required_insert_count);
+
+  // Provide a data fragment to decode.
+  void Decode(QuicStringPiece data);
+
+  // Signal that the entire header block has been received and passed in
+  // through Decode().  No methods must be called afterwards.
+  void EndHeaderBlock();
+
+  // QpackInstructionDecoder::Delegate implementation.
+  bool OnInstructionDecoded(const QpackInstruction* instruction) override;
+  void OnError(QuicStringPiece error_message) override;
+
+ private:
+  bool DoIndexedHeaderFieldInstruction();
+  bool DoIndexedHeaderFieldPostBaseInstruction();
+  bool DoLiteralHeaderFieldNameReferenceInstruction();
+  bool DoLiteralHeaderFieldPostBaseInstruction();
+  bool DoLiteralHeaderFieldInstruction();
+  bool DoPrefixInstruction();
+
+  // Calculates Base from |required_insert_count_|, which must be set before
+  // calling this method, and sign bit and Delta Base in the Header Data Prefix,
+  // which are passed in as arguments.  Returns true on success, false on
+  // failure due to overflow/underflow.
+  bool DeltaBaseToBase(bool sign, uint64_t delta_base, uint64_t* base);
+
+  // The request stream can use relative index (but different from the kind of
+  // relative index used on the encoder stream), and post-base index.
+  // These methods convert relative index and post-base index to absolute index
+  // (one based).  They return true on success, or false if conversion fails due
+  // to overflow/underflow.  On success, |*absolute_index| is guaranteed to be
+  // strictly less than std::numeric_limits<uint64_t>::max().
+  bool RequestStreamRelativeIndexToAbsoluteIndex(
+      uint64_t relative_index,
+      uint64_t* absolute_index) const;
+  bool PostBaseIndexToAbsoluteIndex(uint64_t post_base_index,
+                                    uint64_t* absolute_index) const;
+
+  const QuicStreamId stream_id_;
+
+  // |prefix_decoder_| only decodes a handful of bytes then it can be
+  // destroyed to conserve memory.  |instruction_decoder_|, on the other hand,
+  // is used until the entire header block is decoded.
+  std::unique_ptr<QpackInstructionDecoder> prefix_decoder_;
+  QpackInstructionDecoder instruction_decoder_;
+
+  const QpackHeaderTable* const header_table_;
+  QpackDecoderStreamSender* const decoder_stream_sender_;
+  HeadersHandlerInterface* const handler_;
+
+  // Required Insert Count and Base are decoded from the Header Data Prefix.
+  uint64_t required_insert_count_;
+  uint64_t base_;
+
+  // Required Insert Count is one larger than the largest absolute index of all
+  // referenced dynamic table entries, or zero if no dynamic table entries are
+  // referenced.  |required_insert_count_so_far_| starts out as zero and keeps
+  // track of the Required Insert Count based on entries decoded so far.
+  // After decoding is completed, it is compared to |required_insert_count_|.
+  uint64_t required_insert_count_so_far_;
+
+  // False until prefix is fully read and decoded.
+  bool prefix_decoded_;
+
+  // True until EndHeaderBlock() is called.
+  bool decoding_;
+
+  // True if a decoding error has been detected.
+  bool error_detected_;
+};
+
+}  // namespace quic
+
+#endif  // QUICHE_QUIC_CORE_QPACK_QPACK_PROGRESSIVE_DECODER_H_