// 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.

#include "net/third_party/quiche/src/quic/core/qpack/qpack_progressive_encoder.h"

#include "base/logging.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_constants.h"
#include "net/third_party/quiche/src/quic/core/qpack/qpack_header_table.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 {

QpackProgressiveEncoder::QpackProgressiveEncoder(
    QuicStreamId stream_id,
    QpackHeaderTable* header_table,
    QpackEncoderStreamSender* encoder_stream_sender,
    const spdy::SpdyHeaderBlock* header_list)
    : stream_id_(stream_id),
      header_table_(header_table),
      encoder_stream_sender_(encoder_stream_sender),
      header_list_(header_list),
      header_list_iterator_(header_list_->begin()),
      prefix_encoded_(false) {
  // TODO(bnc): Use |stream_id_| for dynamic table entry management, and
  // remove this dummy DCHECK.
  DCHECK_LE(0u, stream_id_);

  DCHECK(header_table_);
  DCHECK(encoder_stream_sender_);
  DCHECK(header_list_);
}

bool QpackProgressiveEncoder::HasNext() const {
  return header_list_iterator_ != header_list_->end() || !prefix_encoded_;
}

void QpackProgressiveEncoder::Next(size_t max_encoded_bytes,
                                   QuicString* output) {
  DCHECK_NE(0u, max_encoded_bytes);
  DCHECK(HasNext());

  // Since QpackInstructionEncoder::Next() does not indicate the number of bytes
  // written, save the maximum new size of |*output|.
  const size_t max_length = output->size() + max_encoded_bytes;

  DCHECK_LT(output->size(), max_length);

  if (!prefix_encoded_ && !instruction_encoder_.HasNext()) {
    // TODO(bnc): Implement dynamic entries and set Required Insert Count and
    // Delta Base accordingly.
    instruction_encoder_.set_varint(0);
    instruction_encoder_.set_varint2(0);
    instruction_encoder_.set_s_bit(false);

    instruction_encoder_.Encode(QpackPrefixInstruction());

    DCHECK(instruction_encoder_.HasNext());
  }

  do {
    // Call QpackInstructionEncoder::Encode for |*header_list_iterator_| if it
    // has not been called yet.
    if (!instruction_encoder_.HasNext()) {
      DCHECK(prefix_encoded_);

      // Even after |name| and |value| go out of scope, copies of these
      // QuicStringPieces retained by QpackInstructionEncoder are still valid as
      // long as |header_list_| is valid.
      QuicStringPiece name = header_list_iterator_->first;
      QuicStringPiece value = header_list_iterator_->second;

      // |is_static| and |index| are saved by QpackInstructionEncoder by value,
      // there are no lifetime concerns.
      bool is_static;
      uint64_t index;

      auto match_type =
          header_table_->FindHeaderField(name, value, &is_static, &index);

      switch (match_type) {
        case QpackHeaderTable::MatchType::kNameAndValue:
          DCHECK(is_static) << "Dynamic table entries not supported yet.";

          instruction_encoder_.set_s_bit(is_static);
          instruction_encoder_.set_varint(index);

          instruction_encoder_.Encode(QpackIndexedHeaderFieldInstruction());

          break;
        case QpackHeaderTable::MatchType::kName:
          DCHECK(is_static) << "Dynamic table entries not supported yet.";

          instruction_encoder_.set_s_bit(is_static);
          instruction_encoder_.set_varint(index);
          instruction_encoder_.set_value(value);

          instruction_encoder_.Encode(
              QpackLiteralHeaderFieldNameReferenceInstruction());

          break;
        case QpackHeaderTable::MatchType::kNoMatch:
          instruction_encoder_.set_name(name);
          instruction_encoder_.set_value(value);

          instruction_encoder_.Encode(QpackLiteralHeaderFieldInstruction());

          break;
      }
    }

    DCHECK(instruction_encoder_.HasNext());

    instruction_encoder_.Next(max_length - output->size(), output);

    if (instruction_encoder_.HasNext()) {
      // There was not enough room to completely encode current header field.
      DCHECK_EQ(output->size(), max_length);

      return;
    }

    // It is possible that the output buffer was just large enough for encoding
    // the current header field, hence equality is allowed here.
    DCHECK_LE(output->size(), max_length);

    if (prefix_encoded_) {
      // Move on to the next header field.
      ++header_list_iterator_;
    } else {
      // Mark prefix as encoded.
      prefix_encoded_ = true;
    }
  } while (HasNext() && output->size() < max_length);
}

}  // namespace quic
