Merge pull request #434 from haberman/def-to-proto

Added util library for converting defs back to descriptor protos
pull/13171/head
Joshua Haberman 3 years ago committed by GitHub
commit 40dfcc2838
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 20
      cmake/google/protobuf/descriptor.upb.c
  2. 35
      upb/def.c
  3. 4
      upb/def.h
  4. 7
      upb/def.hpp
  5. 42
      upb/util/BUILD
  6. 520
      upb/util/def_to_proto.c
  7. 62
      upb/util/def_to_proto.h
  8. 28
      upb/util/def_to_proto_public_import_test.proto
  9. 28
      upb/util/def_to_proto_regular_import_test.proto
  10. 127
      upb/util/def_to_proto_test.cc
  11. 76
      upb/util/def_to_proto_test.proto
  12. 28
      upb/util/def_to_proto_weak_import_test.proto
  13. 28
      upb/util/def_to_proto_wweak_import_test.proto
  14. 12
      upbc/protoc-gen-upb.cc

@ -518,15 +518,21 @@ static const upb_msglayout *messages_layout[27] = {
&google_protobuf_GeneratedCodeInfo_Annotation_msginit,
};
const upb_enumlayout google_protobuf_FieldDescriptorProto_Type_enuminit = {
NULL,
0x7fffeULL,
0,
};
const upb_enumlayout google_protobuf_FieldDescriptorProto_Label_enuminit = {
NULL,
0xeULL,
0,
};
const upb_enumlayout google_protobuf_FieldDescriptorProto_Type_enuminit = {
const upb_enumlayout google_protobuf_FileOptions_OptimizeMode_enuminit = {
NULL,
0x7fffeULL,
0xeULL,
0,
};
@ -542,12 +548,6 @@ const upb_enumlayout google_protobuf_FieldOptions_JSType_enuminit = {
0,
};
const upb_enumlayout google_protobuf_FileOptions_OptimizeMode_enuminit = {
NULL,
0xeULL,
0,
};
const upb_enumlayout google_protobuf_MethodOptions_IdempotencyLevel_enuminit = {
NULL,
0x7ULL,
@ -555,11 +555,11 @@ const upb_enumlayout google_protobuf_MethodOptions_IdempotencyLevel_enuminit = {
};
static const upb_enumlayout *enums_layout[6] = {
&google_protobuf_FieldDescriptorProto_Label_enuminit,
&google_protobuf_FieldDescriptorProto_Type_enuminit,
&google_protobuf_FieldDescriptorProto_Label_enuminit,
&google_protobuf_FileOptions_OptimizeMode_enuminit,
&google_protobuf_FieldOptions_CType_enuminit,
&google_protobuf_FieldOptions_JSType_enuminit,
&google_protobuf_FileOptions_OptimizeMode_enuminit,
&google_protobuf_MethodOptions_IdempotencyLevel_enuminit,
};

@ -77,6 +77,7 @@ struct upb_fielddef {
bool is_extension_;
bool packed_;
bool proto3_optional_;
bool has_json_name_;
upb_descriptortype_t type_;
upb_label_t label_;
};
@ -156,6 +157,7 @@ struct upb_filedef {
const upb_filedef **deps;
const int32_t* public_deps;
const int32_t* weak_deps;
const upb_msgdef *top_lvl_msgs;
const upb_enumdef *top_lvl_enums;
const upb_fielddef *top_lvl_exts;
@ -165,6 +167,7 @@ struct upb_filedef {
int dep_count;
int public_dep_count;
int weak_dep_count;
int top_lvl_msg_count;
int top_lvl_enum_count;
int top_lvl_ext_count;
@ -547,6 +550,10 @@ const char *upb_fielddef_jsonname(const upb_fielddef *f) {
return f->json_name;
}
bool upb_fielddef_hasjsonname(const upb_fielddef *f) {
return f->has_json_name_;
}
const upb_filedef *upb_fielddef_file(const upb_fielddef *f) {
return f->file;
}
@ -1047,10 +1054,18 @@ int upb_filedef_publicdepcount(const upb_filedef *f) {
return f->public_dep_count;
}
int upb_filedef_weakdepcount(const upb_filedef *f) {
return f->weak_dep_count;
}
const int32_t *_upb_filedef_publicdepnums(const upb_filedef *f) {
return f->public_deps;
}
const int32_t *_upb_filedef_weakdepnums(const upb_filedef *f) {
return f->weak_deps;
}
int upb_filedef_toplvlenumcount(const upb_filedef *f) {
return f->top_lvl_enum_count;
}
@ -1073,6 +1088,11 @@ const upb_filedef *upb_filedef_publicdep(const upb_filedef *f, int i) {
return f->deps[f->public_deps[i]];
}
const upb_filedef *upb_filedef_weakdep(const upb_filedef *f, int i) {
UPB_ASSERT(0 <= i && i < f->public_dep_count);
return f->deps[f->weak_deps[i]];
}
const upb_msgdef *upb_filedef_toplvlmsg(const upb_filedef *f, int i) {
UPB_ASSERT(0 <= i && i < f->top_lvl_msg_count);
return &f->top_lvl_msgs[i];
@ -2152,8 +2172,10 @@ static void create_fielddef(
if (google_protobuf_FieldDescriptorProto_has_json_name(field_proto)) {
json_name = strviewdup(
ctx, google_protobuf_FieldDescriptorProto_json_name(field_proto));
f->has_json_name_ = true;
} else {
json_name = makejsonname(ctx, shortname);
f->has_json_name_ = false;
}
field_number = google_protobuf_FieldDescriptorProto_number(field_proto);
@ -2751,6 +2773,7 @@ static void build_filedef(
const google_protobuf_ServiceDescriptorProto *const *services;
const upb_strview *strs;
const int32_t *public_deps;
const int32_t *weak_deps;
size_t i, n;
file->symtab = ctx->symtab;
@ -2843,6 +2866,18 @@ static void build_filedef(
mutable_public_deps[i] = public_deps[i];
}
weak_deps =
google_protobuf_FileDescriptorProto_weak_dependency(file_proto, &n);
file->weak_dep_count = n;
file->weak_deps = symtab_alloc(ctx, sizeof(*file->weak_deps) * n);
int32_t *mutable_weak_deps = (int32_t*)file->weak_deps;
for (i = 0; i < n; i++) {
if (weak_deps[i] >= file->dep_count) {
symtab_errf(ctx, "public_dep %d is out of range", (int)public_deps[i]);
}
mutable_weak_deps[i] = weak_deps[i];
}
/* Create enums. */
enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
file->top_lvl_enum_count = n;

@ -121,6 +121,7 @@ upb_label_t upb_fielddef_label(const upb_fielddef *f);
uint32_t upb_fielddef_number(const upb_fielddef *f);
const char *upb_fielddef_name(const upb_fielddef *f);
const char *upb_fielddef_jsonname(const upb_fielddef *f);
bool upb_fielddef_hasjsonname(const upb_fielddef *f);
bool upb_fielddef_isextension(const upb_fielddef *f);
bool upb_fielddef_packed(const upb_fielddef *f);
const upb_filedef *upb_fielddef_file(const upb_fielddef *f);
@ -354,18 +355,21 @@ const char *upb_filedef_phpnamespace(const upb_filedef *f);
upb_syntax_t upb_filedef_syntax(const upb_filedef *f);
int upb_filedef_depcount(const upb_filedef *f);
int upb_filedef_publicdepcount(const upb_filedef *f);
int upb_filedef_weakdepcount(const upb_filedef *f);
int upb_filedef_toplvlmsgcount(const upb_filedef *f);
int upb_filedef_toplvlenumcount(const upb_filedef *f);
int upb_filedef_toplvlextcount(const upb_filedef *f);
int upb_filedef_servicecount(const upb_filedef *f);
const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i);
const upb_filedef *upb_filedef_publicdep(const upb_filedef *f, int i);
const upb_filedef *upb_filedef_weakdep(const upb_filedef *f, int i);
const upb_msgdef *upb_filedef_toplvlmsg(const upb_filedef *f, int i);
const upb_enumdef *upb_filedef_toplvlenum(const upb_filedef *f, int i);
const upb_fielddef *upb_filedef_toplvlext(const upb_filedef *f, int i);
const upb_servicedef *upb_filedef_service(const upb_filedef *f, int i);
const upb_symtab *upb_filedef_symtab(const upb_filedef *f);
const int32_t *_upb_filedef_publicdepnums(const upb_filedef *f);
const int32_t *_upb_filedef_weakdepnums(const upb_filedef *f);
/* upb_methoddef **************************************************************/

@ -40,6 +40,7 @@ namespace upb {
typedef upb_msgval MessageValue;
class EnumDefPtr;
class FileDefPtr;
class MessageDefPtr;
class OneofDefPtr;
@ -192,6 +193,8 @@ class MessageDefPtr {
const upb_msgdef* ptr() const { return ptr_; }
explicit operator bool() const { return ptr_ != nullptr; }
FileDefPtr file() const;
const char* full_name() const { return upb_msgdef_fullname(ptr_); }
const char* name() const { return upb_msgdef_name(ptr_); }
@ -447,6 +450,10 @@ class SymbolTable {
std::unique_ptr<upb_symtab, decltype(&upb_symtab_free)> ptr_;
};
inline FileDefPtr MessageDefPtr::file() const {
return FileDefPtr(upb_msgdef_file(ptr_));
}
inline MessageDefPtr FieldDefPtr::message_subdef() const {
return MessageDefPtr(upb_fielddef_msgsubdef(ptr_));
}

@ -5,6 +5,48 @@ load(
"upb_proto_reflection_library",
)
cc_library(
name = "def_to_proto",
srcs = ["def_to_proto.c"],
hdrs = ["def_to_proto.h"],
deps = ["//:reflection"],
visibility = ["//visibility:public"],
)
proto_library(
name = "def_to_proto_test_proto",
srcs = [
"def_to_proto_test.proto",
"def_to_proto_regular_import_test.proto",
"def_to_proto_public_import_test.proto",
"def_to_proto_weak_import_test.proto",
],
)
upb_proto_library(
name = "def_to_proto_test_upb_proto",
deps = ["def_to_proto_test_proto"],
)
upb_proto_reflection_library(
name = "def_to_proto_test_upb_proto_reflection",
deps = ["def_to_proto_test_proto"],
)
cc_test(
name = "def_to_proto_test",
srcs = ["def_to_proto_test.cc"],
deps = [
"@com_google_absl//absl/strings",
"@com_google_googletest//:gtest_main",
"//:descriptor_upb_proto_reflection",
"@com_google_protobuf//:protobuf",
":def_to_proto",
":def_to_proto_test_upb_proto",
":def_to_proto_test_upb_proto_reflection",
],
)
cc_library(
name = "required_fields",
srcs = ["required_fields.c"],

@ -0,0 +1,520 @@
/*
* Copyright (c) 2009-2021, Google LLC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Google LLC nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "upb/util/def_to_proto.h"
#include <inttypes.h>
#include <setjmp.h>
#include <stdio.h>
#include "upb/reflection.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_strview strviewdup2(upb_ToProto_Context *ctx, upb_strview str) {
char *p = upb_arena_malloc(ctx->arena, str.size);
CHK_OOM(p);
memcpy(p, str.data, str.size);
return (upb_strview){.data = p, .size = str.size};
}
static upb_strview strviewdup(upb_ToProto_Context *ctx, const char *s) {
return strviewdup2(ctx, (upb_strview){.data = s, .size = strlen(s)});
}
static upb_strview 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_strview){.data = p, .size = n + 1};
}
UPB_PRINTF(2, 3)
static upb_strview 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 = vsnprintf(p, max, fmt, args);
va_end(args);
UPB_ASSERT(n < max);
return (upb_strview){.data = p, .size = n};
}
static upb_strview default_string(upb_ToProto_Context *ctx,
const upb_fielddef *f) {
upb_msgval d = upb_fielddef_default(f);
switch (upb_fielddef_type(f)) {
case UPB_TYPE_BOOL:
return strviewdup(ctx, d.bool_val ? "true" : "false");
case UPB_TYPE_ENUM: {
const upb_enumdef *e = upb_fielddef_enumsubdef(f);
const upb_enumvaldef *ev = upb_enumdef_lookupnum(e, d.int32_val);
return strviewdup(ctx, upb_enumvaldef_name(ev));
}
case UPB_TYPE_INT64:
return printf_dup(ctx, "%" PRId64, d.int64_val);
case UPB_TYPE_UINT64:
return printf_dup(ctx, "%" PRIu64, d.uint64_val);
case UPB_TYPE_INT32:
return printf_dup(ctx, "%" PRId32, d.int32_val);
case UPB_TYPE_UINT32:
return printf_dup(ctx, "%" PRIu32, d.uint32_val);
case UPB_TYPE_FLOAT:
return printf_dup(ctx, "%.9g", d.float_val);
case UPB_TYPE_DOUBLE:
return printf_dup(ctx, "%.17g", d.double_val);
case UPB_TYPE_STRING:
return strviewdup2(ctx, d.str_val);
case UPB_TYPE_BYTES:
return strviewdup2(ctx, d.str_val); // XXX C-escape
default:
UPB_UNREACHABLE();
}
}
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));
google_protobuf_FieldDescriptorProto_set_label(proto, upb_fielddef_label(f));
google_protobuf_FieldDescriptorProto_set_type(proto,
upb_fielddef_descriptortype(f));
if (upb_fielddef_hasjsonname(f)) {
google_protobuf_FieldDescriptorProto_set_json_name(
proto, strviewdup(ctx, upb_fielddef_jsonname(f)));
}
if (upb_fielddef_issubmsg(f)) {
google_protobuf_FieldDescriptorProto_set_type_name(
proto, qual_dup(ctx, upb_msgdef_fullname(upb_fielddef_msgsubdef(f))));
} else if (upb_fielddef_type(f) == UPB_TYPE_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_msgdef_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_proto3optional(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_enumvaldef *e) {
google_protobuf_EnumValueDescriptorProto *proto =
google_protobuf_EnumValueDescriptorProto_new(ctx->arena);
CHK_OOM(proto);
google_protobuf_EnumValueDescriptorProto_set_name(
proto, strviewdup(ctx, upb_enumvaldef_name(e)));
google_protobuf_EnumValueDescriptorProto_set_number(proto,
upb_enumvaldef_number(e));
if (upb_enumvaldef_hasoptions(e)) {
SET_OPTIONS(proto, EnumValueDescriptorProto, EnumValueOptions,
upb_enumvaldef_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;
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));
}
// TODO: reserved range, reserved name
if (upb_enumdef_hasoptions(e)) {
SET_OPTIONS(proto, EnumDescriptorProto, EnumOptions,
upb_enumdef_options(e));
}
return proto;
}
static google_protobuf_DescriptorProto_ExtensionRange *extrange_toproto(
upb_ToProto_Context *ctx, const upb_extrange *e) {
google_protobuf_DescriptorProto_ExtensionRange *proto =
google_protobuf_DescriptorProto_ExtensionRange_new(ctx->arena);
CHK_OOM(proto);
google_protobuf_DescriptorProto_ExtensionRange_set_start(
proto, upb_extrange_start(e));
google_protobuf_DescriptorProto_ExtensionRange_set_end(proto,
upb_extrange_end(e));
if (upb_extrange_hasoptions(e)) {
SET_OPTIONS(proto, DescriptorProto_ExtensionRange, ExtensionRangeOptions,
upb_extrange_options(e));
}
return proto;
}
static google_protobuf_DescriptorProto *msgdef_toproto(upb_ToProto_Context *ctx,
const upb_msgdef *m) {
google_protobuf_DescriptorProto *proto =
google_protobuf_DescriptorProto_new(ctx->arena);
CHK_OOM(proto);
google_protobuf_DescriptorProto_set_name(proto,
strviewdup(ctx, upb_msgdef_name(m)));
int n;
n = upb_msgdef_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_msgdef_field(m, i));
}
n = upb_msgdef_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_msgdef_oneof(m, i));
}
n = upb_msgdef_nestedmsgcount(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_msgdef_nestedmsg(m, i));
}
n = upb_msgdef_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_msgdef_nestedenum(m, i));
}
n = upb_msgdef_nestedextcount(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_msgdef_nestedext(m, i));
}
n = upb_msgdef_extrangecount(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_msgdef_extrange(m, i));
}
// TODO: reserved ranges and reserved names
if (upb_msgdef_hasoptions(m)) {
SET_OPTIONS(proto, DescriptorProto, MessageOptions, upb_msgdef_options(m));
}
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_msgdef_fullname(upb_methoddef_inputtype(m))));
google_protobuf_MethodDescriptorProto_set_output_type(
proto, qual_dup(ctx, upb_msgdef_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 (int 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)));
size_t n = strlen(upb_filedef_package(f));
if (n) {
google_protobuf_FileDescriptorProto_set_package(
proto, strviewdup(ctx, upb_filedef_package(f)));
}
if (upb_filedef_syntax(f) == UPB_SYNTAX_PROTO3) {
google_protobuf_FileDescriptorProto_set_syntax(proto,
strviewdup(ctx, "proto3"));
}
n = upb_filedef_depcount(f);
upb_strview *deps = google_protobuf_FileDescriptorProto_resize_dependency(
proto, n, ctx->arena);
for (int i = 0; i < n; i++) {
deps[i] = strviewdup(ctx, upb_filedef_name(upb_filedef_dep(f, i)));
}
n = upb_filedef_publicdepcount(f);
int32_t *public_deps =
google_protobuf_FileDescriptorProto_resize_public_dependency(proto, n,
ctx->arena);
const int32_t *public_dep_nums = _upb_filedef_publicdepnums(f);
memcpy(public_deps, public_dep_nums, n * sizeof(int32_t));
n = upb_filedef_weakdepcount(f);
int32_t *weak_deps =
google_protobuf_FileDescriptorProto_resize_weak_dependency(proto, n,
ctx->arena);
const int32_t *weak_dep_nums = _upb_filedef_weakdepnums(f);
memcpy(weak_deps, weak_dep_nums, n * sizeof(int32_t));
n = upb_filedef_toplvlmsgcount(f);
google_protobuf_DescriptorProto **msgs =
google_protobuf_FileDescriptorProto_resize_message_type(proto, n,
ctx->arena);
for (int i = 0; i < n; i++) {
msgs[i] = msgdef_toproto(ctx, upb_filedef_toplvlmsg(f, i));
}
n = upb_filedef_toplvlenumcount(f);
google_protobuf_EnumDescriptorProto **enums =
google_protobuf_FileDescriptorProto_resize_enum_type(proto, n,
ctx->arena);
for (int i = 0; i < n; i++) {
enums[i] = enumdef_toproto(ctx, upb_filedef_toplvlenum(f, i));
}
n = upb_filedef_servicecount(f);
google_protobuf_ServiceDescriptorProto **services =
google_protobuf_FileDescriptorProto_resize_service(proto, n, ctx->arena);
for (int i = 0; i < n; i++) {
services[i] = servicedef_toproto(ctx, upb_filedef_service(f, i));
}
n = upb_filedef_toplvlextcount(f);
google_protobuf_FieldDescriptorProto **exts =
google_protobuf_FileDescriptorProto_resize_extension(proto, n,
ctx->arena);
for (int i = 0; i < n; i++) {
exts[i] = fielddef_toproto(ctx, upb_filedef_toplvlext(f, i));
}
if (upb_filedef_hasoptions(f)) {
SET_OPTIONS(proto, FileDescriptorProto, FileOptions,
upb_filedef_options(f));
}
return proto;
}
google_protobuf_DescriptorProto *upb_MessageDef_ToProto(const upb_msgdef *m,
upb_arena *a) {
upb_ToProto_Context ctx = {a};
if (UPB_SETJMP(ctx.err)) return NULL;
return msgdef_toproto(&ctx, m);
}
google_protobuf_EnumDescriptorProto *upb_EnumDef_ToProto(const upb_enumdef *e,
upb_arena *a) {
upb_ToProto_Context ctx = {a};
if (UPB_SETJMP(ctx.err)) return NULL;
return enumdef_toproto(&ctx, e);
}
google_protobuf_EnumValueDescriptorProto *upb_EnumValueDef_ToProto(
const upb_enumvaldef *e, upb_arena *a) {
upb_ToProto_Context ctx = {a};
if (UPB_SETJMP(ctx.err)) return NULL;
return enumvaldef_toproto(&ctx, e);
}
google_protobuf_FieldDescriptorProto *upb_FieldDef_ToProto(
const upb_fielddef *f, upb_arena *a) {
upb_ToProto_Context ctx = {a};
if (UPB_SETJMP(ctx.err)) return NULL;
return fielddef_toproto(&ctx, f);
}
google_protobuf_OneofDescriptorProto *upb_OneofDef_ToProto(
const upb_oneofdef *o, upb_arena *a) {
upb_ToProto_Context ctx = {a};
if (UPB_SETJMP(ctx.err)) return NULL;
return oneofdef_toproto(&ctx, o);
}
google_protobuf_FileDescriptorProto *upb_FileDef_ToProto(const upb_filedef *f,
upb_arena *a) {
upb_ToProto_Context ctx = {a};
if (UPB_SETJMP(ctx.err)) return NULL;
return filedef_toproto(&ctx, f);
}
google_protobuf_MethodDescriptorProto *upb_MethodDef_ToProto(
const upb_methoddef *m, upb_arena *a) {
upb_ToProto_Context ctx = {a};
if (UPB_SETJMP(ctx.err)) return NULL;
return methoddef_toproto(&ctx, m);
}
google_protobuf_ServiceDescriptorProto *upb_ServiceDef_ToProto(
const upb_servicedef *s, upb_arena *a) {
upb_ToProto_Context ctx = {a};
if (UPB_SETJMP(ctx.err)) return NULL;
return servicedef_toproto(&ctx, s);
}

@ -0,0 +1,62 @@
/*
* Copyright (c) 2009-2021, Google LLC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Google LLC nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef UPB_UTIL_DEF_TO_PROTO_H_
#define UPB_UTIL_DEF_TO_PROTO_H_
#include "upb/def.h"
#ifdef __cplusplus
extern "C" {
#endif
// Functions for converting defs back to the equivalent descriptor proto.
// Ultimately the goal is that a round-trip proto->def->proto is lossless. Each
// function returns a new proto created in arena `a`, or NULL if memory
// allocation failed.
google_protobuf_DescriptorProto* upb_MessageDef_ToProto(const upb_msgdef* m,
upb_arena* a);
google_protobuf_EnumDescriptorProto* upb_EnumDef_ToProto(const upb_enumdef* e,
upb_arena* a);
google_protobuf_EnumValueDescriptorProto* upb_EnumValueDef_ToProto(
const upb_enumvaldef* e, upb_arena* a);
google_protobuf_FieldDescriptorProto* upb_FieldDef_ToProto(
const upb_fielddef* f, upb_arena* a);
google_protobuf_OneofDescriptorProto* upb_OneofDef_ToProto(
const upb_oneofdef* o, upb_arena* a);
google_protobuf_FileDescriptorProto* upb_FileDef_ToProto(const upb_filedef* f,
upb_arena* a);
google_protobuf_MethodDescriptorProto* upb_MethodDef_ToProto(
const upb_methoddef* m, upb_arena* a);
google_protobuf_ServiceDescriptorProto* upb_ServiceDef_ToProto(
const upb_servicedef* s, upb_arena* a);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* UPB_UTIL_DEF_TO_PROTO_H_ */

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

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

@ -0,0 +1,127 @@
/*
* Copyright (c) 2009-2021, Google LLC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Google LLC nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "upb/util/def_to_proto.h"
#include "gmock/gmock.h"
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/descriptor.upbdefs.h"
#include "google/protobuf/dynamic_message.h"
#include "google/protobuf/util/message_differencer.h"
#include "gtest/gtest.h"
#include "upb/def.hpp"
#include "upb/upb.hpp"
#include "upb/util/def_to_proto_test.upbdefs.h"
// Loads and retrieves a descriptor for `msgdef` into the given `pool`.
const google::protobuf::Descriptor* AddMessageDescriptor(
upb::MessageDefPtr msgdef, google::protobuf::DescriptorPool* pool) {
upb::Arena tmp_arena;
upb::FileDefPtr file = msgdef.file();
google_protobuf_FileDescriptorProto* upb_proto =
upb_FileDef_ToProto(file.ptr(), tmp_arena.ptr());
size_t size;
const char* buf = google_protobuf_FileDescriptorProto_serialize(
upb_proto, tmp_arena.ptr(), &size);
google::protobuf::FileDescriptorProto google_proto;
google_proto.ParseFromArray(buf, size);
const google::protobuf::FileDescriptor* file_desc =
pool->BuildFile(google_proto);
EXPECT_TRUE(file_desc != nullptr);
return pool->FindMessageTypeByName(msgdef.full_name());
}
// Converts a upb `msg` (with type `msgdef`) into a protobuf Message object from
// the given factory and descriptor.
std::unique_ptr<google::protobuf::Message> ToProto(
const upb_msg* msg, const upb_msgdef* msgdef,
const google::protobuf::Descriptor* desc,
google::protobuf::MessageFactory* factory) {
upb::Arena arena;
EXPECT_TRUE(desc != nullptr);
std::unique_ptr<google::protobuf::Message> google_msg(
factory->GetPrototype(desc)->New());
size_t size;
const char* buf =
upb_encode(msg, upb_msgdef_layout(msgdef), arena.ptr(), &size);
google_msg->ParseFromArray(buf, size);
return google_msg;
}
// A gtest matcher that verifies that a proto is equal to `proto`. Both `proto`
// and `arg` must be messages of type `msgdef_func` (a .upbdefs.h function that
// loads a known msgdef into the given symtab).
MATCHER_P2(EqualsUpbProto, proto, msgdef_func,
negation ? "are not equal" : "are equal") {
upb::SymbolTable symtab;
google::protobuf::DescriptorPool pool;
google::protobuf::DynamicMessageFactory factory;
upb::MessageDefPtr msgdef(msgdef_func(symtab.ptr()));
EXPECT_TRUE(msgdef.ptr() != nullptr);
const google::protobuf::Descriptor* desc =
AddMessageDescriptor(msgdef, &pool);
EXPECT_TRUE(desc != nullptr);
std::unique_ptr<google::protobuf::Message> m1(
ToProto(proto, msgdef.ptr(), desc, &factory));
std::unique_ptr<google::protobuf::Message> m2(
ToProto(arg, msgdef.ptr(), desc, &factory));
std::string differences;
google::protobuf::util::MessageDifferencer differencer;
differencer.ReportDifferencesToString(&differences);
bool eq = differencer.Compare(*m2, *m1);
if (!eq) {
*result_listener << differences;
}
return eq;
}
// Verifies that the given upb FileDef can be converted to a proto that matches
// `proto`.
void CheckFile(const upb::FileDefPtr file,
const google_protobuf_FileDescriptorProto* proto) {
upb::Arena arena;
google_protobuf_FileDescriptorProto* proto2 =
upb_FileDef_ToProto(file.ptr(), arena.ptr());
ASSERT_THAT(
proto,
EqualsUpbProto(proto2, google_protobuf_FileDescriptorProto_getmsgdef));
}
// Verifies that upb/util/def_to_proto_test.proto can round-trip:
// serialized descriptor -> upb def -> serialized descriptor
TEST(DefToProto, Test) {
upb::Arena arena;
upb::SymbolTable symtab;
upb_strview test_file_desc =
upb_util_def_to_proto_test_proto_upbdefinit.descriptor;
const auto* file_desc = google_protobuf_FileDescriptorProto_parse(
test_file_desc.data, test_file_desc.size, arena.ptr());
upb::MessageDefPtr msgdef(pkg_Message_getmsgdef(symtab.ptr()));
upb::FileDefPtr file = msgdef.file();
CheckFile(file, file_desc);
}

@ -0,0 +1,76 @@
/*
* Copyright (c) 2009-2021, Google LLC
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Google LLC nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
syntax = "proto2";
import "upb/util/def_to_proto_regular_import_test.proto";
import public "upb/util/def_to_proto_public_import_test.proto";
import weak "upb/util/def_to_proto_weak_import_test.proto";
package pkg;
option optimize_for = CODE_SIZE;
option go_package = "foo_go_package";
option java_package = "bar_java_package";
option java_outer_classname = "baz_java_outer_classname";
option csharp_namespace = "quux_csharp_namespace";
option objc_class_prefix = "the_objc_prefix";
option cc_enable_arenas = true;
message Message {
optional int32 a = 1 [default = 3];
oneof foo {
string oneof_string = 2 [default = "abc\n"];
string oneof_bool = 3 [default = "true"];
bytes oneof_bytes = 4 [default = "abc\xef\xfe"];
}
extensions 1000 to max;
extend Message {
optional int32 ext = 1000;
}
message NestedMessage {}
message NestedEnum {}
// TODO: support reserved ranges in defs.
// (At the moment they are ignored and will not round-trip through defs).
// reserved 4, 6 to 8;
}
enum Enum {
ZERO = 0;
ONE = 1;
NEGATIVE_ONE = -1;
}
service Service {
rpc Bar(Message) returns (Message);
}
extend Message {
optional int32 ext = 1001;
}

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

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

@ -83,12 +83,6 @@ void AddEnums(const protobuf::Descriptor* message,
}
}
template <class T>
void SortDefs(std::vector<T>* defs) {
std::sort(defs->begin(), defs->end(),
[](T a, T b) { return a->full_name() < b->full_name(); });
}
std::vector<const protobuf::EnumDescriptor*> SortedEnums(
const protobuf::FileDescriptor* file) {
std::vector<const protobuf::EnumDescriptor*> enums;
@ -98,7 +92,6 @@ std::vector<const protobuf::EnumDescriptor*> SortedEnums(
for (int i = 0; i < file->message_type_count(); i++) {
AddEnums(file->message_type(i), &enums);
}
SortDefs(&enums);
return enums;
}
@ -780,6 +773,11 @@ void WriteHeader(const protobuf::FileDescriptor* file, Output& output) {
std::vector<const protobuf::EnumDescriptor*> this_file_enums =
SortedEnums(file);
std::sort(
this_file_enums.begin(), this_file_enums.end(),
[](const protobuf::EnumDescriptor* a, const protobuf::EnumDescriptor* b) {
return a->full_name() < b->full_name();
});
for (auto enumdesc : this_file_enums) {
output("typedef enum {\n");

Loading…
Cancel
Save