// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "google/protobuf/json/internal/unparser.h"

#include <cfloat>
#include <complex>
#include <cstdint>
#include <cstring>
#include <memory>
#include <sstream>
#include <string>
#include <utility>

#include "google/protobuf/stubs/logging.h"
#include "google/protobuf/stubs/common.h"
#include "google/protobuf/descriptor.h"
#include "google/protobuf/dynamic_message.h"
#include "google/protobuf/message.h"
#include "absl/status/status.h"
#include "absl/strings/ascii.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "google/protobuf/io/coded_stream.h"
#include "google/protobuf/io/zero_copy_stream.h"
#include "google/protobuf/json/internal/descriptor_traits.h"
#include "google/protobuf/json/internal/unparser_traits.h"
#include "google/protobuf/json/internal/writer.h"
#include "google/protobuf/stubs/status_macros.h"

// Must be included last.
#include "google/protobuf/port_def.inc"

namespace google {
namespace protobuf {
namespace json_internal {
namespace {
template <typename Traits>
bool IsEmpty(const Msg<Traits>& msg, const Desc<Traits>& desc) {
  size_t count = Traits::FieldCount(desc);
  for (size_t i = 0; i < count; ++i) {
    if (Traits::GetSize(Traits::FieldByIndex(desc, i), msg) > 0) {
      return false;
    }
  }
  return true;
}

enum class IntegerEnumStyle {
  kQuoted,
  kUnquoted,
};

template <typename Traits>
void WriteEnum(JsonWriter& writer, Field<Traits> field, int32_t value,
               IntegerEnumStyle int_style = IntegerEnumStyle::kUnquoted) {
  if (ClassifyMessage(Traits::FieldTypeName(field)) == MessageType::kNull) {
    writer.Write("null");
    return;
  }

  if (!writer.options().always_print_enums_as_ints) {
    auto name = Traits::EnumNameByNumber(field, value);
    if (name.ok()) {
      writer.Write("\"", *name, "\"");
      return;
    }
  }

  if (int_style == IntegerEnumStyle::kQuoted) {
    writer.Write("\"", value, "\"");
  } else {
    writer.Write(value);
  }
}

// Mutually recursive with functions that follow.
template <typename Traits>
absl::Status WriteMessage(JsonWriter& writer, const Msg<Traits>& msg,
                          const Desc<Traits>& desc, bool is_top_level = false);

// This is templatized so that defaults, singular, and repeated fields can both
// use the same enormous switch-case.
template <typename Traits, typename... Args>
absl::Status WriteSingular(JsonWriter& writer, Field<Traits> field,
                           Args&&... args) {
  // When the pack `args` is empty, the caller has requested printing the
  // default value.
  bool is_default = sizeof...(Args) == 0;
  switch (Traits::FieldType(field)) {
    case FieldDescriptor::TYPE_FLOAT: {
      auto x = Traits::GetFloat(field, std::forward<Args>(args)...);
      RETURN_IF_ERROR(x.status());
      if (writer.options().allow_legacy_syntax && is_default &&
          !std::isfinite(*x)) {
        *x = 0;
      }
      writer.Write(*x);
      break;
    }
    case FieldDescriptor::TYPE_DOUBLE: {
      auto x = Traits::GetDouble(field, std::forward<Args>(args)...);
      RETURN_IF_ERROR(x.status());
      if (writer.options().allow_legacy_syntax && is_default &&
          !std::isfinite(*x)) {
        *x = 0;
      }
      writer.Write(*x);
      break;
    }
    case FieldDescriptor::TYPE_SFIXED64:
    case FieldDescriptor::TYPE_SINT64:
    case FieldDescriptor::TYPE_INT64: {
      auto x = Traits::GetInt64(field, std::forward<Args>(args)...);
      RETURN_IF_ERROR(x.status());
      writer.Write(MakeQuoted(*x));
      break;
    }
    case FieldDescriptor::TYPE_FIXED64:
    case FieldDescriptor::TYPE_UINT64: {
      auto x = Traits::GetUInt64(field, std::forward<Args>(args)...);
      RETURN_IF_ERROR(x.status());
      writer.Write(MakeQuoted(*x));
      break;
    }
    case FieldDescriptor::TYPE_SFIXED32:
    case FieldDescriptor::TYPE_SINT32:
    case FieldDescriptor::TYPE_INT32: {
      auto x = Traits::GetInt32(field, std::forward<Args>(args)...);
      RETURN_IF_ERROR(x.status());
      writer.Write(*x);
      break;
    }
    case FieldDescriptor::TYPE_FIXED32:
    case FieldDescriptor::TYPE_UINT32: {
      auto x = Traits::GetUInt32(field, std::forward<Args>(args)...);
      RETURN_IF_ERROR(x.status());
      writer.Write(*x);
      break;
    }
    case FieldDescriptor::TYPE_BOOL: {
      auto x = Traits::GetBool(field, std::forward<Args>(args)...);
      RETURN_IF_ERROR(x.status());
      writer.Write(*x ? "true" : "false");
      break;
    }
    case FieldDescriptor::TYPE_STRING: {
      auto x = Traits::GetString(field, writer.ScratchBuf(),
                                 std::forward<Args>(args)...);
      RETURN_IF_ERROR(x.status());
      writer.Write(MakeQuoted(*x));
      break;
    }
    case FieldDescriptor::TYPE_BYTES: {
      auto x = Traits::GetString(field, writer.ScratchBuf(),
                                 std::forward<Args>(args)...);
      RETURN_IF_ERROR(x.status());
      if (writer.options().allow_legacy_syntax && is_default) {
        // Although difficult to verify, it appears that the original ESF parser
        // fails to unescape the contents of a
        // google.protobuf.Field.default_value, which may potentially be
        // escaped if it is for a `bytes` field (note that default_value is a
        // `string` regardless of what type the field is).
        //
        // However, our parser's type.proto guts actually know to do this
        // correctly, so this bug must be manually re-introduced.
        writer.WriteBase64(absl::CEscape(*x));
      } else {
        writer.WriteBase64(*x);
      }
      break;
    }
    case FieldDescriptor::TYPE_ENUM: {
      auto x = Traits::GetEnumValue(field, std::forward<Args>(args)...);
      RETURN_IF_ERROR(x.status());
      WriteEnum<Traits>(writer, field, *x);
      break;
    }
    case FieldDescriptor::TYPE_MESSAGE:
    case FieldDescriptor::TYPE_GROUP: {
      auto x = Traits::GetMessage(field, std::forward<Args>(args)...);
      RETURN_IF_ERROR(x.status());
      return WriteMessage<Traits>(writer, **x, Traits::GetDesc(**x));
    }
    default:
      return absl::InvalidArgumentError(
          absl::StrCat("unsupported field type: ", Traits::FieldType(field)));
  }

  return absl::OkStatus();
}

template <typename Traits>
absl::Status WriteRepeated(JsonWriter& writer, const Msg<Traits>& msg,
                           Field<Traits> field) {
  writer.Write("[");
  writer.Push();

  size_t count = Traits::GetSize(field, msg);
  bool first = true;
  for (size_t i = 0; i < count; ++i) {
    if (ClassifyMessage(Traits::FieldTypeName(field)) == MessageType::kValue) {
      bool empty = false;
      RETURN_IF_ERROR(Traits::WithFieldType(
          field, [&](const Desc<Traits>& desc) -> absl::Status {
            auto inner = Traits::GetMessage(field, msg, i);
            RETURN_IF_ERROR(inner.status());
            empty = IsEmpty<Traits>(**inner, desc);
            return absl::OkStatus();
          }));

      // Empty google.protobuf.Values are silently discarded.
      if (empty) {
        continue;
      }
    }
    writer.WriteComma(first);
    writer.NewLine();
    RETURN_IF_ERROR(WriteSingular<Traits>(writer, field, msg, i));
  }

  writer.Pop();
  if (!first) {
    writer.NewLine();
  }
  writer.Write("]");
  return absl::OkStatus();
}

template <typename Traits>
absl::Status WriteMapKey(JsonWriter& writer, const Msg<Traits>& entry,
                         Field<Traits> field) {
  switch (Traits::FieldType(field)) {
    case FieldDescriptor::TYPE_SFIXED64:
    case FieldDescriptor::TYPE_SINT64:
    case FieldDescriptor::TYPE_INT64: {
      auto x = Traits::GetInt64(field, entry);
      RETURN_IF_ERROR(x.status());
      writer.Write(MakeQuoted(*x));
      break;
    }
    case FieldDescriptor::TYPE_FIXED64:
    case FieldDescriptor::TYPE_UINT64: {
      auto x = Traits::GetUInt64(field, entry);
      RETURN_IF_ERROR(x.status());
      writer.Write(MakeQuoted(*x));
      break;
    }
    case FieldDescriptor::TYPE_SFIXED32:
    case FieldDescriptor::TYPE_SINT32:
    case FieldDescriptor::TYPE_INT32: {
      auto x = Traits::GetInt32(field, entry);
      RETURN_IF_ERROR(x.status());
      writer.Write(MakeQuoted(*x));
      break;
    }
    case FieldDescriptor::TYPE_FIXED32:
    case FieldDescriptor::TYPE_UINT32: {
      auto x = Traits::GetUInt32(field, entry);
      RETURN_IF_ERROR(x.status());
      writer.Write(MakeQuoted(*x));
      break;
    }
    case FieldDescriptor::TYPE_BOOL: {
      auto x = Traits::GetBool(field, entry);
      RETURN_IF_ERROR(x.status());
      writer.Write(MakeQuoted(*x ? "true" : "false"));
      break;
    }
    case FieldDescriptor::TYPE_STRING: {
      auto x = Traits::GetString(field, writer.ScratchBuf(), entry);
      RETURN_IF_ERROR(x.status());
      writer.Write(MakeQuoted(*x));
      break;
    }
    case FieldDescriptor::TYPE_ENUM: {
      auto x = Traits::GetEnumValue(field, entry);
      RETURN_IF_ERROR(x.status());
      WriteEnum<Traits>(writer, field, *x, IntegerEnumStyle::kQuoted);
      break;
    }
    default:
      return absl::InvalidArgumentError(
          absl::StrCat("unsupported map key type: ", Traits::FieldType(field)));
  }
  return absl::OkStatus();
}

template <typename Traits>
absl::StatusOr<bool> IsEmptyValue(const Msg<Traits>& msg, Field<Traits> field) {
  if (ClassifyMessage(Traits::FieldTypeName(field)) != MessageType::kValue) {
    return false;
  }
  bool empty = false;
  RETURN_IF_ERROR(Traits::WithFieldType(
      field, [&](const Desc<Traits>& desc) -> absl::Status {
        auto inner = Traits::GetMessage(field, msg);
        RETURN_IF_ERROR(inner.status());
        empty = IsEmpty<Traits>(**inner, desc);
        return absl::OkStatus();
      }));
  return empty;
}

template <typename Traits>
absl::Status WriteMap(JsonWriter& writer, const Msg<Traits>& msg,
                      Field<Traits> field) {
  writer.Write("{");
  writer.Push();

  size_t count = Traits::GetSize(field, msg);
  bool first = true;
  for (size_t i = 0; i < count; ++i) {
    absl::StatusOr<const Msg<Traits>*> entry =
        Traits::GetMessage(field, msg, i);
    RETURN_IF_ERROR(entry.status());
    const Desc<Traits>& type = Traits::GetDesc(**entry);

    auto is_empty = IsEmptyValue<Traits>(**entry, Traits::ValueField(type));
    RETURN_IF_ERROR(is_empty.status());
    if (*is_empty) {
      // Empty google.protobuf.Values are silently discarded.
      continue;
    }

    writer.WriteComma(first);
    writer.NewLine();
    RETURN_IF_ERROR(
        WriteMapKey<Traits>(writer, **entry, Traits::KeyField(type)));
    writer.Write(":");
    writer.Whitespace(" ");
    RETURN_IF_ERROR(
        WriteSingular<Traits>(writer, Traits::ValueField(type), **entry));
  }

  writer.Pop();
  if (!first) {
    writer.NewLine();
  }
  writer.Write("}");
  return absl::OkStatus();
}

template <typename Traits>
absl::Status WriteField(JsonWriter& writer, const Msg<Traits>& msg,
                        Field<Traits> field, bool& first) {
  if (!Traits::IsRepeated(field)) {  // Repeated case is handled in
                                     // WriteRepeated.
    auto is_empty = IsEmptyValue<Traits>(msg, field);
    RETURN_IF_ERROR(is_empty.status());
    if (*is_empty) {
      // Empty google.protobuf.Values are silently discarded.
      return absl::OkStatus();
    }
  }

  writer.WriteComma(first);
  writer.NewLine();

  if (Traits::IsExtension(field)) {
    writer.Write(MakeQuoted("[", Traits::FieldFullName(field), "]"), ":");
  } else if (writer.options().preserve_proto_field_names) {
    writer.Write(MakeQuoted(Traits::FieldName(field)), ":");
  } else {
    // The generator for type.proto and the internals of descriptor.cc disagree
    // on what the json name of a PascalCase field is supposed to be; type.proto
    // seems to (incorrectly?) capitalize the first letter, which is the
    // behavior ESF defaults to. To fix this, if the original field name starts
    // with an uppercase letter, and the Json name does not, we uppercase it.
    absl::string_view original_name = Traits::FieldName(field);
    absl::string_view json_name = Traits::FieldJsonName(field);
    if (writer.options().allow_legacy_syntax &&
        absl::ascii_isupper(original_name[0]) &&
        !absl::ascii_isupper(json_name[0])) {
      writer.Write(MakeQuoted(absl::ascii_toupper(original_name[0]),
                              original_name.substr(1)),
                   ":");
    } else {
      writer.Write(MakeQuoted(json_name), ":");
    }
  }
  writer.Whitespace(" ");

  if (Traits::IsMap(field)) {
    return WriteMap<Traits>(writer, msg, field);
  } else if (Traits::IsRepeated(field)) {
    return WriteRepeated<Traits>(writer, msg, field);
  } else if (Traits::GetSize(field, msg) == 0) {
    // We can only get here if always_print_primitive_fields is true.
    GOOGLE_DCHECK(writer.options().always_print_primitive_fields);

    if (Traits::FieldType(field) == FieldDescriptor::TYPE_GROUP) {
      // We do not yet have full group support, but this is required so that we
      // pass the same tests as the ESF parser.
      writer.Write("null");
      return absl::OkStatus();
    }
    return WriteSingular<Traits>(writer, field);
  }

  return WriteSingular<Traits>(writer, field, msg);
}

template <typename Traits>
absl::Status WriteFields(JsonWriter& writer, const Msg<Traits>& msg,
                         const Desc<Traits>& desc, bool& first) {
  std::vector<Field<Traits>> fields;
  size_t total = Traits::FieldCount(desc);
  fields.reserve(total);
  for (size_t i = 0; i < total; ++i) {
    Field<Traits> field = Traits::FieldByIndex(desc, i);

    bool has = Traits::GetSize(field, msg) > 0;
    if (writer.options().always_print_primitive_fields) {
      bool is_singular_message =
          !Traits::IsRepeated(field) &&
          Traits::FieldType(field) == FieldDescriptor::TYPE_MESSAGE;
      has |= !is_singular_message && !Traits::IsOneof(field);
    }

    if (has) {
      fields.push_back(field);
    }
  }

  // Add extensions *before* sorting.
  Traits::FindAndAppendExtensions(msg, fields);

  // Fields are guaranteed to be serialized in field number order.
  absl::c_sort(fields, [](const auto& a, const auto& b) {
    return Traits::FieldNumber(a) < Traits::FieldNumber(b);
  });

  for (auto field : fields) {
    RETURN_IF_ERROR(WriteField<Traits>(writer, msg, field, first));
  }

  return absl::OkStatus();
}

template <typename Traits>
absl::Status WriteStructValue(JsonWriter& writer, const Msg<Traits>& msg,
                              const Desc<Traits>& desc);
template <typename Traits>
absl::Status WriteListValue(JsonWriter& writer, const Msg<Traits>& msg,
                            const Desc<Traits>& desc);

template <typename Traits>
absl::Status WriteValue(JsonWriter& writer, const Msg<Traits>& msg,
                        const Desc<Traits>& desc, bool is_top_level) {
  // NOTE: The field numbers 1 through 6 are the numbers of the oneof fields in
  // google.protobuf.Value. Conformance tests verify the correctness of these
  // numbers.
  if (Traits::GetSize(Traits::MustHaveField(desc, 1), msg) > 0) {
    writer.Write("null");
    return absl::OkStatus();
  }

  auto number_field = Traits::MustHaveField(desc, 2);
  if (Traits::GetSize(number_field, msg) > 0) {
    auto x = Traits::GetDouble(number_field, msg);
    RETURN_IF_ERROR(x.status());
    writer.Write(*x);
    return absl::OkStatus();
  }

  auto string_field = Traits::MustHaveField(desc, 3);
  if (Traits::GetSize(string_field, msg) > 0) {
    auto x = Traits::GetString(string_field, writer.ScratchBuf(), msg);
    RETURN_IF_ERROR(x.status());
    writer.Write(MakeQuoted(*x));
    return absl::OkStatus();
  }

  auto bool_field = Traits::MustHaveField(desc, 4);
  if (Traits::GetSize(bool_field, msg) > 0) {
    auto x = Traits::GetBool(bool_field, msg);
    RETURN_IF_ERROR(x.status());
    writer.Write(*x ? "true" : "false");
    return absl::OkStatus();
  }

  auto struct_field = Traits::MustHaveField(desc, 5);
  if (Traits::GetSize(struct_field, msg) > 0) {
    auto x = Traits::GetMessage(struct_field, msg);
    RETURN_IF_ERROR(x.status());
    return Traits::WithFieldType(struct_field, [&](const Desc<Traits>& type) {
      return WriteStructValue<Traits>(writer, **x, type);
    });
  }

  auto list_field = Traits::MustHaveField(desc, 6);
  if (Traits::GetSize(list_field, msg) > 0) {
    auto x = Traits::GetMessage(list_field, msg);
    RETURN_IF_ERROR(x.status());
    return Traits::WithFieldType(list_field, [&](const Desc<Traits>& type) {
      return WriteListValue<Traits>(writer, **x, type);
    });
  }

  GOOGLE_CHECK(is_top_level) << "empty, non-top-level Value must be handled one layer "
                         "up, since it prints an empty string; reaching this "
                         "statement is always a bug";
  return absl::OkStatus();
}

template <typename Traits>
absl::Status WriteStructValue(JsonWriter& writer, const Msg<Traits>& msg,
                              const Desc<Traits>& desc) {
  return WriteMap<Traits>(writer, msg, Traits::MustHaveField(desc, 1));
}

template <typename Traits>
absl::Status WriteListValue(JsonWriter& writer, const Msg<Traits>& msg,
                            const Desc<Traits>& desc) {
  return WriteRepeated<Traits>(writer, msg, Traits::MustHaveField(desc, 1));
}

template <typename Traits>
absl::Status WriteTimestamp(JsonWriter& writer, const Msg<Traits>& msg,
                            const Desc<Traits>& desc) {
  auto secs_field = Traits::MustHaveField(desc, 1);
  auto secs = Traits::GetSize(secs_field, msg) > 0
                  ? Traits::GetInt64(secs_field, msg)
                  : 0;
  RETURN_IF_ERROR(secs.status());

  if (*secs < -62135596800) {
    return absl::InvalidArgumentError(
        "minimum acceptable time value is 0001-01-01T00:00:00Z");
  } else if (*secs > 253402300799) {
    return absl::InvalidArgumentError(
        "maximum acceptable time value is 9999-12-31T23:59:59Z");
  }

  // Ensure seconds is positive.
  *secs += 62135596800;

  auto nanos_field = Traits::MustHaveField(desc, 2);
  auto nanos = Traits::GetSize(nanos_field, msg) > 0
                   ? Traits::GetInt32(nanos_field, msg)
                   : 0;
  RETURN_IF_ERROR(nanos.status());

  // Julian Day -> Y/M/D, Algorithm from:
  // Fliegel, H. F., and Van Flandern, T. C., "A Machine Algorithm for
  //   Processing Calendar Dates," Communications of the Association of
  //   Computing Machines, vol. 11 (1968), p. 657.
  int32_t L, N, I, J, K;
  L = static_cast<int32_t>(*secs / 86400) - 719162 + 68569 + 2440588;
  N = 4 * L / 146097;
  L = L - (146097 * N + 3) / 4;
  I = 4000 * (L + 1) / 1461001;
  L = L - 1461 * I / 4 + 31;
  J = 80 * L / 2447;
  K = L - 2447 * J / 80;
  L = J / 11;
  J = J + 2 - 12 * L;
  I = 100 * (N - 49) + I + L;

  int32_t sec = *secs % 60;
  int32_t min = (*secs / 60) % 60;
  int32_t hour = (*secs / 3600) % 24;

  if (*nanos == 0) {
    writer.Write(absl::StrFormat(R"("%04d-%02d-%02dT%02d:%02d:%02dZ")", I, J, K,
                                 hour, min, sec));
    return absl::OkStatus();
  }

  size_t digits = 9;
  uint32_t frac_seconds = std::abs(*nanos);
  while (frac_seconds % 1000 == 0) {
    frac_seconds /= 1000;
    digits -= 3;
  }

  writer.Write(absl::StrFormat(R"("%04d-%02d-%02dT%02d:%02d:%02d.%.*dZ")", I, J,
                               K, hour, min, sec, digits, frac_seconds));
  return absl::OkStatus();
}

template <typename Traits>
absl::Status WriteDuration(JsonWriter& writer, const Msg<Traits>& msg,
                           const Desc<Traits>& desc) {
  constexpr int64_t kMaxSeconds = int64_t{3652500} * 86400;
  constexpr int64_t kMaxNanos = 999999999;

  auto secs_field = Traits::MustHaveField(desc, 1);
  auto secs = Traits::GetSize(secs_field, msg) > 0
                  ? Traits::GetInt64(secs_field, msg)
                  : 0;
  RETURN_IF_ERROR(secs.status());

  if (*secs > kMaxSeconds || *secs < -kMaxSeconds) {
    return absl::InvalidArgumentError("duration out of range");
  }

  auto nanos_field = Traits::MustHaveField(desc, 2);
  auto nanos = Traits::GetSize(nanos_field, msg) > 0
                   ? Traits::GetInt32(nanos_field, msg)
                   : 0;
  RETURN_IF_ERROR(nanos.status());

  if (*nanos > kMaxNanos || *nanos < -kMaxNanos) {
    return absl::InvalidArgumentError("duration out of range");
  }
  if ((*secs != 0) && (*nanos != 0) && ((*secs < 0) != (*nanos < 0))) {
    return absl::InvalidArgumentError("nanos and seconds signs do not match");
  }

  if (*nanos == 0) {
    writer.Write(absl::StrFormat(R"("%ds")", *secs));
    return absl::OkStatus();
  }

  size_t digits = 9;
  uint32_t frac_seconds = std::abs(*nanos);
  while (frac_seconds % 1000 == 0) {
    frac_seconds /= 1000;
    digits -= 3;
  }

  absl::string_view sign = ((*secs < 0) || (*nanos < 0)) ? "-" : "";
  writer.Write(absl::StrFormat(R"("%s%d.%.*ds")", sign, std::abs(*secs), digits,
                               frac_seconds));
  return absl::OkStatus();
}

template <typename Traits>
absl::Status WriteFieldMask(JsonWriter& writer, const Msg<Traits>& msg,
                            const Desc<Traits>& desc) {
  // google.protobuf.FieldMask has a single field with number 1.
  auto paths_field = Traits::MustHaveField(desc, 1);
  size_t paths = Traits::GetSize(paths_field, msg);
  writer.Write('"');

  bool first = true;
  for (size_t i = 0; i < paths; ++i) {
    writer.WriteComma(first);
    auto path = Traits::GetString(paths_field, writer.ScratchBuf(), msg, i);
    RETURN_IF_ERROR(path.status());
    bool saw_under = false;
    for (char c : *path) {
      if (absl::ascii_islower(c) && saw_under) {
        writer.Write(absl::ascii_toupper(c));
      } else if (absl::ascii_isdigit(c) || absl::ascii_islower(c) || c == '.') {
        writer.Write(c);
      } else if (c == '_' &&
                 (!saw_under || writer.options().allow_legacy_syntax)) {
        saw_under = true;
        continue;
      } else if (!writer.options().allow_legacy_syntax) {
        return absl::InvalidArgumentError("unexpected character in FieldMask");
      } else {
        if (saw_under) {
          writer.Write('_');
        }
        writer.Write(c);
      }
      saw_under = false;
    }
  }
  writer.Write('"');

  return absl::OkStatus();
}

template <typename Traits>
absl::Status WriteAny(JsonWriter& writer, const Msg<Traits>& msg,
                      const Desc<Traits>& desc) {
  auto type_url_field = Traits::MustHaveField(desc, 1);
  auto value_field = Traits::MustHaveField(desc, 2);

  bool has_type_url = Traits::GetSize(type_url_field, msg) > 0;
  bool has_value = Traits::GetSize(value_field, msg) > 0;
  if (!has_type_url && !has_value) {
    writer.Write("{}");
    return absl::OkStatus();
  } else if (!has_type_url) {
    return absl::InvalidArgumentError("broken Any: missing type URL");
  } else if (!has_value && !writer.options().allow_legacy_syntax) {
    return absl::InvalidArgumentError("broken Any: missing value");
  }

  writer.Write("{");
  writer.Push();

  auto type_url = Traits::GetString(type_url_field, writer.ScratchBuf(), msg);
  RETURN_IF_ERROR(type_url.status());
  writer.NewLine();
  writer.Write("\"@type\":");
  writer.Whitespace(" ");
  writer.Write(MakeQuoted(*type_url));

  return Traits::WithDynamicType(
      desc, std::string(*type_url),
      [&](const Desc<Traits>& any_desc) -> absl::Status {
        absl::string_view any_bytes;
        if (has_value) {
          absl::StatusOr<absl::string_view> bytes =
              Traits::GetString(value_field, writer.ScratchBuf(), msg);
          RETURN_IF_ERROR(bytes.status());
          any_bytes = *bytes;
        }

        return Traits::WithDecodedMessage(
            any_desc, any_bytes,
            [&](const Msg<Traits>& unerased) -> absl::Status {
              bool first = false;
              if (ClassifyMessage(Traits::TypeName(any_desc)) !=
                  MessageType::kNotWellKnown) {
                writer.WriteComma(first);
                writer.NewLine();
                writer.Write("\"value\":");
                writer.Whitespace(" ");
                RETURN_IF_ERROR(
                    WriteMessage<Traits>(writer, unerased, any_desc));
              } else {
                RETURN_IF_ERROR(
                    WriteFields<Traits>(writer, unerased, any_desc, first));
              }
              writer.Pop();
              if (!first) {
                writer.NewLine();
              }
              writer.Write("}");
              return absl::OkStatus();
            });
      });
}

template <typename Traits>
absl::Status WriteMessage(JsonWriter& writer, const Msg<Traits>& msg,
                          const Desc<Traits>& desc, bool is_top_level) {
  switch (ClassifyMessage(Traits::TypeName(desc))) {
    case MessageType::kAny:
      return WriteAny<Traits>(writer, msg, desc);
    case MessageType::kWrapper: {
      auto field = Traits::MustHaveField(desc, 1);
      if (Traits::GetSize(field, msg) == 0) {
        return WriteSingular<Traits>(writer, field);
      }
      return WriteSingular<Traits>(writer, field, msg);
    }
    case MessageType::kValue:
      return WriteValue<Traits>(writer, msg, desc, is_top_level);
    case MessageType::kStruct:
      return WriteStructValue<Traits>(writer, msg, desc);
    case MessageType::kList:
      return WriteListValue<Traits>(writer, msg, desc);
    case MessageType::kTimestamp:
      return WriteTimestamp<Traits>(writer, msg, desc);
    case MessageType::kDuration:
      return WriteDuration<Traits>(writer, msg, desc);
    case MessageType::kFieldMask:
      return WriteFieldMask<Traits>(writer, msg, desc);
    default: {
      writer.Write("{");
      writer.Push();
      bool first = true;
      RETURN_IF_ERROR(WriteFields<Traits>(writer, msg, desc, first));
      writer.Pop();
      if (!first) {
        writer.NewLine();
      }
      writer.Write("}");
      return absl::OkStatus();
    }
  }
}
}  // namespace

absl::Status MessageToJsonString(const Message& message, std::string* output,
                                 json_internal::WriterOptions options) {
  PROTOBUF_DLOG(INFO) << "json2/input: " << message.DebugString();
  io::StringOutputStream out(output);
  JsonWriter writer(&out, options);
  absl::Status s = WriteMessage<UnparseProto2Descriptor>(
      writer, message, *message.GetDescriptor(), /*is_top_level=*/true);
  PROTOBUF_DLOG(INFO) << "json2/status: " << s;
  RETURN_IF_ERROR(s);

  writer.NewLine();
  PROTOBUF_DLOG(INFO) << "json2/output: " << absl::CHexEscape(*output);
  return absl::OkStatus();
}

absl::Status BinaryToJsonStream(google::protobuf::util::TypeResolver* resolver,
                                const std::string& type_url,
                                io::ZeroCopyInputStream* binary_input,
                                io::ZeroCopyOutputStream* json_output,
                                json_internal::WriterOptions options) {
  // NOTE: Most of the contortions in this function are to allow for capture of
  // input and output of the parser in GOOGLE_DLOG mode. Destruction order is very
  // critical in this function, because io::ZeroCopy*Stream types usually only
  // flush on destruction.

  // For GOOGLE_DLOG, we would like to print out the input and output, which requires
  // buffering both instead of doing "zero copy". This block, and the one at
  // the end of the function, set up and tear down interception of the input
  // and output streams.
  std::string copy;
  std::string out;
  absl::optional<io::ArrayInputStream> tee_input;
  absl::optional<io::StringOutputStream> tee_output;
  if (PROTOBUF_DEBUG) {
    const void* data;
    int len;
    while (binary_input->Next(&data, &len)) {
      copy.resize(copy.size() + len);
      std::memcpy(&copy[copy.size() - len], data, len);
    }
    tee_input.emplace(copy.data(), copy.size());
    tee_output.emplace(&out);
  }

  PROTOBUF_DLOG(INFO) << "json2/input: " << absl::BytesToHexString(copy);

  ResolverPool pool(resolver);
  auto desc = pool.FindMessage(type_url);
  RETURN_IF_ERROR(desc.status());

  io::CodedInputStream stream(tee_input.has_value() ? &*tee_input
                                                    : binary_input);
  auto msg = UntypedMessage::ParseFromStream(*desc, stream);
  RETURN_IF_ERROR(msg.status());

  JsonWriter writer(tee_output.has_value() ? &*tee_output : json_output,
                    options);
  absl::Status s = WriteMessage<UnparseProto3Type>(
      writer, *msg, UnparseProto3Type::GetDesc(*msg),
      /*is_top_level=*/true);
  PROTOBUF_DLOG(INFO) << "json2/status: " << s;
  RETURN_IF_ERROR(s);

  if (PROTOBUF_DEBUG) {
    tee_output.reset();  // Flush the output stream.
    io::zc_sink_internal::ZeroCopyStreamByteSink(json_output)
        .Append(out.data(), out.size());
  }

  PROTOBUF_DLOG(INFO) << "json2/output: " << absl::CHexEscape(out);

  writer.NewLine();
  return absl::OkStatus();
}
}  // namespace json_internal
}  // namespace protobuf
}  // namespace google
