#include "quiche/binary_http/binary_http_message.h"

#include <algorithm>
#include <cstdint>
#include <functional>
#include <iterator>
#include <memory>
#include <optional>
#include <ostream>
#include <string>
#include <utility>
#include <vector>

#include "absl/base/attributes.h"
#include "absl/container/flat_hash_map.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/ascii.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "quiche/common/quiche_callbacks.h"
#include "quiche/common/quiche_data_reader.h"
#include "quiche/common/quiche_data_writer.h"

namespace quiche {
namespace {

constexpr uint64_t kKnownLengthRequestFraming = 0;
constexpr uint64_t kKnownLengthResponseFraming = 1;
constexpr uint64_t kIndeterminateLengthRequestFraming = 2;
constexpr uint64_t kIndeterminateLengthResponseFraming = 3;
constexpr uint64_t kContentTerminator = 0;

bool ReadStringValue(quiche::QuicheDataReader& reader, std::string& data) {
  absl::string_view data_view;
  if (!reader.ReadStringPieceVarInt62(&data_view)) {
    return false;
  }
  data = std::string(data_view);
  return true;
}

bool IsValidPadding(absl::string_view data) {
  return std::all_of(data.begin(), data.end(),
                     [](char c) { return c == '\0'; });
}

absl::StatusOr<BinaryHttpRequest::ControlData> DecodeControlData(
    quiche::QuicheDataReader& reader) {
  BinaryHttpRequest::ControlData control_data;
  if (!ReadStringValue(reader, control_data.method)) {
    return absl::InvalidArgumentError("Failed to read method.");
  }
  if (!ReadStringValue(reader, control_data.scheme)) {
    return absl::InvalidArgumentError("Failed to read scheme.");
  }
  if (!ReadStringValue(reader, control_data.authority)) {
    return absl::InvalidArgumentError("Failed to read authority.");
  }
  if (!ReadStringValue(reader, control_data.path)) {
    return absl::InvalidArgumentError("Failed to read path.");
  }
  return control_data;
}

// Decodes a header/trailer name and value. This takes a length which represents
// only the name length.
absl::StatusOr<BinaryHttpMessage::FieldView> DecodeField(
    QuicheDataReader& reader, uint64_t name_length) {
  absl::string_view name;
  if (!reader.ReadStringPiece(&name, name_length)) {
    return absl::OutOfRangeError("Not enough data to read field name.");
  }
  absl::string_view value;
  if (!reader.ReadStringPieceVarInt62(&value)) {
    return absl::OutOfRangeError("Not enough data to read field value.");
  }
  return BinaryHttpMessage::FieldView{name, value};
}

absl::Status DecodeFields(quiche::QuicheDataReader& reader,
                          quiche::UnretainedCallback<void(
                              absl::string_view name, absl::string_view value)>
                              callback) {
  absl::string_view fields;
  if (!reader.ReadStringPieceVarInt62(&fields)) {
    return absl::InvalidArgumentError("Failed to read fields.");
  }
  quiche::QuicheDataReader fields_reader(fields);
  while (!fields_reader.IsDoneReading()) {
    absl::string_view name;
    if (!fields_reader.ReadStringPieceVarInt62(&name)) {
      return absl::InvalidArgumentError("Failed to read field name.");
    }
    absl::string_view value;
    if (!fields_reader.ReadStringPieceVarInt62(&value)) {
      return absl::InvalidArgumentError("Failed to read field value.");
    }
    callback(name, value);
  }
  return absl::OkStatus();
}

absl::Status DecodeFieldsAndBody(quiche::QuicheDataReader& reader,
                                 BinaryHttpMessage& message) {
  if (const absl::Status status = DecodeFields(
          reader,
          [&message](absl::string_view name, absl::string_view value) {
            message.AddHeaderField({std::string(name), std::string(value)});
          });
      !status.ok()) {
    return status;
  }
  // Exit early if message has been truncated.
  // https://www.rfc-editor.org/rfc/rfc9292#section-3.8
  if (reader.IsDoneReading()) {
    return absl::OkStatus();
  }

  absl::string_view body;
  if (!reader.ReadStringPieceVarInt62(&body)) {
    return absl::InvalidArgumentError("Failed to read body.");
  }
  message.set_body(std::string(body));
  // TODO(bschneider): Check for / read-in any trailer-fields
  return absl::OkStatus();
}

absl::StatusOr<BinaryHttpRequest> DecodeKnownLengthRequest(
    quiche::QuicheDataReader& reader) {
  const auto control_data = DecodeControlData(reader);
  if (!control_data.ok()) {
    return control_data.status();
  }
  BinaryHttpRequest request(std::move(*control_data));
  if (reader.IsDoneReading()) {
    // Per RFC 9292, Section 3.8, "Decoders MUST treat missing truncated fields
    // as equivalent to having been sent with the length field set to zero."
    // If we've run out of payload, stop parsing and return the request.
    return request;
  }
  if (const absl::Status status = DecodeFieldsAndBody(reader, request);
      !status.ok()) {
    return status;
  }
  if (!IsValidPadding(reader.PeekRemainingPayload())) {
    return absl::InvalidArgumentError("Non-zero padding.");
  }
  request.set_num_padding_bytes(reader.BytesRemaining());
  return request;
}

absl::StatusOr<BinaryHttpResponse> DecodeKnownLengthResponse(
    quiche::QuicheDataReader& reader) {
  std::vector<std::pair<uint16_t, std::vector<BinaryHttpMessage::Field>>>
      informational_responses;
  uint64_t status_code;
  bool reading_response_control_data = true;
  while (reading_response_control_data) {
    if (!reader.ReadVarInt62(&status_code)) {
      return absl::InvalidArgumentError("Failed to read status code.");
    }
    if (status_code >= 100 && status_code <= 199) {
      std::vector<BinaryHttpMessage::Field> fields;
      if (const absl::Status status = DecodeFields(
              reader,
              [&fields](absl::string_view name, absl::string_view value) {
                fields.push_back({std::string(name), std::string(value)});
              });
          !status.ok()) {
        return status;
      }
      informational_responses.emplace_back(status_code, std::move(fields));
    } else {
      reading_response_control_data = false;
    }
  }
  BinaryHttpResponse response(status_code);
  for (const auto& informational_response : informational_responses) {
    if (const absl::Status status = response.AddInformationalResponse(
            informational_response.first,
            std::move(informational_response.second));
        !status.ok()) {
      return status;
    }
  }
  if (const absl::Status status = DecodeFieldsAndBody(reader, response);
      !status.ok()) {
    return status;
  }
  if (!IsValidPadding(reader.PeekRemainingPayload())) {
    return absl::InvalidArgumentError("Non-zero padding.");
  }
  response.set_num_padding_bytes(reader.BytesRemaining());
  return response;
}

uint64_t StringPieceVarInt62Len(absl::string_view s) {
  return quiche::QuicheDataWriter::GetVarInt62Len(s.length()) + s.length();
}
}  // namespace

void BinaryHttpMessage::Fields::AddField(BinaryHttpMessage::Field field) {
  fields_.push_back(std::move(field));
}

// Encode fields in the order they were initially inserted.
// Updates do not change order.
absl::Status BinaryHttpMessage::Fields::Encode(
    quiche::QuicheDataWriter& writer) const {
  if (!writer.WriteVarInt62(EncodedFieldsSize())) {
    return absl::InvalidArgumentError("Failed to write encoded field size.");
  }
  for (const BinaryHttpMessage::Field& field : fields_) {
    if (!writer.WriteStringPieceVarInt62(field.name)) {
      return absl::InvalidArgumentError("Failed to write field name.");
    }
    if (!writer.WriteStringPieceVarInt62(field.value)) {
      return absl::InvalidArgumentError("Failed to write field value.");
    }
  }
  return absl::OkStatus();
}

size_t BinaryHttpMessage::Fields::EncodedSize() const {
  const size_t size = EncodedFieldsSize();
  return size + quiche::QuicheDataWriter::GetVarInt62Len(size);
}

size_t BinaryHttpMessage::Fields::EncodedFieldsSize() const {
  size_t size = 0;
  for (const BinaryHttpMessage::Field& field : fields_) {
    size += StringPieceVarInt62Len(field.name) +
            StringPieceVarInt62Len(field.value);
  }
  return size;
}

BinaryHttpMessage* BinaryHttpMessage::AddHeaderField(
    BinaryHttpMessage::Field field) {
  const std::string lower_name = absl::AsciiStrToLower(field.name);
  if (lower_name == "host") {
    has_host_ = true;
  }
  header_fields_.AddField({std::move(lower_name), std::move(field.value)});
  return this;
}

// Appends the encoded fields and body to data.
absl::Status BinaryHttpMessage::EncodeKnownLengthFieldsAndBody(
    quiche::QuicheDataWriter& writer) const {
  if (const absl::Status status = header_fields_.Encode(writer); !status.ok()) {
    return status;
  }
  if (!writer.WriteStringPieceVarInt62(body_)) {
    return absl::InvalidArgumentError("Failed to encode body.");
  }
  // TODO(bschneider): Consider support for trailer fields on known-length
  // requests. Trailers are atypical for a known-length request.
  return absl::OkStatus();
}

size_t BinaryHttpMessage::EncodedKnownLengthFieldsAndBodySize() const {
  return header_fields_.EncodedSize() + StringPieceVarInt62Len(body_);
}

absl::Status BinaryHttpResponse::AddInformationalResponse(
    uint16_t status_code, std::vector<Field> header_fields) {
  if (status_code < 100) {
    return absl::InvalidArgumentError("status code < 100");
  }
  if (status_code > 199) {
    return absl::InvalidArgumentError("status code > 199");
  }
  InformationalResponse data(status_code);
  for (Field& header : header_fields) {
    data.AddField(header.name, std::move(header.value));
  }
  informational_response_control_data_.push_back(std::move(data));
  return absl::OkStatus();
}

absl::StatusOr<std::string> BinaryHttpResponse::Serialize() const {
  // Only supporting known length requests so far.
  return EncodeAsKnownLength();
}

absl::StatusOr<std::string> BinaryHttpResponse::EncodeAsKnownLength() const {
  std::string data;
  data.resize(EncodedSize());
  quiche::QuicheDataWriter writer(data.size(), data.data());
  if (!writer.WriteVarInt62(kKnownLengthResponseFraming)) {
    return absl::InvalidArgumentError("Failed to write framing indicator");
  }
  // Informational response
  for (const auto& informational : informational_response_control_data_) {
    if (const absl::Status status = informational.Encode(writer);
        !status.ok()) {
      return status;
    }
  }
  if (!writer.WriteVarInt62(status_code_)) {
    return absl::InvalidArgumentError("Failed to write status code");
  }
  if (const absl::Status status = EncodeKnownLengthFieldsAndBody(writer);
      !status.ok()) {
    return status;
  }
  QUICHE_DCHECK_EQ(writer.remaining(), num_padding_bytes());
  writer.WritePadding();
  return data;
}

size_t BinaryHttpResponse::EncodedSize() const {
  size_t size = QuicheDataWriter::GetVarInt62Len(kKnownLengthResponseFraming);
  for (const auto& informational : informational_response_control_data_) {
    size += informational.EncodedSize();
  }
  return size + quiche::QuicheDataWriter::GetVarInt62Len(status_code_) +
         EncodedKnownLengthFieldsAndBodySize() + num_padding_bytes();
}

void BinaryHttpResponse::InformationalResponse::AddField(absl::string_view name,
                                                         std::string value) {
  fields_.AddField({absl::AsciiStrToLower(name), std::move(value)});
}

// Appends the encoded fields and body to data.
absl::Status BinaryHttpResponse::InformationalResponse::Encode(
    quiche::QuicheDataWriter& writer) const {
  writer.WriteVarInt62(status_code_);
  return fields_.Encode(writer);
}

size_t BinaryHttpResponse::InformationalResponse::EncodedSize() const {
  return quiche::QuicheDataWriter::GetVarInt62Len(status_code_) +
         fields_.EncodedSize();
}

absl::StatusOr<std::string> BinaryHttpRequest::Serialize() const {
  // Only supporting known length requests so far.
  return EncodeAsKnownLength();
}

// https://www.ietf.org/archive/id/draft-ietf-httpbis-binary-message-06.html#name-request-control-data
absl::Status BinaryHttpRequest::EncodeControlData(
    quiche::QuicheDataWriter& writer) const {
  if (!writer.WriteStringPieceVarInt62(control_data_.method)) {
    return absl::InvalidArgumentError("Failed to encode method.");
  }
  if (!writer.WriteStringPieceVarInt62(control_data_.scheme)) {
    return absl::InvalidArgumentError("Failed to encode scheme.");
  }
  // the Host header field is not replicated in the :authority field, as is
  // required for ensuring that the request is reproduced accurately; see
  // Section 8.1.2.3 of [H2].
  if (!has_host()) {
    if (!writer.WriteStringPieceVarInt62(control_data_.authority)) {
      return absl::InvalidArgumentError("Failed to encode authority.");
    }
  } else {
    if (!writer.WriteStringPieceVarInt62("")) {
      return absl::InvalidArgumentError("Failed to encode authority.");
    }
  }
  if (!writer.WriteStringPieceVarInt62(control_data_.path)) {
    return absl::InvalidArgumentError("Failed to encode path.");
  }
  return absl::OkStatus();
}

size_t BinaryHttpRequest::EncodedControlDataSize() const {
  size_t size = StringPieceVarInt62Len(control_data_.method) +
                StringPieceVarInt62Len(control_data_.scheme) +
                StringPieceVarInt62Len(control_data_.path);
  if (!has_host()) {
    size += StringPieceVarInt62Len(control_data_.authority);
  } else {
    size += StringPieceVarInt62Len("");
  }
  return size;
}

size_t BinaryHttpRequest::EncodedSize() const {
  return QuicheDataWriter::GetVarInt62Len(kKnownLengthRequestFraming) +
         EncodedControlDataSize() + EncodedKnownLengthFieldsAndBodySize() +
         num_padding_bytes();
}

// https://www.ietf.org/archive/id/draft-ietf-httpbis-binary-message-06.html#name-known-length-messages
absl::StatusOr<std::string> BinaryHttpRequest::EncodeAsKnownLength() const {
  std::string data;
  data.resize(EncodedSize());
  quiche::QuicheDataWriter writer(data.size(), data.data());
  if (!writer.WriteVarInt62(kKnownLengthRequestFraming)) {
    return absl::InvalidArgumentError("Failed to encode framing indicator.");
  }
  if (const absl::Status status = EncodeControlData(writer); !status.ok()) {
    return status;
  }
  if (const absl::Status status = EncodeKnownLengthFieldsAndBody(writer);
      !status.ok()) {
    return status;
  }
  QUICHE_DCHECK_EQ(writer.remaining(), num_padding_bytes());
  writer.WritePadding();
  return data;
}

absl::StatusOr<BinaryHttpRequest> BinaryHttpRequest::Create(
    absl::string_view data) {
  quiche::QuicheDataReader reader(data);
  uint64_t framing;
  if (!reader.ReadVarInt62(&framing)) {
    return absl::InvalidArgumentError("Missing framing indicator.");
  }
  if (framing == kKnownLengthRequestFraming) {
    return DecodeKnownLengthRequest(reader);
  }
  return absl::UnimplementedError(
      absl::StrCat("Unsupported framing type ", framing));
}

absl::Status
BinaryHttpRequest::IndeterminateLengthDecoder::DecodeContentTerminatedSection(
    QuicheDataReader& reader) {
  uint64_t length_or_content_terminator;
  do {
    if (!reader.ReadVarInt62(&length_or_content_terminator)) {
      return absl::OutOfRangeError("Not enough data to read section.");
    }
    if (length_or_content_terminator != kContentTerminator) {
      switch (current_section_) {
        case MessageSection::kHeader: {
          const absl::StatusOr<FieldView> field =
              DecodeField(reader, length_or_content_terminator);
          if (!field.ok()) {
            return field.status();
          }
          const absl::Status section_status =
              message_section_handler_.OnHeader(field->name, field->value);
          if (!section_status.ok()) {
            return absl::InternalError(absl::StrCat("Failed to handle header: ",
                                                    section_status.message()));
          }
          break;
        }
        case MessageSection::kBody: {
          absl::string_view body_chunk;
          if (!reader.ReadStringPiece(&body_chunk,
                                      length_or_content_terminator)) {
            return absl::OutOfRangeError("Failed to read body chunk.");
          }
          const absl::Status section_status =
              message_section_handler_.OnBodyChunk(body_chunk);
          if (!section_status.ok()) {
            return absl::InternalError(absl::StrCat(
                "Failed to handle body chunk: ", section_status.message()));
          }
          break;
        }
        case MessageSection::kTrailer: {
          const absl::StatusOr<FieldView> field =
              DecodeField(reader, length_or_content_terminator);
          if (!field.ok()) {
            return field.status();
          }
          const absl::Status section_status =
              message_section_handler_.OnTrailer(field->name, field->value);
          if (!section_status.ok()) {
            return absl::InternalError(absl::StrCat(
                "Failed to handle trailer: ", section_status.message()));
          }
          break;
        }
        default:
          return absl::InternalError(
              "Unexpected section in DecodeContentTerminatedSection.");
      }
    }
    // Either a section was successfully decoded or a content terminator was
    // encountered, save the checkpoint.
    SaveCheckpoint(reader);
  } while (length_or_content_terminator != kContentTerminator);
  return absl::OkStatus();
}

// Returns Ok status only if the decoding processes the Padding section
// successfully or if the message is truncated properly. All other points of
// return are errors.
absl::Status
BinaryHttpRequest::IndeterminateLengthDecoder::DecodeCheckpointData(
    bool end_stream) {
  QuicheDataReader reader(checkpoint_view_);
  switch (current_section_) {
    case MessageSection::kEnd:
      return absl::InternalError("Decoder is invalid.");
    case MessageSection::kControlData: {
      uint64_t framing;
      if (!reader.ReadVarInt62(&framing)) {
        return absl::OutOfRangeError("Failed to read framing.");
      }
      if (framing != kIndeterminateLengthRequestFraming) {
        return absl::InvalidArgumentError(
            absl::StrFormat("Unsupported framing type: 0x%02x", framing));
      }

      const absl::StatusOr<BinaryHttpRequest::ControlData> control_data =
          DecodeControlData(reader);
      // Only fails if there is not enough data to read the entire control data.
      if (!control_data.ok()) {
        return absl::OutOfRangeError("Failed to read control data.");
      }

      const absl::Status section_status =
          message_section_handler_.OnControlData(control_data.value());
      if (!section_status.ok()) {
        return absl::InternalError(absl::StrCat(
            "Failed to handle control data: ", section_status.message()));
      }
      SaveCheckpoint(reader);
      current_section_ = MessageSection::kHeader;
    }
      ABSL_FALLTHROUGH_INTENDED;
    case MessageSection::kHeader: {
      const absl::Status status = DecodeContentTerminatedSection(reader);
      if (!status.ok()) {
        return status;
      }
      const absl::Status section_status =
          message_section_handler_.OnHeadersDone();
      if (!section_status.ok()) {
        return absl::InternalError(absl::StrCat(
            "Failed to handle headers done: ", section_status.message()));
      }
      current_section_ = MessageSection::kBody;
    }
      ABSL_FALLTHROUGH_INTENDED;
    case MessageSection::kBody: {
      if (!reader.IsDoneReading()) {
        maybe_truncated_ = false;
      }
      // Body and trailers truncation is valid only if:
      // 1. There is no data to read after the headers section.
      // 2. This is signaled as the last piece of data (end_stream).
      if (maybe_truncated_ && end_stream) {
        absl::Status section_status =
            message_section_handler_.OnBodyChunksDone();
        if (!section_status.ok()) {
          return absl::InternalError(absl::StrCat(
              "Failed to handle body chunks done: ", section_status.message()));
        }
        section_status = message_section_handler_.OnTrailersDone();
        if (!section_status.ok()) {
          return absl::InternalError(absl::StrCat(
              "Failed to handle trailers done: ", section_status.message()));
        }
        return absl::OkStatus();
      }

      absl::Status section_status = DecodeContentTerminatedSection(reader);
      if (!section_status.ok()) {
        return section_status;
      }
      section_status = message_section_handler_.OnBodyChunksDone();
      if (!section_status.ok()) {
        return absl::InternalError(absl::StrCat(
            "Failed to handle body chunks done: ", section_status.message()));
      }
      current_section_ = MessageSection::kTrailer;
      // Reset the truncation flag before entering the trailers section.
      maybe_truncated_ = true;
    }
      ABSL_FALLTHROUGH_INTENDED;
    case MessageSection::kTrailer: {
      if (!reader.IsDoneReading()) {
        maybe_truncated_ = false;
      }
      // Trailers truncation is valid only if:
      // 1. There is no data to read after the body section.
      // 2. This is signaled as the last piece of data (end_stream).
      if (maybe_truncated_ && end_stream) {
        const absl::Status section_status =
            message_section_handler_.OnTrailersDone();
        if (!section_status.ok()) {
          return absl::InternalError(absl::StrCat(
              "Failed to handle trailers done: ", section_status.message()));
        }
        return absl::OkStatus();
      }

      absl::Status section_status = DecodeContentTerminatedSection(reader);
      if (!section_status.ok()) {
        return section_status;
      }
      section_status = message_section_handler_.OnTrailersDone();
      if (!section_status.ok()) {
        return absl::InternalError(absl::StrCat(
            "Failed to handle trailers done: ", section_status.message()));
      }
      current_section_ = MessageSection::kPadding;
    }
      ABSL_FALLTHROUGH_INTENDED;
    case MessageSection::kPadding: {
      if (!IsValidPadding(reader.PeekRemainingPayload())) {
        return absl::InvalidArgumentError("Non-zero padding.");
      }
      return absl::OkStatus();
    }
  }
}

void BinaryHttpRequest::IndeterminateLengthDecoder::InitializeCheckpoint(
    absl::string_view data) {
  checkpoint_view_ = data;
  // Prepend buffered data if present. This is the data from a previous call to
  // Decode that could not finish because it needed this new data.
  if (!buffer_.empty()) {
    absl::StrAppend(&buffer_, data);
    checkpoint_view_ = buffer_;
  }
}

absl::Status BinaryHttpRequest::IndeterminateLengthDecoder::Decode(
    absl::string_view data, bool end_stream) {
  if (current_section_ == MessageSection::kEnd) {
    return absl::InternalError("Decoder is invalid.");
  }

  InitializeCheckpoint(data);
  absl::Status status = DecodeCheckpointData(end_stream);
  if (end_stream) {
    current_section_ = MessageSection::kEnd;
    buffer_.clear();
    // Out of range errors shall be treated as invalid argument errors when the
    // stream is ending.
    if (absl::IsOutOfRange(status)) {
      return absl::InvalidArgumentError(status.message());
    }
    return status;
  }
  if (absl::IsOutOfRange(status)) {
    BufferCheckpoint();
    return absl::OkStatus();
  }
  if (!status.ok()) {
    current_section_ = MessageSection::kEnd;
  }

  buffer_.clear();
  return status;
}

absl::StatusOr<BinaryHttpResponse> BinaryHttpResponse::Create(
    absl::string_view data) {
  quiche::QuicheDataReader reader(data);
  uint64_t framing;
  if (!reader.ReadVarInt62(&framing)) {
    return absl::InvalidArgumentError("Missing framing indicator.");
  }
  if (framing == kKnownLengthResponseFraming) {
    return DecodeKnownLengthResponse(reader);
  }
  return absl::UnimplementedError(
      absl::StrCat("Unsupported framing type ", framing));
}

absl::StatusOr<std::string>
BinaryHttpResponse::IndeterminateLengthEncoder::EncodeFieldSection(
    std::optional<uint16_t> status_code, absl::Span<FieldView> fields) {
  uint64_t total_length = 0;
  if (!framing_indicator_encoded_) {
    total_length += quiche::QuicheDataWriter::GetVarInt62Len(
        kIndeterminateLengthResponseFraming);
  }
  if (status_code.has_value()) {
    total_length += QuicheDataWriter::GetVarInt62Len(*status_code);
  }
  for (const auto& field : fields) {
    uint8_t length = QuicheDataWriter::GetVarInt62Len(field.name.size());
    if (length == 0) {
      return absl::InvalidArgumentError("Field name exceeds maximum length.");
    }
    total_length += length + field.name.size();

    length = QuicheDataWriter::GetVarInt62Len(field.value.size());
    if (length == 0) {
      return absl::InvalidArgumentError("Field value exceeds maximum length.");
    }
    total_length += length + field.value.size();
  }
  total_length += quiche::QuicheDataWriter::GetVarInt62Len(kContentTerminator);

  std::string data(total_length, '\0');
  QuicheDataWriter writer(total_length, data.data());

  if (!framing_indicator_encoded_) {
    if (!writer.WriteVarInt62(kIndeterminateLengthResponseFraming)) {
      return absl::InternalError("Failed to write framing indicator.");
    }
    framing_indicator_encoded_ = true;
  }
  if (status_code.has_value() && !writer.WriteVarInt62(*status_code)) {
    return absl::InternalError("Failed to write status code.");
  }
  for (const auto& field : fields) {
    if (!writer.WriteStringPieceVarInt62(absl::AsciiStrToLower(field.name))) {
      return absl::InternalError("Failed to write field name.");
    }
    if (!writer.WriteStringPieceVarInt62(field.value)) {
      return absl::InternalError("Failed to write field value.");
    }
  }
  if (!writer.WriteVarInt62(kContentTerminator)) {
    return absl::InternalError("Failed to write content terminator.");
  }
  if (writer.remaining() != 0) {
    return absl::InternalError("Failed to write all data.");
  }
  return data;
}

std::string
BinaryHttpResponse::IndeterminateLengthEncoder::GetMessageSectionString(
    MessageSection section) const {
  switch (section) {
    case MessageSection::kInformationalResponseOrHeader:
      return "InformationalResponseOrHeader";
    case MessageSection::kBody:
      return "Body";
    case MessageSection::kTrailer:
      return "Trailer";
    case MessageSection::kEnd:
      return "End";
    default:
      return "Unknown";
  }
}

absl::StatusOr<std::string>
BinaryHttpResponse::IndeterminateLengthEncoder::EncodeInformationalResponse(
    uint16_t status_code, absl::Span<FieldView> fields) {
  if (current_section_ != MessageSection::kInformationalResponseOrHeader) {
    current_section_ = MessageSection::kEnd;
    return absl::InvalidArgumentError(absl::StrCat(
        "EncodeInformationalResponse called in incorrect section: ",
        GetMessageSectionString(current_section_)));
  }
  if (status_code < 100 || status_code > 199) {
    current_section_ = MessageSection::kEnd;
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid informational response status code: ", status_code));
  }

  absl::StatusOr<std::string> data = EncodeFieldSection(status_code, fields);
  if (!data.ok()) {
    current_section_ = MessageSection::kEnd;
  }

  return data;
}

absl::StatusOr<std::string>
BinaryHttpResponse::IndeterminateLengthEncoder::EncodeHeaders(
    uint16_t status_code, absl::Span<FieldView> headers) {
  if (current_section_ != MessageSection::kInformationalResponseOrHeader) {
    current_section_ = MessageSection::kEnd;
    return absl::InvalidArgumentError(
        absl::StrCat("EncodeHeaders called in incorrect section: ",
                     GetMessageSectionString(current_section_)));
  }
  if (status_code < 200 || status_code > 599) {
    current_section_ = MessageSection::kEnd;
    return absl::InvalidArgumentError(
        absl::StrCat("Invalid response status code: ", status_code));
  }

  absl::StatusOr<std::string> data = EncodeFieldSection(status_code, headers);
  if (!data.ok()) {
    current_section_ = MessageSection::kEnd;
    return data;
  }
  current_section_ = MessageSection::kBody;
  return data;
}

absl::StatusOr<std::string>
BinaryHttpResponse::IndeterminateLengthEncoder::EncodeBodyChunks(
    absl::Span<absl::string_view> body_chunks, bool body_chunks_done) {
  if (current_section_ != MessageSection::kBody) {
    current_section_ = MessageSection::kEnd;
    return absl::InvalidArgumentError(
        absl::StrCat("EncodeBodyChunks called in incorrect section: ",
                     GetMessageSectionString(current_section_)));
  }
  uint64_t total_length = 0;
  for (const auto& body_chunk : body_chunks) {
    uint8_t body_chunk_var_int_length =
        QuicheDataWriter::GetVarInt62Len(body_chunk.size());
    if (body_chunk_var_int_length == 0) {
      current_section_ = MessageSection::kEnd;
      return absl::InvalidArgumentError(
          "Body chunk size exceeds maximum length.");
    }
    total_length += body_chunk_var_int_length + body_chunk.size();
  }
  if (body_chunks_done) {
    total_length +=
        quiche::QuicheDataWriter::GetVarInt62Len(kContentTerminator);
  }

  std::string data(total_length, '\0');
  QuicheDataWriter writer(total_length, data.data());

  for (const auto& body_chunk : body_chunks) {
    if (!writer.WriteStringPieceVarInt62(body_chunk)) {
      current_section_ = MessageSection::kEnd;
      return absl::InternalError("Failed to write body chunk.");
    }
  }
  if (body_chunks_done) {
    if (!writer.WriteVarInt62(kContentTerminator)) {
      current_section_ = MessageSection::kEnd;
      return absl::InternalError("Failed to write content terminator.");
    }
    current_section_ = MessageSection::kTrailer;
  }

  if (writer.remaining() != 0) {
    current_section_ = MessageSection::kEnd;
    return absl::InternalError("Failed to write all data.");
  }
  return data;
}

absl::StatusOr<std::string>
BinaryHttpResponse::IndeterminateLengthEncoder::EncodeTrailers(
    absl::Span<FieldView> trailers) {
  if (current_section_ != MessageSection::kTrailer) {
    current_section_ = MessageSection::kEnd;
    return absl::InvalidArgumentError(
        absl::StrCat("EncodeTrailers called in incorrect section: ",
                     GetMessageSectionString(current_section_)));
  }

  absl::StatusOr<std::string> data =
      EncodeFieldSection(/*status_code=*/std::nullopt, trailers);

  current_section_ = MessageSection::kEnd;
  return data;
}

std::string BinaryHttpMessage::DebugString() const {
  std::vector<std::string> headers;
  for (const auto& field : GetHeaderFields()) {
    headers.emplace_back(field.DebugString());
  }
  return absl::StrCat("BinaryHttpMessage{Headers{", absl::StrJoin(headers, ";"),
                      "}Body{", body(), "}}");
}

std::string BinaryHttpMessage::Field::DebugString() const {
  return absl::StrCat("Field{", name, "=", value, "}");
}

std::string BinaryHttpResponse::InformationalResponse::DebugString() const {
  std::vector<std::string> fs;
  for (const auto& field : fields()) {
    fs.emplace_back(field.DebugString());
  }
  return absl::StrCat("InformationalResponse{", absl::StrJoin(fs, ";"), "}");
}

std::string BinaryHttpResponse::DebugString() const {
  std::vector<std::string> irs;
  for (const auto& ir : informational_responses()) {
    irs.emplace_back(ir.DebugString());
  }
  return absl::StrCat("BinaryHttpResponse(", status_code_, "){",
                      BinaryHttpMessage::DebugString(), absl::StrJoin(irs, ";"),
                      "}");
}

std::string BinaryHttpRequest::DebugString() const {
  return absl::StrCat("BinaryHttpRequest{", BinaryHttpMessage::DebugString(),
                      "}");
}

void PrintTo(const BinaryHttpRequest& msg, std::ostream* os) {
  *os << msg.DebugString();
}

void PrintTo(const BinaryHttpResponse& msg, std::ostream* os) {
  *os << msg.DebugString();
}

void PrintTo(const BinaryHttpMessage::Field& msg, std::ostream* os) {
  *os << msg.DebugString();
}

}  // namespace quiche
