// 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/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_PRIVATE 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_PRIVATE 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 = absl::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{absl::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_PRIVATE BalsaHeaders : public HeaderApi {
 public:
  // Each header line is parsed into a HeaderLineDescription, which maintains
  // pointers into the BalsaBuffer.
  struct HeaderLineDescription;

  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_PRIVATE 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_;
};

// Succinctly describes one header line as indices into a buffer.
struct QUICHE_EXPORT_PRIVATE BalsaHeaders::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;
};

// Base class for iterating the headers in a BalsaHeaders object, returning a
// pair of string_view's for each header.
class QUICHE_EXPORT_PRIVATE 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_PRIVATE 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_PRIVATE 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_PRIVATE 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_
