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

// A lightweight implementation for storing HTTP headers.

#ifndef QUICHE_BALSA_BALSA_HEADERS_H_
#define QUICHE_BALSA_BALSA_HEADERS_H_

#include <cstddef>
#include <cstring>
#include <functional>
#include <iterator>
#include <memory>
#include <ostream>
#include <string>
#include <utility>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/memory/memory.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "quiche/balsa/balsa_enums.h"
#include "quiche/balsa/header_api.h"
#include "quiche/balsa/standard_header_map.h"
#include "quiche/common/platform/api/quiche_bug_tracker.h"
#include "quiche/common/platform/api/quiche_export.h"
#include "quiche/common/platform/api/quiche_logging.h"

namespace gfe2 {
class Http2HeaderValidator;
}  // namespace gfe2

namespace quiche {

namespace test {
class BalsaHeadersTestPeer;
}  // namespace test

// WARNING:
// Note that -no- char* returned by any function in this
// file is null-terminated.

// This class exists to service the specific needs of BalsaHeaders.
//
// Functional goals:
//   1) provide a backing-store for all of the StringPieces that BalsaHeaders
//      returns. Every StringPiece returned from BalsaHeaders should remain
//      valid until the BalsaHeader's object is cleared, or the header-line is
//      erased.
//   2) provide a backing-store for BalsaFrame, which requires contiguous memory
//      for its fast-path parsing functions. Note that the cost of copying is
//      less than the cost of requiring the parser to do slow-path parsing, as
//      it would have to check for bounds every byte, instead of every 16 bytes.
//
// This class is optimized for the case where headers are stored in one of two
// buffers. It doesn't make a lot of effort to densely pack memory-- in fact,
// it -may- be somewhat memory inefficient. This possible inefficiency allows a
// certain simplicity of implementation and speed which makes it worthwhile.
// If, in the future, better memory density is required, it should be possible
// to reuse the abstraction presented by this object to achieve those goals.
//
// In the most common use-case, this memory inefficiency should be relatively
// small.
//
// Alternate implementations of BalsaBuffer may include:
//  - vector of strings, one per header line (similar to HTTPHeaders)
//  - densely packed strings:
//    - keep a sorted array/map of free-space linked lists or numbers.
//      - use the entry that most closely first your needs.
//    - at this point, perhaps just use a vector of strings, and let
//      the allocator do the right thing.
//
class QUICHE_EXPORT BalsaBuffer {
 public:
  static constexpr size_t kDefaultBlocksize = 4096;

  // The BufferBlock is a structure used internally by the
  // BalsaBuffer class to store the base buffer pointers to
  // each block, as well as the important metadata for buffer
  // sizes and bytes free. It *may* be possible to replace this
  // with a vector<char>, but it's unclear whether moving a vector
  // can invalidate pointers into it. LWG issue 2321 proposes to fix this.
  struct QUICHE_EXPORT BufferBlock {
   public:
    std::unique_ptr<char[]> buffer;
    size_t buffer_size = 0;
    size_t bytes_free = 0;

    size_t bytes_used() const { return buffer_size - bytes_free; }
    char* start_of_unused_bytes() const { return buffer.get() + bytes_used(); }

    BufferBlock() {}

    BufferBlock(std::unique_ptr<char[]> buf, size_t size, size_t free)
        : buffer(std::move(buf)), buffer_size(size), bytes_free(free) {}

    BufferBlock(const BufferBlock&) = delete;
    BufferBlock& operator=(const BufferBlock&) = delete;
    BufferBlock(BufferBlock&&) = default;
    BufferBlock& operator=(BufferBlock&&) = default;

    // Note: allocating a fresh buffer even if we could reuse an old one may let
    // us shed memory, and invalidates old StringPieces (making them easier to
    // catch with asan).
    void CopyFrom(const BufferBlock& rhs) {
      QUICHE_DCHECK(this != &rhs);
      buffer_size = rhs.buffer_size;
      bytes_free = rhs.bytes_free;
      if (rhs.buffer == nullptr) {
        buffer = nullptr;
      } else {
        buffer = std::make_unique<char[]>(buffer_size);
        memcpy(buffer.get(), rhs.buffer.get(), rhs.bytes_used());
      }
    }
  };

  typedef std::vector<BufferBlock> Blocks;

  BalsaBuffer()
      : blocksize_(kDefaultBlocksize), can_write_to_contiguous_buffer_(true) {}

  explicit BalsaBuffer(size_t blocksize)
      : blocksize_(blocksize), can_write_to_contiguous_buffer_(true) {}

  BalsaBuffer(const BalsaBuffer&) = delete;
  BalsaBuffer& operator=(const BalsaBuffer&) = delete;
  BalsaBuffer(BalsaBuffer&&) = default;
  BalsaBuffer& operator=(BalsaBuffer&&) = default;

  // Returns the total amount of memory reserved by the buffer blocks.
  size_t GetTotalBufferBlockSize() const {
    size_t buffer_size = 0;
    for (Blocks::const_iterator iter = blocks_.begin(); iter != blocks_.end();
         ++iter) {
      buffer_size += iter->buffer_size;
    }
    return buffer_size;
  }

  // Returns the total amount of memory used by the buffer blocks.
  size_t GetTotalBytesUsed() const {
    size_t bytes_used = 0;
    for (const auto& b : blocks_) {
      bytes_used += b.bytes_used();
    }
    return bytes_used;
  }

  const char* GetPtr(Blocks::size_type block_idx) const {
    QUICHE_DCHECK_LT(block_idx, blocks_.size())
        << block_idx << ", " << blocks_.size();
    return block_idx >= blocks_.size() ? nullptr
                                       : blocks_[block_idx].buffer.get();
  }

  char* GetPtr(Blocks::size_type block_idx) {
    QUICHE_DCHECK_LT(block_idx, blocks_.size())
        << block_idx << ", " << blocks_.size();
    return block_idx >= blocks_.size() ? nullptr
                                       : blocks_[block_idx].buffer.get();
  }

  // This function is different from Reserve(), as it ensures that the data
  // stored via subsequent calls to this function are all contiguous (and in
  // the order in which these writes happened). This is essentially the same
  // as a string append.
  //
  // You may call this function at any time between object
  // construction/Clear(), and the calling of the
  // NoMoreWriteToContiguousBuffer() function.
  //
  // You must not call this function after the NoMoreWriteToContiguousBuffer()
  // function is called, unless a Clear() has been called since.
  // If you do, the program will abort().
  //
  // This condition is placed upon this code so that calls to Reserve() can
  // append to the buffer in the first block safely, and without invaliding
  // the StringPiece which it returns.
  //
  // This function's main intended user is the BalsaFrame class, which,
  // for reasons of efficiency, requires that the buffer from which it parses
  // the headers be contiguous.
  //
  void WriteToContiguousBuffer(absl::string_view sp) {
    if (sp.empty()) {
      return;
    }
    QUICHE_CHECK(can_write_to_contiguous_buffer_);

    if (blocks_.empty()) {
      blocks_.push_back(AllocBlock());
    }

    QUICHE_DCHECK_GE(blocks_.size(), 1u);
    if (blocks_[0].buffer == nullptr && sp.size() <= blocksize_) {
      blocks_[0] = AllocBlock();
      memcpy(blocks_[0].start_of_unused_bytes(), sp.data(), sp.size());
    } else if (blocks_[0].bytes_free < sp.size()) {
      // the first block isn't big enough, resize it.
      const size_t old_storage_size_used = blocks_[0].bytes_used();
      // Increase to at least 2*old_storage_size_used; if sp.size() is larger,
      // we'll increase by that amount.
      const size_t new_storage_size =
          old_storage_size_used + (old_storage_size_used < sp.size()
                                       ? sp.size()
                                       : old_storage_size_used);
      std::unique_ptr<char[]> new_storage{new char[new_storage_size]};
      char* old_storage = blocks_[0].buffer.get();
      if (old_storage_size_used != 0u) {
        memcpy(new_storage.get(), old_storage, old_storage_size_used);
      }
      memcpy(new_storage.get() + old_storage_size_used, sp.data(), sp.size());
      blocks_[0].buffer = std::move(new_storage);
      blocks_[0].bytes_free = new_storage_size - old_storage_size_used;
      blocks_[0].buffer_size = new_storage_size;
    } else {
      memcpy(blocks_[0].start_of_unused_bytes(), sp.data(), sp.size());
    }
    blocks_[0].bytes_free -= sp.size();
  }

  void NoMoreWriteToContiguousBuffer() {
    can_write_to_contiguous_buffer_ = false;
  }

  // Reserves "permanent" storage of the size indicated. Returns a pointer to
  // the beginning of that storage, and assigns the index of the block used to
  // block_buffer_idx. This function uses the first block IFF the
  // NoMoreWriteToContiguousBuffer function has been called since the last
  // Clear/Construction.
  char* Reserve(size_t size, Blocks::size_type* block_buffer_idx) {
    if (blocks_.empty()) {
      blocks_.push_back(AllocBlock());
    }

    // There should always be a 'first_block', even if it
    // contains nothing.
    QUICHE_DCHECK_GE(blocks_.size(), 1u);
    BufferBlock* block = nullptr;
    Blocks::size_type block_idx = can_write_to_contiguous_buffer_ ? 1 : 0;
    for (; block_idx < blocks_.size(); ++block_idx) {
      if (blocks_[block_idx].bytes_free >= size) {
        block = &blocks_[block_idx];
        break;
      }
    }
    if (block == nullptr) {
      if (blocksize_ < size) {
        blocks_.push_back(AllocCustomBlock(size));
      } else {
        blocks_.push_back(AllocBlock());
      }
      block = &blocks_.back();
    }

    char* storage = block->start_of_unused_bytes();
    block->bytes_free -= size;
    if (block_buffer_idx != nullptr) {
      *block_buffer_idx = block_idx;
    }
    return storage;
  }

  void Clear() {
    blocks_.clear();
    blocks_.shrink_to_fit();
    can_write_to_contiguous_buffer_ = true;
  }

  void CopyFrom(const BalsaBuffer& b) {
    blocks_.resize(b.blocks_.size());
    for (Blocks::size_type i = 0; i < blocks_.size(); ++i) {
      blocks_[i].CopyFrom(b.blocks_[i]);
    }
    blocksize_ = b.blocksize_;
    can_write_to_contiguous_buffer_ = b.can_write_to_contiguous_buffer_;
  }

  const char* StartOfFirstBlock() const {
    QUICHE_BUG_IF(bug_if_1182_1, blocks_.empty())
        << "First block not allocated yet!";
    return blocks_.empty() ? nullptr : blocks_[0].buffer.get();
  }

  const char* EndOfFirstBlock() const {
    QUICHE_BUG_IF(bug_if_1182_2, blocks_.empty())
        << "First block not allocated yet!";
    return blocks_.empty() ? nullptr : blocks_[0].start_of_unused_bytes();
  }

  size_t GetReadableBytesOfFirstBlock() const {
    return blocks_.empty() ? 0 : blocks_[0].bytes_used();
  }

  bool can_write_to_contiguous_buffer() const {
    return can_write_to_contiguous_buffer_;
  }
  size_t blocksize() const { return blocksize_; }
  Blocks::size_type num_blocks() const { return blocks_.size(); }
  size_t buffer_size(size_t idx) const { return blocks_[idx].buffer_size; }
  size_t bytes_used(size_t idx) const { return blocks_[idx].bytes_used(); }

 private:
  BufferBlock AllocBlock() { return AllocCustomBlock(blocksize_); }

  BufferBlock AllocCustomBlock(size_t blocksize) {
    return BufferBlock{std::make_unique<char[]>(blocksize), blocksize,
                       blocksize};
  }

  // A container of BufferBlocks
  Blocks blocks_;

  // The default allocation size for a block.
  // In general, blocksize_ bytes will be allocated for
  // each buffer.
  size_t blocksize_;

  // If set to true, then the first block cannot be used for Reserve() calls as
  // the WriteToContiguous... function will modify the base pointer for this
  // block, and the Reserve() calls need to be sure that the base pointer will
  // not be changing in order to provide the user with StringPieces which
  // continue to be valid.
  bool can_write_to_contiguous_buffer_;
};

////////////////////////////////////////////////////////////////////////////////

// All of the functions in the BalsaHeaders class use string pieces, by either
// using the StringPiece class, or giving an explicit size and char* (as these
// are the native representation for these string pieces).
// This is done for several reasons.
//  1) This minimizes copying/allocation/deallocation as compared to using
//  string parameters
//  2) This reduces the number of strlen() calls done (as the length of any
//  string passed in is relatively likely to be known at compile time, and for
//  those strings passed back we obviate the need for a strlen() to determine
//  the size of new storage allocations if a new allocation is required.
//  3) This class attempts to store all of its data in two linear buffers in
//  order to enhance the speed of parsing and writing out to a buffer. As a
//  result, many string pieces are -not- terminated by '\0', and are not
//  c-strings.  Since this is the case, we must delineate the length of the
//  string explicitly via a length.
//
//  WARNING:  The side effect of using StringPiece is that if the underlying
//  buffer changes (due to modifying the headers) the StringPieces which point
//  to the data which was modified, may now contain "garbage", and should not
//  be dereferenced.
//  For example, If you fetch some component of the first-line, (request or
//  response), and then you modify the first line, the StringPieces you
//  originally received from the original first-line may no longer be valid).
//
//  StringPieces pointing to pieces of header lines which have not been
//  erased() or modified should be valid until the object is cleared or
//  destroyed.
//
//  Key comparisons are case-insensitive.

class QUICHE_EXPORT BalsaHeaders : public HeaderApi {
 public:
  // Each header line is parsed into a HeaderLineDescription, which maintains
  // pointers into the BalsaBuffer.
  //
  // Succinctly describes one header line as indices into a buffer.
  struct QUICHE_EXPORT HeaderLineDescription {
    HeaderLineDescription(size_t first_character_index, size_t key_end_index,
                          size_t value_begin_index, size_t last_character_index,
                          size_t buffer_base_index)
        : first_char_idx(first_character_index),
          key_end_idx(key_end_index),
          value_begin_idx(value_begin_index),
          last_char_idx(last_character_index),
          buffer_base_idx(buffer_base_index),
          skip(false) {}

    HeaderLineDescription()
        : first_char_idx(0),
          key_end_idx(0),
          value_begin_idx(0),
          last_char_idx(0),
          buffer_base_idx(0),
          skip(false) {}

    size_t KeyLength() const {
      QUICHE_DCHECK_GE(key_end_idx, first_char_idx);
      return key_end_idx - first_char_idx;
    }
    size_t ValuesLength() const {
      QUICHE_DCHECK_GE(last_char_idx, value_begin_idx);
      return last_char_idx - value_begin_idx;
    }

    size_t first_char_idx;
    size_t key_end_idx;
    size_t value_begin_idx;
    size_t last_char_idx;
    BalsaBuffer::Blocks::size_type buffer_base_idx;
    bool skip;
  };

  using HeaderTokenList = std::vector<absl::string_view>;

  // An iterator for walking through all the header lines.
  class const_header_lines_iterator;

  // An iterator that only stops at lines with a particular key
  // (case-insensitive).  See also GetIteratorForKey.
  //
  // Check against header_lines_key_end() to determine when iteration is
  // finished. lines().end() will also work.
  class const_header_lines_key_iterator;

  // A simple class that can be used in a range-based for loop.
  template <typename IteratorType>
  class QUICHE_EXPORT iterator_range {
   public:
    using iterator = IteratorType;
    using const_iterator = IteratorType;
    using value_type = typename std::iterator_traits<IteratorType>::value_type;

    iterator_range(IteratorType begin_iterator, IteratorType end_iterator)
        : begin_iterator_(std::move(begin_iterator)),
          end_iterator_(std::move(end_iterator)) {}

    IteratorType begin() const { return begin_iterator_; }
    IteratorType end() const { return end_iterator_; }

   private:
    IteratorType begin_iterator_, end_iterator_;
  };

  // Set of names of headers that might have multiple values.
  // CoalesceOption::kCoalesce can be used to match Envoy behavior in
  // WriteToBuffer().
  using MultivaluedHeadersSet =
      absl::flat_hash_set<absl::string_view, StringPieceCaseHash,
                          StringPieceCaseEqual>;

  // Map of key => vector<value>, where vector contains ordered list of all
  // values for |key| (ignoring the casing).
  using MultivaluedHeadersValuesMap =
      absl::flat_hash_map<absl::string_view, std::vector<absl::string_view>,
                          StringPieceCaseHash, StringPieceCaseEqual>;

  // TODO(fenix): Revisit the amount of bytes initially allocated to the second
  // block of the balsa_buffer_. It may make sense to pre-allocate some amount
  // (roughly the amount we'd append in new headers such as X-User-Ip, etc.)
  BalsaHeaders()
      : balsa_buffer_(4096),
        content_length_(0),
        content_length_status_(BalsaHeadersEnums::NO_CONTENT_LENGTH),
        parsed_response_code_(0),
        firstline_buffer_base_idx_(0),
        whitespace_1_idx_(0),
        non_whitespace_1_idx_(0),
        whitespace_2_idx_(0),
        non_whitespace_2_idx_(0),
        whitespace_3_idx_(0),
        non_whitespace_3_idx_(0),
        whitespace_4_idx_(0),
        transfer_encoding_is_chunked_(false) {}

  explicit BalsaHeaders(size_t bufsize)
      : balsa_buffer_(bufsize),
        content_length_(0),
        content_length_status_(BalsaHeadersEnums::NO_CONTENT_LENGTH),
        parsed_response_code_(0),
        firstline_buffer_base_idx_(0),
        whitespace_1_idx_(0),
        non_whitespace_1_idx_(0),
        whitespace_2_idx_(0),
        non_whitespace_2_idx_(0),
        whitespace_3_idx_(0),
        non_whitespace_3_idx_(0),
        whitespace_4_idx_(0),
        transfer_encoding_is_chunked_(false) {}

  // Copying BalsaHeaders is expensive, so require that it be visible.
  BalsaHeaders(const BalsaHeaders&) = delete;
  BalsaHeaders& operator=(const BalsaHeaders&) = delete;
  BalsaHeaders(BalsaHeaders&&) = default;
  BalsaHeaders& operator=(BalsaHeaders&&) = default;

  // Returns a range that represents all of the header lines.
  iterator_range<const_header_lines_iterator> lines() const;

  // Returns an iterator range consisting of the header lines matching key.
  // String backing 'key' must remain valid for lifetime of range.
  iterator_range<const_header_lines_key_iterator> lines(
      absl::string_view key) const;

  // Returns a forward-only iterator that only stops at lines matching key.
  // String backing 'key' must remain valid for lifetime of iterator.
  //
  // Check returned iterator against header_lines_key_end() to determine when
  // iteration is finished.
  //
  // Consider calling lines(key)--it may be more readable.
  const_header_lines_key_iterator GetIteratorForKey(
      absl::string_view key) const;

  const_header_lines_key_iterator header_lines_key_end() const;

  void erase(const const_header_lines_iterator& it);

  void Clear();

  // Explicit copy functions to avoid risk of accidental copies.
  BalsaHeaders Copy() const {
    BalsaHeaders copy;
    copy.CopyFrom(*this);
    return copy;
  }
  void CopyFrom(const BalsaHeaders& other);

  // Replaces header entries with key 'key' if they exist, or appends
  // a new header if none exist.  See 'AppendHeader' below for additional
  // comments about ContentLength and TransferEncoding headers. Note that this
  // will allocate new storage every time that it is called.
  // TODO(fenix): modify this function to reuse existing storage
  // if it is available.
  void ReplaceOrAppendHeader(absl::string_view key,
                             absl::string_view value) override;

  // Append a new header entry to the header object. Clients who wish to append
  // Content-Length header should use SetContentLength() method instead of
  // adding the content length header using AppendHeader (manually adding the
  // content length header will not update the content_length_ and
  // content_length_status_ values).
  // Similarly, clients who wish to add or remove the transfer encoding header
  // in order to apply or remove chunked encoding should use
  // SetTransferEncodingToChunkedAndClearContentLength() or
  // SetNoTransferEncoding() instead.
  void AppendHeader(absl::string_view key, absl::string_view value) override;

  // Appends ',value' to an existing header named 'key'.  If no header with the
  // correct key exists, it will call AppendHeader(key, value).  Calling this
  // function on a key which exists several times in the headers will produce
  // unpredictable results.
  void AppendToHeader(absl::string_view key, absl::string_view value) override;

  // Appends ', value' to an existing header named 'key'.  If no header with the
  // correct key exists, it will call AppendHeader(key, value).  Calling this
  // function on a key which exists several times in the headers will produce
  // unpredictable results.
  void AppendToHeaderWithCommaAndSpace(absl::string_view key,
                                       absl::string_view value) override;

  // Returns the value corresponding to the given header key. Returns an empty
  // string if the header key does not exist. For headers that may consist of
  // multiple lines, use GetAllOfHeader() instead.
  // Make the QuicheLowerCaseString overload visible,
  // and only override the absl::string_view one.
  using HeaderApi::GetHeader;
  absl::string_view GetHeader(absl::string_view key) const override;

  // Iterates over all currently valid header lines, appending their
  // values into the vector 'out', in top-to-bottom order.
  // Header-lines which have been erased are not currently valid, and
  // will not have their values appended. Empty values will be
  // represented as empty string. If 'key' doesn't exist in the headers at
  // all, out will not be changed. We do not clear the vector out
  // before adding new entries. If there are header lines with matching
  // key but empty value then they are also added to the vector out.
  // (Basically empty values are not treated in any special manner).
  //
  // Example:
  // Input header:
  // "GET / HTTP/1.0\r\n"
  //    "key1: v1\r\n"
  //    "key1: \r\n"
  //    "key1:\r\n"
  //    "key1:  v1\r\n"
  //    "key1:v2\r\n"
  //
  //  vector out is initially: ["foo"]
  //  vector out after GetAllOfHeader("key1", &out) is:
  // ["foo", "v1", "", "", "v1", "v2"]
  //
  // See gfe::header_properties::IsMultivaluedHeader() for which headers
  // GFE treats as being multivalued.

  // Make the QuicheLowerCaseString overload visible,
  // and only override the absl::string_view one.
  using HeaderApi::GetAllOfHeader;
  void GetAllOfHeader(absl::string_view key,
                      std::vector<absl::string_view>* out) const override;

  // Same as above, but iterates over all header lines including removed ones.
  // Appends their values into the vector 'out' in top-to-bottom order,
  // first all valid headers then all that were removed.
  void GetAllOfHeaderIncludeRemoved(absl::string_view key,
                                    std::vector<absl::string_view>* out) const;

  // Joins all values for `key` into a comma-separated string.
  // Make the QuicheLowerCaseString overload visible,
  // and only override the absl::string_view one.
  using HeaderApi::GetAllOfHeaderAsString;
  std::string GetAllOfHeaderAsString(absl::string_view key) const override;

  // Determine if a given header is present.  Case-insensitive.
  inline bool HasHeader(absl::string_view key) const override {
    return GetConstHeaderLinesIterator(key) != header_lines_.end();
  }

  // Goes through all headers with key 'key' and checks to see if one of the
  // values is 'value'.  Returns true if there are headers with the desired key
  // and value, false otherwise.  Case-insensitive for the key; case-sensitive
  // for the value.
  bool HeaderHasValue(absl::string_view key,
                      absl::string_view value) const override {
    return HeaderHasValueHelper(key, value, true);
  }
  // Same as above, but also case-insensitive for the value.
  bool HeaderHasValueIgnoreCase(absl::string_view key,
                                absl::string_view value) const override {
    return HeaderHasValueHelper(key, value, false);
  }

  // Returns true iff any header 'key' exists with non-empty value.
  bool HasNonEmptyHeader(absl::string_view key) const override;

  const_header_lines_iterator GetHeaderPosition(absl::string_view key) const;

  // Removes all headers in given set |keys| at once efficiently. Keys
  // are case insensitive.
  //
  // Alternatives considered:
  //
  // 1. Use string_hash_set<>, the caller (such as ClearHopByHopHeaders) lower
  // cases the keys and RemoveAllOfHeaderInList just does lookup. This according
  // to microbenchmark gives the best performance because it does not require
  // an extra copy of the hash table. However, it is not taken because of the
  // possible risk that caller could forget to lowercase the keys.
  //
  // 2. Use flat_hash_set<StringPiece, StringPieceCaseHash,StringPieceCaseEqual>
  // or string_hash_set<StringPieceCaseHash, StringPieceCaseEqual>. Both appear
  // to have (much) worse performance with WithoutDupToken and LongHeader case
  // in microbenchmark.
  void RemoveAllOfHeaderInList(const HeaderTokenList& keys) override;

  void RemoveAllOfHeader(absl::string_view key) override;

  // Removes all headers starting with 'key' [case insensitive]
  void RemoveAllHeadersWithPrefix(absl::string_view prefix) override;

  // Returns true if we have at least one header with given prefix
  // [case insensitive]. Currently for test use only.
  bool HasHeadersWithPrefix(absl::string_view prefix) const override;

  // Returns the key value pairs for all headers where the header key begins
  // with the specified prefix.
  void GetAllOfHeaderWithPrefix(
      absl::string_view prefix,
      std::vector<std::pair<absl::string_view, absl::string_view>>* out)
      const override;

  void GetAllHeadersWithLimit(
      std::vector<std::pair<absl::string_view, absl::string_view>>* out,
      int limit) const override;

  // Removes all values equal to a given value from header lines with given key.
  // All string operations done here are case-sensitive.
  // If a header line has only values matching the given value, the entire
  // line is removed.
  // If the given value is found in a multi-value header line mixed with other
  // values, the line is edited in-place to remove the values.
  // Returns the number of occurrences of value that were removed.
  // This method runs in linear time.
  size_t RemoveValue(absl::string_view key, absl::string_view value);

  // Returns the upper bound on the required buffer space to fully write out
  // the header object (this include the first line, all header lines, and the
  // final line separator that marks the ending of the header).
  size_t GetSizeForWriteBuffer() const override;

  // Indicates if to serialize headers with lower-case header keys.
  enum class CaseOption { kNoModification, kLowercase, kPropercase };

  // Indicates if to coalesce headers with multiple values to match Envoy/GFE3.
  enum class CoalesceOption { kNoCoalesce, kCoalesce };

  // The following WriteHeader* methods are template member functions that
  // place one requirement on the Buffer class: it must implement a Write
  // method that takes a pointer and a length. The buffer passed in is not
  // required to be stretchable. For non-stretchable buffers, the user must
  // call GetSizeForWriteBuffer() to find out the upper bound on the output
  // buffer space required to make sure that the entire header is serialized.
  // BalsaHeaders will not check that there is adequate space in the buffer
  // object during the write.

  // Writes the entire header and the final line separator that marks the end
  // of the HTTP header section to the buffer. After this method returns, no
  // more header data should be written to the buffer.
  template <typename Buffer>
  void WriteHeaderAndEndingToBuffer(Buffer* buffer, CaseOption case_option,
                                    CoalesceOption coalesce_option) const {
    WriteToBuffer(buffer, case_option, coalesce_option);
    WriteHeaderEndingToBuffer(buffer);
  }

  template <typename Buffer>
  void WriteHeaderAndEndingToBuffer(Buffer* buffer) const {
    WriteHeaderAndEndingToBuffer(buffer, CaseOption::kNoModification,
                                 CoalesceOption::kNoCoalesce);
  }

  // Writes the final line separator to the buffer to terminate the HTTP header
  // section.  After this method returns, no more header data should be written
  // to the buffer.
  template <typename Buffer>
  static void WriteHeaderEndingToBuffer(Buffer* buffer) {
    buffer->WriteString("\r\n");
  }

  // Writes the entire header to the buffer without the line separator that
  // terminates the HTTP header. This lets users append additional header lines
  // using WriteHeaderLineToBuffer and then terminate the header with
  // WriteHeaderEndingToBuffer as the header is serialized to the buffer,
  // without having to first copy the header.
  template <typename Buffer>
  void WriteToBuffer(Buffer* buffer, CaseOption case_option,
                     CoalesceOption coalesce_option) const;

  template <typename Buffer>
  void WriteToBuffer(Buffer* buffer) const {
    WriteToBuffer(buffer, CaseOption::kNoModification,
                  CoalesceOption::kNoCoalesce);
  }

  // Used by WriteToBuffer to coalesce multiple values of headers listed in
  // |multivalued_headers| into a single comma-separated value. Public for test.
  template <typename Buffer>
  void WriteToBufferCoalescingMultivaluedHeaders(
      Buffer* buffer, const MultivaluedHeadersSet& multivalued_headers,
      CaseOption case_option) const;

  // Populates |multivalues| with values of |header_lines_| with keys present
  // in |multivalued_headers| set.
  void GetValuesOfMultivaluedHeaders(
      const MultivaluedHeadersSet& multivalued_headers,
      MultivaluedHeadersValuesMap* multivalues) const;

  static std::string ToPropercase(absl::string_view header) {
    std::string copy = std::string(header);
    bool should_uppercase = true;
    for (char& c : copy) {
      if (!absl::ascii_isalnum(c)) {
        should_uppercase = true;
      } else if (should_uppercase) {
        c = absl::ascii_toupper(c);
        should_uppercase = false;
      } else {
        c = absl::ascii_tolower(c);
      }
    }
    return copy;
  }

  template <typename Buffer>
  void WriteHeaderKeyToBuffer(Buffer* buffer, absl::string_view key,
                              CaseOption case_option) const {
    if (case_option == CaseOption::kLowercase) {
      buffer->WriteString(absl::AsciiStrToLower(key));
    } else if (case_option == CaseOption::kPropercase) {
      const auto& header_set = quiche::GetStandardHeaderSet();
      auto it = header_set.find(key);
      if (it != header_set.end()) {
        buffer->WriteString(*it);
      } else {
        buffer->WriteString(ToPropercase(key));
      }
    } else {
      buffer->WriteString(key);
    }
  }

  // Takes a header line in the form of a key/value pair and append it to the
  // buffer. This function should be called after WriteToBuffer to
  // append additional header lines to the header without copying the header.
  // When the user is done with appending to the buffer,
  // WriteHeaderEndingToBuffer must be used to terminate the HTTP
  // header in the buffer. This method is a no-op if key is empty.
  template <typename Buffer>
  void WriteHeaderLineToBuffer(Buffer* buffer, absl::string_view key,
                               absl::string_view value,
                               CaseOption case_option) const {
    // If the key is empty, we don't want to write the rest because it
    // will not be a well-formed header line.
    if (!key.empty()) {
      WriteHeaderKeyToBuffer(buffer, key, case_option);
      buffer->WriteString(": ");
      buffer->WriteString(value);
      buffer->WriteString("\r\n");
    }
  }

  // Takes a header line in the form of a key and vector of values and appends
  // it to the buffer. This function should be called after WriteToBuffer to
  // append additional header lines to the header without copying the header.
  // When the user is done with appending to the buffer,
  // WriteHeaderEndingToBuffer must be used to terminate the HTTP
  // header in the buffer. This method is a no-op if the |key| is empty.
  template <typename Buffer>
  void WriteHeaderLineValuesToBuffer(
      Buffer* buffer, absl::string_view key,
      const std::vector<absl::string_view>& values,
      CaseOption case_option) const {
    // If the key is empty, we don't want to write the rest because it
    // will not be a well-formed header line.
    if (!key.empty()) {
      WriteHeaderKeyToBuffer(buffer, key, case_option);
      buffer->WriteString(": ");
      for (auto it = values.begin();;) {
        buffer->WriteString(*it);
        if (++it == values.end()) {
          break;
        }
        buffer->WriteString(",");
      }
      buffer->WriteString("\r\n");
    }
  }

  // Dump the textural representation of the header object to a string, which
  // is suitable for writing out to logs. All CRLF will be printed out as \n.
  // This function can be called on a header object in any state. Raw header
  // data will be printed out if the header object is not completely parsed,
  // e.g., when there was an error in the middle of parsing.
  // The header content is appended to the string; the original content is not
  // cleared.
  // If used in test cases, WillNotWriteFromFramer() may be of interest.
  void DumpToString(std::string* str) const;
  std::string DebugString() const override;

  bool ForEachHeader(std::function<bool(const absl::string_view key,
                                        const absl::string_view value)>
                         fn) const override;

  void DumpToPrefixedString(const char* spaces, std::string* str) const;

  absl::string_view first_line() const {
    QUICHE_DCHECK_GE(whitespace_4_idx_, non_whitespace_1_idx_);
    return whitespace_4_idx_ == non_whitespace_1_idx_
               ? ""
               : absl::string_view(
                     BeginningOfFirstLine() + non_whitespace_1_idx_,
                     whitespace_4_idx_ - non_whitespace_1_idx_);
  }
  std::string first_line_of_request() const override {
    return std::string(first_line());
  }

  // Returns the parsed value of the response code if it has been parsed.
  // Guaranteed to return 0 when unparsed (though it is a much better idea to
  // verify that the BalsaFrame had no errors while parsing).
  // This may return response codes which are outside the normal bounds of
  // HTTP response codes-- it is up to the user of this class to ensure that
  // the response code is one which is interpretable.
  size_t parsed_response_code() const override { return parsed_response_code_; }

  absl::string_view request_method() const override {
    QUICHE_DCHECK_GE(whitespace_2_idx_, non_whitespace_1_idx_);
    return whitespace_2_idx_ == non_whitespace_1_idx_
               ? ""
               : absl::string_view(
                     BeginningOfFirstLine() + non_whitespace_1_idx_,
                     whitespace_2_idx_ - non_whitespace_1_idx_);
  }

  absl::string_view response_version() const override {
    // Note: There is no difference between request_method() and
    // response_version(). They both could be called
    // GetFirstTokenFromFirstline()... but that wouldn't be anywhere near as
    // descriptive.
    return request_method();
  }

  absl::string_view request_uri() const override {
    QUICHE_DCHECK_GE(whitespace_3_idx_, non_whitespace_2_idx_);
    return whitespace_3_idx_ == non_whitespace_2_idx_
               ? ""
               : absl::string_view(
                     BeginningOfFirstLine() + non_whitespace_2_idx_,
                     whitespace_3_idx_ - non_whitespace_2_idx_);
  }

  absl::string_view response_code() const override {
    // Note: There is no difference between request_uri() and response_code().
    // They both could be called GetSecondtTokenFromFirstline(), but, as noted
    // in an earlier comment, that wouldn't be as descriptive.
    return request_uri();
  }

  absl::string_view request_version() const override {
    QUICHE_DCHECK_GE(whitespace_4_idx_, non_whitespace_3_idx_);
    return whitespace_4_idx_ == non_whitespace_3_idx_
               ? ""
               : absl::string_view(
                     BeginningOfFirstLine() + non_whitespace_3_idx_,
                     whitespace_4_idx_ - non_whitespace_3_idx_);
  }

  absl::string_view response_reason_phrase() const override {
    // Note: There is no difference between request_version() and
    // response_reason_phrase(). They both could be called
    // GetThirdTokenFromFirstline(), but, as noted in an earlier comment, that
    // wouldn't be as descriptive.
    return request_version();
  }

  void SetRequestFirstlineFromStringPieces(absl::string_view method,
                                           absl::string_view uri,
                                           absl::string_view version) {
    SetFirstlineFromStringPieces(method, uri, version);
  }

  void SetResponseFirstline(absl::string_view version,
                            size_t parsed_response_code,
                            absl::string_view reason_phrase);

  // These functions are exactly the same, except that their names are
  // different. This is done so that the code using this class is more
  // expressive.
  void SetRequestMethod(absl::string_view method) override;
  void SetResponseVersion(absl::string_view version) override;

  void SetRequestUri(absl::string_view uri) override;
  void SetResponseCode(absl::string_view code) override;
  void set_parsed_response_code(size_t parsed_response_code) {
    parsed_response_code_ = parsed_response_code;
  }
  void SetParsedResponseCodeAndUpdateFirstline(
      size_t parsed_response_code) override;

  // These functions are exactly the same, except that their names are
  // different. This is done so that the code using this class is more
  // expressive.
  void SetRequestVersion(absl::string_view version) override;
  void SetResponseReasonPhrase(absl::string_view reason_phrase) override;

  // Simple accessors to some of the internal state
  bool transfer_encoding_is_chunked() const {
    return transfer_encoding_is_chunked_;
  }

  static bool ResponseCodeImpliesNoBody(size_t code) {
    // From HTTP spec section 6.1.1 all 1xx responses must not have a body,
    // as well as 204 No Content and 304 Not Modified.
    return ((code >= 100) && (code <= 199)) || (code == 204) || (code == 304);
  }

  // Note: never check this for requests. Nothing bad will happen if you do,
  // but spec does not allow requests framed by connection close.
  // TODO(vitaliyl): refactor.
  bool is_framed_by_connection_close() const {
    // We declare that response is framed by connection close if it has no
    // content-length, no transfer encoding, and is allowed to have a body by
    // the HTTP spec.
    // parsed_response_code_ is 0 for requests, so ResponseCodeImpliesNoBody
    // will return false.
    return (content_length_status_ == BalsaHeadersEnums::NO_CONTENT_LENGTH) &&
           !transfer_encoding_is_chunked_ &&
           !ResponseCodeImpliesNoBody(parsed_response_code_);
  }

  size_t content_length() const override { return content_length_; }
  BalsaHeadersEnums::ContentLengthStatus content_length_status() const {
    return content_length_status_;
  }
  bool content_length_valid() const override {
    return content_length_status_ == BalsaHeadersEnums::VALID_CONTENT_LENGTH;
  }

  // SetContentLength, SetTransferEncodingToChunkedAndClearContentLength, and
  // SetNoTransferEncoding modifies the header object to use
  // content-length and transfer-encoding headers in a consistent
  // manner. They set all internal flags and status so client can get
  // a consistent view from various accessors.
  void SetContentLength(size_t length) override;
  // Sets transfer-encoding to chunked and updates internal state.
  void SetTransferEncodingToChunkedAndClearContentLength() override;
  // Removes transfer-encoding headers and updates internal state.
  void SetNoTransferEncoding() override;

  // If you have a response that needs framing by connection close, use this
  // method instead of RemoveAllOfHeader("Content-Length"). Has no effect if
  // transfer_encoding_is_chunked().
  void ClearContentLength();

  // This should be called if balsa headers are created entirely manually (not
  // by any of the framer classes) to make sure that function calls like
  // DumpToString will work correctly.
  void WillNotWriteFromFramer() {
    balsa_buffer_.NoMoreWriteToContiguousBuffer();
  }

  // True if DoneWritingFromFramer or WillNotWriteFromFramer is called.
  bool FramerIsDoneWriting() const {
    return !balsa_buffer_.can_write_to_contiguous_buffer();
  }

  bool IsEmpty() const override;

  // From HeaderApi and ConstHeaderApi.
  absl::string_view Authority() const override;
  void ReplaceOrAppendAuthority(absl::string_view value) override;
  void RemoveAuthority() override;
  void ApplyToCookie(
      std::function<void(absl::string_view cookie)> f) const override;

  void set_enforce_header_policy(bool enforce) override {
    enforce_header_policy_ = enforce;
  }

  // Removes the last token from the header value. In the presence of multiple
  // header lines with given key, will remove the last token of the last line.
  // Can be useful if the last encoding has to be removed.
  void RemoveLastTokenFromHeaderValue(absl::string_view key);

  // Gets the list of names of headers that are multivalued in Envoy.
  static const MultivaluedHeadersSet& multivalued_envoy_headers();

  // Returns true if HTTP responses with this response code have bodies.
  static bool ResponseCanHaveBody(int response_code);

  // Given a pointer to the beginning and the end of the header value
  // in some buffer, populates tokens list with beginning and end indices
  // of all tokens present in the value string.
  static void ParseTokenList(absl::string_view header_value,
                             HeaderTokenList* tokens);

 private:
  typedef std::vector<HeaderLineDescription> HeaderLines;

  class iterator_base;

  friend class BalsaFrame;
  friend class gfe2::Http2HeaderValidator;
  friend class SpdyPayloadFramer;
  friend class HTTPMessage;
  friend class test::BalsaHeadersTestPeer;

  friend bool ParseHTTPFirstLine(const char* begin, const char* end,
                                 bool is_request, BalsaHeaders* headers,
                                 BalsaFrameEnums::ErrorCode* error_code);

  // Reverse iterators have been removed for lack of use, refer to
  // cl/30618773 in case they are needed.

  const char* BeginningOfFirstLine() const {
    return GetPtr(firstline_buffer_base_idx_);
  }

  char* BeginningOfFirstLine() { return GetPtr(firstline_buffer_base_idx_); }

  char* GetPtr(BalsaBuffer::Blocks::size_type block_idx) {
    return balsa_buffer_.GetPtr(block_idx);
  }

  const char* GetPtr(BalsaBuffer::Blocks::size_type block_idx) const {
    return balsa_buffer_.GetPtr(block_idx);
  }

  void WriteFromFramer(const char* ptr, size_t size) {
    balsa_buffer_.WriteToContiguousBuffer(absl::string_view(ptr, size));
  }

  void DoneWritingFromFramer() {
    balsa_buffer_.NoMoreWriteToContiguousBuffer();
  }

  const char* OriginalHeaderStreamBegin() const {
    return balsa_buffer_.StartOfFirstBlock();
  }

  const char* OriginalHeaderStreamEnd() const {
    return balsa_buffer_.EndOfFirstBlock();
  }

  size_t GetReadableBytesFromHeaderStream() const {
    return balsa_buffer_.GetReadableBytesOfFirstBlock();
  }

  absl::string_view GetReadablePtrFromHeaderStream() {
    return {OriginalHeaderStreamBegin(), GetReadableBytesFromHeaderStream()};
  }

  absl::string_view GetValueFromHeaderLineDescription(
      const HeaderLineDescription& line) const;

  void AddAndMakeDescription(absl::string_view key, absl::string_view value,
                             HeaderLineDescription* d);

  void AppendAndMakeDescription(absl::string_view key, absl::string_view value,
                                HeaderLineDescription* d);

  // Removes all header lines with the given key starting at start.
  void RemoveAllOfHeaderStartingAt(absl::string_view key,
                                   HeaderLines::iterator start);

  HeaderLines::const_iterator GetConstHeaderLinesIterator(
      absl::string_view key) const;

  HeaderLines::iterator GetHeaderLinesIterator(absl::string_view key,
                                               HeaderLines::iterator start);

  HeaderLines::iterator GetHeaderLinesIteratorForLastMultivaluedHeader(
      absl::string_view key);

  template <typename IteratorType>
  const IteratorType HeaderLinesBeginHelper() const;

  template <typename IteratorType>
  const IteratorType HeaderLinesEndHelper() const;

  // Helper function for HeaderHasValue and HeaderHasValueIgnoreCase that
  // does most of the work.
  bool HeaderHasValueHelper(absl::string_view key, absl::string_view value,
                            bool case_sensitive) const;

  // Called by header removal methods to reset internal values for transfer
  // encoding or content length if we're removing the corresponding headers.
  void MaybeClearSpecialHeaderValues(absl::string_view key);

  void SetFirstlineFromStringPieces(absl::string_view firstline_a,
                                    absl::string_view firstline_b,
                                    absl::string_view firstline_c);
  BalsaBuffer balsa_buffer_;

  size_t content_length_;
  BalsaHeadersEnums::ContentLengthStatus content_length_status_;
  size_t parsed_response_code_;
  // HTTP firstlines all have the following structure:
  //  LWS         NONWS  LWS    NONWS   LWS    NONWS   NOTCRLF  CRLF
  //  [\t \r\n]+ [^\t ]+ [\t ]+ [^\t ]+ [\t ]+ [^\t ]+ [^\r\n]+ "\r\n"
  //  ws1        nws1    ws2    nws2    ws3    nws3             ws4
  //  |          [-------)      [-------)      [----------------)
  //    REQ:     method         request_uri    version
  //   RESP:     version        statuscode     reason
  //
  //   The first NONWS->LWS component we'll call firstline_a.
  //   The second firstline_b, and the third firstline_c.
  //
  //   firstline_a goes from nws1 to (but not including) ws2
  //   firstline_b goes from nws2 to (but not including) ws3
  //   firstline_c goes from nws3 to (but not including) ws4
  //
  // In the code:
  //    ws1 == whitespace_1_idx_
  //   nws1 == non_whitespace_1_idx_
  //    ws2 == whitespace_2_idx_
  //   nws2 == non_whitespace_2_idx_
  //    ws3 == whitespace_3_idx_
  //   nws3 == non_whitespace_3_idx_
  //    ws4 == whitespace_4_idx_
  BalsaBuffer::Blocks::size_type firstline_buffer_base_idx_;
  size_t whitespace_1_idx_;
  size_t non_whitespace_1_idx_;
  size_t whitespace_2_idx_;
  size_t non_whitespace_2_idx_;
  size_t whitespace_3_idx_;
  size_t non_whitespace_3_idx_;
  size_t whitespace_4_idx_;

  bool transfer_encoding_is_chunked_;

  // If true, QUICHE_BUG if a header that starts with an invalid prefix is
  // explicitly set.
  bool enforce_header_policy_ = true;

  HeaderLines header_lines_;
};

// Base class for iterating the headers in a BalsaHeaders object, returning a
// pair of string_view's for each header.
class QUICHE_EXPORT BalsaHeaders::iterator_base
    : public std::iterator<std::forward_iterator_tag,
                           std::pair<absl::string_view, absl::string_view>> {
 public:
  iterator_base() : headers_(nullptr), idx_(0) {}

  std::pair<absl::string_view, absl::string_view>& operator*() const {
    return Lookup(idx_);
  }

  std::pair<absl::string_view, absl::string_view>* operator->() const {
    return &(this->operator*());
  }

  bool operator==(const BalsaHeaders::iterator_base& it) const {
    return idx_ == it.idx_;
  }

  bool operator<(const BalsaHeaders::iterator_base& it) const {
    return idx_ < it.idx_;
  }

  bool operator<=(const BalsaHeaders::iterator_base& it) const {
    return idx_ <= it.idx_;
  }

  bool operator!=(const BalsaHeaders::iterator_base& it) const {
    return !(*this == it);
  }

  bool operator>(const BalsaHeaders::iterator_base& it) const {
    return it < *this;
  }

  bool operator>=(const BalsaHeaders::iterator_base& it) const {
    return it <= *this;
  }

  // This mainly exists so that we can have interesting output for
  // unittesting. The EXPECT_EQ, EXPECT_NE functions require that
  // operator<< work for the classes it sees.  It would be better if there
  // was an additional traits-like system for the gUnit output... but oh
  // well.
  friend QUICHE_EXPORT std::ostream& operator<<(std::ostream& os,
                                                const iterator_base& it) {
    os << "[" << it.headers_ << ", " << it.idx_ << "]";
    return os;
  }

 private:
  friend class BalsaHeaders;

  iterator_base(const BalsaHeaders* headers, HeaderLines::size_type index)
      : headers_(headers), idx_(index) {}

  void increment() {
    value_.reset();
    const HeaderLines& header_lines = headers_->header_lines_;
    const HeaderLines::size_type header_lines_size = header_lines.size();
    const HeaderLines::size_type original_idx = idx_;
    do {
      ++idx_;
    } while (idx_ < header_lines_size && header_lines[idx_].skip == true);
    // The condition below exists so that ++(end() - 1) == end(), even
    // if there are only 'skip == true' elements between the end() iterator
    // and the end of the vector of HeaderLineDescriptions.
    // TODO(fenix): refactor this list so that we don't have to do
    // linear scanning through skipped headers (and this condition is
    // then unnecessary)
    if (idx_ == header_lines_size) {
      idx_ = original_idx + 1;
    }
  }

  std::pair<absl::string_view, absl::string_view>& Lookup(
      HeaderLines::size_type index) const {
    QUICHE_DCHECK_LT(index, headers_->header_lines_.size());
    if (!value_.has_value()) {
      const HeaderLineDescription& line = headers_->header_lines_[index];
      const char* stream_begin = headers_->GetPtr(line.buffer_base_idx);
      value_ =
          std::make_pair(absl::string_view(stream_begin + line.first_char_idx,
                                           line.KeyLength()),
                         absl::string_view(stream_begin + line.value_begin_idx,
                                           line.ValuesLength()));
    }
    return value_.value();
  }

  const BalsaHeaders* headers_;
  HeaderLines::size_type idx_;
  mutable absl::optional<std::pair<absl::string_view, absl::string_view>>
      value_;
};

// A const iterator for all the header lines.
class QUICHE_EXPORT BalsaHeaders::const_header_lines_iterator
    : public BalsaHeaders::iterator_base {
 public:
  const_header_lines_iterator() : iterator_base() {}

  const_header_lines_iterator& operator++() {
    iterator_base::increment();
    return *this;
  }

 private:
  friend class BalsaHeaders;

  const_header_lines_iterator(const BalsaHeaders* headers,
                              HeaderLines::size_type index)
      : iterator_base(headers, index) {}
};

// A const iterator that stops only on header lines for a particular key.
class QUICHE_EXPORT BalsaHeaders::const_header_lines_key_iterator
    : public BalsaHeaders::iterator_base {
 public:
  const_header_lines_key_iterator& operator++() {
    do {
      iterator_base::increment();
    } while (!AtEnd() && !absl::EqualsIgnoreCase(key_, (**this).first));
    return *this;
  }

  // Only forward-iteration makes sense, so no operator-- defined.

 private:
  friend class BalsaHeaders;

  const_header_lines_key_iterator(const BalsaHeaders* headers,
                                  HeaderLines::size_type index,
                                  absl::string_view key)
      : iterator_base(headers, index), key_(key) {}

  // Should only be used for creating an end iterator.
  const_header_lines_key_iterator(const BalsaHeaders* headers,
                                  HeaderLines::size_type index)
      : iterator_base(headers, index) {}

  bool AtEnd() const { return *this >= headers_->lines().end(); }

  absl::string_view key_;
};

inline BalsaHeaders::iterator_range<BalsaHeaders::const_header_lines_iterator>
BalsaHeaders::lines() const {
  return {HeaderLinesBeginHelper<const_header_lines_iterator>(),
          HeaderLinesEndHelper<const_header_lines_iterator>()};
}

inline BalsaHeaders::iterator_range<
    BalsaHeaders::const_header_lines_key_iterator>
BalsaHeaders::lines(absl::string_view key) const {
  return {GetIteratorForKey(key), header_lines_key_end()};
}

inline BalsaHeaders::const_header_lines_key_iterator
BalsaHeaders::header_lines_key_end() const {
  return HeaderLinesEndHelper<const_header_lines_key_iterator>();
}

inline void BalsaHeaders::erase(const const_header_lines_iterator& it) {
  QUICHE_DCHECK_EQ(it.headers_, this);
  QUICHE_DCHECK_LT(it.idx_, header_lines_.size());
  header_lines_[it.idx_].skip = true;
}

template <typename Buffer>
void BalsaHeaders::WriteToBuffer(Buffer* buffer, CaseOption case_option,
                                 CoalesceOption coalesce_option) const {
  // write the first line.
  const absl::string_view firstline = first_line();
  if (!firstline.empty()) {
    buffer->WriteString(firstline);
  }
  buffer->WriteString("\r\n");
  if (coalesce_option != CoalesceOption::kCoalesce) {
    const HeaderLines::size_type end = header_lines_.size();
    for (HeaderLines::size_type i = 0; i < end; ++i) {
      const HeaderLineDescription& line = header_lines_[i];
      if (line.skip) {
        continue;
      }
      const char* line_ptr = GetPtr(line.buffer_base_idx);
      WriteHeaderLineToBuffer(
          buffer,
          absl::string_view(line_ptr + line.first_char_idx, line.KeyLength()),
          absl::string_view(line_ptr + line.value_begin_idx,
                            line.ValuesLength()),
          case_option);
    }
  } else {
    WriteToBufferCoalescingMultivaluedHeaders(
        buffer, multivalued_envoy_headers(), case_option);
  }
}

inline void BalsaHeaders::GetValuesOfMultivaluedHeaders(
    const MultivaluedHeadersSet& multivalued_headers,
    MultivaluedHeadersValuesMap* multivalues) const {
  multivalues->reserve(header_lines_.capacity());

  // Find lines that need to be coalesced and store them in |multivalues|.
  for (const auto& line : header_lines_) {
    if (line.skip) {
      continue;
    }
    const char* line_ptr = GetPtr(line.buffer_base_idx);
    absl::string_view header_key =
        absl::string_view(line_ptr + line.first_char_idx, line.KeyLength());
    // If this is multivalued header, it may need to be coalesced.
    if (multivalued_headers.contains(header_key)) {
      absl::string_view header_value = absl::string_view(
          line_ptr + line.value_begin_idx, line.ValuesLength());
      // Add |header_value| to the vector of values for this |header_key|,
      // therefore preserving the order of values for the same key.
      (*multivalues)[header_key].push_back(header_value);
    }
  }
}

template <typename Buffer>
void BalsaHeaders::WriteToBufferCoalescingMultivaluedHeaders(
    Buffer* buffer, const MultivaluedHeadersSet& multivalued_headers,
    CaseOption case_option) const {
  MultivaluedHeadersValuesMap multivalues;
  GetValuesOfMultivaluedHeaders(multivalued_headers, &multivalues);

  // Write out header lines while coalescing those that need to be coalesced.
  for (const auto& line : header_lines_) {
    if (line.skip) {
      continue;
    }
    const char* line_ptr = GetPtr(line.buffer_base_idx);
    absl::string_view header_key =
        absl::string_view(line_ptr + line.first_char_idx, line.KeyLength());
    auto header_multivalue = multivalues.find(header_key);
    // If current line doesn't need to be coalesced (as it is either not
    // multivalue, or has just a single value so it equals to current line),
    // then just write it out.
    if (header_multivalue == multivalues.end() ||
        header_multivalue->second.size() == 1) {
      WriteHeaderLineToBuffer(buffer, header_key,
                              absl::string_view(line_ptr + line.value_begin_idx,
                                                line.ValuesLength()),
                              case_option);
    } else {
      // If this line needs to be coalesced, then write all its values and clear
      // them, so the subsequent same header keys will not be written.
      if (!header_multivalue->second.empty()) {
        WriteHeaderLineValuesToBuffer(buffer, header_key,
                                      header_multivalue->second, case_option);
        // Clear the multivalue list as it is already written out, so subsequent
        // same header keys will not be written.
        header_multivalue->second.clear();
      }
    }
  }
}

template <typename IteratorType>
const IteratorType BalsaHeaders::HeaderLinesBeginHelper() const {
  if (header_lines_.empty()) {
    return IteratorType(this, 0);
  }
  const HeaderLines::size_type header_lines_size = header_lines_.size();
  for (HeaderLines::size_type i = 0; i < header_lines_size; ++i) {
    if (header_lines_[i].skip == false) {
      return IteratorType(this, i);
    }
  }
  return IteratorType(this, 0);
}

template <typename IteratorType>
const IteratorType BalsaHeaders::HeaderLinesEndHelper() const {
  if (header_lines_.empty()) {
    return IteratorType(this, 0);
  }
  const HeaderLines::size_type header_lines_size = header_lines_.size();
  HeaderLines::size_type i = header_lines_size;
  do {
    --i;
    if (header_lines_[i].skip == false) {
      return IteratorType(this, i + 1);
    }
  } while (i != 0);
  return IteratorType(this, 0);
}

}  // namespace quiche

#endif  // QUICHE_BALSA_BALSA_HEADERS_H_
