Skip to content

Commit

Permalink
Add to_proto to descriptor classes (#19971)
Browse files Browse the repository at this point in the history
Some APIs (e.g. [BigQuery Storage](https://github.com/googleapis/googleapis/blob/ab61c52324b39d1c8619a96ab19cc6c173b13f2c/google/cloud/bigquery/storage/v1/protobuf.proto#L39)) use DescriptorProto for schema descriptions. But,  in Ruby, there are no methods for that so far.

This PR implements the method for that(`to_proto`) to descriptor classes.

Fixes #12044.

Closes #19971

FUTURE_COPYBARA_INTEGRATE_REVIEW=#19971 from y-yagi:add_to_proto_to_descriptors 8d50ae2
PiperOrigin-RevId: 723117256
  • Loading branch information
y-yagi authored and copybara-github committed Feb 4, 2025
1 parent de9f4ff commit 15cf1f2
Show file tree
Hide file tree
Showing 23 changed files with 1,193 additions and 12 deletions.
6 changes: 3 additions & 3 deletions php/ext/google/protobuf/php-upb.c
Original file line number Diff line number Diff line change
Expand Up @@ -15420,7 +15420,7 @@ bool upb_FileDef_Resolves(const upb_FileDef* f, const char* path) {
return false;
}

static char* strviewdup(upb_DefBuilder* ctx, upb_StringView view) {
static char* _strviewdup(upb_DefBuilder* ctx, upb_StringView view) {
char* ret = upb_strdup2(view.data, view.size, _upb_DefBuilder_Arena(ctx));
if (!ret) _upb_DefBuilder_OomErr(ctx);
return ret;
Expand Down Expand Up @@ -15549,7 +15549,7 @@ void _upb_FileDef_Create(upb_DefBuilder* ctx,
}

upb_StringView name = UPB_DESC(FileDescriptorProto_name)(file_proto);
file->name = strviewdup(ctx, name);
file->name = _strviewdup(ctx, name);
if (strlen(file->name) != name.size) {
_upb_DefBuilder_Errf(ctx, "File name contained embedded NULL");
}
Expand All @@ -15558,7 +15558,7 @@ void _upb_FileDef_Create(upb_DefBuilder* ctx,

if (package.size) {
_upb_DefBuilder_CheckIdentFull(ctx, package);
file->package = strviewdup(ctx, package);
file->package = _strviewdup(ctx, package);
} else {
file->package = NULL;
}
Expand Down
159 changes: 159 additions & 0 deletions ruby/ext/google/protobuf_c/defs.c
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,27 @@ static VALUE Descriptor_options(VALUE _self) {
return message_options;
}

/*
* call-seq:
* Descriptor.to_proto => DescriptorProto
*
* Returns the `DescriptorProto` of this `Descriptor`.
*/
static VALUE Descriptor_to_proto(VALUE _self) {
Descriptor* self = ruby_to_Descriptor(_self);
upb_Arena* arena = upb_Arena_New();
google_protobuf_DescriptorProto* proto =
upb_MessageDef_ToProto(self->msgdef, arena);
size_t size;
const char* serialized =
google_protobuf_DescriptorProto_serialize(proto, arena, &size);
VALUE proto_class = rb_path2class("Google::Protobuf::DescriptorProto");
VALUE proto_rb =
Message_decode_bytes(size, serialized, 0, proto_class, false);
upb_Arena_Free(arena);
return proto_rb;
}

static void Descriptor_register(VALUE module) {
VALUE klass = rb_define_class_under(module, "Descriptor", rb_cObject);
rb_define_alloc_func(klass, Descriptor_alloc);
Expand All @@ -463,6 +484,7 @@ static void Descriptor_register(VALUE module) {
rb_define_method(klass, "name", Descriptor_name, 0);
rb_define_method(klass, "file_descriptor", Descriptor_file_descriptor, 0);
rb_define_method(klass, "options", Descriptor_options, 0);
rb_define_method(klass, "to_proto", Descriptor_to_proto, 0);
rb_include_module(klass, rb_mEnumerable);
rb_gc_register_address(&cDescriptor);
cDescriptor = klass;
Expand Down Expand Up @@ -558,12 +580,37 @@ static VALUE FileDescriptor_options(VALUE _self) {
return file_options;
}

/*
* call-seq:
* FileDescriptor.to_proto => FileDescriptorProto
*
* Returns the `FileDescriptorProto` of this `FileDescriptor`.
*/
static VALUE FileDescriptor_to_proto(VALUE _self) {
FileDescriptor* self = ruby_to_FileDescriptor(_self);
upb_Arena* arena = upb_Arena_New();
google_protobuf_FileDescriptorProto* file_proto =
upb_FileDef_ToProto(self->filedef, arena);

size_t size;
const char* serialized =
google_protobuf_FileDescriptorProto_serialize(file_proto, arena, &size);

VALUE file_proto_class =
rb_path2class("Google::Protobuf::FileDescriptorProto");
VALUE proto_rb =
Message_decode_bytes(size, serialized, 0, file_proto_class, false);
upb_Arena_Free(arena);
return proto_rb;
}

static void FileDescriptor_register(VALUE module) {
VALUE klass = rb_define_class_under(module, "FileDescriptor", rb_cObject);
rb_define_alloc_func(klass, FileDescriptor_alloc);
rb_define_method(klass, "initialize", FileDescriptor_initialize, 3);
rb_define_method(klass, "name", FileDescriptor_name, 0);
rb_define_method(klass, "options", FileDescriptor_options, 0);
rb_define_method(klass, "to_proto", FileDescriptor_to_proto, 0);
rb_gc_register_address(&cFileDescriptor);
cFileDescriptor = klass;
}
Expand Down Expand Up @@ -956,6 +1003,27 @@ static VALUE FieldDescriptor_options(VALUE _self) {
return field_options;
}

/*
* call-seq:
* FieldDescriptor.to_proto => FieldDescriptorProto
*
* Returns the `FieldDescriptorProto` of this `FieldDescriptor`.
*/
static VALUE FieldDescriptor_to_proto(VALUE _self) {
FieldDescriptor* self = ruby_to_FieldDescriptor(_self);
upb_Arena* arena = upb_Arena_New();
google_protobuf_FieldDescriptorProto* proto =
upb_FieldDef_ToProto(self->fielddef, arena);
size_t size;
const char* serialized =
google_protobuf_FieldDescriptorProto_serialize(proto, arena, &size);
VALUE proto_class = rb_path2class("Google::Protobuf::FieldDescriptorProto");
VALUE proto_rb =
Message_decode_bytes(size, serialized, 0, proto_class, false);
upb_Arena_Free(arena);
return proto_rb;
}

static void FieldDescriptor_register(VALUE module) {
VALUE klass = rb_define_class_under(module, "FieldDescriptor", rb_cObject);
rb_define_alloc_func(klass, FieldDescriptor_alloc);
Expand All @@ -975,6 +1043,7 @@ static void FieldDescriptor_register(VALUE module) {
rb_define_method(klass, "get", FieldDescriptor_get, 1);
rb_define_method(klass, "set", FieldDescriptor_set, 2);
rb_define_method(klass, "options", FieldDescriptor_options, 0);
rb_define_method(klass, "to_proto", FieldDescriptor_to_proto, 0);
rb_gc_register_address(&cFieldDescriptor);
cFieldDescriptor = klass;
}
Expand Down Expand Up @@ -1093,13 +1162,35 @@ static VALUE OneOfDescriptor_options(VALUE _self) {
return oneof_options;
}

/*
* call-seq:
* OneofDescriptor.to_proto => OneofDescriptorProto
*
* Returns the `OneofDescriptorProto` of this `OneofDescriptor`.
*/
static VALUE OneOfDescriptor_to_proto(VALUE _self) {
OneofDescriptor* self = ruby_to_OneofDescriptor(_self);
upb_Arena* arena = upb_Arena_New();
google_protobuf_OneofDescriptorProto* proto =
upb_OneofDef_ToProto(self->oneofdef, arena);
size_t size;
const char* serialized =
google_protobuf_OneofDescriptorProto_serialize(proto, arena, &size);
VALUE proto_class = rb_path2class("Google::Protobuf::OneofDescriptorProto");
VALUE proto_rb =
Message_decode_bytes(size, serialized, 0, proto_class, false);
upb_Arena_Free(arena);
return proto_rb;
}

static void OneofDescriptor_register(VALUE module) {
VALUE klass = rb_define_class_under(module, "OneofDescriptor", rb_cObject);
rb_define_alloc_func(klass, OneofDescriptor_alloc);
rb_define_method(klass, "initialize", OneofDescriptor_initialize, 3);
rb_define_method(klass, "name", OneofDescriptor_name, 0);
rb_define_method(klass, "each", OneofDescriptor_each, 0);
rb_define_method(klass, "options", OneOfDescriptor_options, 0);
rb_define_method(klass, "to_proto", OneOfDescriptor_to_proto, 0);
rb_include_module(klass, rb_mEnumerable);
rb_gc_register_address(&cOneofDescriptor);
cOneofDescriptor = klass;
Expand Down Expand Up @@ -1298,6 +1389,29 @@ static VALUE EnumDescriptor_options(VALUE _self) {
return enum_options;
}

/*
* call-seq:
* EnumDescriptor.to_proto => EnumDescriptorProto
*
* Returns the `EnumDescriptorProto` of this `EnumDescriptor`.
*/
static VALUE EnumDescriptor_to_proto(VALUE _self) {
EnumDescriptor* self = ruby_to_EnumDescriptor(_self);
upb_Arena* arena = upb_Arena_New();
google_protobuf_EnumDescriptorProto* proto =
upb_EnumDef_ToProto(self->enumdef, arena);

size_t size;
const char* serialized =
google_protobuf_EnumDescriptorProto_serialize(proto, arena, &size);

VALUE proto_class = rb_path2class("Google::Protobuf::EnumDescriptorProto");
VALUE proto_rb =
Message_decode_bytes(size, serialized, 0, proto_class, false);
upb_Arena_Free(arena);
return proto_rb;
}

static void EnumDescriptor_register(VALUE module) {
VALUE klass = rb_define_class_under(module, "EnumDescriptor", rb_cObject);
rb_define_alloc_func(klass, EnumDescriptor_alloc);
Expand All @@ -1310,6 +1424,7 @@ static void EnumDescriptor_register(VALUE module) {
rb_define_method(klass, "file_descriptor", EnumDescriptor_file_descriptor, 0);
rb_define_method(klass, "is_closed?", EnumDescriptor_is_closed, 0);
rb_define_method(klass, "options", EnumDescriptor_options, 0);
rb_define_method(klass, "to_proto", EnumDescriptor_to_proto, 0);
rb_include_module(klass, rb_mEnumerable);
rb_gc_register_address(&cEnumDescriptor);
cEnumDescriptor = klass;
Expand Down Expand Up @@ -1438,6 +1553,27 @@ static VALUE ServiceDescriptor_options(VALUE _self) {
return service_options;
}

/*
* call-seq:
* ServiceDescriptor.to_proto => ServiceDescriptorProto
*
* Returns the `ServiceDescriptorProto` of this `ServiceDescriptor`.
*/
static VALUE ServiceDescriptor_to_proto(VALUE _self) {
ServiceDescriptor* self = ruby_to_ServiceDescriptor(_self);
upb_Arena* arena = upb_Arena_New();
google_protobuf_ServiceDescriptorProto* proto =
upb_ServiceDef_ToProto(self->servicedef, arena);
size_t size;
const char* serialized =
google_protobuf_ServiceDescriptorProto_serialize(proto, arena, &size);
VALUE proto_class = rb_path2class("Google::Protobuf::ServiceDescriptorProto");
VALUE proto_rb =
Message_decode_bytes(size, serialized, 0, proto_class, false);
upb_Arena_Free(arena);
return proto_rb;
}

static void ServiceDescriptor_register(VALUE module) {
VALUE klass = rb_define_class_under(module, "ServiceDescriptor", rb_cObject);
rb_define_alloc_func(klass, ServiceDescriptor_alloc);
Expand All @@ -1447,6 +1583,7 @@ static void ServiceDescriptor_register(VALUE module) {
rb_define_method(klass, "file_descriptor", ServiceDescriptor_file_descriptor,
0);
rb_define_method(klass, "options", ServiceDescriptor_options, 0);
rb_define_method(klass, "to_proto", ServiceDescriptor_to_proto, 0);
rb_include_module(klass, rb_mEnumerable);
rb_gc_register_address(&cServiceDescriptor);
cServiceDescriptor = klass;
Expand Down Expand Up @@ -1580,6 +1717,27 @@ static VALUE MethodDescriptor_client_streaming(VALUE _self) {
return upb_MethodDef_ClientStreaming(self->methoddef) ? Qtrue : Qfalse;
}

/*
* call-seq:
* MethodDescriptor.to_proto => MethodDescriptorProto
*
* Returns the `MethodDescriptorProto` of this `MethodDescriptor`.
*/
static VALUE MethodDescriptor_to_proto(VALUE _self) {
MethodDescriptor* self = ruby_to_MethodDescriptor(_self);
upb_Arena* arena = upb_Arena_New();
google_protobuf_MethodDescriptorProto* proto =
upb_MethodDef_ToProto(self->methoddef, arena);
size_t size;
const char* serialized =
google_protobuf_MethodDescriptorProto_serialize(proto, arena, &size);
VALUE proto_class = rb_path2class("Google::Protobuf::MethodDescriptorProto");
VALUE proto_rb =
Message_decode_bytes(size, serialized, 0, proto_class, false);
upb_Arena_Free(arena);
return proto_rb;
}

/*
* call-seq:
* MethodDescriptor.server_streaming => bool
Expand All @@ -1603,6 +1761,7 @@ static void MethodDescriptor_register(VALUE module) {
0);
rb_define_method(klass, "server_streaming", MethodDescriptor_server_streaming,
0);
rb_define_method(klass, "to_proto", MethodDescriptor_to_proto, 0);
rb_gc_register_address(&cMethodDescriptor);
cMethodDescriptor = klass;
}
Expand Down
63 changes: 63 additions & 0 deletions ruby/ext/google/protobuf_c/glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,31 @@ char* EnumDescriptor_serialized_options(const upb_EnumDef* enumdef,
return serialized;
}

char* EnumDescriptor_serialized_to_proto(const upb_EnumDef* enumdef,
size_t* size, upb_Arena* arena) {
const google_protobuf_EnumDescriptorProto* file_proto =
upb_EnumDef_ToProto(enumdef, arena);
char* serialized =
google_protobuf_EnumDescriptorProto_serialize(file_proto, arena, size);
return serialized;
}

char* FileDescriptor_serialized_options(const upb_FileDef* filedef,
size_t* size, upb_Arena* arena) {
const google_protobuf_FileOptions* opts = upb_FileDef_Options(filedef);
char* serialized = google_protobuf_FileOptions_serialize(opts, arena, size);
return serialized;
}

char* FileDescriptor_serialized_to_proto(const upb_FileDef* filedef,
size_t* size, upb_Arena* arena) {
const google_protobuf_FileDescriptorProto* file_proto =
upb_FileDef_ToProto(filedef, arena);
char* serialized =
google_protobuf_FileDescriptorProto_serialize(file_proto, arena, size);
return serialized;
}

char* Descriptor_serialized_options(const upb_MessageDef* msgdef, size_t* size,
upb_Arena* arena) {
const google_protobuf_MessageOptions* opts = upb_MessageDef_Options(msgdef);
Expand All @@ -41,20 +59,47 @@ char* Descriptor_serialized_options(const upb_MessageDef* msgdef, size_t* size,
return serialized;
}

char* Descriptor_serialized_to_proto(const upb_MessageDef* msgdef, size_t* size,
upb_Arena* arena) {
const google_protobuf_DescriptorProto* proto =
upb_MessageDef_ToProto(msgdef, arena);
char* serialized =
google_protobuf_DescriptorProto_serialize(proto, arena, size);
return serialized;
}

char* OneOfDescriptor_serialized_options(const upb_OneofDef* oneofdef,
size_t* size, upb_Arena* arena) {
const google_protobuf_OneofOptions* opts = upb_OneofDef_Options(oneofdef);
char* serialized = google_protobuf_OneofOptions_serialize(opts, arena, size);
return serialized;
}

char* OneOfDescriptor_serialized_to_proto(const upb_OneofDef* oneofdef,
size_t* size, upb_Arena* arena) {
const google_protobuf_OneofDescriptorProto* proto =
upb_OneofDef_ToProto(oneofdef, arena);
char* serialized =
google_protobuf_OneofDescriptorProto_serialize(proto, arena, size);
return serialized;
}

char* FieldDescriptor_serialized_options(const upb_FieldDef* fielddef,
size_t* size, upb_Arena* arena) {
const google_protobuf_FieldOptions* opts = upb_FieldDef_Options(fielddef);
char* serialized = google_protobuf_FieldOptions_serialize(opts, arena, size);
return serialized;
}

char* FieldDescriptor_serialized_to_proto(const upb_FieldDef* fieldef,
size_t* size, upb_Arena* arena) {
const google_protobuf_FieldDescriptorProto* proto =
upb_FieldDef_ToProto(fieldef, arena);
char* serialized =
google_protobuf_FieldDescriptorProto_serialize(proto, arena, size);
return serialized;
}

char* ServiceDescriptor_serialized_options(const upb_ServiceDef* servicedef,
size_t* size, upb_Arena* arena) {
const google_protobuf_ServiceOptions* opts =
Expand All @@ -64,9 +109,27 @@ char* ServiceDescriptor_serialized_options(const upb_ServiceDef* servicedef,
return serialized;
}

char* ServiceDescriptor_serialized_to_proto(const upb_ServiceDef* servicedef,
size_t* size, upb_Arena* arena) {
const google_protobuf_ServiceDescriptorProto* proto =
upb_ServiceDef_ToProto(servicedef, arena);
char* serialized =
google_protobuf_ServiceDescriptorProto_serialize(proto, arena, size);
return serialized;
}

char* MethodDescriptor_serialized_options(const upb_MethodDef* methoddef,
size_t* size, upb_Arena* arena) {
const google_protobuf_MethodOptions* opts = upb_MethodDef_Options(methoddef);
char* serialized = google_protobuf_MethodOptions_serialize(opts, arena, size);
return serialized;
}

char* MethodDescriptor_serialized_to_proto(const upb_MethodDef* methodef,
size_t* size, upb_Arena* arena) {
const google_protobuf_MethodDescriptorProto* proto =
upb_MethodDef_ToProto(methodef, arena);
char* serialized =
google_protobuf_MethodDescriptorProto_serialize(proto, arena, size);
return serialized;
}
Loading

0 comments on commit 15cf1f2

Please sign in to comment.