Coverage Report

Created: 2024-02-11 06:09

/proc/self/cwd/external/com_google_protobuf/src/google/protobuf/json/internal/unparser.cc
Line
Count
Source (jump to first uncovered line)
1
// Protocol Buffers - Google's data interchange format
2
// Copyright 2008 Google Inc.  All rights reserved.
3
// https://developers.google.com/protocol-buffers/
4
//
5
// Redistribution and use in source and binary forms, with or without
6
// modification, are permitted provided that the following conditions are
7
// met:
8
//
9
//     * Redistributions of source code must retain the above copyright
10
// notice, this list of conditions and the following disclaimer.
11
//     * Redistributions in binary form must reproduce the above
12
// copyright notice, this list of conditions and the following disclaimer
13
// in the documentation and/or other materials provided with the
14
// distribution.
15
//     * Neither the name of Google Inc. nor the names of its
16
// contributors may be used to endorse or promote products derived from
17
// this software without specific prior written permission.
18
//
19
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31
#include "google/protobuf/json/internal/unparser.h"
32
33
#include <cfloat>
34
#include <cmath>
35
#include <complex>
36
#include <cstdint>
37
#include <cstring>
38
#include <limits>
39
#include <memory>
40
#include <sstream>
41
#include <string>
42
#include <type_traits>
43
#include <utility>
44
45
#include "google/protobuf/descriptor.h"
46
#include "google/protobuf/dynamic_message.h"
47
#include "google/protobuf/message.h"
48
#include "absl/log/absl_check.h"
49
#include "absl/log/absl_log.h"
50
#include "absl/status/status.h"
51
#include "absl/strings/ascii.h"
52
#include "absl/strings/escaping.h"
53
#include "absl/strings/str_cat.h"
54
#include "absl/strings/str_format.h"
55
#include "absl/strings/string_view.h"
56
#include "absl/types/optional.h"
57
#include "google/protobuf/io/coded_stream.h"
58
#include "google/protobuf/io/zero_copy_stream.h"
59
#include "google/protobuf/json/internal/descriptor_traits.h"
60
#include "google/protobuf/json/internal/unparser_traits.h"
61
#include "google/protobuf/json/internal/writer.h"
62
#include "google/protobuf/stubs/status_macros.h"
63
64
// Must be included last.
65
#include "google/protobuf/port_def.inc"
66
67
namespace google {
68
namespace protobuf {
69
namespace json_internal {
70
namespace {
71
template <typename Traits>
72
0
bool IsEmpty(const Msg<Traits>& msg, const Desc<Traits>& desc) {
73
0
  size_t count = Traits::FieldCount(desc);
74
0
  for (size_t i = 0; i < count; ++i) {
75
0
    if (Traits::GetSize(Traits::FieldByIndex(desc, i), msg) > 0) {
76
0
      return false;
77
0
    }
78
0
  }
79
0
  return true;
80
0
}
Unexecuted instantiation: unparser.cc:bool google::protobuf::json_internal::(anonymous namespace)::IsEmpty<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Desc const&)
Unexecuted instantiation: unparser.cc:bool google::protobuf::json_internal::(anonymous namespace)::IsEmpty<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Desc const&)
81
82
enum class IntegerEnumStyle {
83
  kQuoted,
84
  kUnquoted,
85
};
86
87
template <typename Traits>
88
void WriteEnum(JsonWriter& writer, Field<Traits> field, int32_t value,
89
0
               IntegerEnumStyle int_style = IntegerEnumStyle::kUnquoted) {
90
0
  if (ClassifyMessage(Traits::FieldTypeName(field)) == MessageType::kNull) {
91
0
    writer.Write("null");
92
0
    return;
93
0
  }
94
95
0
  if (!writer.options().always_print_enums_as_ints) {
96
0
    auto name = Traits::EnumNameByNumber(field, value);
97
0
    if (name.ok()) {
98
0
      writer.Write("\"", *name, "\"");
99
0
      return;
100
0
    }
101
0
  }
102
103
0
  if (int_style == IntegerEnumStyle::kQuoted) {
104
0
    writer.Write("\"", value, "\"");
105
0
  } else {
106
0
    writer.Write(value);
107
0
  }
108
0
}
Unexecuted instantiation: unparser.cc:void google::protobuf::json_internal::(anonymous namespace)::WriteEnum<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Field, int, google::protobuf::json_internal::(anonymous namespace)::IntegerEnumStyle)
Unexecuted instantiation: unparser.cc:void google::protobuf::json_internal::(anonymous namespace)::WriteEnum<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Field, int, google::protobuf::json_internal::(anonymous namespace)::IntegerEnumStyle)
109
110
// Returns true if x round-trips through being cast to a double, i.e., if
111
// x is represenable exactly as a double. This is a slightly weaker condition
112
// than x < 2^52.
113
template <typename Int>
114
0
bool RoundTripsThroughDouble(Int x) {
115
0
  auto d = static_cast<double>(x);
116
  // d has guaranteed to be finite with no fractional part, because it came from
117
  // an integer, so we only need to check that it is not outside of the
118
  // representable range of `int`. The way to do this is somewhat not obvious:
119
  // UINT64_MAX isn't representable, and what it gets rounded to when we go
120
  // int->double is unspecified!
121
  //
122
  // Thus, we have to go through ldexp.
123
0
  double min = 0;
124
0
  double max_plus_one = std::ldexp(1.0, sizeof(Int) * 8);
125
0
  if (std::is_signed<Int>::value) {
126
0
    max_plus_one /= 2;
127
0
    min = -max_plus_one;
128
0
  }
129
130
0
  if (d < min || d >= max_plus_one) {
131
0
    return false;
132
0
  }
133
134
0
  return static_cast<Int>(d) == x;
135
0
}
Unexecuted instantiation: unparser.cc:bool google::protobuf::json_internal::(anonymous namespace)::RoundTripsThroughDouble<long>(long)
Unexecuted instantiation: unparser.cc:bool google::protobuf::json_internal::(anonymous namespace)::RoundTripsThroughDouble<unsigned long>(unsigned long)
136
137
// Mutually recursive with functions that follow.
138
template <typename Traits>
139
absl::Status WriteMessage(JsonWriter& writer, const Msg<Traits>& msg,
140
                          const Desc<Traits>& desc, bool is_top_level = false);
141
142
// This is templatized so that defaults, singular, and repeated fields can both
143
// use the same enormous switch-case.
144
template <typename Traits, typename... Args>
145
absl::Status WriteSingular(JsonWriter& writer, Field<Traits> field,
146
0
                           Args&&... args) {
147
  // When the pack `args` is empty, the caller has requested printing the
148
  // default value.
149
0
  bool is_default = sizeof...(Args) == 0;
150
0
  switch (Traits::FieldType(field)) {
151
0
    case FieldDescriptor::TYPE_FLOAT: {
152
0
      auto x = Traits::GetFloat(field, std::forward<Args>(args)...);
153
0
      RETURN_IF_ERROR(x.status());
154
0
      if (writer.options().allow_legacy_syntax && is_default &&
155
0
          !std::isfinite(*x)) {
156
0
        *x = 0;
157
0
      }
158
0
      writer.Write(*x);
159
0
      break;
160
0
    }
161
0
    case FieldDescriptor::TYPE_DOUBLE: {
162
0
      auto x = Traits::GetDouble(field, std::forward<Args>(args)...);
163
0
      RETURN_IF_ERROR(x.status());
164
0
      if (writer.options().allow_legacy_syntax && is_default &&
165
0
          !std::isfinite(*x)) {
166
0
        *x = 0;
167
0
      }
168
0
      writer.Write(*x);
169
0
      break;
170
0
    }
171
0
    case FieldDescriptor::TYPE_SFIXED64:
172
0
    case FieldDescriptor::TYPE_SINT64:
173
0
    case FieldDescriptor::TYPE_INT64: {
174
0
      auto x = Traits::GetInt64(field, std::forward<Args>(args)...);
175
0
      RETURN_IF_ERROR(x.status());
176
0
      if (writer.options().unquote_int64_if_possible &&
177
0
          RoundTripsThroughDouble(*x)) {
178
0
        writer.Write(*x);
179
0
      } else {
180
0
        writer.Write(MakeQuoted(*x));
181
0
      }
182
0
      break;
183
0
    }
184
0
    case FieldDescriptor::TYPE_FIXED64:
185
0
    case FieldDescriptor::TYPE_UINT64: {
186
0
      auto x = Traits::GetUInt64(field, std::forward<Args>(args)...);
187
0
      RETURN_IF_ERROR(x.status());
188
0
      if (writer.options().unquote_int64_if_possible &&
189
0
          RoundTripsThroughDouble(*x)) {
190
0
        writer.Write(*x);
191
0
      } else {
192
0
        writer.Write(MakeQuoted(*x));
193
0
      }
194
0
      break;
195
0
    }
196
0
    case FieldDescriptor::TYPE_SFIXED32:
197
0
    case FieldDescriptor::TYPE_SINT32:
198
0
    case FieldDescriptor::TYPE_INT32: {
199
0
      auto x = Traits::GetInt32(field, std::forward<Args>(args)...);
200
0
      RETURN_IF_ERROR(x.status());
201
0
      writer.Write(*x);
202
0
      break;
203
0
    }
204
0
    case FieldDescriptor::TYPE_FIXED32:
205
0
    case FieldDescriptor::TYPE_UINT32: {
206
0
      auto x = Traits::GetUInt32(field, std::forward<Args>(args)...);
207
0
      RETURN_IF_ERROR(x.status());
208
0
      writer.Write(*x);
209
0
      break;
210
0
    }
211
0
    case FieldDescriptor::TYPE_BOOL: {
212
0
      auto x = Traits::GetBool(field, std::forward<Args>(args)...);
213
0
      RETURN_IF_ERROR(x.status());
214
0
      writer.Write(*x ? "true" : "false");
215
0
      break;
216
0
    }
217
0
    case FieldDescriptor::TYPE_STRING: {
218
0
      auto x = Traits::GetString(field, writer.ScratchBuf(),
219
0
                                 std::forward<Args>(args)...);
220
0
      RETURN_IF_ERROR(x.status());
221
0
      writer.Write(MakeQuoted(*x));
222
0
      break;
223
0
    }
224
0
    case FieldDescriptor::TYPE_BYTES: {
225
0
      auto x = Traits::GetString(field, writer.ScratchBuf(),
226
0
                                 std::forward<Args>(args)...);
227
0
      RETURN_IF_ERROR(x.status());
228
0
      if (writer.options().allow_legacy_syntax && is_default) {
229
        // Although difficult to verify, it appears that the original ESF parser
230
        // fails to unescape the contents of a
231
        // google.protobuf.Field.default_value, which may potentially be
232
        // escaped if it is for a `bytes` field (note that default_value is a
233
        // `string` regardless of what type the field is).
234
        //
235
        // However, our parser's type.proto guts actually know to do this
236
        // correctly, so this bug must be manually re-introduced.
237
0
        writer.WriteBase64(absl::CEscape(*x));
238
0
      } else {
239
0
        writer.WriteBase64(*x);
240
0
      }
241
0
      break;
242
0
    }
243
0
    case FieldDescriptor::TYPE_ENUM: {
244
0
      auto x = Traits::GetEnumValue(field, std::forward<Args>(args)...);
245
0
      RETURN_IF_ERROR(x.status());
246
0
      WriteEnum<Traits>(writer, field, *x);
247
0
      break;
248
0
    }
249
0
    case FieldDescriptor::TYPE_MESSAGE:
250
0
    case FieldDescriptor::TYPE_GROUP: {
251
0
      auto x = Traits::GetMessage(field, std::forward<Args>(args)...);
252
0
      RETURN_IF_ERROR(x.status());
253
0
      return WriteMessage<Traits>(writer, **x, Traits::GetDesc(**x));
254
0
    }
255
0
    default:
256
0
      return absl::InvalidArgumentError(
257
0
          absl::StrCat("unsupported field type: ", Traits::FieldType(field)));
258
0
  }
259
260
0
  return absl::OkStatus();
261
0
}
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteSingular<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Field)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteSingular<google::protobuf::json_internal::UnparseProto2Descriptor, google::protobuf::Message const&>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Field, google::protobuf::Message const&)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteSingular<google::protobuf::json_internal::UnparseProto2Descriptor, google::protobuf::Message const&, unsigned long&>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Field, google::protobuf::Message const&, unsigned long&)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteSingular<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Field)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteSingular<google::protobuf::json_internal::UnparseProto3Type, google::protobuf::json_internal::UntypedMessage const&>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Field, google::protobuf::json_internal::UntypedMessage const&)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteSingular<google::protobuf::json_internal::UnparseProto3Type, google::protobuf::json_internal::UntypedMessage const&, unsigned long&>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Field, google::protobuf::json_internal::UntypedMessage const&, unsigned long&)
262
263
template <typename Traits>
264
absl::Status WriteRepeated(JsonWriter& writer, const Msg<Traits>& msg,
265
0
                           Field<Traits> field) {
266
0
  writer.Write("[");
267
0
  writer.Push();
268
269
0
  size_t count = Traits::GetSize(field, msg);
270
0
  bool first = true;
271
0
  for (size_t i = 0; i < count; ++i) {
272
0
    if (ClassifyMessage(Traits::FieldTypeName(field)) == MessageType::kValue) {
273
0
      bool empty = false;
274
0
      RETURN_IF_ERROR(Traits::WithFieldType(
275
0
          field, [&](const Desc<Traits>& desc) -> absl::Status {
276
0
            auto inner = Traits::GetMessage(field, msg, i);
277
0
            RETURN_IF_ERROR(inner.status());
278
0
            empty = IsEmpty<Traits>(**inner, desc);
279
0
            return absl::OkStatus();
280
0
          }));
281
282
      // Empty google.protobuf.Values are silently discarded.
283
0
      if (empty) {
284
0
        continue;
285
0
      }
286
0
    }
287
0
    writer.WriteComma(first);
288
0
    writer.NewLine();
289
0
    RETURN_IF_ERROR(WriteSingular<Traits>(writer, field, msg, i));
290
0
  }
291
292
0
  writer.Pop();
293
0
  if (!first) {
294
0
    writer.NewLine();
295
0
  }
296
0
  writer.Write("]");
297
0
  return absl::OkStatus();
298
0
}
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteRepeated<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Field)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteRepeated<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Field)
299
300
template <typename Traits>
301
absl::Status WriteMapKey(JsonWriter& writer, const Msg<Traits>& entry,
302
0
                         Field<Traits> field) {
303
0
  switch (Traits::FieldType(field)) {
304
0
    case FieldDescriptor::TYPE_SFIXED64:
305
0
    case FieldDescriptor::TYPE_SINT64:
306
0
    case FieldDescriptor::TYPE_INT64: {
307
0
      auto x = Traits::GetInt64(field, entry);
308
0
      RETURN_IF_ERROR(x.status());
309
0
      writer.Write(MakeQuoted(*x));
310
0
      break;
311
0
    }
312
0
    case FieldDescriptor::TYPE_FIXED64:
313
0
    case FieldDescriptor::TYPE_UINT64: {
314
0
      auto x = Traits::GetUInt64(field, entry);
315
0
      RETURN_IF_ERROR(x.status());
316
0
      writer.Write(MakeQuoted(*x));
317
0
      break;
318
0
    }
319
0
    case FieldDescriptor::TYPE_SFIXED32:
320
0
    case FieldDescriptor::TYPE_SINT32:
321
0
    case FieldDescriptor::TYPE_INT32: {
322
0
      auto x = Traits::GetInt32(field, entry);
323
0
      RETURN_IF_ERROR(x.status());
324
0
      writer.Write(MakeQuoted(*x));
325
0
      break;
326
0
    }
327
0
    case FieldDescriptor::TYPE_FIXED32:
328
0
    case FieldDescriptor::TYPE_UINT32: {
329
0
      auto x = Traits::GetUInt32(field, entry);
330
0
      RETURN_IF_ERROR(x.status());
331
0
      writer.Write(MakeQuoted(*x));
332
0
      break;
333
0
    }
334
0
    case FieldDescriptor::TYPE_BOOL: {
335
0
      auto x = Traits::GetBool(field, entry);
336
0
      RETURN_IF_ERROR(x.status());
337
0
      writer.Write(MakeQuoted(*x ? "true" : "false"));
338
0
      break;
339
0
    }
340
0
    case FieldDescriptor::TYPE_STRING: {
341
0
      auto x = Traits::GetString(field, writer.ScratchBuf(), entry);
342
0
      RETURN_IF_ERROR(x.status());
343
0
      writer.Write(MakeQuoted(*x));
344
0
      break;
345
0
    }
346
0
    case FieldDescriptor::TYPE_ENUM: {
347
0
      auto x = Traits::GetEnumValue(field, entry);
348
0
      RETURN_IF_ERROR(x.status());
349
0
      WriteEnum<Traits>(writer, field, *x, IntegerEnumStyle::kQuoted);
350
0
      break;
351
0
    }
352
0
    default:
353
0
      return absl::InvalidArgumentError(
354
0
          absl::StrCat("unsupported map key type: ", Traits::FieldType(field)));
355
0
  }
356
0
  return absl::OkStatus();
357
0
}
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteMapKey<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Field)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteMapKey<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Field)
358
359
template <typename Traits>
360
0
absl::StatusOr<bool> IsEmptyValue(const Msg<Traits>& msg, Field<Traits> field) {
361
0
  if (ClassifyMessage(Traits::FieldTypeName(field)) != MessageType::kValue) {
362
0
    return false;
363
0
  }
364
0
  bool empty = false;
365
0
  RETURN_IF_ERROR(Traits::WithFieldType(
366
0
      field, [&](const Desc<Traits>& desc) -> absl::Status {
367
0
        auto inner = Traits::GetMessage(field, msg);
368
0
        RETURN_IF_ERROR(inner.status());
369
0
        empty = IsEmpty<Traits>(**inner, desc);
370
0
        return absl::OkStatus();
371
0
      }));
372
0
  return empty;
373
0
}
Unexecuted instantiation: unparser.cc:absl::lts_20230125::StatusOr<bool> google::protobuf::json_internal::(anonymous namespace)::IsEmptyValue<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Field)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::StatusOr<bool> google::protobuf::json_internal::(anonymous namespace)::IsEmptyValue<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Field)
374
375
template <typename Traits>
376
absl::Status WriteMap(JsonWriter& writer, const Msg<Traits>& msg,
377
0
                      Field<Traits> field) {
378
0
  writer.Write("{");
379
0
  writer.Push();
380
381
0
  size_t count = Traits::GetSize(field, msg);
382
0
  bool first = true;
383
0
  for (size_t i = 0; i < count; ++i) {
384
0
    absl::StatusOr<const Msg<Traits>*> entry =
385
0
        Traits::GetMessage(field, msg, i);
386
0
    RETURN_IF_ERROR(entry.status());
387
0
    const Desc<Traits>& type = Traits::GetDesc(**entry);
388
389
0
    auto is_empty = IsEmptyValue<Traits>(**entry, Traits::ValueField(type));
390
0
    RETURN_IF_ERROR(is_empty.status());
391
0
    if (*is_empty) {
392
      // Empty google.protobuf.Values are silently discarded.
393
0
      continue;
394
0
    }
395
396
0
    writer.WriteComma(first);
397
0
    writer.NewLine();
398
0
    RETURN_IF_ERROR(
399
0
        WriteMapKey<Traits>(writer, **entry, Traits::KeyField(type)));
400
0
    writer.Write(":");
401
0
    writer.Whitespace(" ");
402
0
    RETURN_IF_ERROR(
403
0
        WriteSingular<Traits>(writer, Traits::ValueField(type), **entry));
404
0
  }
405
406
0
  writer.Pop();
407
0
  if (!first) {
408
0
    writer.NewLine();
409
0
  }
410
0
  writer.Write("}");
411
0
  return absl::OkStatus();
412
0
}
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteMap<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Field)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteMap<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Field)
413
414
template <typename Traits>
415
absl::Status WriteField(JsonWriter& writer, const Msg<Traits>& msg,
416
0
                        Field<Traits> field, bool& first) {
417
0
  if (!Traits::IsRepeated(field)) {  // Repeated case is handled in
418
                                     // WriteRepeated.
419
0
    auto is_empty = IsEmptyValue<Traits>(msg, field);
420
0
    RETURN_IF_ERROR(is_empty.status());
421
0
    if (*is_empty) {
422
      // Empty google.protobuf.Values are silently discarded.
423
0
      return absl::OkStatus();
424
0
    }
425
0
  }
426
427
0
  writer.WriteComma(first);
428
0
  writer.NewLine();
429
430
0
  if (Traits::IsExtension(field)) {
431
0
    writer.Write(MakeQuoted("[", Traits::FieldFullName(field), "]"), ":");
432
0
  } else if (writer.options().preserve_proto_field_names) {
433
0
    writer.Write(MakeQuoted(Traits::FieldName(field)), ":");
434
0
  } else {
435
    // The generator for type.proto and the internals of descriptor.cc disagree
436
    // on what the json name of a PascalCase field is supposed to be; type.proto
437
    // seems to (incorrectly?) capitalize the first letter, which is the
438
    // behavior ESF defaults to. To fix this, if the original field name starts
439
    // with an uppercase letter, and the Json name does not, we uppercase it.
440
0
    absl::string_view original_name = Traits::FieldName(field);
441
0
    absl::string_view json_name = Traits::FieldJsonName(field);
442
0
    if (writer.options().allow_legacy_syntax &&
443
0
        absl::ascii_isupper(original_name[0]) &&
444
0
        !absl::ascii_isupper(json_name[0])) {
445
0
      writer.Write(MakeQuoted(absl::ascii_toupper(original_name[0]),
446
0
                              original_name.substr(1)),
447
0
                   ":");
448
0
    } else {
449
0
      writer.Write(MakeQuoted(json_name), ":");
450
0
    }
451
0
  }
452
0
  writer.Whitespace(" ");
453
454
0
  if (Traits::IsMap(field)) {
455
0
    return WriteMap<Traits>(writer, msg, field);
456
0
  } else if (Traits::IsRepeated(field)) {
457
0
    return WriteRepeated<Traits>(writer, msg, field);
458
0
  } else if (Traits::GetSize(field, msg) == 0) {
459
    // We can only get here if always_print_primitive_fields is true.
460
0
    ABSL_DCHECK(writer.options().always_print_primitive_fields);
461
462
0
    if (Traits::FieldType(field) == FieldDescriptor::TYPE_GROUP) {
463
      // We do not yet have full group support, but this is required so that we
464
      // pass the same tests as the ESF parser.
465
0
      writer.Write("null");
466
0
      return absl::OkStatus();
467
0
    }
468
0
    return WriteSingular<Traits>(writer, field);
469
0
  }
470
471
0
  return WriteSingular<Traits>(writer, field, msg);
472
0
}
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteField<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Field, bool&)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteField<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Field, bool&)
473
474
template <typename Traits>
475
absl::Status WriteFields(JsonWriter& writer, const Msg<Traits>& msg,
476
0
                         const Desc<Traits>& desc, bool& first) {
477
0
  std::vector<Field<Traits>> fields;
478
0
  size_t total = Traits::FieldCount(desc);
479
0
  fields.reserve(total);
480
0
  for (size_t i = 0; i < total; ++i) {
481
0
    Field<Traits> field = Traits::FieldByIndex(desc, i);
482
483
0
    bool has = Traits::GetSize(field, msg) > 0;
484
0
    if (writer.options().always_print_primitive_fields) {
485
0
      bool is_singular_message =
486
0
          !Traits::IsRepeated(field) &&
487
0
          Traits::FieldType(field) == FieldDescriptor::TYPE_MESSAGE;
488
0
      has |= !is_singular_message && !Traits::IsOneof(field);
489
0
    }
490
491
0
    if (has) {
492
0
      fields.push_back(field);
493
0
    }
494
0
  }
495
496
  // Add extensions *before* sorting.
497
0
  Traits::FindAndAppendExtensions(msg, fields);
498
499
  // Fields are guaranteed to be serialized in field number order.
500
0
  absl::c_sort(fields, [](const auto& a, const auto& b) {
501
0
    return Traits::FieldNumber(a) < Traits::FieldNumber(b);
502
0
  });
Unexecuted instantiation: unparser.cc:auto google::protobuf::json_internal::(anonymous namespace)::WriteFields<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Desc const&, bool&)::{lambda(auto:1 const&, auto:2 const&)#1}::operator()<google::protobuf::FieldDescriptor const*, google::protobuf::FieldDescriptor const>(google::protobuf::FieldDescriptor const* const&, google::protobuf::FieldDescriptor const&) const
Unexecuted instantiation: unparser.cc:auto google::protobuf::json_internal::(anonymous namespace)::WriteFields<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Desc const&, bool&)::{lambda(auto:1 const&, auto:2 const&)#1}::operator()<google::protobuf::json_internal::ResolverPool::Field const*, google::protobuf::json_internal::ResolverPool::Field const>(google::protobuf::json_internal::ResolverPool::Field const* const&, google::protobuf::json_internal::ResolverPool::Field const&) const
503
504
0
  for (auto field : fields) {
505
0
    RETURN_IF_ERROR(WriteField<Traits>(writer, msg, field, first));
506
0
  }
507
508
0
  return absl::OkStatus();
509
0
}
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteFields<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Desc const&, bool&)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteFields<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Desc const&, bool&)
510
511
template <typename Traits>
512
absl::Status WriteStructValue(JsonWriter& writer, const Msg<Traits>& msg,
513
                              const Desc<Traits>& desc);
514
template <typename Traits>
515
absl::Status WriteListValue(JsonWriter& writer, const Msg<Traits>& msg,
516
                            const Desc<Traits>& desc);
517
518
template <typename Traits>
519
absl::Status WriteValue(JsonWriter& writer, const Msg<Traits>& msg,
520
0
                        const Desc<Traits>& desc, bool is_top_level) {
521
  // NOTE: The field numbers 1 through 6 are the numbers of the oneof fields in
522
  // google.protobuf.Value. Conformance tests verify the correctness of these
523
  // numbers.
524
0
  if (Traits::GetSize(Traits::MustHaveField(desc, 1), msg) > 0) {
525
0
    writer.Write("null");
526
0
    return absl::OkStatus();
527
0
  }
528
529
0
  auto number_field = Traits::MustHaveField(desc, 2);
530
0
  if (Traits::GetSize(number_field, msg) > 0) {
531
0
    auto x = Traits::GetDouble(number_field, msg);
532
0
    RETURN_IF_ERROR(x.status());
533
0
    if (std::isnan(*x)) {
534
0
      return absl::InvalidArgumentError(
535
0
          "google.protobuf.Value cannot encode double values for nan, "
536
0
          "because it would be parsed as a string");
537
0
    }
538
0
    if (*x == std::numeric_limits<double>::infinity() ||
539
0
        *x == -std::numeric_limits<double>::infinity()) {
540
0
      return absl::InvalidArgumentError(
541
0
          "google.protobuf.Value cannot encode double values for "
542
0
          "infinity, because it would be parsed as a string");
543
0
    }
544
0
    writer.Write(*x);
545
0
    return absl::OkStatus();
546
0
  }
547
548
0
  auto string_field = Traits::MustHaveField(desc, 3);
549
0
  if (Traits::GetSize(string_field, msg) > 0) {
550
0
    auto x = Traits::GetString(string_field, writer.ScratchBuf(), msg);
551
0
    RETURN_IF_ERROR(x.status());
552
0
    writer.Write(MakeQuoted(*x));
553
0
    return absl::OkStatus();
554
0
  }
555
556
0
  auto bool_field = Traits::MustHaveField(desc, 4);
557
0
  if (Traits::GetSize(bool_field, msg) > 0) {
558
0
    auto x = Traits::GetBool(bool_field, msg);
559
0
    RETURN_IF_ERROR(x.status());
560
0
    writer.Write(*x ? "true" : "false");
561
0
    return absl::OkStatus();
562
0
  }
563
564
0
  auto struct_field = Traits::MustHaveField(desc, 5);
565
0
  if (Traits::GetSize(struct_field, msg) > 0) {
566
0
    auto x = Traits::GetMessage(struct_field, msg);
567
0
    RETURN_IF_ERROR(x.status());
568
0
    return Traits::WithFieldType(struct_field, [&](const Desc<Traits>& type) {
569
0
      return WriteStructValue<Traits>(writer, **x, type);
570
0
    });
Unexecuted instantiation: unparser.cc:google::protobuf::json_internal::(anonymous namespace)::WriteValue<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Desc const&, bool)::{lambda(google::protobuf::Descriptor const&)#1}::operator()(google::protobuf::Descriptor const&) const
Unexecuted instantiation: unparser.cc:google::protobuf::json_internal::(anonymous namespace)::WriteValue<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Desc const&, bool)::{lambda(google::protobuf::json_internal::ResolverPool::Message const&)#1}::operator()(google::protobuf::json_internal::ResolverPool::Message const&) const
571
0
  }
572
573
0
  auto list_field = Traits::MustHaveField(desc, 6);
574
0
  if (Traits::GetSize(list_field, msg) > 0) {
575
0
    auto x = Traits::GetMessage(list_field, msg);
576
0
    RETURN_IF_ERROR(x.status());
577
0
    return Traits::WithFieldType(list_field, [&](const Desc<Traits>& type) {
578
0
      return WriteListValue<Traits>(writer, **x, type);
579
0
    });
Unexecuted instantiation: unparser.cc:google::protobuf::json_internal::(anonymous namespace)::WriteValue<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Desc const&, bool)::{lambda(google::protobuf::Descriptor const&)#2}::operator()(google::protobuf::Descriptor const&) const
Unexecuted instantiation: unparser.cc:google::protobuf::json_internal::(anonymous namespace)::WriteValue<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Desc const&, bool)::{lambda(google::protobuf::json_internal::ResolverPool::Message const&)#2}::operator()(google::protobuf::json_internal::ResolverPool::Message const&) const
580
0
  }
581
582
0
  ABSL_CHECK(is_top_level)
583
0
      << "empty, non-top-level Value must be handled one layer "
584
0
         "up, since it prints an empty string; reaching this "
585
0
         "statement is always a bug";
586
0
  return absl::OkStatus();
587
0
}
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteValue<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Desc const&, bool)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteValue<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Desc const&, bool)
588
589
template <typename Traits>
590
absl::Status WriteStructValue(JsonWriter& writer, const Msg<Traits>& msg,
591
0
                              const Desc<Traits>& desc) {
592
0
  return WriteMap<Traits>(writer, msg, Traits::MustHaveField(desc, 1));
593
0
}
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteStructValue<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Desc const&)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteStructValue<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Desc const&)
594
595
template <typename Traits>
596
absl::Status WriteListValue(JsonWriter& writer, const Msg<Traits>& msg,
597
0
                            const Desc<Traits>& desc) {
598
0
  return WriteRepeated<Traits>(writer, msg, Traits::MustHaveField(desc, 1));
599
0
}
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteListValue<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Desc const&)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteListValue<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Desc const&)
600
601
template <typename Traits>
602
absl::Status WriteTimestamp(JsonWriter& writer, const Msg<Traits>& msg,
603
0
                            const Desc<Traits>& desc) {
604
0
  auto secs_field = Traits::MustHaveField(desc, 1);
605
0
  auto secs = Traits::GetSize(secs_field, msg) > 0
606
0
                  ? Traits::GetInt64(secs_field, msg)
607
0
                  : 0;
608
0
  RETURN_IF_ERROR(secs.status());
609
610
0
  if (*secs < -62135596800) {
611
0
    return absl::InvalidArgumentError(
612
0
        "minimum acceptable time value is 0001-01-01T00:00:00Z");
613
0
  } else if (*secs > 253402300799) {
614
0
    return absl::InvalidArgumentError(
615
0
        "maximum acceptable time value is 9999-12-31T23:59:59Z");
616
0
  }
617
618
  // Ensure seconds is positive.
619
0
  *secs += 62135596800;
620
621
0
  auto nanos_field = Traits::MustHaveField(desc, 2);
622
0
  auto nanos = Traits::GetSize(nanos_field, msg) > 0
623
0
                   ? Traits::GetInt32(nanos_field, msg)
624
0
                   : 0;
625
0
  RETURN_IF_ERROR(nanos.status());
626
627
  // Julian Day -> Y/M/D, Algorithm from:
628
  // Fliegel, H. F., and Van Flandern, T. C., "A Machine Algorithm for
629
  //   Processing Calendar Dates," Communications of the Association of
630
  //   Computing Machines, vol. 11 (1968), p. 657.
631
0
  int32_t L, N, I, J, K;
632
0
  L = static_cast<int32_t>(*secs / 86400) - 719162 + 68569 + 2440588;
633
0
  N = 4 * L / 146097;
634
0
  L = L - (146097 * N + 3) / 4;
635
0
  I = 4000 * (L + 1) / 1461001;
636
0
  L = L - 1461 * I / 4 + 31;
637
0
  J = 80 * L / 2447;
638
0
  K = L - 2447 * J / 80;
639
0
  L = J / 11;
640
0
  J = J + 2 - 12 * L;
641
0
  I = 100 * (N - 49) + I + L;
642
643
0
  int32_t sec = *secs % 60;
644
0
  int32_t min = (*secs / 60) % 60;
645
0
  int32_t hour = (*secs / 3600) % 24;
646
647
0
  if (*nanos == 0) {
648
0
    writer.Write(absl::StrFormat(R"("%04d-%02d-%02dT%02d:%02d:%02dZ")", I, J, K,
649
0
                                 hour, min, sec));
650
0
    return absl::OkStatus();
651
0
  }
652
653
0
  size_t digits = 9;
654
0
  uint32_t frac_seconds = std::abs(*nanos);
655
0
  while (frac_seconds % 1000 == 0) {
656
0
    frac_seconds /= 1000;
657
0
    digits -= 3;
658
0
  }
659
660
0
  writer.Write(absl::StrFormat(R"("%04d-%02d-%02dT%02d:%02d:%02d.%.*dZ")", I, J,
661
0
                               K, hour, min, sec, digits, frac_seconds));
662
0
  return absl::OkStatus();
663
0
}
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteTimestamp<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Desc const&)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteTimestamp<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Desc const&)
664
665
template <typename Traits>
666
absl::Status WriteDuration(JsonWriter& writer, const Msg<Traits>& msg,
667
0
                           const Desc<Traits>& desc) {
668
0
  constexpr int64_t kMaxSeconds = int64_t{3652500} * 86400;
669
0
  constexpr int64_t kMaxNanos = 999999999;
670
671
0
  auto secs_field = Traits::MustHaveField(desc, 1);
672
0
  auto secs = Traits::GetSize(secs_field, msg) > 0
673
0
                  ? Traits::GetInt64(secs_field, msg)
674
0
                  : 0;
675
0
  RETURN_IF_ERROR(secs.status());
676
677
0
  if (*secs > kMaxSeconds || *secs < -kMaxSeconds) {
678
0
    return absl::InvalidArgumentError("duration out of range");
679
0
  }
680
681
0
  auto nanos_field = Traits::MustHaveField(desc, 2);
682
0
  auto nanos = Traits::GetSize(nanos_field, msg) > 0
683
0
                   ? Traits::GetInt32(nanos_field, msg)
684
0
                   : 0;
685
0
  RETURN_IF_ERROR(nanos.status());
686
687
0
  if (*nanos > kMaxNanos || *nanos < -kMaxNanos) {
688
0
    return absl::InvalidArgumentError("duration out of range");
689
0
  }
690
0
  if ((*secs != 0) && (*nanos != 0) && ((*secs < 0) != (*nanos < 0))) {
691
0
    return absl::InvalidArgumentError("nanos and seconds signs do not match");
692
0
  }
693
694
0
  if (*nanos == 0) {
695
0
    writer.Write(absl::StrFormat(R"("%ds")", *secs));
696
0
    return absl::OkStatus();
697
0
  }
698
699
0
  size_t digits = 9;
700
0
  uint32_t frac_seconds = std::abs(*nanos);
701
0
  while (frac_seconds % 1000 == 0) {
702
0
    frac_seconds /= 1000;
703
0
    digits -= 3;
704
0
  }
705
706
0
  absl::string_view sign = ((*secs < 0) || (*nanos < 0)) ? "-" : "";
707
0
  writer.Write(absl::StrFormat(R"("%s%d.%.*ds")", sign, std::abs(*secs), digits,
708
0
                               frac_seconds));
709
0
  return absl::OkStatus();
710
0
}
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteDuration<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Desc const&)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteDuration<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Desc const&)
711
712
template <typename Traits>
713
absl::Status WriteFieldMask(JsonWriter& writer, const Msg<Traits>& msg,
714
0
                            const Desc<Traits>& desc) {
715
  // google.protobuf.FieldMask has a single field with number 1.
716
0
  auto paths_field = Traits::MustHaveField(desc, 1);
717
0
  size_t paths = Traits::GetSize(paths_field, msg);
718
0
  writer.Write('"');
719
720
0
  bool first = true;
721
0
  for (size_t i = 0; i < paths; ++i) {
722
0
    writer.WriteComma(first);
723
0
    auto path = Traits::GetString(paths_field, writer.ScratchBuf(), msg, i);
724
0
    RETURN_IF_ERROR(path.status());
725
0
    bool saw_under = false;
726
0
    for (char c : *path) {
727
0
      if (absl::ascii_islower(c) && saw_under) {
728
0
        writer.Write(absl::ascii_toupper(c));
729
0
      } else if (absl::ascii_isdigit(c) || absl::ascii_islower(c) || c == '.') {
730
0
        writer.Write(c);
731
0
      } else if (c == '_' &&
732
0
                 (!saw_under || writer.options().allow_legacy_syntax)) {
733
0
        saw_under = true;
734
0
        continue;
735
0
      } else if (!writer.options().allow_legacy_syntax) {
736
0
        return absl::InvalidArgumentError("unexpected character in FieldMask");
737
0
      } else {
738
0
        if (saw_under) {
739
0
          writer.Write('_');
740
0
        }
741
0
        writer.Write(c);
742
0
      }
743
0
      saw_under = false;
744
0
    }
745
0
  }
746
0
  writer.Write('"');
747
748
0
  return absl::OkStatus();
749
0
}
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteFieldMask<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Desc const&)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteFieldMask<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Desc const&)
750
751
template <typename Traits>
752
absl::Status WriteAny(JsonWriter& writer, const Msg<Traits>& msg,
753
0
                      const Desc<Traits>& desc) {
754
0
  auto type_url_field = Traits::MustHaveField(desc, 1);
755
0
  auto value_field = Traits::MustHaveField(desc, 2);
756
757
0
  bool has_type_url = Traits::GetSize(type_url_field, msg) > 0;
758
0
  bool has_value = Traits::GetSize(value_field, msg) > 0;
759
0
  if (!has_type_url && !has_value) {
760
0
    writer.Write("{}");
761
0
    return absl::OkStatus();
762
0
  } else if (!has_type_url) {
763
0
    return absl::InvalidArgumentError("broken Any: missing type URL");
764
0
  } else if (!has_value && !writer.options().allow_legacy_syntax) {
765
0
    return absl::InvalidArgumentError("broken Any: missing value");
766
0
  }
767
768
0
  writer.Write("{");
769
0
  writer.Push();
770
771
0
  auto type_url = Traits::GetString(type_url_field, writer.ScratchBuf(), msg);
772
0
  RETURN_IF_ERROR(type_url.status());
773
0
  writer.NewLine();
774
0
  writer.Write("\"@type\":");
775
0
  writer.Whitespace(" ");
776
0
  writer.Write(MakeQuoted(*type_url));
777
778
0
  return Traits::WithDynamicType(
779
0
      desc, std::string(*type_url),
780
0
      [&](const Desc<Traits>& any_desc) -> absl::Status {
781
0
        absl::string_view any_bytes;
782
0
        if (has_value) {
783
0
          absl::StatusOr<absl::string_view> bytes =
784
0
              Traits::GetString(value_field, writer.ScratchBuf(), msg);
785
0
          RETURN_IF_ERROR(bytes.status());
786
0
          any_bytes = *bytes;
787
0
        }
788
789
0
        return Traits::WithDecodedMessage(
790
0
            any_desc, any_bytes,
791
0
            [&](const Msg<Traits>& unerased) -> absl::Status {
792
0
              bool first = false;
793
0
              if (ClassifyMessage(Traits::TypeName(any_desc)) !=
794
0
                  MessageType::kNotWellKnown) {
795
0
                writer.WriteComma(first);
796
0
                writer.NewLine();
797
0
                writer.Write("\"value\":");
798
0
                writer.Whitespace(" ");
799
0
                RETURN_IF_ERROR(
800
0
                    WriteMessage<Traits>(writer, unerased, any_desc));
801
0
              } else {
802
0
                RETURN_IF_ERROR(
803
0
                    WriteFields<Traits>(writer, unerased, any_desc, first));
804
0
              }
805
0
              writer.Pop();
806
0
              if (!first) {
807
0
                writer.NewLine();
808
0
              }
809
0
              writer.Write("}");
810
0
              return absl::OkStatus();
811
0
            });
Unexecuted instantiation: unparser.cc:google::protobuf::json_internal::(anonymous namespace)::WriteAny<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Desc const&)::{lambda(google::protobuf::Descriptor const&)#1}::operator()(google::protobuf::Descriptor const&) const::{lambda(google::protobuf::Message const&)#1}::operator()(google::protobuf::Message const) const
Unexecuted instantiation: unparser.cc:google::protobuf::json_internal::(anonymous namespace)::WriteAny<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Desc const&)::{lambda(google::protobuf::json_internal::ResolverPool::Message const&)#1}::operator()(google::protobuf::json_internal::ResolverPool::Message const&) const::{lambda(google::protobuf::json_internal::UntypedMessage const&)#1}::operator()(google::protobuf::json_internal::UntypedMessage const) const
812
0
      });
Unexecuted instantiation: unparser.cc:google::protobuf::json_internal::(anonymous namespace)::WriteAny<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Desc const&)::{lambda(google::protobuf::Descriptor const&)#1}::operator()(google::protobuf::Descriptor const&) const
Unexecuted instantiation: unparser.cc:google::protobuf::json_internal::(anonymous namespace)::WriteAny<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Desc const&)::{lambda(google::protobuf::json_internal::ResolverPool::Message const&)#1}::operator()(google::protobuf::json_internal::ResolverPool::Message const&) const
813
0
}
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteAny<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Desc const&)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteAny<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Desc const&)
814
815
template <typename Traits>
816
absl::Status WriteMessage(JsonWriter& writer, const Msg<Traits>& msg,
817
0
                          const Desc<Traits>& desc, bool is_top_level) {
818
0
  switch (ClassifyMessage(Traits::TypeName(desc))) {
819
0
    case MessageType::kAny:
820
0
      return WriteAny<Traits>(writer, msg, desc);
821
0
    case MessageType::kWrapper: {
822
0
      auto field = Traits::MustHaveField(desc, 1);
823
0
      if (Traits::GetSize(field, msg) == 0) {
824
0
        return WriteSingular<Traits>(writer, field);
825
0
      }
826
0
      return WriteSingular<Traits>(writer, field, msg);
827
0
    }
828
0
    case MessageType::kValue:
829
0
      return WriteValue<Traits>(writer, msg, desc, is_top_level);
830
0
    case MessageType::kStruct:
831
0
      return WriteStructValue<Traits>(writer, msg, desc);
832
0
    case MessageType::kList:
833
0
      return WriteListValue<Traits>(writer, msg, desc);
834
0
    case MessageType::kTimestamp:
835
0
      return WriteTimestamp<Traits>(writer, msg, desc);
836
0
    case MessageType::kDuration:
837
0
      return WriteDuration<Traits>(writer, msg, desc);
838
0
    case MessageType::kFieldMask:
839
0
      return WriteFieldMask<Traits>(writer, msg, desc);
840
0
    default: {
841
0
      writer.Write("{");
842
0
      writer.Push();
843
0
      bool first = true;
844
0
      RETURN_IF_ERROR(WriteFields<Traits>(writer, msg, desc, first));
845
0
      writer.Pop();
846
0
      if (!first) {
847
0
        writer.NewLine();
848
0
      }
849
0
      writer.Write("}");
850
0
      return absl::OkStatus();
851
0
    }
852
0
  }
853
0
}
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteMessage<google::protobuf::json_internal::UnparseProto2Descriptor>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto2Descriptor::Msg const&, google::protobuf::json_internal::UnparseProto2Descriptor::Desc const&, bool)
Unexecuted instantiation: unparser.cc:absl::lts_20230125::Status google::protobuf::json_internal::(anonymous namespace)::WriteMessage<google::protobuf::json_internal::UnparseProto3Type>(google::protobuf::json_internal::JsonWriter&, google::protobuf::json_internal::UnparseProto3Type::Msg const&, google::protobuf::json_internal::UnparseProto3Type::Desc const&, bool)
854
}  // namespace
855
856
absl::Status MessageToJsonString(const Message& message, std::string* output,
857
0
                                 json_internal::WriterOptions options) {
858
0
  if (PROTOBUF_DEBUG) {
859
0
    ABSL_DLOG(INFO) << "json2/input: " << message.DebugString();
860
0
  }
861
0
  io::StringOutputStream out(output);
862
0
  JsonWriter writer(&out, options);
863
0
  absl::Status s = WriteMessage<UnparseProto2Descriptor>(
864
0
      writer, message, *message.GetDescriptor(), /*is_top_level=*/true);
865
0
  if (PROTOBUF_DEBUG) ABSL_DLOG(INFO) << "json2/status: " << s;
866
0
  RETURN_IF_ERROR(s);
867
868
0
  writer.NewLine();
869
0
  if (PROTOBUF_DEBUG) {
870
0
    ABSL_DLOG(INFO) << "json2/output: " << absl::CHexEscape(*output);
871
0
  }
872
0
  return absl::OkStatus();
873
0
}
874
875
absl::Status BinaryToJsonStream(google::protobuf::util::TypeResolver* resolver,
876
                                const std::string& type_url,
877
                                io::ZeroCopyInputStream* binary_input,
878
                                io::ZeroCopyOutputStream* json_output,
879
0
                                json_internal::WriterOptions options) {
880
  // NOTE: Most of the contortions in this function are to allow for capture of
881
  // input and output of the parser in ABSL_DLOG mode. Destruction order is very
882
  // critical in this function, because io::ZeroCopy*Stream types usually only
883
  // flush on destruction.
884
885
  // For ABSL_DLOG, we would like to print out the input and output, which
886
  // requires buffering both instead of doing "zero copy". This block, and the
887
  // one at the end of the function, set up and tear down interception of the
888
  // input and output streams.
889
0
  std::string copy;
890
0
  std::string out;
891
0
  absl::optional<io::ArrayInputStream> tee_input;
892
0
  absl::optional<io::StringOutputStream> tee_output;
893
0
  if (PROTOBUF_DEBUG) {
894
0
    const void* data;
895
0
    int len;
896
0
    while (binary_input->Next(&data, &len)) {
897
0
      copy.resize(copy.size() + len);
898
0
      std::memcpy(&copy[copy.size() - len], data, len);
899
0
    }
900
0
    tee_input.emplace(copy.data(), copy.size());
901
0
    tee_output.emplace(&out);
902
0
    ABSL_DLOG(INFO) << "json2/input: " << absl::BytesToHexString(copy);
903
0
  }
904
905
0
  ResolverPool pool(resolver);
906
0
  auto desc = pool.FindMessage(type_url);
907
0
  RETURN_IF_ERROR(desc.status());
908
909
0
  io::CodedInputStream stream(tee_input.has_value() ? &*tee_input
910
0
                                                    : binary_input);
911
0
  auto msg = UntypedMessage::ParseFromStream(*desc, stream);
912
0
  RETURN_IF_ERROR(msg.status());
913
914
0
  JsonWriter writer(tee_output.has_value() ? &*tee_output : json_output,
915
0
                    options);
916
0
  absl::Status s = WriteMessage<UnparseProto3Type>(
917
0
      writer, *msg, UnparseProto3Type::GetDesc(*msg),
918
0
      /*is_top_level=*/true);
919
0
  if (PROTOBUF_DEBUG) ABSL_DLOG(INFO) << "json2/status: " << s;
920
0
  RETURN_IF_ERROR(s);
921
922
0
  if (PROTOBUF_DEBUG) {
923
0
    tee_output.reset();  // Flush the output stream.
924
0
    io::zc_sink_internal::ZeroCopyStreamByteSink(json_output)
925
0
        .Append(out.data(), out.size());
926
0
    ABSL_DLOG(INFO) << "json2/output: " << absl::CHexEscape(out);
927
0
  }
928
929
0
  writer.NewLine();
930
0
  return absl::OkStatus();
931
0
}
932
}  // namespace json_internal
933
}  // namespace protobuf
934
}  // namespace google