// 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_COMMON_BALSA_BALSA_HEADERS_H_
#define QUICHE_COMMON_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 "quiche/common/balsa/balsa_enums.h"
#include "quiche/common/balsa/header_api.h"
#include "quiche/common/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.
  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 all methods in this overload set visible, and override just 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.
  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 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 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() {
    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());
    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_;
  }

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

// A const iterator for all the header lines.
class 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 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());
  QUICHE_DCHECK_GE(it.idx_, 0u);
  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_COMMON_BALSA_BALSA_HEADERS_H_
