1 /*
2  * Copyright (c) 2009-2021, Google LLC
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of Google LLC nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "upb/util/def_to_proto.h"
29 
30 #include <inttypes.h>
31 #include <math.h>
32 
33 #include "upb/port/vsnprintf_compat.h"
34 #include "upb/reflection/enum_reserved_range.h"
35 #include "upb/reflection/extension_range.h"
36 #include "upb/reflection/field_def_internal.h"
37 #include "upb/reflection/file_def_internal.h"
38 #include "upb/reflection/message.h"
39 #include "upb/reflection/message_reserved_range.h"
40 
41 // Must be last.
42 #include "upb/port/def.inc"
43 
44 typedef struct {
45   upb_Arena* arena;
46   jmp_buf err;
47 } upb_ToProto_Context;
48 
49 #define CHK_OOM(val) \
50   if (!(val)) UPB_LONGJMP(ctx->err, 1);
51 
52 // We want to copy the options verbatim into the destination options proto.
53 // We use serialize+parse as our deep copy.
54 #define SET_OPTIONS(proto, desc_type, options_type, src)                  \
55   {                                                                       \
56     size_t size;                                                          \
57     /* MEM: could use a temporary arena here instead. */                  \
58     char* pb = google_protobuf_##options_type##_serialize(src, ctx->arena, &size); \
59     CHK_OOM(pb);                                                          \
60     google_protobuf_##options_type* dst =                                          \
61         google_protobuf_##options_type##_parse(pb, size, ctx->arena);              \
62     CHK_OOM(dst);                                                         \
63     google_protobuf_##desc_type##_set_options(proto, dst);                         \
64   }
65 
strviewdup2(upb_ToProto_Context * ctx,upb_StringView str)66 static upb_StringView strviewdup2(upb_ToProto_Context* ctx,
67                                   upb_StringView str) {
68   char* p = upb_Arena_Malloc(ctx->arena, str.size);
69   CHK_OOM(p);
70   memcpy(p, str.data, str.size);
71   return (upb_StringView){.data = p, .size = str.size};
72 }
73 
strviewdup(upb_ToProto_Context * ctx,const char * s)74 static upb_StringView strviewdup(upb_ToProto_Context* ctx, const char* s) {
75   return strviewdup2(ctx, (upb_StringView){.data = s, .size = strlen(s)});
76 }
77 
qual_dup(upb_ToProto_Context * ctx,const char * s)78 static upb_StringView qual_dup(upb_ToProto_Context* ctx, const char* s) {
79   size_t n = strlen(s);
80   char* p = upb_Arena_Malloc(ctx->arena, n + 1);
81   CHK_OOM(p);
82   p[0] = '.';
83   memcpy(p + 1, s, n);
84   return (upb_StringView){.data = p, .size = n + 1};
85 }
86 
87 UPB_PRINTF(2, 3)
printf_dup(upb_ToProto_Context * ctx,const char * fmt,...)88 static upb_StringView printf_dup(upb_ToProto_Context* ctx, const char* fmt,
89                                  ...) {
90   const size_t max = 32;
91   char* p = upb_Arena_Malloc(ctx->arena, max);
92   CHK_OOM(p);
93   va_list args;
94   va_start(args, fmt);
95   size_t n = _upb_vsnprintf(p, max, fmt, args);
96   va_end(args);
97   UPB_ASSERT(n < max);
98   return (upb_StringView){.data = p, .size = n};
99 }
100 
upb_isprint(char ch)101 static bool upb_isprint(char ch) { return ch >= 0x20 && ch <= 0x7f; }
102 
special_escape(char ch)103 static int special_escape(char ch) {
104   switch (ch) {
105     // This is the same set of special escapes recognized by
106     // absl::CEscape().
107     case '\n':
108       return 'n';
109     case '\r':
110       return 'r';
111     case '\t':
112       return 't';
113     case '\\':
114       return '\\';
115     case '\'':
116       return '\'';
117     case '"':
118       return '"';
119     default:
120       return -1;
121   }
122 }
123 
default_bytes(upb_ToProto_Context * ctx,upb_StringView val)124 static upb_StringView default_bytes(upb_ToProto_Context* ctx,
125                                     upb_StringView val) {
126   size_t n = 0;
127   for (size_t i = 0; i < val.size; i++) {
128     char ch = val.data[i];
129     if (special_escape(ch) >= 0)
130       n += 2;  // '\C'
131     else if (upb_isprint(ch))
132       n += 1;
133     else
134       n += 4;  // '\123'
135   }
136   char* p = upb_Arena_Malloc(ctx->arena, n);
137   CHK_OOM(p);
138   char* dst = p;
139   const char* src = val.data;
140   const char* end = src + val.size;
141   while (src < end) {
142     unsigned char ch = *src++;
143     if (special_escape(ch) >= 0) {
144       *dst++ = '\\';
145       *dst++ = (char)special_escape(ch);
146     } else if (upb_isprint(ch)) {
147       *dst++ = ch;
148     } else {
149       *dst++ = '\\';
150       *dst++ = '0' + (ch >> 6);
151       *dst++ = '0' + ((ch >> 3) & 0x7);
152       *dst++ = '0' + (ch & 0x7);
153     }
154   }
155   return (upb_StringView){.data = p, .size = n};
156 }
157 
default_string(upb_ToProto_Context * ctx,const upb_FieldDef * f)158 static upb_StringView default_string(upb_ToProto_Context* ctx,
159                                      const upb_FieldDef* f) {
160   upb_MessageValue d = upb_FieldDef_Default(f);
161   upb_CType type = upb_FieldDef_CType(f);
162 
163   if (type == kUpb_CType_Float || type == kUpb_CType_Double) {
164     double val = type == kUpb_CType_Float ? d.float_val : d.double_val;
165     if (val == INFINITY) {
166       return strviewdup(ctx, "inf");
167     } else if (val == -INFINITY) {
168       return strviewdup(ctx, "-inf");
169     } else if (val != val) {
170       return strviewdup(ctx, "nan");
171     }
172   }
173 
174   switch (upb_FieldDef_CType(f)) {
175     case kUpb_CType_Bool:
176       return strviewdup(ctx, d.bool_val ? "true" : "false");
177     case kUpb_CType_Enum: {
178       const upb_EnumDef* e = upb_FieldDef_EnumSubDef(f);
179       const upb_EnumValueDef* ev =
180           upb_EnumDef_FindValueByNumber(e, d.int32_val);
181       return strviewdup(ctx, upb_EnumValueDef_Name(ev));
182     }
183     case kUpb_CType_Int64:
184       return printf_dup(ctx, "%" PRId64, d.int64_val);
185     case kUpb_CType_UInt64:
186       return printf_dup(ctx, "%" PRIu64, d.uint64_val);
187     case kUpb_CType_Int32:
188       return printf_dup(ctx, "%" PRId32, d.int32_val);
189     case kUpb_CType_UInt32:
190       return printf_dup(ctx, "%" PRIu32, d.uint32_val);
191     case kUpb_CType_Float:
192       return printf_dup(ctx, "%.9g", d.float_val);
193     case kUpb_CType_Double:
194       return printf_dup(ctx, "%.17g", d.double_val);
195     case kUpb_CType_String:
196       return strviewdup2(ctx, d.str_val);
197     case kUpb_CType_Bytes:
198       return default_bytes(ctx, d.str_val);
199     default:
200       UPB_UNREACHABLE();
201   }
202 }
203 
resrange_toproto(upb_ToProto_Context * ctx,const upb_MessageReservedRange * r)204 static google_protobuf_DescriptorProto_ReservedRange* resrange_toproto(
205     upb_ToProto_Context* ctx, const upb_MessageReservedRange* r) {
206   google_protobuf_DescriptorProto_ReservedRange* proto =
207       google_protobuf_DescriptorProto_ReservedRange_new(ctx->arena);
208   CHK_OOM(proto);
209 
210   google_protobuf_DescriptorProto_ReservedRange_set_start(
211       proto, upb_MessageReservedRange_Start(r));
212   google_protobuf_DescriptorProto_ReservedRange_set_end(proto,
213                                                upb_MessageReservedRange_End(r));
214 
215   return proto;
216 }
217 
enumresrange_toproto(upb_ToProto_Context * ctx,const upb_EnumReservedRange * r)218 static google_protobuf_EnumDescriptorProto_EnumReservedRange* enumresrange_toproto(
219     upb_ToProto_Context* ctx, const upb_EnumReservedRange* r) {
220   google_protobuf_EnumDescriptorProto_EnumReservedRange* proto =
221       google_protobuf_EnumDescriptorProto_EnumReservedRange_new(ctx->arena);
222   CHK_OOM(proto);
223 
224   google_protobuf_EnumDescriptorProto_EnumReservedRange_set_start(
225       proto, upb_EnumReservedRange_Start(r));
226   google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(
227       proto, upb_EnumReservedRange_End(r));
228 
229   return proto;
230 }
231 
fielddef_toproto(upb_ToProto_Context * ctx,const upb_FieldDef * f)232 static google_protobuf_FieldDescriptorProto* fielddef_toproto(upb_ToProto_Context* ctx,
233                                                      const upb_FieldDef* f) {
234   google_protobuf_FieldDescriptorProto* proto =
235       google_protobuf_FieldDescriptorProto_new(ctx->arena);
236   CHK_OOM(proto);
237 
238   google_protobuf_FieldDescriptorProto_set_name(proto,
239                                        strviewdup(ctx, upb_FieldDef_Name(f)));
240   google_protobuf_FieldDescriptorProto_set_number(proto, upb_FieldDef_Number(f));
241   google_protobuf_FieldDescriptorProto_set_label(proto, upb_FieldDef_Label(f));
242   google_protobuf_FieldDescriptorProto_set_type(proto, upb_FieldDef_Type(f));
243 
244   if (upb_FieldDef_HasJsonName(f)) {
245     google_protobuf_FieldDescriptorProto_set_json_name(
246         proto, strviewdup(ctx, upb_FieldDef_JsonName(f)));
247   }
248 
249   if (upb_FieldDef_IsSubMessage(f)) {
250     google_protobuf_FieldDescriptorProto_set_type_name(
251         proto,
252         qual_dup(ctx, upb_MessageDef_FullName(upb_FieldDef_MessageSubDef(f))));
253   } else if (upb_FieldDef_CType(f) == kUpb_CType_Enum) {
254     google_protobuf_FieldDescriptorProto_set_type_name(
255         proto, qual_dup(ctx, upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(f))));
256   }
257 
258   if (upb_FieldDef_IsExtension(f)) {
259     google_protobuf_FieldDescriptorProto_set_extendee(
260         proto,
261         qual_dup(ctx, upb_MessageDef_FullName(upb_FieldDef_ContainingType(f))));
262   }
263 
264   if (upb_FieldDef_HasDefault(f)) {
265     google_protobuf_FieldDescriptorProto_set_default_value(proto,
266                                                   default_string(ctx, f));
267   }
268 
269   const upb_OneofDef* o = upb_FieldDef_ContainingOneof(f);
270   if (o) {
271     google_protobuf_FieldDescriptorProto_set_oneof_index(proto, upb_OneofDef_Index(o));
272   }
273 
274   if (_upb_FieldDef_IsProto3Optional(f)) {
275     google_protobuf_FieldDescriptorProto_set_proto3_optional(proto, true);
276   }
277 
278   if (upb_FieldDef_HasOptions(f)) {
279     SET_OPTIONS(proto, FieldDescriptorProto, FieldOptions,
280                 upb_FieldDef_Options(f));
281   }
282 
283   return proto;
284 }
285 
oneofdef_toproto(upb_ToProto_Context * ctx,const upb_OneofDef * o)286 static google_protobuf_OneofDescriptorProto* oneofdef_toproto(upb_ToProto_Context* ctx,
287                                                      const upb_OneofDef* o) {
288   google_protobuf_OneofDescriptorProto* proto =
289       google_protobuf_OneofDescriptorProto_new(ctx->arena);
290   CHK_OOM(proto);
291 
292   google_protobuf_OneofDescriptorProto_set_name(proto,
293                                        strviewdup(ctx, upb_OneofDef_Name(o)));
294 
295   if (upb_OneofDef_HasOptions(o)) {
296     SET_OPTIONS(proto, OneofDescriptorProto, OneofOptions,
297                 upb_OneofDef_Options(o));
298   }
299 
300   return proto;
301 }
302 
enumvaldef_toproto(upb_ToProto_Context * ctx,const upb_EnumValueDef * e)303 static google_protobuf_EnumValueDescriptorProto* enumvaldef_toproto(
304     upb_ToProto_Context* ctx, const upb_EnumValueDef* e) {
305   google_protobuf_EnumValueDescriptorProto* proto =
306       google_protobuf_EnumValueDescriptorProto_new(ctx->arena);
307   CHK_OOM(proto);
308 
309   google_protobuf_EnumValueDescriptorProto_set_name(
310       proto, strviewdup(ctx, upb_EnumValueDef_Name(e)));
311   google_protobuf_EnumValueDescriptorProto_set_number(proto, upb_EnumValueDef_Number(e));
312 
313   if (upb_EnumValueDef_HasOptions(e)) {
314     SET_OPTIONS(proto, EnumValueDescriptorProto, EnumValueOptions,
315                 upb_EnumValueDef_Options(e));
316   }
317 
318   return proto;
319 }
320 
enumdef_toproto(upb_ToProto_Context * ctx,const upb_EnumDef * e)321 static google_protobuf_EnumDescriptorProto* enumdef_toproto(upb_ToProto_Context* ctx,
322                                                    const upb_EnumDef* e) {
323   google_protobuf_EnumDescriptorProto* proto =
324       google_protobuf_EnumDescriptorProto_new(ctx->arena);
325   CHK_OOM(proto);
326 
327   google_protobuf_EnumDescriptorProto_set_name(proto,
328                                       strviewdup(ctx, upb_EnumDef_Name(e)));
329 
330   int n = upb_EnumDef_ValueCount(e);
331   google_protobuf_EnumValueDescriptorProto** vals =
332       google_protobuf_EnumDescriptorProto_resize_value(proto, n, ctx->arena);
333   CHK_OOM(vals);
334   for (int i = 0; i < n; i++) {
335     vals[i] = enumvaldef_toproto(ctx, upb_EnumDef_Value(e, i));
336   }
337 
338   n = upb_EnumDef_ReservedRangeCount(e);
339   google_protobuf_EnumDescriptorProto_EnumReservedRange** res_ranges =
340       google_protobuf_EnumDescriptorProto_resize_reserved_range(proto, n, ctx->arena);
341   for (int i = 0; i < n; i++) {
342     res_ranges[i] = enumresrange_toproto(ctx, upb_EnumDef_ReservedRange(e, i));
343   }
344 
345   n = upb_EnumDef_ReservedNameCount(e);
346   upb_StringView* res_names =
347       google_protobuf_EnumDescriptorProto_resize_reserved_name(proto, n, ctx->arena);
348   for (int i = 0; i < n; i++) {
349     res_names[i] = upb_EnumDef_ReservedName(e, i);
350   }
351 
352   if (upb_EnumDef_HasOptions(e)) {
353     SET_OPTIONS(proto, EnumDescriptorProto, EnumOptions,
354                 upb_EnumDef_Options(e));
355   }
356 
357   return proto;
358 }
359 
extrange_toproto(upb_ToProto_Context * ctx,const upb_ExtensionRange * e)360 static google_protobuf_DescriptorProto_ExtensionRange* extrange_toproto(
361     upb_ToProto_Context* ctx, const upb_ExtensionRange* e) {
362   google_protobuf_DescriptorProto_ExtensionRange* proto =
363       google_protobuf_DescriptorProto_ExtensionRange_new(ctx->arena);
364   CHK_OOM(proto);
365 
366   google_protobuf_DescriptorProto_ExtensionRange_set_start(proto,
367                                                   upb_ExtensionRange_Start(e));
368   google_protobuf_DescriptorProto_ExtensionRange_set_end(proto,
369                                                 upb_ExtensionRange_End(e));
370 
371   if (upb_ExtensionRange_HasOptions(e)) {
372     SET_OPTIONS(proto, DescriptorProto_ExtensionRange, ExtensionRangeOptions,
373                 upb_ExtensionRange_Options(e));
374   }
375 
376   return proto;
377 }
378 
msgdef_toproto(upb_ToProto_Context * ctx,const upb_MessageDef * m)379 static google_protobuf_DescriptorProto* msgdef_toproto(upb_ToProto_Context* ctx,
380                                               const upb_MessageDef* m) {
381   google_protobuf_DescriptorProto* proto = google_protobuf_DescriptorProto_new(ctx->arena);
382   CHK_OOM(proto);
383 
384   google_protobuf_DescriptorProto_set_name(proto,
385                                   strviewdup(ctx, upb_MessageDef_Name(m)));
386 
387   int n;
388 
389   n = upb_MessageDef_FieldCount(m);
390   google_protobuf_FieldDescriptorProto** fields =
391       google_protobuf_DescriptorProto_resize_field(proto, n, ctx->arena);
392   CHK_OOM(fields);
393   for (int i = 0; i < n; i++) {
394     fields[i] = fielddef_toproto(ctx, upb_MessageDef_Field(m, i));
395   }
396 
397   n = upb_MessageDef_OneofCount(m);
398   google_protobuf_OneofDescriptorProto** oneofs =
399       google_protobuf_DescriptorProto_resize_oneof_decl(proto, n, ctx->arena);
400   for (int i = 0; i < n; i++) {
401     oneofs[i] = oneofdef_toproto(ctx, upb_MessageDef_Oneof(m, i));
402   }
403 
404   n = upb_MessageDef_NestedMessageCount(m);
405   google_protobuf_DescriptorProto** nested_msgs =
406       google_protobuf_DescriptorProto_resize_nested_type(proto, n, ctx->arena);
407   for (int i = 0; i < n; i++) {
408     nested_msgs[i] = msgdef_toproto(ctx, upb_MessageDef_NestedMessage(m, i));
409   }
410 
411   n = upb_MessageDef_NestedEnumCount(m);
412   google_protobuf_EnumDescriptorProto** nested_enums =
413       google_protobuf_DescriptorProto_resize_enum_type(proto, n, ctx->arena);
414   for (int i = 0; i < n; i++) {
415     nested_enums[i] = enumdef_toproto(ctx, upb_MessageDef_NestedEnum(m, i));
416   }
417 
418   n = upb_MessageDef_NestedExtensionCount(m);
419   google_protobuf_FieldDescriptorProto** nested_exts =
420       google_protobuf_DescriptorProto_resize_extension(proto, n, ctx->arena);
421   for (int i = 0; i < n; i++) {
422     nested_exts[i] =
423         fielddef_toproto(ctx, upb_MessageDef_NestedExtension(m, i));
424   }
425 
426   n = upb_MessageDef_ExtensionRangeCount(m);
427   google_protobuf_DescriptorProto_ExtensionRange** ext_ranges =
428       google_protobuf_DescriptorProto_resize_extension_range(proto, n, ctx->arena);
429   for (int i = 0; i < n; i++) {
430     ext_ranges[i] = extrange_toproto(ctx, upb_MessageDef_ExtensionRange(m, i));
431   }
432 
433   n = upb_MessageDef_ReservedRangeCount(m);
434   google_protobuf_DescriptorProto_ReservedRange** res_ranges =
435       google_protobuf_DescriptorProto_resize_reserved_range(proto, n, ctx->arena);
436   for (int i = 0; i < n; i++) {
437     res_ranges[i] = resrange_toproto(ctx, upb_MessageDef_ReservedRange(m, i));
438   }
439 
440   n = upb_MessageDef_ReservedNameCount(m);
441   upb_StringView* res_names =
442       google_protobuf_DescriptorProto_resize_reserved_name(proto, n, ctx->arena);
443   for (int i = 0; i < n; i++) {
444     res_names[i] = upb_MessageDef_ReservedName(m, i);
445   }
446 
447   if (upb_MessageDef_HasOptions(m)) {
448     SET_OPTIONS(proto, DescriptorProto, MessageOptions,
449                 upb_MessageDef_Options(m));
450   }
451 
452   return proto;
453 }
454 
methoddef_toproto(upb_ToProto_Context * ctx,const upb_MethodDef * m)455 static google_protobuf_MethodDescriptorProto* methoddef_toproto(upb_ToProto_Context* ctx,
456                                                        const upb_MethodDef* m) {
457   google_protobuf_MethodDescriptorProto* proto =
458       google_protobuf_MethodDescriptorProto_new(ctx->arena);
459   CHK_OOM(proto);
460 
461   google_protobuf_MethodDescriptorProto_set_name(proto,
462                                         strviewdup(ctx, upb_MethodDef_Name(m)));
463 
464   google_protobuf_MethodDescriptorProto_set_input_type(
465       proto,
466       qual_dup(ctx, upb_MessageDef_FullName(upb_MethodDef_InputType(m))));
467   google_protobuf_MethodDescriptorProto_set_output_type(
468       proto,
469       qual_dup(ctx, upb_MessageDef_FullName(upb_MethodDef_OutputType(m))));
470 
471   if (upb_MethodDef_ClientStreaming(m)) {
472     google_protobuf_MethodDescriptorProto_set_client_streaming(proto, true);
473   }
474 
475   if (upb_MethodDef_ServerStreaming(m)) {
476     google_protobuf_MethodDescriptorProto_set_server_streaming(proto, true);
477   }
478 
479   if (upb_MethodDef_HasOptions(m)) {
480     SET_OPTIONS(proto, MethodDescriptorProto, MethodOptions,
481                 upb_MethodDef_Options(m));
482   }
483 
484   return proto;
485 }
486 
servicedef_toproto(upb_ToProto_Context * ctx,const upb_ServiceDef * s)487 static google_protobuf_ServiceDescriptorProto* servicedef_toproto(
488     upb_ToProto_Context* ctx, const upb_ServiceDef* s) {
489   google_protobuf_ServiceDescriptorProto* proto =
490       google_protobuf_ServiceDescriptorProto_new(ctx->arena);
491   CHK_OOM(proto);
492 
493   google_protobuf_ServiceDescriptorProto_set_name(
494       proto, strviewdup(ctx, upb_ServiceDef_Name(s)));
495 
496   size_t n = upb_ServiceDef_MethodCount(s);
497   google_protobuf_MethodDescriptorProto** methods =
498       google_protobuf_ServiceDescriptorProto_resize_method(proto, n, ctx->arena);
499   for (int i = 0; i < n; i++) {
500     methods[i] = methoddef_toproto(ctx, upb_ServiceDef_Method(s, i));
501   }
502 
503   if (upb_ServiceDef_HasOptions(s)) {
504     SET_OPTIONS(proto, ServiceDescriptorProto, ServiceOptions,
505                 upb_ServiceDef_Options(s));
506   }
507 
508   return proto;
509 }
510 
filedef_toproto(upb_ToProto_Context * ctx,const upb_FileDef * f)511 static google_protobuf_FileDescriptorProto* filedef_toproto(upb_ToProto_Context* ctx,
512                                                    const upb_FileDef* f) {
513   google_protobuf_FileDescriptorProto* proto =
514       google_protobuf_FileDescriptorProto_new(ctx->arena);
515   CHK_OOM(proto);
516 
517   google_protobuf_FileDescriptorProto_set_name(proto,
518                                       strviewdup(ctx, upb_FileDef_Name(f)));
519 
520   const char* package = upb_FileDef_Package(f);
521   if (package) {
522     size_t n = strlen(package);
523     if (n) {
524       google_protobuf_FileDescriptorProto_set_package(proto, strviewdup(ctx, package));
525     }
526   }
527 
528   const char* edition = upb_FileDef_Edition(f);
529   if (edition != NULL) {
530     size_t n = strlen(edition);
531     if (n != 0) {
532       google_protobuf_FileDescriptorProto_set_edition(proto, strviewdup(ctx, edition));
533     }
534   }
535 
536   if (upb_FileDef_Syntax(f) == kUpb_Syntax_Proto3) {
537     google_protobuf_FileDescriptorProto_set_syntax(proto, strviewdup(ctx, "proto3"));
538   }
539 
540   size_t n;
541   n = upb_FileDef_DependencyCount(f);
542   upb_StringView* deps =
543       google_protobuf_FileDescriptorProto_resize_dependency(proto, n, ctx->arena);
544   for (int i = 0; i < n; i++) {
545     deps[i] = strviewdup(ctx, upb_FileDef_Name(upb_FileDef_Dependency(f, i)));
546   }
547 
548   n = upb_FileDef_PublicDependencyCount(f);
549   int32_t* public_deps =
550       google_protobuf_FileDescriptorProto_resize_public_dependency(proto, n, ctx->arena);
551   const int32_t* public_dep_nums = _upb_FileDef_PublicDependencyIndexes(f);
552   if (n) memcpy(public_deps, public_dep_nums, n * sizeof(int32_t));
553 
554   n = upb_FileDef_WeakDependencyCount(f);
555   int32_t* weak_deps =
556       google_protobuf_FileDescriptorProto_resize_weak_dependency(proto, n, ctx->arena);
557   const int32_t* weak_dep_nums = _upb_FileDef_WeakDependencyIndexes(f);
558   if (n) memcpy(weak_deps, weak_dep_nums, n * sizeof(int32_t));
559 
560   n = upb_FileDef_TopLevelMessageCount(f);
561   google_protobuf_DescriptorProto** msgs =
562       google_protobuf_FileDescriptorProto_resize_message_type(proto, n, ctx->arena);
563   for (int i = 0; i < n; i++) {
564     msgs[i] = msgdef_toproto(ctx, upb_FileDef_TopLevelMessage(f, i));
565   }
566 
567   n = upb_FileDef_TopLevelEnumCount(f);
568   google_protobuf_EnumDescriptorProto** enums =
569       google_protobuf_FileDescriptorProto_resize_enum_type(proto, n, ctx->arena);
570   for (int i = 0; i < n; i++) {
571     enums[i] = enumdef_toproto(ctx, upb_FileDef_TopLevelEnum(f, i));
572   }
573 
574   n = upb_FileDef_ServiceCount(f);
575   google_protobuf_ServiceDescriptorProto** services =
576       google_protobuf_FileDescriptorProto_resize_service(proto, n, ctx->arena);
577   for (int i = 0; i < n; i++) {
578     services[i] = servicedef_toproto(ctx, upb_FileDef_Service(f, i));
579   }
580 
581   n = upb_FileDef_TopLevelExtensionCount(f);
582   google_protobuf_FieldDescriptorProto** exts =
583       google_protobuf_FileDescriptorProto_resize_extension(proto, n, ctx->arena);
584   for (int i = 0; i < n; i++) {
585     exts[i] = fielddef_toproto(ctx, upb_FileDef_TopLevelExtension(f, i));
586   }
587 
588   if (upb_FileDef_HasOptions(f)) {
589     SET_OPTIONS(proto, FileDescriptorProto, FileOptions,
590                 upb_FileDef_Options(f));
591   }
592 
593   return proto;
594 }
595 
upb_ToProto_ConvertMessageDef(upb_ToProto_Context * const ctx,const upb_MessageDef * const m)596 static google_protobuf_DescriptorProto* upb_ToProto_ConvertMessageDef(
597     upb_ToProto_Context* const ctx, const upb_MessageDef* const m) {
598   if (UPB_SETJMP(ctx->err)) return NULL;
599   return msgdef_toproto(ctx, m);
600 }
601 
upb_MessageDef_ToProto(const upb_MessageDef * m,upb_Arena * a)602 google_protobuf_DescriptorProto* upb_MessageDef_ToProto(const upb_MessageDef* m,
603                                                upb_Arena* a) {
604   upb_ToProto_Context ctx = {a};
605   return upb_ToProto_ConvertMessageDef(&ctx, m);
606 }
607 
upb_ToProto_ConvertEnumDef(upb_ToProto_Context * const ctx,const upb_EnumDef * const e)608 google_protobuf_EnumDescriptorProto* upb_ToProto_ConvertEnumDef(
609     upb_ToProto_Context* const ctx, const upb_EnumDef* const e) {
610   if (UPB_SETJMP(ctx->err)) return NULL;
611   return enumdef_toproto(ctx, e);
612 }
613 
upb_EnumDef_ToProto(const upb_EnumDef * e,upb_Arena * a)614 google_protobuf_EnumDescriptorProto* upb_EnumDef_ToProto(const upb_EnumDef* e,
615                                                 upb_Arena* a) {
616   upb_ToProto_Context ctx = {a};
617   return upb_ToProto_ConvertEnumDef(&ctx, e);
618 }
619 
upb_ToProto_ConvertEnumValueDef(upb_ToProto_Context * const ctx,const upb_EnumValueDef * e)620 google_protobuf_EnumValueDescriptorProto* upb_ToProto_ConvertEnumValueDef(
621     upb_ToProto_Context* const ctx, const upb_EnumValueDef* e) {
622   if (UPB_SETJMP(ctx->err)) return NULL;
623   return enumvaldef_toproto(ctx, e);
624 }
625 
upb_EnumValueDef_ToProto(const upb_EnumValueDef * e,upb_Arena * a)626 google_protobuf_EnumValueDescriptorProto* upb_EnumValueDef_ToProto(
627     const upb_EnumValueDef* e, upb_Arena* a) {
628   upb_ToProto_Context ctx = {a};
629   return upb_ToProto_ConvertEnumValueDef(&ctx, e);
630 }
631 
upb_ToProto_ConvertFieldDef(upb_ToProto_Context * const ctx,const upb_FieldDef * f)632 google_protobuf_FieldDescriptorProto* upb_ToProto_ConvertFieldDef(
633     upb_ToProto_Context* const ctx, const upb_FieldDef* f) {
634   if (UPB_SETJMP(ctx->err)) return NULL;
635   return fielddef_toproto(ctx, f);
636 }
637 
upb_FieldDef_ToProto(const upb_FieldDef * f,upb_Arena * a)638 google_protobuf_FieldDescriptorProto* upb_FieldDef_ToProto(const upb_FieldDef* f,
639                                                   upb_Arena* a) {
640   upb_ToProto_Context ctx = {a};
641   return upb_ToProto_ConvertFieldDef(&ctx, f);
642 }
643 
upb_ToProto_ConvertOneofDef(upb_ToProto_Context * const ctx,const upb_OneofDef * o)644 google_protobuf_OneofDescriptorProto* upb_ToProto_ConvertOneofDef(
645     upb_ToProto_Context* const ctx, const upb_OneofDef* o) {
646   if (UPB_SETJMP(ctx->err)) return NULL;
647   return oneofdef_toproto(ctx, o);
648 }
649 
upb_OneofDef_ToProto(const upb_OneofDef * o,upb_Arena * a)650 google_protobuf_OneofDescriptorProto* upb_OneofDef_ToProto(const upb_OneofDef* o,
651                                                   upb_Arena* a) {
652   upb_ToProto_Context ctx = {a};
653   return upb_ToProto_ConvertOneofDef(&ctx, o);
654 }
655 
upb_ToProto_ConvertFileDef(upb_ToProto_Context * const ctx,const upb_FileDef * const f)656 google_protobuf_FileDescriptorProto* upb_ToProto_ConvertFileDef(
657     upb_ToProto_Context* const ctx, const upb_FileDef* const f) {
658   if (UPB_SETJMP(ctx->err)) return NULL;
659   return filedef_toproto(ctx, f);
660 }
661 
upb_FileDef_ToProto(const upb_FileDef * f,upb_Arena * a)662 google_protobuf_FileDescriptorProto* upb_FileDef_ToProto(const upb_FileDef* f,
663                                                 upb_Arena* a) {
664   upb_ToProto_Context ctx = {a};
665   return upb_ToProto_ConvertFileDef(&ctx, f);
666 }
667 
upb_ToProto_ConvertMethodDef(upb_ToProto_Context * const ctx,const upb_MethodDef * m)668 google_protobuf_MethodDescriptorProto* upb_ToProto_ConvertMethodDef(
669     upb_ToProto_Context* const ctx, const upb_MethodDef* m) {
670   if (UPB_SETJMP(ctx->err)) return NULL;
671   return methoddef_toproto(ctx, m);
672 }
673 
upb_MethodDef_ToProto(const upb_MethodDef * const m,upb_Arena * a)674 google_protobuf_MethodDescriptorProto* upb_MethodDef_ToProto(
675     const upb_MethodDef* const m, upb_Arena* a) {
676   upb_ToProto_Context ctx = {a};
677   return upb_ToProto_ConvertMethodDef(&ctx, m);
678 }
679 
upb_ToProto_ConvertServiceDef(upb_ToProto_Context * const ctx,const upb_ServiceDef * const s)680 google_protobuf_ServiceDescriptorProto* upb_ToProto_ConvertServiceDef(
681     upb_ToProto_Context* const ctx, const upb_ServiceDef* const s) {
682   if (UPB_SETJMP(ctx->err)) return NULL;
683   return servicedef_toproto(ctx, s);
684 }
685 
upb_ServiceDef_ToProto(const upb_ServiceDef * s,upb_Arena * a)686 google_protobuf_ServiceDescriptorProto* upb_ServiceDef_ToProto(const upb_ServiceDef* s,
687                                                       upb_Arena* a) {
688   upb_ToProto_Context ctx = {a};
689   return upb_ToProto_ConvertServiceDef(&ctx, s);
690 }
691