|  | // Protocol Buffers - Google's data interchange format | 
|  | // Copyright 2023 Google LLC.  All rights reserved. | 
|  | // | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file or at | 
|  | // https://developers.google.com/open-source/licenses/bsd | 
|  |  | 
|  | #include "upb/util/def_to_proto.h" | 
|  |  | 
|  | #include <inttypes.h> | 
|  | #include <math.h> | 
|  |  | 
|  | #include "google/protobuf/descriptor.upb.h" | 
|  | #include "upb/base/descriptor_constants.h" | 
|  | #include "upb/port/vsnprintf_compat.h" | 
|  | #include "upb/reflection/def.h" | 
|  | #include "upb/reflection/enum_reserved_range.h" | 
|  | #include "upb/reflection/extension_range.h" | 
|  | #include "upb/reflection/internal/field_def.h" | 
|  | #include "upb/reflection/internal/file_def.h" | 
|  | #include "upb/reflection/message.h" | 
|  | #include "upb/reflection/message_reserved_range.h" | 
|  |  | 
|  | // Must be last. | 
|  | #include "upb/port/def.inc" | 
|  |  | 
|  | typedef struct { | 
|  | upb_Arena* arena; | 
|  | jmp_buf err; | 
|  | } upb_ToProto_Context; | 
|  |  | 
|  | #define CHK_OOM(val) \ | 
|  | if (!(val)) UPB_LONGJMP(ctx->err, 1); | 
|  |  | 
|  | // We want to copy the options verbatim into the destination options proto. | 
|  | // We use serialize+parse as our deep copy. | 
|  | #define SET_OPTIONS(proto, desc_type, options_type, src)                  \ | 
|  | {                                                                       \ | 
|  | size_t size;                                                          \ | 
|  | /* MEM: could use a temporary arena here instead. */                  \ | 
|  | char* pb = google_protobuf_##options_type##_serialize(src, ctx->arena, &size); \ | 
|  | CHK_OOM(pb);                                                          \ | 
|  | google_protobuf_##options_type* dst =                                          \ | 
|  | google_protobuf_##options_type##_parse(pb, size, ctx->arena);              \ | 
|  | CHK_OOM(dst);                                                         \ | 
|  | google_protobuf_##desc_type##_set_options(proto, dst);                         \ | 
|  | } | 
|  |  | 
|  | static upb_StringView strviewdup2(upb_ToProto_Context* ctx, | 
|  | upb_StringView str) { | 
|  | char* p = upb_Arena_Malloc(ctx->arena, str.size); | 
|  | CHK_OOM(p); | 
|  | memcpy(p, str.data, str.size); | 
|  | return (upb_StringView){.data = p, .size = str.size}; | 
|  | } | 
|  |  | 
|  | static upb_StringView strviewdup(upb_ToProto_Context* ctx, const char* s) { | 
|  | return strviewdup2(ctx, (upb_StringView){.data = s, .size = strlen(s)}); | 
|  | } | 
|  |  | 
|  | static upb_StringView qual_dup(upb_ToProto_Context* ctx, const char* s) { | 
|  | size_t n = strlen(s); | 
|  | char* p = upb_Arena_Malloc(ctx->arena, n + 1); | 
|  | CHK_OOM(p); | 
|  | p[0] = '.'; | 
|  | memcpy(p + 1, s, n); | 
|  | return (upb_StringView){.data = p, .size = n + 1}; | 
|  | } | 
|  |  | 
|  | UPB_PRINTF(2, 3) | 
|  | static upb_StringView printf_dup(upb_ToProto_Context* ctx, const char* fmt, | 
|  | ...) { | 
|  | const size_t max = 32; | 
|  | char* p = upb_Arena_Malloc(ctx->arena, max); | 
|  | CHK_OOM(p); | 
|  | va_list args; | 
|  | va_start(args, fmt); | 
|  | size_t n = _upb_vsnprintf(p, max, fmt, args); | 
|  | va_end(args); | 
|  | UPB_ASSERT(n < max); | 
|  | return (upb_StringView){.data = p, .size = n}; | 
|  | } | 
|  |  | 
|  | static bool upb_isprint(char ch) { return ch >= 0x20 && ch <= 0x7f; } | 
|  |  | 
|  | static int special_escape(char ch) { | 
|  | switch (ch) { | 
|  | // This is the same set of special escapes recognized by | 
|  | // absl::CEscape(). | 
|  | case '\n': | 
|  | return 'n'; | 
|  | case '\r': | 
|  | return 'r'; | 
|  | case '\t': | 
|  | return 't'; | 
|  | case '\\': | 
|  | return '\\'; | 
|  | case '\'': | 
|  | return '\''; | 
|  | case '"': | 
|  | return '"'; | 
|  | default: | 
|  | return -1; | 
|  | } | 
|  | } | 
|  |  | 
|  | static upb_StringView default_bytes(upb_ToProto_Context* ctx, | 
|  | upb_StringView val) { | 
|  | size_t n = 0; | 
|  | for (size_t i = 0; i < val.size; i++) { | 
|  | char ch = val.data[i]; | 
|  | if (special_escape(ch) >= 0) | 
|  | n += 2;  // '\C' | 
|  | else if (upb_isprint(ch)) | 
|  | n += 1; | 
|  | else | 
|  | n += 4;  // '\123' | 
|  | } | 
|  | char* p = upb_Arena_Malloc(ctx->arena, n); | 
|  | CHK_OOM(p); | 
|  | char* dst = p; | 
|  | const char* src = val.data; | 
|  | const char* end = src + val.size; | 
|  | while (src < end) { | 
|  | unsigned char ch = *src++; | 
|  | if (special_escape(ch) >= 0) { | 
|  | *dst++ = '\\'; | 
|  | *dst++ = (char)special_escape(ch); | 
|  | } else if (upb_isprint(ch)) { | 
|  | *dst++ = ch; | 
|  | } else { | 
|  | *dst++ = '\\'; | 
|  | *dst++ = '0' + (ch >> 6); | 
|  | *dst++ = '0' + ((ch >> 3) & 0x7); | 
|  | *dst++ = '0' + (ch & 0x7); | 
|  | } | 
|  | } | 
|  | return (upb_StringView){.data = p, .size = n}; | 
|  | } | 
|  |  | 
|  | static upb_StringView default_string(upb_ToProto_Context* ctx, | 
|  | const upb_FieldDef* f) { | 
|  | upb_MessageValue d = upb_FieldDef_Default(f); | 
|  | upb_CType type = upb_FieldDef_CType(f); | 
|  |  | 
|  | if (type == kUpb_CType_Float || type == kUpb_CType_Double) { | 
|  | double val = type == kUpb_CType_Float ? d.float_val : d.double_val; | 
|  | if (val == INFINITY) { | 
|  | return strviewdup(ctx, "inf"); | 
|  | } else if (val == -INFINITY) { | 
|  | return strviewdup(ctx, "-inf"); | 
|  | } else if (val != val) { | 
|  | return strviewdup(ctx, "nan"); | 
|  | } | 
|  | } | 
|  |  | 
|  | switch (upb_FieldDef_CType(f)) { | 
|  | case kUpb_CType_Bool: | 
|  | return strviewdup(ctx, d.bool_val ? "true" : "false"); | 
|  | case kUpb_CType_Enum: { | 
|  | const upb_EnumDef* e = upb_FieldDef_EnumSubDef(f); | 
|  | const upb_EnumValueDef* ev = | 
|  | upb_EnumDef_FindValueByNumber(e, d.int32_val); | 
|  | return strviewdup(ctx, upb_EnumValueDef_Name(ev)); | 
|  | } | 
|  | case kUpb_CType_Int64: | 
|  | return printf_dup(ctx, "%" PRId64, d.int64_val); | 
|  | case kUpb_CType_UInt64: | 
|  | return printf_dup(ctx, "%" PRIu64, d.uint64_val); | 
|  | case kUpb_CType_Int32: | 
|  | return printf_dup(ctx, "%" PRId32, d.int32_val); | 
|  | case kUpb_CType_UInt32: | 
|  | return printf_dup(ctx, "%" PRIu32, d.uint32_val); | 
|  | case kUpb_CType_Float: | 
|  | return printf_dup(ctx, "%.9g", d.float_val); | 
|  | case kUpb_CType_Double: | 
|  | return printf_dup(ctx, "%.17g", d.double_val); | 
|  | case kUpb_CType_String: | 
|  | return strviewdup2(ctx, d.str_val); | 
|  | case kUpb_CType_Bytes: | 
|  | return default_bytes(ctx, d.str_val); | 
|  | default: | 
|  | UPB_UNREACHABLE(); | 
|  | } | 
|  | } | 
|  |  | 
|  | static google_protobuf_DescriptorProto_ReservedRange* resrange_toproto( | 
|  | upb_ToProto_Context* ctx, const upb_MessageReservedRange* r) { | 
|  | google_protobuf_DescriptorProto_ReservedRange* proto = | 
|  | google_protobuf_DescriptorProto_ReservedRange_new(ctx->arena); | 
|  | CHK_OOM(proto); | 
|  |  | 
|  | google_protobuf_DescriptorProto_ReservedRange_set_start( | 
|  | proto, upb_MessageReservedRange_Start(r)); | 
|  | google_protobuf_DescriptorProto_ReservedRange_set_end(proto, | 
|  | upb_MessageReservedRange_End(r)); | 
|  |  | 
|  | return proto; | 
|  | } | 
|  |  | 
|  | static google_protobuf_EnumDescriptorProto_EnumReservedRange* enumresrange_toproto( | 
|  | upb_ToProto_Context* ctx, const upb_EnumReservedRange* r) { | 
|  | google_protobuf_EnumDescriptorProto_EnumReservedRange* proto = | 
|  | google_protobuf_EnumDescriptorProto_EnumReservedRange_new(ctx->arena); | 
|  | CHK_OOM(proto); | 
|  |  | 
|  | google_protobuf_EnumDescriptorProto_EnumReservedRange_set_start( | 
|  | proto, upb_EnumReservedRange_Start(r)); | 
|  | google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end( | 
|  | proto, upb_EnumReservedRange_End(r)); | 
|  |  | 
|  | return proto; | 
|  | } | 
|  |  | 
|  | static google_protobuf_FieldDescriptorProto* fielddef_toproto(upb_ToProto_Context* ctx, | 
|  | const upb_FieldDef* f) { | 
|  | google_protobuf_FieldDescriptorProto* proto = | 
|  | google_protobuf_FieldDescriptorProto_new(ctx->arena); | 
|  | CHK_OOM(proto); | 
|  |  | 
|  | google_protobuf_FieldDescriptorProto_set_name(proto, | 
|  | strviewdup(ctx, upb_FieldDef_Name(f))); | 
|  | google_protobuf_FieldDescriptorProto_set_number(proto, upb_FieldDef_Number(f)); | 
|  |  | 
|  | if (upb_FieldDef_IsRequired(f) && | 
|  | upb_FileDef_Edition(upb_FieldDef_File(f)) >= UPB_DESC(EDITION_2023)) { | 
|  | google_protobuf_FieldDescriptorProto_set_label( | 
|  | proto, UPB_DESC(FieldDescriptorProto_LABEL_OPTIONAL)); | 
|  | } else { | 
|  | google_protobuf_FieldDescriptorProto_set_label(proto, upb_FieldDef_Label(f)); | 
|  | } | 
|  | if (upb_FieldDef_Type(f) == kUpb_FieldType_Group && | 
|  | upb_FileDef_Edition(upb_FieldDef_File(f)) >= UPB_DESC(EDITION_2023)) { | 
|  | google_protobuf_FieldDescriptorProto_set_type(proto, kUpb_FieldType_Message); | 
|  | } else { | 
|  | google_protobuf_FieldDescriptorProto_set_type(proto, upb_FieldDef_Type(f)); | 
|  | } | 
|  |  | 
|  | if (upb_FieldDef_HasJsonName(f)) { | 
|  | google_protobuf_FieldDescriptorProto_set_json_name( | 
|  | proto, strviewdup(ctx, upb_FieldDef_JsonName(f))); | 
|  | } | 
|  |  | 
|  | if (upb_FieldDef_IsSubMessage(f)) { | 
|  | google_protobuf_FieldDescriptorProto_set_type_name( | 
|  | proto, | 
|  | qual_dup(ctx, upb_MessageDef_FullName(upb_FieldDef_MessageSubDef(f)))); | 
|  | } else if (upb_FieldDef_CType(f) == kUpb_CType_Enum) { | 
|  | google_protobuf_FieldDescriptorProto_set_type_name( | 
|  | proto, qual_dup(ctx, upb_EnumDef_FullName(upb_FieldDef_EnumSubDef(f)))); | 
|  | } | 
|  |  | 
|  | if (upb_FieldDef_IsExtension(f)) { | 
|  | google_protobuf_FieldDescriptorProto_set_extendee( | 
|  | proto, | 
|  | qual_dup(ctx, upb_MessageDef_FullName(upb_FieldDef_ContainingType(f)))); | 
|  | } | 
|  |  | 
|  | if (upb_FieldDef_HasDefault(f)) { | 
|  | google_protobuf_FieldDescriptorProto_set_default_value(proto, | 
|  | default_string(ctx, f)); | 
|  | } | 
|  |  | 
|  | const upb_OneofDef* o = upb_FieldDef_ContainingOneof(f); | 
|  | if (o) { | 
|  | google_protobuf_FieldDescriptorProto_set_oneof_index(proto, upb_OneofDef_Index(o)); | 
|  | } | 
|  |  | 
|  | if (_upb_FieldDef_IsProto3Optional(f)) { | 
|  | google_protobuf_FieldDescriptorProto_set_proto3_optional(proto, true); | 
|  | } | 
|  |  | 
|  | if (upb_FieldDef_HasOptions(f)) { | 
|  | SET_OPTIONS(proto, FieldDescriptorProto, FieldOptions, | 
|  | upb_FieldDef_Options(f)); | 
|  | } | 
|  |  | 
|  | return proto; | 
|  | } | 
|  |  | 
|  | static google_protobuf_OneofDescriptorProto* oneofdef_toproto(upb_ToProto_Context* ctx, | 
|  | const upb_OneofDef* o) { | 
|  | google_protobuf_OneofDescriptorProto* proto = | 
|  | google_protobuf_OneofDescriptorProto_new(ctx->arena); | 
|  | CHK_OOM(proto); | 
|  |  | 
|  | google_protobuf_OneofDescriptorProto_set_name(proto, | 
|  | strviewdup(ctx, upb_OneofDef_Name(o))); | 
|  |  | 
|  | if (upb_OneofDef_HasOptions(o)) { | 
|  | SET_OPTIONS(proto, OneofDescriptorProto, OneofOptions, | 
|  | upb_OneofDef_Options(o)); | 
|  | } | 
|  |  | 
|  | return proto; | 
|  | } | 
|  |  | 
|  | static google_protobuf_EnumValueDescriptorProto* enumvaldef_toproto( | 
|  | upb_ToProto_Context* ctx, const upb_EnumValueDef* e) { | 
|  | google_protobuf_EnumValueDescriptorProto* proto = | 
|  | google_protobuf_EnumValueDescriptorProto_new(ctx->arena); | 
|  | CHK_OOM(proto); | 
|  |  | 
|  | google_protobuf_EnumValueDescriptorProto_set_name( | 
|  | proto, strviewdup(ctx, upb_EnumValueDef_Name(e))); | 
|  | google_protobuf_EnumValueDescriptorProto_set_number(proto, upb_EnumValueDef_Number(e)); | 
|  |  | 
|  | if (upb_EnumValueDef_HasOptions(e)) { | 
|  | SET_OPTIONS(proto, EnumValueDescriptorProto, EnumValueOptions, | 
|  | upb_EnumValueDef_Options(e)); | 
|  | } | 
|  |  | 
|  | return proto; | 
|  | } | 
|  |  | 
|  | static google_protobuf_EnumDescriptorProto* enumdef_toproto(upb_ToProto_Context* ctx, | 
|  | const upb_EnumDef* e) { | 
|  | google_protobuf_EnumDescriptorProto* proto = | 
|  | google_protobuf_EnumDescriptorProto_new(ctx->arena); | 
|  | CHK_OOM(proto); | 
|  |  | 
|  | google_protobuf_EnumDescriptorProto_set_name(proto, | 
|  | strviewdup(ctx, upb_EnumDef_Name(e))); | 
|  |  | 
|  | int n = upb_EnumDef_ValueCount(e); | 
|  | google_protobuf_EnumValueDescriptorProto** vals = | 
|  | google_protobuf_EnumDescriptorProto_resize_value(proto, n, ctx->arena); | 
|  | CHK_OOM(vals); | 
|  | for (int i = 0; i < n; i++) { | 
|  | vals[i] = enumvaldef_toproto(ctx, upb_EnumDef_Value(e, i)); | 
|  | } | 
|  |  | 
|  | n = upb_EnumDef_ReservedRangeCount(e); | 
|  | google_protobuf_EnumDescriptorProto_EnumReservedRange** res_ranges = | 
|  | google_protobuf_EnumDescriptorProto_resize_reserved_range(proto, n, ctx->arena); | 
|  | for (int i = 0; i < n; i++) { | 
|  | res_ranges[i] = enumresrange_toproto(ctx, upb_EnumDef_ReservedRange(e, i)); | 
|  | } | 
|  |  | 
|  | n = upb_EnumDef_ReservedNameCount(e); | 
|  | upb_StringView* res_names = | 
|  | google_protobuf_EnumDescriptorProto_resize_reserved_name(proto, n, ctx->arena); | 
|  | for (int i = 0; i < n; i++) { | 
|  | res_names[i] = upb_EnumDef_ReservedName(e, i); | 
|  | } | 
|  |  | 
|  | if (upb_EnumDef_HasOptions(e)) { | 
|  | SET_OPTIONS(proto, EnumDescriptorProto, EnumOptions, | 
|  | upb_EnumDef_Options(e)); | 
|  | } | 
|  |  | 
|  | UPB_DESC(SymbolVisibility) visibility = upb_EnumDef_Visibility(e); | 
|  | if (visibility != UPB_DESC(VISIBILITY_UNSET)) { | 
|  | google_protobuf_EnumDescriptorProto_set_visibility(proto, visibility); | 
|  | } | 
|  |  | 
|  | return proto; | 
|  | } | 
|  |  | 
|  | static google_protobuf_DescriptorProto_ExtensionRange* extrange_toproto( | 
|  | upb_ToProto_Context* ctx, const upb_ExtensionRange* e) { | 
|  | google_protobuf_DescriptorProto_ExtensionRange* proto = | 
|  | google_protobuf_DescriptorProto_ExtensionRange_new(ctx->arena); | 
|  | CHK_OOM(proto); | 
|  |  | 
|  | google_protobuf_DescriptorProto_ExtensionRange_set_start(proto, | 
|  | upb_ExtensionRange_Start(e)); | 
|  | google_protobuf_DescriptorProto_ExtensionRange_set_end(proto, | 
|  | upb_ExtensionRange_End(e)); | 
|  |  | 
|  | if (upb_ExtensionRange_HasOptions(e)) { | 
|  | SET_OPTIONS(proto, DescriptorProto_ExtensionRange, ExtensionRangeOptions, | 
|  | upb_ExtensionRange_Options(e)); | 
|  | } | 
|  |  | 
|  | return proto; | 
|  | } | 
|  |  | 
|  | static google_protobuf_DescriptorProto* msgdef_toproto(upb_ToProto_Context* ctx, | 
|  | const upb_MessageDef* m) { | 
|  | google_protobuf_DescriptorProto* proto = google_protobuf_DescriptorProto_new(ctx->arena); | 
|  | CHK_OOM(proto); | 
|  |  | 
|  | google_protobuf_DescriptorProto_set_name(proto, | 
|  | strviewdup(ctx, upb_MessageDef_Name(m))); | 
|  |  | 
|  | int n; | 
|  |  | 
|  | n = upb_MessageDef_FieldCount(m); | 
|  | google_protobuf_FieldDescriptorProto** fields = | 
|  | google_protobuf_DescriptorProto_resize_field(proto, n, ctx->arena); | 
|  | CHK_OOM(fields); | 
|  | for (int i = 0; i < n; i++) { | 
|  | fields[i] = fielddef_toproto(ctx, upb_MessageDef_Field(m, i)); | 
|  | } | 
|  |  | 
|  | n = upb_MessageDef_OneofCount(m); | 
|  | google_protobuf_OneofDescriptorProto** oneofs = | 
|  | google_protobuf_DescriptorProto_resize_oneof_decl(proto, n, ctx->arena); | 
|  | for (int i = 0; i < n; i++) { | 
|  | oneofs[i] = oneofdef_toproto(ctx, upb_MessageDef_Oneof(m, i)); | 
|  | } | 
|  |  | 
|  | n = upb_MessageDef_NestedMessageCount(m); | 
|  | google_protobuf_DescriptorProto** nested_msgs = | 
|  | google_protobuf_DescriptorProto_resize_nested_type(proto, n, ctx->arena); | 
|  | for (int i = 0; i < n; i++) { | 
|  | nested_msgs[i] = msgdef_toproto(ctx, upb_MessageDef_NestedMessage(m, i)); | 
|  | } | 
|  |  | 
|  | n = upb_MessageDef_NestedEnumCount(m); | 
|  | google_protobuf_EnumDescriptorProto** nested_enums = | 
|  | google_protobuf_DescriptorProto_resize_enum_type(proto, n, ctx->arena); | 
|  | for (int i = 0; i < n; i++) { | 
|  | nested_enums[i] = enumdef_toproto(ctx, upb_MessageDef_NestedEnum(m, i)); | 
|  | } | 
|  |  | 
|  | n = upb_MessageDef_NestedExtensionCount(m); | 
|  | google_protobuf_FieldDescriptorProto** nested_exts = | 
|  | google_protobuf_DescriptorProto_resize_extension(proto, n, ctx->arena); | 
|  | for (int i = 0; i < n; i++) { | 
|  | nested_exts[i] = | 
|  | fielddef_toproto(ctx, upb_MessageDef_NestedExtension(m, i)); | 
|  | } | 
|  |  | 
|  | n = upb_MessageDef_ExtensionRangeCount(m); | 
|  | google_protobuf_DescriptorProto_ExtensionRange** ext_ranges = | 
|  | google_protobuf_DescriptorProto_resize_extension_range(proto, n, ctx->arena); | 
|  | for (int i = 0; i < n; i++) { | 
|  | ext_ranges[i] = extrange_toproto(ctx, upb_MessageDef_ExtensionRange(m, i)); | 
|  | } | 
|  |  | 
|  | n = upb_MessageDef_ReservedRangeCount(m); | 
|  | google_protobuf_DescriptorProto_ReservedRange** res_ranges = | 
|  | google_protobuf_DescriptorProto_resize_reserved_range(proto, n, ctx->arena); | 
|  | for (int i = 0; i < n; i++) { | 
|  | res_ranges[i] = resrange_toproto(ctx, upb_MessageDef_ReservedRange(m, i)); | 
|  | } | 
|  |  | 
|  | n = upb_MessageDef_ReservedNameCount(m); | 
|  | upb_StringView* res_names = | 
|  | google_protobuf_DescriptorProto_resize_reserved_name(proto, n, ctx->arena); | 
|  | for (int i = 0; i < n; i++) { | 
|  | res_names[i] = upb_MessageDef_ReservedName(m, i); | 
|  | } | 
|  |  | 
|  | if (upb_MessageDef_HasOptions(m)) { | 
|  | SET_OPTIONS(proto, DescriptorProto, MessageOptions, | 
|  | upb_MessageDef_Options(m)); | 
|  | } | 
|  |  | 
|  | UPB_DESC(SymbolVisibility) visibility = upb_MessageDef_Visibility(m); | 
|  | if (visibility != UPB_DESC(VISIBILITY_UNSET)) { | 
|  | google_protobuf_DescriptorProto_set_visibility(proto, visibility); | 
|  | } | 
|  |  | 
|  | return proto; | 
|  | } | 
|  |  | 
|  | static google_protobuf_MethodDescriptorProto* methoddef_toproto(upb_ToProto_Context* ctx, | 
|  | const upb_MethodDef* m) { | 
|  | google_protobuf_MethodDescriptorProto* proto = | 
|  | google_protobuf_MethodDescriptorProto_new(ctx->arena); | 
|  | CHK_OOM(proto); | 
|  |  | 
|  | google_protobuf_MethodDescriptorProto_set_name(proto, | 
|  | strviewdup(ctx, upb_MethodDef_Name(m))); | 
|  |  | 
|  | google_protobuf_MethodDescriptorProto_set_input_type( | 
|  | proto, | 
|  | qual_dup(ctx, upb_MessageDef_FullName(upb_MethodDef_InputType(m)))); | 
|  | google_protobuf_MethodDescriptorProto_set_output_type( | 
|  | proto, | 
|  | qual_dup(ctx, upb_MessageDef_FullName(upb_MethodDef_OutputType(m)))); | 
|  |  | 
|  | if (upb_MethodDef_ClientStreaming(m)) { | 
|  | google_protobuf_MethodDescriptorProto_set_client_streaming(proto, true); | 
|  | } | 
|  |  | 
|  | if (upb_MethodDef_ServerStreaming(m)) { | 
|  | google_protobuf_MethodDescriptorProto_set_server_streaming(proto, true); | 
|  | } | 
|  |  | 
|  | if (upb_MethodDef_HasOptions(m)) { | 
|  | SET_OPTIONS(proto, MethodDescriptorProto, MethodOptions, | 
|  | upb_MethodDef_Options(m)); | 
|  | } | 
|  |  | 
|  | return proto; | 
|  | } | 
|  |  | 
|  | static google_protobuf_ServiceDescriptorProto* servicedef_toproto( | 
|  | upb_ToProto_Context* ctx, const upb_ServiceDef* s) { | 
|  | google_protobuf_ServiceDescriptorProto* proto = | 
|  | google_protobuf_ServiceDescriptorProto_new(ctx->arena); | 
|  | CHK_OOM(proto); | 
|  |  | 
|  | google_protobuf_ServiceDescriptorProto_set_name( | 
|  | proto, strviewdup(ctx, upb_ServiceDef_Name(s))); | 
|  |  | 
|  | size_t n = upb_ServiceDef_MethodCount(s); | 
|  | google_protobuf_MethodDescriptorProto** methods = | 
|  | google_protobuf_ServiceDescriptorProto_resize_method(proto, n, ctx->arena); | 
|  | for (size_t i = 0; i < n; i++) { | 
|  | methods[i] = methoddef_toproto(ctx, upb_ServiceDef_Method(s, i)); | 
|  | } | 
|  |  | 
|  | if (upb_ServiceDef_HasOptions(s)) { | 
|  | SET_OPTIONS(proto, ServiceDescriptorProto, ServiceOptions, | 
|  | upb_ServiceDef_Options(s)); | 
|  | } | 
|  |  | 
|  | return proto; | 
|  | } | 
|  |  | 
|  | static google_protobuf_FileDescriptorProto* filedef_toproto(upb_ToProto_Context* ctx, | 
|  | const upb_FileDef* f) { | 
|  | google_protobuf_FileDescriptorProto* proto = | 
|  | google_protobuf_FileDescriptorProto_new(ctx->arena); | 
|  | CHK_OOM(proto); | 
|  |  | 
|  | google_protobuf_FileDescriptorProto_set_name(proto, | 
|  | strviewdup(ctx, upb_FileDef_Name(f))); | 
|  |  | 
|  | const char* package = upb_FileDef_Package(f); | 
|  | if (package) { | 
|  | size_t n = strlen(package); | 
|  | if (n) { | 
|  | google_protobuf_FileDescriptorProto_set_package(proto, strviewdup(ctx, package)); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (upb_FileDef_Syntax(f) == kUpb_Syntax_Editions) { | 
|  | google_protobuf_FileDescriptorProto_set_edition(proto, upb_FileDef_Edition(f)); | 
|  | } | 
|  |  | 
|  | if (upb_FileDef_Syntax(f) == kUpb_Syntax_Proto3) { | 
|  | google_protobuf_FileDescriptorProto_set_syntax(proto, strviewdup(ctx, "proto3")); | 
|  | } else if (upb_FileDef_Syntax(f) == kUpb_Syntax_Editions) { | 
|  | google_protobuf_FileDescriptorProto_set_syntax(proto, strviewdup(ctx, "editions")); | 
|  | } | 
|  |  | 
|  | size_t n; | 
|  | n = upb_FileDef_DependencyCount(f); | 
|  | upb_StringView* deps = | 
|  | google_protobuf_FileDescriptorProto_resize_dependency(proto, n, ctx->arena); | 
|  | for (size_t i = 0; i < n; i++) { | 
|  | deps[i] = strviewdup(ctx, upb_FileDef_Name(upb_FileDef_Dependency(f, i))); | 
|  | } | 
|  |  | 
|  | n = upb_FileDef_PublicDependencyCount(f); | 
|  | int32_t* public_deps = | 
|  | google_protobuf_FileDescriptorProto_resize_public_dependency(proto, n, ctx->arena); | 
|  | const int32_t* public_dep_nums = _upb_FileDef_PublicDependencyIndexes(f); | 
|  | if (n) memcpy(public_deps, public_dep_nums, n * sizeof(int32_t)); | 
|  |  | 
|  | n = upb_FileDef_WeakDependencyCount(f); | 
|  | int32_t* weak_deps = | 
|  | google_protobuf_FileDescriptorProto_resize_weak_dependency(proto, n, ctx->arena); | 
|  | const int32_t* weak_dep_nums = _upb_FileDef_WeakDependencyIndexes(f); | 
|  | if (n) memcpy(weak_deps, weak_dep_nums, n * sizeof(int32_t)); | 
|  |  | 
|  | n = upb_FileDef_TopLevelMessageCount(f); | 
|  | google_protobuf_DescriptorProto** msgs = | 
|  | google_protobuf_FileDescriptorProto_resize_message_type(proto, n, ctx->arena); | 
|  | for (size_t i = 0; i < n; i++) { | 
|  | msgs[i] = msgdef_toproto(ctx, upb_FileDef_TopLevelMessage(f, i)); | 
|  | } | 
|  |  | 
|  | n = upb_FileDef_TopLevelEnumCount(f); | 
|  | google_protobuf_EnumDescriptorProto** enums = | 
|  | google_protobuf_FileDescriptorProto_resize_enum_type(proto, n, ctx->arena); | 
|  | for (size_t i = 0; i < n; i++) { | 
|  | enums[i] = enumdef_toproto(ctx, upb_FileDef_TopLevelEnum(f, i)); | 
|  | } | 
|  |  | 
|  | n = upb_FileDef_ServiceCount(f); | 
|  | google_protobuf_ServiceDescriptorProto** services = | 
|  | google_protobuf_FileDescriptorProto_resize_service(proto, n, ctx->arena); | 
|  | for (size_t i = 0; i < n; i++) { | 
|  | services[i] = servicedef_toproto(ctx, upb_FileDef_Service(f, i)); | 
|  | } | 
|  |  | 
|  | n = upb_FileDef_TopLevelExtensionCount(f); | 
|  | google_protobuf_FieldDescriptorProto** exts = | 
|  | google_protobuf_FileDescriptorProto_resize_extension(proto, n, ctx->arena); | 
|  | for (size_t i = 0; i < n; i++) { | 
|  | exts[i] = fielddef_toproto(ctx, upb_FileDef_TopLevelExtension(f, i)); | 
|  | } | 
|  |  | 
|  | if (upb_FileDef_HasOptions(f)) { | 
|  | SET_OPTIONS(proto, FileDescriptorProto, FileOptions, | 
|  | upb_FileDef_Options(f)); | 
|  | } | 
|  |  | 
|  | return proto; | 
|  | } | 
|  |  | 
|  | static google_protobuf_DescriptorProto* upb_ToProto_ConvertMessageDef( | 
|  | upb_ToProto_Context* const ctx, const upb_MessageDef* const m) { | 
|  | if (UPB_SETJMP(ctx->err)) return NULL; | 
|  | return msgdef_toproto(ctx, m); | 
|  | } | 
|  |  | 
|  | google_protobuf_DescriptorProto* upb_MessageDef_ToProto(const upb_MessageDef* m, | 
|  | upb_Arena* a) { | 
|  | upb_ToProto_Context ctx = {a}; | 
|  | return upb_ToProto_ConvertMessageDef(&ctx, m); | 
|  | } | 
|  |  | 
|  | google_protobuf_EnumDescriptorProto* upb_ToProto_ConvertEnumDef( | 
|  | upb_ToProto_Context* const ctx, const upb_EnumDef* const e) { | 
|  | if (UPB_SETJMP(ctx->err)) return NULL; | 
|  | return enumdef_toproto(ctx, e); | 
|  | } | 
|  |  | 
|  | google_protobuf_EnumDescriptorProto* upb_EnumDef_ToProto(const upb_EnumDef* e, | 
|  | upb_Arena* a) { | 
|  | upb_ToProto_Context ctx = {a}; | 
|  | return upb_ToProto_ConvertEnumDef(&ctx, e); | 
|  | } | 
|  |  | 
|  | google_protobuf_EnumValueDescriptorProto* upb_ToProto_ConvertEnumValueDef( | 
|  | upb_ToProto_Context* const ctx, const upb_EnumValueDef* e) { | 
|  | if (UPB_SETJMP(ctx->err)) return NULL; | 
|  | return enumvaldef_toproto(ctx, e); | 
|  | } | 
|  |  | 
|  | google_protobuf_EnumValueDescriptorProto* upb_EnumValueDef_ToProto( | 
|  | const upb_EnumValueDef* e, upb_Arena* a) { | 
|  | upb_ToProto_Context ctx = {a}; | 
|  | return upb_ToProto_ConvertEnumValueDef(&ctx, e); | 
|  | } | 
|  |  | 
|  | google_protobuf_FieldDescriptorProto* upb_ToProto_ConvertFieldDef( | 
|  | upb_ToProto_Context* const ctx, const upb_FieldDef* f) { | 
|  | if (UPB_SETJMP(ctx->err)) return NULL; | 
|  | return fielddef_toproto(ctx, f); | 
|  | } | 
|  |  | 
|  | google_protobuf_FieldDescriptorProto* upb_FieldDef_ToProto(const upb_FieldDef* f, | 
|  | upb_Arena* a) { | 
|  | upb_ToProto_Context ctx = {a}; | 
|  | return upb_ToProto_ConvertFieldDef(&ctx, f); | 
|  | } | 
|  |  | 
|  | google_protobuf_OneofDescriptorProto* upb_ToProto_ConvertOneofDef( | 
|  | upb_ToProto_Context* const ctx, const upb_OneofDef* o) { | 
|  | if (UPB_SETJMP(ctx->err)) return NULL; | 
|  | return oneofdef_toproto(ctx, o); | 
|  | } | 
|  |  | 
|  | google_protobuf_OneofDescriptorProto* upb_OneofDef_ToProto(const upb_OneofDef* o, | 
|  | upb_Arena* a) { | 
|  | upb_ToProto_Context ctx = {a}; | 
|  | return upb_ToProto_ConvertOneofDef(&ctx, o); | 
|  | } | 
|  |  | 
|  | google_protobuf_FileDescriptorProto* upb_ToProto_ConvertFileDef( | 
|  | upb_ToProto_Context* const ctx, const upb_FileDef* const f) { | 
|  | if (UPB_SETJMP(ctx->err)) return NULL; | 
|  | return filedef_toproto(ctx, f); | 
|  | } | 
|  |  | 
|  | google_protobuf_FileDescriptorProto* upb_FileDef_ToProto(const upb_FileDef* f, | 
|  | upb_Arena* a) { | 
|  | upb_ToProto_Context ctx = {a}; | 
|  | return upb_ToProto_ConvertFileDef(&ctx, f); | 
|  | } | 
|  |  | 
|  | google_protobuf_MethodDescriptorProto* upb_ToProto_ConvertMethodDef( | 
|  | upb_ToProto_Context* const ctx, const upb_MethodDef* m) { | 
|  | if (UPB_SETJMP(ctx->err)) return NULL; | 
|  | return methoddef_toproto(ctx, m); | 
|  | } | 
|  |  | 
|  | google_protobuf_MethodDescriptorProto* upb_MethodDef_ToProto( | 
|  | const upb_MethodDef* const m, upb_Arena* a) { | 
|  | upb_ToProto_Context ctx = {a}; | 
|  | return upb_ToProto_ConvertMethodDef(&ctx, m); | 
|  | } | 
|  |  | 
|  | google_protobuf_ServiceDescriptorProto* upb_ToProto_ConvertServiceDef( | 
|  | upb_ToProto_Context* const ctx, const upb_ServiceDef* const s) { | 
|  | if (UPB_SETJMP(ctx->err)) return NULL; | 
|  | return servicedef_toproto(ctx, s); | 
|  | } | 
|  |  | 
|  | google_protobuf_ServiceDescriptorProto* upb_ServiceDef_ToProto(const upb_ServiceDef* s, | 
|  | upb_Arena* a) { | 
|  | upb_ToProto_Context ctx = {a}; | 
|  | return upb_ToProto_ConvertServiceDef(&ctx, s); | 
|  | } |