1// Protocol Buffers - Google's data interchange format 2// Copyright 2014 Google Inc. All rights reserved. 3// https://developers.google.com/protocol-buffers/ 4// 5// Redistribution and use in source and binary forms, with or without 6// modification, are permitted provided that the following conditions are 7// met: 8// 9// * Redistributions of source code must retain the above copyright 10// notice, this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above 12// copyright notice, this list of conditions and the following disclaimer 13// in the documentation and/or other materials provided with the 14// distribution. 15// * Neither the name of Google Inc. nor the names of its 16// contributors may be used to endorse or promote products derived from 17// this software without specific prior written permission. 18// 19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31#include <ctype.h> 32#include <errno.h> 33#include "protobuf.h" 34 35// ----------------------------------------------------------------------------- 36// Common utilities. 37// ----------------------------------------------------------------------------- 38 39static const char* get_str(VALUE str) { 40 Check_Type(str, T_STRING); 41 return RSTRING_PTR(str); 42} 43 44static VALUE rb_str_maybe_null(const char* s) { 45 if (s == NULL) { 46 s = ""; 47 } 48 return rb_str_new2(s); 49} 50 51static void rewrite_enum_default(const upb_symtab* symtab, 52 google_protobuf_FileDescriptorProto* file, 53 google_protobuf_FieldDescriptorProto* field) { 54 upb_strview defaultval; 55 const char *type_name_str; 56 char *end; 57 long val; 58 const upb_enumdef *e; 59 upb_strview type_name; 60 61 /* Look for TYPE_ENUM fields that have a default. */ 62 if (google_protobuf_FieldDescriptorProto_type(field) != 63 google_protobuf_FieldDescriptorProto_TYPE_ENUM || 64 !google_protobuf_FieldDescriptorProto_has_default_value(field) || 65 !google_protobuf_FieldDescriptorProto_has_type_name(field)) { 66 return; 67 } 68 69 defaultval = google_protobuf_FieldDescriptorProto_default_value(field); 70 type_name = google_protobuf_FieldDescriptorProto_type_name(field); 71 72 if (defaultval.size == 0 || !isdigit(defaultval.data[0])) { 73 return; 74 } 75 76 if (type_name.size == 0 || type_name.data[0] != '.') { 77 return; 78 } 79 80 type_name_str = type_name.data + 1; 81 82 errno = 0; 83 val = strtol(defaultval.data, &end, 10); 84 85 if (errno != 0 || *end != 0 || val < INT32_MIN || val > INT32_MAX) { 86 return; 87 } 88 89 /* Now find the corresponding enum definition. */ 90 e = upb_symtab_lookupenum(symtab, type_name_str); 91 if (e) { 92 /* Look in previously loaded files. */ 93 const char *label = upb_enumdef_iton(e, val); 94 if (!label) { 95 return; 96 } 97 google_protobuf_FieldDescriptorProto_set_default_value( 98 field, upb_strview_makez(label)); 99 } else { 100 /* Look in enums defined in this file. */ 101 const google_protobuf_EnumDescriptorProto* matching_enum = NULL; 102 size_t i, n; 103 const google_protobuf_EnumDescriptorProto* const* enums = 104 google_protobuf_FileDescriptorProto_enum_type(file, &n); 105 const google_protobuf_EnumValueDescriptorProto* const* values; 106 107 for (i = 0; i < n; i++) { 108 if (upb_strview_eql(google_protobuf_EnumDescriptorProto_name(enums[i]), 109 upb_strview_makez(type_name_str))) { 110 matching_enum = enums[i]; 111 break; 112 } 113 } 114 115 if (!matching_enum) { 116 return; 117 } 118 119 values = google_protobuf_EnumDescriptorProto_value(matching_enum, &n); 120 for (i = 0; i < n; i++) { 121 if (google_protobuf_EnumValueDescriptorProto_number(values[i]) == val) { 122 google_protobuf_FieldDescriptorProto_set_default_value( 123 field, google_protobuf_EnumValueDescriptorProto_name(values[i])); 124 return; 125 } 126 } 127 128 /* We failed to find an enum default. But we'll just leave the enum 129 * untouched and let the normal def-building code catch it. */ 130 } 131} 132 133/* Historically we allowed enum defaults to be specified as a number. In 134 * retrospect this was a mistake as descriptors require defaults to be 135 * specified as a label. This can make a difference if multiple labels have the 136 * same number. 137 * 138 * Here we do a pass over all enum defaults and rewrite numeric defaults by 139 * looking up their labels. This is complicated by the fact that the enum 140 * definition can live in either the symtab or the file_proto. 141 * */ 142static void rewrite_enum_defaults( 143 const upb_symtab* symtab, google_protobuf_FileDescriptorProto* file_proto) { 144 size_t i, n; 145 google_protobuf_DescriptorProto** msgs = 146 google_protobuf_FileDescriptorProto_mutable_message_type(file_proto, &n); 147 148 for (i = 0; i < n; i++) { 149 size_t j, m; 150 google_protobuf_FieldDescriptorProto** fields = 151 google_protobuf_DescriptorProto_mutable_field(msgs[i], &m); 152 for (j = 0; j < m; j++) { 153 rewrite_enum_default(symtab, file_proto, fields[j]); 154 } 155 } 156} 157 158static void remove_path(upb_strview *name) { 159 const char* last = strrchr(name->data, '.'); 160 if (last) { 161 size_t remove = last - name->data + 1; 162 name->data += remove; 163 name->size -= remove; 164 } 165} 166 167static void rewrite_nesting(VALUE msg_ent, google_protobuf_DescriptorProto* msg, 168 google_protobuf_DescriptorProto* const* msgs, 169 google_protobuf_EnumDescriptorProto* const* enums, 170 upb_arena *arena) { 171 VALUE submsgs = rb_hash_aref(msg_ent, ID2SYM(rb_intern("msgs"))); 172 VALUE enum_pos = rb_hash_aref(msg_ent, ID2SYM(rb_intern("enums"))); 173 int submsg_count; 174 int enum_count; 175 int i; 176 google_protobuf_DescriptorProto** msg_msgs; 177 google_protobuf_EnumDescriptorProto** msg_enums; 178 179 Check_Type(submsgs, T_ARRAY); 180 Check_Type(enum_pos, T_ARRAY); 181 182 submsg_count = RARRAY_LEN(submsgs); 183 enum_count = RARRAY_LEN(enum_pos); 184 185 msg_msgs = google_protobuf_DescriptorProto_resize_nested_type( 186 msg, submsg_count, arena); 187 msg_enums = 188 google_protobuf_DescriptorProto_resize_enum_type(msg, enum_count, arena); 189 190 for (i = 0; i < submsg_count; i++) { 191 VALUE submsg_ent = RARRAY_PTR(submsgs)[i]; 192 VALUE pos = rb_hash_aref(submsg_ent, ID2SYM(rb_intern("pos"))); 193 upb_strview name; 194 195 msg_msgs[i] = msgs[NUM2INT(pos)]; 196 name = google_protobuf_DescriptorProto_name(msg_msgs[i]); 197 remove_path(&name); 198 google_protobuf_DescriptorProto_set_name(msg_msgs[i], name); 199 rewrite_nesting(submsg_ent, msg_msgs[i], msgs, enums, arena); 200 } 201 202 for (i = 0; i < enum_count; i++) { 203 VALUE pos = RARRAY_PTR(enum_pos)[i]; 204 msg_enums[i] = enums[NUM2INT(pos)]; 205 } 206} 207 208/* We have to do some relatively complicated logic here for backward 209 * compatibility. 210 * 211 * In descriptor.proto, messages are nested inside other messages if that is 212 * what the original .proto file looks like. For example, suppose we have this 213 * foo.proto: 214 * 215 * package foo; 216 * message Bar { 217 * message Baz {} 218 * } 219 * 220 * The descriptor for this must look like this: 221 * 222 * file { 223 * name: "test.proto" 224 * package: "foo" 225 * message_type { 226 * name: "Bar" 227 * nested_type { 228 * name: "Baz" 229 * } 230 * } 231 * } 232 * 233 * However, the Ruby generated code has always generated messages in a flat, 234 * non-nested way: 235 * 236 * Google::Protobuf::DescriptorPool.generated_pool.build do 237 * add_message "foo.Bar" do 238 * end 239 * add_message "foo.Bar.Baz" do 240 * end 241 * end 242 * 243 * Here we need to do a translation where we turn this generated code into the 244 * above descriptor. We need to infer that "foo" is the package name, and not 245 * a message itself. 246 * 247 * We delegate to Ruby to compute the transformation, for more concice and 248 * readable code than we can do in C */ 249static void rewrite_names(VALUE _file_builder, 250 google_protobuf_FileDescriptorProto* file_proto) { 251 FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder); 252 upb_arena *arena = file_builder->arena; 253 // Build params (package, msg_names, enum_names). 254 VALUE package = Qnil; 255 VALUE msg_names = rb_ary_new(); 256 VALUE enum_names = rb_ary_new(); 257 size_t msg_count, enum_count, i; 258 VALUE new_package, nesting, msg_ents, enum_ents; 259 google_protobuf_DescriptorProto** msgs; 260 google_protobuf_EnumDescriptorProto** enums; 261 262 if (google_protobuf_FileDescriptorProto_has_package(file_proto)) { 263 upb_strview package_str = 264 google_protobuf_FileDescriptorProto_package(file_proto); 265 package = rb_str_new(package_str.data, package_str.size); 266 } 267 268 msgs = google_protobuf_FileDescriptorProto_mutable_message_type(file_proto, 269 &msg_count); 270 for (i = 0; i < msg_count; i++) { 271 upb_strview name = google_protobuf_DescriptorProto_name(msgs[i]); 272 rb_ary_push(msg_names, rb_str_new(name.data, name.size)); 273 } 274 275 enums = google_protobuf_FileDescriptorProto_mutable_enum_type(file_proto, 276 &enum_count); 277 for (i = 0; i < enum_count; i++) { 278 upb_strview name = google_protobuf_EnumDescriptorProto_name(enums[i]); 279 rb_ary_push(enum_names, rb_str_new(name.data, name.size)); 280 } 281 282 { 283 // Call Ruby code to calculate package name and nesting. 284 VALUE args[3] = { package, msg_names, enum_names }; 285 VALUE internal = rb_eval_string("Google::Protobuf::Internal"); 286 VALUE ret = rb_funcallv(internal, rb_intern("fixup_descriptor"), 3, args); 287 288 new_package = rb_ary_entry(ret, 0); 289 nesting = rb_ary_entry(ret, 1); 290 } 291 292 // Rewrite package and names. 293 if (new_package != Qnil) { 294 upb_strview new_package_str = 295 FileBuilderContext_strdup(_file_builder, new_package); 296 google_protobuf_FileDescriptorProto_set_package(file_proto, 297 new_package_str); 298 } 299 300 for (i = 0; i < msg_count; i++) { 301 upb_strview name = google_protobuf_DescriptorProto_name(msgs[i]); 302 remove_path(&name); 303 google_protobuf_DescriptorProto_set_name(msgs[i], name); 304 } 305 306 for (i = 0; i < enum_count; i++) { 307 upb_strview name = google_protobuf_EnumDescriptorProto_name(enums[i]); 308 remove_path(&name); 309 google_protobuf_EnumDescriptorProto_set_name(enums[i], name); 310 } 311 312 // Rewrite nesting. 313 msg_ents = rb_hash_aref(nesting, ID2SYM(rb_intern("msgs"))); 314 enum_ents = rb_hash_aref(nesting, ID2SYM(rb_intern("enums"))); 315 316 Check_Type(msg_ents, T_ARRAY); 317 Check_Type(enum_ents, T_ARRAY); 318 319 for (i = 0; i < (size_t)RARRAY_LEN(msg_ents); i++) { 320 VALUE msg_ent = rb_ary_entry(msg_ents, i); 321 VALUE pos = rb_hash_aref(msg_ent, ID2SYM(rb_intern("pos"))); 322 msgs[i] = msgs[NUM2INT(pos)]; 323 rewrite_nesting(msg_ent, msgs[i], msgs, enums, arena); 324 } 325 326 for (i = 0; i < (size_t)RARRAY_LEN(enum_ents); i++) { 327 VALUE enum_pos = rb_ary_entry(enum_ents, i); 328 enums[i] = enums[NUM2INT(enum_pos)]; 329 } 330 331 google_protobuf_FileDescriptorProto_resize_message_type( 332 file_proto, RARRAY_LEN(msg_ents), arena); 333 google_protobuf_FileDescriptorProto_resize_enum_type( 334 file_proto, RARRAY_LEN(enum_ents), arena); 335} 336 337// ----------------------------------------------------------------------------- 338// DescriptorPool. 339// ----------------------------------------------------------------------------- 340 341#define DEFINE_CLASS(name, string_name) \ 342 VALUE c ## name = Qnil; \ 343 const rb_data_type_t _ ## name ## _type = { \ 344 string_name, \ 345 { name ## _mark, name ## _free, NULL }, \ 346 }; \ 347 name* ruby_to_ ## name(VALUE val) { \ 348 name* ret; \ 349 TypedData_Get_Struct(val, name, &_ ## name ## _type, ret); \ 350 return ret; \ 351 } \ 352 353#define DEFINE_SELF(type, var, rb_var) \ 354 type* var = ruby_to_ ## type(rb_var) 355 356// Global singleton DescriptorPool. The user is free to create others, but this 357// is used by generated code. 358VALUE generated_pool = Qnil; 359 360DEFINE_CLASS(DescriptorPool, "Google::Protobuf::DescriptorPool"); 361 362void DescriptorPool_mark(void* _self) { 363 DescriptorPool* self = _self; 364 rb_gc_mark(self->def_to_descriptor); 365} 366 367void DescriptorPool_free(void* _self) { 368 DescriptorPool* self = _self; 369 370 upb_symtab_free(self->symtab); 371 upb_handlercache_free(self->fill_handler_cache); 372 upb_handlercache_free(self->pb_serialize_handler_cache); 373 upb_handlercache_free(self->json_serialize_handler_cache); 374 upb_handlercache_free(self->json_serialize_handler_preserve_cache); 375 upb_pbcodecache_free(self->fill_method_cache); 376 upb_json_codecache_free(self->json_fill_method_cache); 377 378 xfree(self); 379} 380 381/* 382 * call-seq: 383 * DescriptorPool.new => pool 384 * 385 * Creates a new, empty, descriptor pool. 386 */ 387VALUE DescriptorPool_alloc(VALUE klass) { 388 DescriptorPool* self = ALLOC(DescriptorPool); 389 VALUE ret; 390 391 self->def_to_descriptor = Qnil; 392 ret = TypedData_Wrap_Struct(klass, &_DescriptorPool_type, self); 393 394 self->def_to_descriptor = rb_hash_new(); 395 self->symtab = upb_symtab_new(); 396 self->fill_handler_cache = 397 upb_handlercache_new(add_handlers_for_message, (void*)ret); 398 self->pb_serialize_handler_cache = upb_pb_encoder_newcache(); 399 self->json_serialize_handler_cache = upb_json_printer_newcache(false); 400 self->json_serialize_handler_preserve_cache = 401 upb_json_printer_newcache(true); 402 self->fill_method_cache = upb_pbcodecache_new(self->fill_handler_cache); 403 self->json_fill_method_cache = upb_json_codecache_new(); 404 405 return ret; 406} 407 408void DescriptorPool_register(VALUE module) { 409 VALUE klass = rb_define_class_under( 410 module, "DescriptorPool", rb_cObject); 411 rb_define_alloc_func(klass, DescriptorPool_alloc); 412 rb_define_method(klass, "build", DescriptorPool_build, -1); 413 rb_define_method(klass, "lookup", DescriptorPool_lookup, 1); 414 rb_define_singleton_method(klass, "generated_pool", 415 DescriptorPool_generated_pool, 0); 416 rb_gc_register_address(&cDescriptorPool); 417 cDescriptorPool = klass; 418 419 rb_gc_register_address(&generated_pool); 420 generated_pool = rb_class_new_instance(0, NULL, klass); 421} 422 423/* 424 * call-seq: 425 * DescriptorPool.build(&block) 426 * 427 * Invokes the block with a Builder instance as self. All message and enum types 428 * added within the block are committed to the pool atomically, and may refer 429 * (co)recursively to each other. The user should call Builder#add_message and 430 * Builder#add_enum within the block as appropriate. This is the recommended, 431 * idiomatic way to define new message and enum types. 432 */ 433VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self) { 434 VALUE ctx = rb_class_new_instance(1, &_self, cBuilder); 435 VALUE block = rb_block_proc(); 436 rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block); 437 Builder_build(ctx); 438 return Qnil; 439} 440 441/* 442 * call-seq: 443 * DescriptorPool.lookup(name) => descriptor 444 * 445 * Finds a Descriptor or EnumDescriptor by name and returns it, or nil if none 446 * exists with the given name. 447 */ 448VALUE DescriptorPool_lookup(VALUE _self, VALUE name) { 449 DEFINE_SELF(DescriptorPool, self, _self); 450 const char* name_str = get_str(name); 451 const upb_msgdef* msgdef; 452 const upb_enumdef* enumdef; 453 454 msgdef = upb_symtab_lookupmsg(self->symtab, name_str); 455 if (msgdef) { 456 return get_msgdef_obj(_self, msgdef); 457 } 458 459 enumdef = upb_symtab_lookupenum(self->symtab, name_str); 460 if (enumdef) { 461 return get_enumdef_obj(_self, enumdef); 462 } 463 464 return Qnil; 465} 466 467/* 468 * call-seq: 469 * DescriptorPool.generated_pool => descriptor_pool 470 * 471 * Class method that returns the global DescriptorPool. This is a singleton into 472 * which generated-code message and enum types are registered. The user may also 473 * register types in this pool for convenience so that they do not have to hold 474 * a reference to a private pool instance. 475 */ 476VALUE DescriptorPool_generated_pool(VALUE _self) { 477 return generated_pool; 478} 479 480// ----------------------------------------------------------------------------- 481// Descriptor. 482// ----------------------------------------------------------------------------- 483 484DEFINE_CLASS(Descriptor, "Google::Protobuf::Descriptor"); 485 486void Descriptor_mark(void* _self) { 487 Descriptor* self = _self; 488 rb_gc_mark(self->klass); 489 rb_gc_mark(self->descriptor_pool); 490 if (self->layout && self->layout->empty_template) { 491 layout_mark(self->layout, self->layout->empty_template); 492 } 493} 494 495void Descriptor_free(void* _self) { 496 Descriptor* self = _self; 497 if (self->layout) { 498 free_layout(self->layout); 499 } 500 xfree(self); 501} 502 503/* 504 * call-seq: 505 * Descriptor.new => descriptor 506 * 507 * Creates a new, empty, message type descriptor. At a minimum, its name must be 508 * set before it is added to a pool. It cannot be used to create messages until 509 * it is added to a pool, after which it becomes immutable (as part of a 510 * finalization process). 511 */ 512VALUE Descriptor_alloc(VALUE klass) { 513 Descriptor* self = ALLOC(Descriptor); 514 VALUE ret = TypedData_Wrap_Struct(klass, &_Descriptor_type, self); 515 self->msgdef = NULL; 516 self->klass = Qnil; 517 self->descriptor_pool = Qnil; 518 self->layout = NULL; 519 return ret; 520} 521 522void Descriptor_register(VALUE module) { 523 VALUE klass = rb_define_class_under( 524 module, "Descriptor", rb_cObject); 525 rb_define_alloc_func(klass, Descriptor_alloc); 526 rb_define_method(klass, "initialize", Descriptor_initialize, 3); 527 rb_define_method(klass, "each", Descriptor_each, 0); 528 rb_define_method(klass, "lookup", Descriptor_lookup, 1); 529 rb_define_method(klass, "each_oneof", Descriptor_each_oneof, 0); 530 rb_define_method(klass, "lookup_oneof", Descriptor_lookup_oneof, 1); 531 rb_define_method(klass, "msgclass", Descriptor_msgclass, 0); 532 rb_define_method(klass, "name", Descriptor_name, 0); 533 rb_define_method(klass, "file_descriptor", Descriptor_file_descriptor, 0); 534 rb_include_module(klass, rb_mEnumerable); 535 rb_gc_register_address(&cDescriptor); 536 cDescriptor = klass; 537} 538 539/* 540 * call-seq: 541 * Descriptor.new(c_only_cookie, ptr) => Descriptor 542 * 543 * Creates a descriptor wrapper object. May only be called from C. 544 */ 545VALUE Descriptor_initialize(VALUE _self, VALUE cookie, 546 VALUE descriptor_pool, VALUE ptr) { 547 DEFINE_SELF(Descriptor, self, _self); 548 549 if (cookie != c_only_cookie) { 550 rb_raise(rb_eRuntimeError, 551 "Descriptor objects may not be created from Ruby."); 552 } 553 554 self->descriptor_pool = descriptor_pool; 555 self->msgdef = (const upb_msgdef*)NUM2ULL(ptr); 556 557 return Qnil; 558} 559 560/* 561 * call-seq: 562 * Descriptor.file_descriptor 563 * 564 * Returns the FileDescriptor object this message belongs to. 565 */ 566VALUE Descriptor_file_descriptor(VALUE _self) { 567 DEFINE_SELF(Descriptor, self, _self); 568 return get_filedef_obj(self->descriptor_pool, upb_msgdef_file(self->msgdef)); 569} 570 571/* 572 * call-seq: 573 * Descriptor.name => name 574 * 575 * Returns the name of this message type as a fully-qualified string (e.g., 576 * My.Package.MessageType). 577 */ 578VALUE Descriptor_name(VALUE _self) { 579 DEFINE_SELF(Descriptor, self, _self); 580 return rb_str_maybe_null(upb_msgdef_fullname(self->msgdef)); 581} 582 583/* 584 * call-seq: 585 * Descriptor.each(&block) 586 * 587 * Iterates over fields in this message type, yielding to the block on each one. 588 */ 589VALUE Descriptor_each(VALUE _self) { 590 DEFINE_SELF(Descriptor, self, _self); 591 592 upb_msg_field_iter it; 593 for (upb_msg_field_begin(&it, self->msgdef); 594 !upb_msg_field_done(&it); 595 upb_msg_field_next(&it)) { 596 const upb_fielddef* field = upb_msg_iter_field(&it); 597 VALUE obj = get_fielddef_obj(self->descriptor_pool, field); 598 rb_yield(obj); 599 } 600 return Qnil; 601} 602 603/* 604 * call-seq: 605 * Descriptor.lookup(name) => FieldDescriptor 606 * 607 * Returns the field descriptor for the field with the given name, if present, 608 * or nil if none. 609 */ 610VALUE Descriptor_lookup(VALUE _self, VALUE name) { 611 DEFINE_SELF(Descriptor, self, _self); 612 const char* s = get_str(name); 613 const upb_fielddef* field = upb_msgdef_ntofz(self->msgdef, s); 614 if (field == NULL) { 615 return Qnil; 616 } 617 return get_fielddef_obj(self->descriptor_pool, field); 618} 619 620/* 621 * call-seq: 622 * Descriptor.each_oneof(&block) => nil 623 * 624 * Invokes the given block for each oneof in this message type, passing the 625 * corresponding OneofDescriptor. 626 */ 627VALUE Descriptor_each_oneof(VALUE _self) { 628 DEFINE_SELF(Descriptor, self, _self); 629 630 upb_msg_oneof_iter it; 631 for (upb_msg_oneof_begin(&it, self->msgdef); 632 !upb_msg_oneof_done(&it); 633 upb_msg_oneof_next(&it)) { 634 const upb_oneofdef* oneof = upb_msg_iter_oneof(&it); 635 VALUE obj = get_oneofdef_obj(self->descriptor_pool, oneof); 636 rb_yield(obj); 637 } 638 return Qnil; 639} 640 641/* 642 * call-seq: 643 * Descriptor.lookup_oneof(name) => OneofDescriptor 644 * 645 * Returns the oneof descriptor for the oneof with the given name, if present, 646 * or nil if none. 647 */ 648VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) { 649 DEFINE_SELF(Descriptor, self, _self); 650 const char* s = get_str(name); 651 const upb_oneofdef* oneof = upb_msgdef_ntooz(self->msgdef, s); 652 if (oneof == NULL) { 653 return Qnil; 654 } 655 return get_oneofdef_obj(self->descriptor_pool, oneof); 656} 657 658/* 659 * call-seq: 660 * Descriptor.msgclass => message_klass 661 * 662 * Returns the Ruby class created for this message type. 663 */ 664VALUE Descriptor_msgclass(VALUE _self) { 665 DEFINE_SELF(Descriptor, self, _self); 666 if (self->klass == Qnil) { 667 self->klass = build_class_from_descriptor(_self); 668 } 669 return self->klass; 670} 671 672// ----------------------------------------------------------------------------- 673// FileDescriptor. 674// ----------------------------------------------------------------------------- 675 676DEFINE_CLASS(FileDescriptor, "Google::Protobuf::FileDescriptor"); 677 678void FileDescriptor_mark(void* _self) { 679 FileDescriptor* self = _self; 680 rb_gc_mark(self->descriptor_pool); 681} 682 683void FileDescriptor_free(void* _self) { 684 xfree(_self); 685} 686 687VALUE FileDescriptor_alloc(VALUE klass) { 688 FileDescriptor* self = ALLOC(FileDescriptor); 689 VALUE ret = TypedData_Wrap_Struct(klass, &_FileDescriptor_type, self); 690 self->descriptor_pool = Qnil; 691 self->filedef = NULL; 692 return ret; 693} 694 695/* 696 * call-seq: 697 * FileDescriptor.new => file 698 * 699 * Returns a new file descriptor. The syntax must be set before it's passed 700 * to a builder. 701 */ 702VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie, 703 VALUE descriptor_pool, VALUE ptr) { 704 DEFINE_SELF(FileDescriptor, self, _self); 705 706 if (cookie != c_only_cookie) { 707 rb_raise(rb_eRuntimeError, 708 "Descriptor objects may not be created from Ruby."); 709 } 710 711 self->descriptor_pool = descriptor_pool; 712 self->filedef = (const upb_filedef*)NUM2ULL(ptr); 713 714 return Qnil; 715} 716 717void FileDescriptor_register(VALUE module) { 718 VALUE klass = rb_define_class_under( 719 module, "FileDescriptor", rb_cObject); 720 rb_define_alloc_func(klass, FileDescriptor_alloc); 721 rb_define_method(klass, "initialize", FileDescriptor_initialize, 3); 722 rb_define_method(klass, "name", FileDescriptor_name, 0); 723 rb_define_method(klass, "syntax", FileDescriptor_syntax, 0); 724 rb_gc_register_address(&cFileDescriptor); 725 cFileDescriptor = klass; 726} 727 728/* 729 * call-seq: 730 * FileDescriptor.name => name 731 * 732 * Returns the name of the file. 733 */ 734VALUE FileDescriptor_name(VALUE _self) { 735 DEFINE_SELF(FileDescriptor, self, _self); 736 const char* name = upb_filedef_name(self->filedef); 737 return name == NULL ? Qnil : rb_str_new2(name); 738} 739 740/* 741 * call-seq: 742 * FileDescriptor.syntax => syntax 743 * 744 * Returns this file descriptors syntax. 745 * 746 * Valid syntax versions are: 747 * :proto2 or :proto3. 748 */ 749VALUE FileDescriptor_syntax(VALUE _self) { 750 DEFINE_SELF(FileDescriptor, self, _self); 751 752 switch (upb_filedef_syntax(self->filedef)) { 753 case UPB_SYNTAX_PROTO3: return ID2SYM(rb_intern("proto3")); 754 case UPB_SYNTAX_PROTO2: return ID2SYM(rb_intern("proto2")); 755 default: return Qnil; 756 } 757} 758 759// ----------------------------------------------------------------------------- 760// FieldDescriptor. 761// ----------------------------------------------------------------------------- 762 763DEFINE_CLASS(FieldDescriptor, "Google::Protobuf::FieldDescriptor"); 764 765void FieldDescriptor_mark(void* _self) { 766 FieldDescriptor* self = _self; 767 rb_gc_mark(self->descriptor_pool); 768} 769 770void FieldDescriptor_free(void* _self) { 771 xfree(_self); 772} 773 774/* 775 * call-seq: 776 * FieldDescriptor.new => field 777 * 778 * Returns a new field descriptor. Its name, type, etc. must be set before it is 779 * added to a message type. 780 */ 781VALUE FieldDescriptor_alloc(VALUE klass) { 782 FieldDescriptor* self = ALLOC(FieldDescriptor); 783 VALUE ret = TypedData_Wrap_Struct(klass, &_FieldDescriptor_type, self); 784 self->fielddef = NULL; 785 return ret; 786} 787 788void FieldDescriptor_register(VALUE module) { 789 VALUE klass = rb_define_class_under( 790 module, "FieldDescriptor", rb_cObject); 791 rb_define_alloc_func(klass, FieldDescriptor_alloc); 792 rb_define_method(klass, "initialize", FieldDescriptor_initialize, 3); 793 rb_define_method(klass, "name", FieldDescriptor_name, 0); 794 rb_define_method(klass, "type", FieldDescriptor_type, 0); 795 rb_define_method(klass, "default", FieldDescriptor_default, 0); 796 rb_define_method(klass, "label", FieldDescriptor_label, 0); 797 rb_define_method(klass, "number", FieldDescriptor_number, 0); 798 rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0); 799 rb_define_method(klass, "subtype", FieldDescriptor_subtype, 0); 800 rb_define_method(klass, "has?", FieldDescriptor_has, 1); 801 rb_define_method(klass, "clear", FieldDescriptor_clear, 1); 802 rb_define_method(klass, "get", FieldDescriptor_get, 1); 803 rb_define_method(klass, "set", FieldDescriptor_set, 2); 804 rb_gc_register_address(&cFieldDescriptor); 805 cFieldDescriptor = klass; 806} 807 808/* 809 * call-seq: 810 * EnumDescriptor.new(c_only_cookie, pool, ptr) => EnumDescriptor 811 * 812 * Creates a descriptor wrapper object. May only be called from C. 813 */ 814VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie, 815 VALUE descriptor_pool, VALUE ptr) { 816 DEFINE_SELF(FieldDescriptor, self, _self); 817 818 if (cookie != c_only_cookie) { 819 rb_raise(rb_eRuntimeError, 820 "Descriptor objects may not be created from Ruby."); 821 } 822 823 self->descriptor_pool = descriptor_pool; 824 self->fielddef = (const upb_fielddef*)NUM2ULL(ptr); 825 826 return Qnil; 827} 828 829/* 830 * call-seq: 831 * FieldDescriptor.name => name 832 * 833 * Returns the name of this field. 834 */ 835VALUE FieldDescriptor_name(VALUE _self) { 836 DEFINE_SELF(FieldDescriptor, self, _self); 837 return rb_str_maybe_null(upb_fielddef_name(self->fielddef)); 838} 839 840upb_fieldtype_t ruby_to_fieldtype(VALUE type) { 841 if (TYPE(type) != T_SYMBOL) { 842 rb_raise(rb_eArgError, "Expected symbol for field type."); 843 } 844 845#define CONVERT(upb, ruby) \ 846 if (SYM2ID(type) == rb_intern( # ruby )) { \ 847 return UPB_TYPE_ ## upb; \ 848 } 849 850 CONVERT(FLOAT, float); 851 CONVERT(DOUBLE, double); 852 CONVERT(BOOL, bool); 853 CONVERT(STRING, string); 854 CONVERT(BYTES, bytes); 855 CONVERT(MESSAGE, message); 856 CONVERT(ENUM, enum); 857 CONVERT(INT32, int32); 858 CONVERT(INT64, int64); 859 CONVERT(UINT32, uint32); 860 CONVERT(UINT64, uint64); 861 862#undef CONVERT 863 864 rb_raise(rb_eArgError, "Unknown field type."); 865 return 0; 866} 867 868VALUE fieldtype_to_ruby(upb_fieldtype_t type) { 869 switch (type) { 870#define CONVERT(upb, ruby) \ 871 case UPB_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby )); 872 CONVERT(FLOAT, float); 873 CONVERT(DOUBLE, double); 874 CONVERT(BOOL, bool); 875 CONVERT(STRING, string); 876 CONVERT(BYTES, bytes); 877 CONVERT(MESSAGE, message); 878 CONVERT(ENUM, enum); 879 CONVERT(INT32, int32); 880 CONVERT(INT64, int64); 881 CONVERT(UINT32, uint32); 882 CONVERT(UINT64, uint64); 883#undef CONVERT 884 } 885 return Qnil; 886} 887 888upb_descriptortype_t ruby_to_descriptortype(VALUE type) { 889 if (TYPE(type) != T_SYMBOL) { 890 rb_raise(rb_eArgError, "Expected symbol for field type."); 891 } 892 893#define CONVERT(upb, ruby) \ 894 if (SYM2ID(type) == rb_intern( # ruby )) { \ 895 return UPB_DESCRIPTOR_TYPE_ ## upb; \ 896 } 897 898 CONVERT(FLOAT, float); 899 CONVERT(DOUBLE, double); 900 CONVERT(BOOL, bool); 901 CONVERT(STRING, string); 902 CONVERT(BYTES, bytes); 903 CONVERT(MESSAGE, message); 904 CONVERT(GROUP, group); 905 CONVERT(ENUM, enum); 906 CONVERT(INT32, int32); 907 CONVERT(INT64, int64); 908 CONVERT(UINT32, uint32); 909 CONVERT(UINT64, uint64); 910 CONVERT(SINT32, sint32); 911 CONVERT(SINT64, sint64); 912 CONVERT(FIXED32, fixed32); 913 CONVERT(FIXED64, fixed64); 914 CONVERT(SFIXED32, sfixed32); 915 CONVERT(SFIXED64, sfixed64); 916 917#undef CONVERT 918 919 rb_raise(rb_eArgError, "Unknown field type."); 920 return 0; 921} 922 923VALUE descriptortype_to_ruby(upb_descriptortype_t type) { 924 switch (type) { 925#define CONVERT(upb, ruby) \ 926 case UPB_DESCRIPTOR_TYPE_ ## upb : return ID2SYM(rb_intern( # ruby )); 927 CONVERT(FLOAT, float); 928 CONVERT(DOUBLE, double); 929 CONVERT(BOOL, bool); 930 CONVERT(STRING, string); 931 CONVERT(BYTES, bytes); 932 CONVERT(MESSAGE, message); 933 CONVERT(GROUP, group); 934 CONVERT(ENUM, enum); 935 CONVERT(INT32, int32); 936 CONVERT(INT64, int64); 937 CONVERT(UINT32, uint32); 938 CONVERT(UINT64, uint64); 939 CONVERT(SINT32, sint32); 940 CONVERT(SINT64, sint64); 941 CONVERT(FIXED32, fixed32); 942 CONVERT(FIXED64, fixed64); 943 CONVERT(SFIXED32, sfixed32); 944 CONVERT(SFIXED64, sfixed64); 945#undef CONVERT 946 } 947 return Qnil; 948} 949 950VALUE ruby_to_label(VALUE label) { 951 upb_label_t upb_label; 952 bool converted = false; 953 954#define CONVERT(upb, ruby) \ 955 if (SYM2ID(label) == rb_intern( # ruby )) { \ 956 upb_label = UPB_LABEL_ ## upb; \ 957 converted = true; \ 958 } 959 960 CONVERT(OPTIONAL, optional); 961 CONVERT(REQUIRED, required); 962 CONVERT(REPEATED, repeated); 963 964#undef CONVERT 965 966 if (!converted) { 967 rb_raise(rb_eArgError, "Unknown field label."); 968 } 969 970 return upb_label; 971} 972 973/* 974 * call-seq: 975 * FieldDescriptor.type => type 976 * 977 * Returns this field's type, as a Ruby symbol, or nil if not yet set. 978 * 979 * Valid field types are: 980 * :int32, :int64, :uint32, :uint64, :float, :double, :bool, :string, 981 * :bytes, :message. 982 */ 983VALUE FieldDescriptor_type(VALUE _self) { 984 DEFINE_SELF(FieldDescriptor, self, _self); 985 return descriptortype_to_ruby(upb_fielddef_descriptortype(self->fielddef)); 986} 987 988/* 989 * call-seq: 990 * FieldDescriptor.default => default 991 * 992 * Returns this field's default, as a Ruby object, or nil if not yet set. 993 */ 994VALUE FieldDescriptor_default(VALUE _self) { 995 DEFINE_SELF(FieldDescriptor, self, _self); 996 return layout_get_default(self->fielddef); 997} 998 999/* 1000 * call-seq: 1001 * FieldDescriptor.label => label 1002 * 1003 * Returns this field's label (i.e., plurality), as a Ruby symbol. 1004 * 1005 * Valid field labels are: 1006 * :optional, :repeated 1007 */ 1008VALUE FieldDescriptor_label(VALUE _self) { 1009 DEFINE_SELF(FieldDescriptor, self, _self); 1010 switch (upb_fielddef_label(self->fielddef)) { 1011#define CONVERT(upb, ruby) \ 1012 case UPB_LABEL_ ## upb : return ID2SYM(rb_intern( # ruby )); 1013 1014 CONVERT(OPTIONAL, optional); 1015 CONVERT(REQUIRED, required); 1016 CONVERT(REPEATED, repeated); 1017 1018#undef CONVERT 1019 } 1020 1021 return Qnil; 1022} 1023 1024/* 1025 * call-seq: 1026 * FieldDescriptor.number => number 1027 * 1028 * Returns the tag number for this field. 1029 */ 1030VALUE FieldDescriptor_number(VALUE _self) { 1031 DEFINE_SELF(FieldDescriptor, self, _self); 1032 return INT2NUM(upb_fielddef_number(self->fielddef)); 1033} 1034 1035/* 1036 * call-seq: 1037 * FieldDescriptor.submsg_name => submsg_name 1038 * 1039 * Returns the name of the message or enum type corresponding to this field, if 1040 * it is a message or enum field (respectively), or nil otherwise. This type 1041 * name will be resolved within the context of the pool to which the containing 1042 * message type is added. 1043 */ 1044VALUE FieldDescriptor_submsg_name(VALUE _self) { 1045 DEFINE_SELF(FieldDescriptor, self, _self); 1046 switch (upb_fielddef_type(self->fielddef)) { 1047 case UPB_TYPE_ENUM: 1048 return rb_str_new2( 1049 upb_enumdef_fullname(upb_fielddef_enumsubdef(self->fielddef))); 1050 case UPB_TYPE_MESSAGE: 1051 return rb_str_new2( 1052 upb_msgdef_fullname(upb_fielddef_msgsubdef(self->fielddef))); 1053 default: 1054 return Qnil; 1055 } 1056} 1057 1058/* 1059 * call-seq: 1060 * FieldDescriptor.subtype => message_or_enum_descriptor 1061 * 1062 * Returns the message or enum descriptor corresponding to this field's type if 1063 * it is a message or enum field, respectively, or nil otherwise. Cannot be 1064 * called *until* the containing message type is added to a pool (and thus 1065 * resolved). 1066 */ 1067VALUE FieldDescriptor_subtype(VALUE _self) { 1068 DEFINE_SELF(FieldDescriptor, self, _self); 1069 switch (upb_fielddef_type(self->fielddef)) { 1070 case UPB_TYPE_ENUM: 1071 return get_enumdef_obj(self->descriptor_pool, 1072 upb_fielddef_enumsubdef(self->fielddef)); 1073 case UPB_TYPE_MESSAGE: 1074 return get_msgdef_obj(self->descriptor_pool, 1075 upb_fielddef_msgsubdef(self->fielddef)); 1076 default: 1077 return Qnil; 1078 } 1079} 1080 1081/* 1082 * call-seq: 1083 * FieldDescriptor.get(message) => value 1084 * 1085 * Returns the value set for this field on the given message. Raises an 1086 * exception if message is of the wrong type. 1087 */ 1088VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) { 1089 DEFINE_SELF(FieldDescriptor, self, _self); 1090 MessageHeader* msg; 1091 TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); 1092 if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) { 1093 rb_raise(cTypeError, "get method called on wrong message type"); 1094 } 1095 return layout_get(msg->descriptor->layout, Message_data(msg), self->fielddef); 1096} 1097 1098/* 1099 * call-seq: 1100 * FieldDescriptor.has?(message) => boolean 1101 * 1102 * Returns whether the value is set on the given message. Raises an 1103 * exception when calling for fields that do not have presence. 1104 */ 1105VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) { 1106 DEFINE_SELF(FieldDescriptor, self, _self); 1107 MessageHeader* msg; 1108 TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); 1109 if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) { 1110 rb_raise(cTypeError, "has method called on wrong message type"); 1111 } else if (!upb_fielddef_haspresence(self->fielddef)) { 1112 rb_raise(rb_eArgError, "does not track presence"); 1113 } 1114 1115 return layout_has(msg->descriptor->layout, Message_data(msg), self->fielddef); 1116} 1117 1118/* 1119 * call-seq: 1120 * FieldDescriptor.clear(message) 1121 * 1122 * Clears the field from the message if it's set. 1123 */ 1124VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb) { 1125 DEFINE_SELF(FieldDescriptor, self, _self); 1126 MessageHeader* msg; 1127 TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); 1128 if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) { 1129 rb_raise(cTypeError, "has method called on wrong message type"); 1130 } 1131 1132 layout_clear(msg->descriptor->layout, Message_data(msg), self->fielddef); 1133 return Qnil; 1134} 1135 1136/* 1137 * call-seq: 1138 * FieldDescriptor.set(message, value) 1139 * 1140 * Sets the value corresponding to this field to the given value on the given 1141 * message. Raises an exception if message is of the wrong type. Performs the 1142 * ordinary type-checks for field setting. 1143 */ 1144VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) { 1145 DEFINE_SELF(FieldDescriptor, self, _self); 1146 MessageHeader* msg; 1147 TypedData_Get_Struct(msg_rb, MessageHeader, &Message_type, msg); 1148 if (msg->descriptor->msgdef != upb_fielddef_containingtype(self->fielddef)) { 1149 rb_raise(cTypeError, "set method called on wrong message type"); 1150 } 1151 layout_set(msg->descriptor->layout, Message_data(msg), self->fielddef, value); 1152 return Qnil; 1153} 1154 1155// ----------------------------------------------------------------------------- 1156// OneofDescriptor. 1157// ----------------------------------------------------------------------------- 1158 1159DEFINE_CLASS(OneofDescriptor, "Google::Protobuf::OneofDescriptor"); 1160 1161void OneofDescriptor_mark(void* _self) { 1162 OneofDescriptor* self = _self; 1163 rb_gc_mark(self->descriptor_pool); 1164} 1165 1166void OneofDescriptor_free(void* _self) { 1167 xfree(_self); 1168} 1169 1170/* 1171 * call-seq: 1172 * OneofDescriptor.new => oneof_descriptor 1173 * 1174 * Creates a new, empty, oneof descriptor. The oneof may only be modified prior 1175 * to being added to a message descriptor which is subsequently added to a pool. 1176 */ 1177VALUE OneofDescriptor_alloc(VALUE klass) { 1178 OneofDescriptor* self = ALLOC(OneofDescriptor); 1179 VALUE ret = TypedData_Wrap_Struct(klass, &_OneofDescriptor_type, self); 1180 self->oneofdef = NULL; 1181 self->descriptor_pool = Qnil; 1182 return ret; 1183} 1184 1185void OneofDescriptor_register(VALUE module) { 1186 VALUE klass = rb_define_class_under( 1187 module, "OneofDescriptor", rb_cObject); 1188 rb_define_alloc_func(klass, OneofDescriptor_alloc); 1189 rb_define_method(klass, "initialize", OneofDescriptor_initialize, 3); 1190 rb_define_method(klass, "name", OneofDescriptor_name, 0); 1191 rb_define_method(klass, "each", OneofDescriptor_each, 0); 1192 rb_include_module(klass, rb_mEnumerable); 1193 rb_gc_register_address(&cOneofDescriptor); 1194 cOneofDescriptor = klass; 1195} 1196 1197/* 1198 * call-seq: 1199 * OneofDescriptor.new(c_only_cookie, pool, ptr) => OneofDescriptor 1200 * 1201 * Creates a descriptor wrapper object. May only be called from C. 1202 */ 1203VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie, 1204 VALUE descriptor_pool, VALUE ptr) { 1205 DEFINE_SELF(OneofDescriptor, self, _self); 1206 1207 if (cookie != c_only_cookie) { 1208 rb_raise(rb_eRuntimeError, 1209 "Descriptor objects may not be created from Ruby."); 1210 } 1211 1212 self->descriptor_pool = descriptor_pool; 1213 self->oneofdef = (const upb_oneofdef*)NUM2ULL(ptr); 1214 1215 return Qnil; 1216} 1217 1218/* 1219 * call-seq: 1220 * OneofDescriptor.name => name 1221 * 1222 * Returns the name of this oneof. 1223 */ 1224VALUE OneofDescriptor_name(VALUE _self) { 1225 DEFINE_SELF(OneofDescriptor, self, _self); 1226 return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef)); 1227} 1228 1229/* 1230 * call-seq: 1231 * OneofDescriptor.each(&block) => nil 1232 * 1233 * Iterates through fields in this oneof, yielding to the block on each one. 1234 */ 1235VALUE OneofDescriptor_each(VALUE _self) { 1236 DEFINE_SELF(OneofDescriptor, self, _self); 1237 upb_oneof_iter it; 1238 for (upb_oneof_begin(&it, self->oneofdef); 1239 !upb_oneof_done(&it); 1240 upb_oneof_next(&it)) { 1241 const upb_fielddef* f = upb_oneof_iter_field(&it); 1242 VALUE obj = get_fielddef_obj(self->descriptor_pool, f); 1243 rb_yield(obj); 1244 } 1245 return Qnil; 1246} 1247 1248// ----------------------------------------------------------------------------- 1249// EnumDescriptor. 1250// ----------------------------------------------------------------------------- 1251 1252DEFINE_CLASS(EnumDescriptor, "Google::Protobuf::EnumDescriptor"); 1253 1254void EnumDescriptor_mark(void* _self) { 1255 EnumDescriptor* self = _self; 1256 rb_gc_mark(self->module); 1257 rb_gc_mark(self->descriptor_pool); 1258} 1259 1260void EnumDescriptor_free(void* _self) { 1261 xfree(_self); 1262} 1263 1264VALUE EnumDescriptor_alloc(VALUE klass) { 1265 EnumDescriptor* self = ALLOC(EnumDescriptor); 1266 VALUE ret = TypedData_Wrap_Struct(klass, &_EnumDescriptor_type, self); 1267 self->enumdef = NULL; 1268 self->module = Qnil; 1269 self->descriptor_pool = Qnil; 1270 return ret; 1271} 1272 1273/* 1274 * call-seq: 1275 * EnumDescriptor.new(c_only_cookie, ptr) => EnumDescriptor 1276 * 1277 * Creates a descriptor wrapper object. May only be called from C. 1278 */ 1279VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie, 1280 VALUE descriptor_pool, VALUE ptr) { 1281 DEFINE_SELF(EnumDescriptor, self, _self); 1282 1283 if (cookie != c_only_cookie) { 1284 rb_raise(rb_eRuntimeError, 1285 "Descriptor objects may not be created from Ruby."); 1286 } 1287 1288 self->descriptor_pool = descriptor_pool; 1289 self->enumdef = (const upb_enumdef*)NUM2ULL(ptr); 1290 1291 return Qnil; 1292} 1293 1294void EnumDescriptor_register(VALUE module) { 1295 VALUE klass = rb_define_class_under( 1296 module, "EnumDescriptor", rb_cObject); 1297 rb_define_alloc_func(klass, EnumDescriptor_alloc); 1298 rb_define_method(klass, "initialize", EnumDescriptor_initialize, 3); 1299 rb_define_method(klass, "name", EnumDescriptor_name, 0); 1300 rb_define_method(klass, "lookup_name", EnumDescriptor_lookup_name, 1); 1301 rb_define_method(klass, "lookup_value", EnumDescriptor_lookup_value, 1); 1302 rb_define_method(klass, "each", EnumDescriptor_each, 0); 1303 rb_define_method(klass, "enummodule", EnumDescriptor_enummodule, 0); 1304 rb_define_method(klass, "file_descriptor", EnumDescriptor_file_descriptor, 0); 1305 rb_include_module(klass, rb_mEnumerable); 1306 rb_gc_register_address(&cEnumDescriptor); 1307 cEnumDescriptor = klass; 1308} 1309 1310/* 1311 * call-seq: 1312 * EnumDescriptor.file_descriptor 1313 * 1314 * Returns the FileDescriptor object this enum belongs to. 1315 */ 1316VALUE EnumDescriptor_file_descriptor(VALUE _self) { 1317 DEFINE_SELF(EnumDescriptor, self, _self); 1318 return get_filedef_obj(self->descriptor_pool, 1319 upb_enumdef_file(self->enumdef)); 1320} 1321 1322/* 1323 * call-seq: 1324 * EnumDescriptor.name => name 1325 * 1326 * Returns the name of this enum type. 1327 */ 1328VALUE EnumDescriptor_name(VALUE _self) { 1329 DEFINE_SELF(EnumDescriptor, self, _self); 1330 return rb_str_maybe_null(upb_enumdef_fullname(self->enumdef)); 1331} 1332 1333/* 1334 * call-seq: 1335 * EnumDescriptor.lookup_name(name) => value 1336 * 1337 * Returns the numeric value corresponding to the given key name (as a Ruby 1338 * symbol), or nil if none. 1339 */ 1340VALUE EnumDescriptor_lookup_name(VALUE _self, VALUE name) { 1341 DEFINE_SELF(EnumDescriptor, self, _self); 1342 const char* name_str= rb_id2name(SYM2ID(name)); 1343 int32_t val = 0; 1344 if (upb_enumdef_ntoiz(self->enumdef, name_str, &val)) { 1345 return INT2NUM(val); 1346 } else { 1347 return Qnil; 1348 } 1349} 1350 1351/* 1352 * call-seq: 1353 * EnumDescriptor.lookup_value(name) => value 1354 * 1355 * Returns the key name (as a Ruby symbol) corresponding to the integer value, 1356 * or nil if none. 1357 */ 1358VALUE EnumDescriptor_lookup_value(VALUE _self, VALUE number) { 1359 DEFINE_SELF(EnumDescriptor, self, _self); 1360 int32_t val = NUM2INT(number); 1361 const char* name = upb_enumdef_iton(self->enumdef, val); 1362 if (name != NULL) { 1363 return ID2SYM(rb_intern(name)); 1364 } else { 1365 return Qnil; 1366 } 1367} 1368 1369/* 1370 * call-seq: 1371 * EnumDescriptor.each(&block) 1372 * 1373 * Iterates over key => value mappings in this enum's definition, yielding to 1374 * the block with (key, value) arguments for each one. 1375 */ 1376VALUE EnumDescriptor_each(VALUE _self) { 1377 DEFINE_SELF(EnumDescriptor, self, _self); 1378 1379 upb_enum_iter it; 1380 for (upb_enum_begin(&it, self->enumdef); 1381 !upb_enum_done(&it); 1382 upb_enum_next(&it)) { 1383 VALUE key = ID2SYM(rb_intern(upb_enum_iter_name(&it))); 1384 VALUE number = INT2NUM(upb_enum_iter_number(&it)); 1385 rb_yield_values(2, key, number); 1386 } 1387 1388 return Qnil; 1389} 1390 1391/* 1392 * call-seq: 1393 * EnumDescriptor.enummodule => module 1394 * 1395 * Returns the Ruby module corresponding to this enum type. 1396 */ 1397VALUE EnumDescriptor_enummodule(VALUE _self) { 1398 DEFINE_SELF(EnumDescriptor, self, _self); 1399 if (self->module == Qnil) { 1400 self->module = build_module_from_enumdesc(_self); 1401 } 1402 return self->module; 1403} 1404 1405// ----------------------------------------------------------------------------- 1406// MessageBuilderContext. 1407// ----------------------------------------------------------------------------- 1408 1409DEFINE_CLASS(MessageBuilderContext, 1410 "Google::Protobuf::Internal::MessageBuilderContext"); 1411 1412void MessageBuilderContext_mark(void* _self) { 1413 MessageBuilderContext* self = _self; 1414 rb_gc_mark(self->file_builder); 1415} 1416 1417void MessageBuilderContext_free(void* _self) { 1418 MessageBuilderContext* self = _self; 1419 xfree(self); 1420} 1421 1422VALUE MessageBuilderContext_alloc(VALUE klass) { 1423 MessageBuilderContext* self = ALLOC(MessageBuilderContext); 1424 VALUE ret = TypedData_Wrap_Struct( 1425 klass, &_MessageBuilderContext_type, self); 1426 self->file_builder = Qnil; 1427 return ret; 1428} 1429 1430void MessageBuilderContext_register(VALUE module) { 1431 VALUE klass = rb_define_class_under( 1432 module, "MessageBuilderContext", rb_cObject); 1433 rb_define_alloc_func(klass, MessageBuilderContext_alloc); 1434 rb_define_method(klass, "initialize", 1435 MessageBuilderContext_initialize, 2); 1436 rb_define_method(klass, "optional", MessageBuilderContext_optional, -1); 1437 rb_define_method(klass, "proto3_optional", MessageBuilderContext_proto3_optional, -1); 1438 rb_define_method(klass, "required", MessageBuilderContext_required, -1); 1439 rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1); 1440 rb_define_method(klass, "map", MessageBuilderContext_map, -1); 1441 rb_define_method(klass, "oneof", MessageBuilderContext_oneof, 1); 1442 rb_gc_register_address(&cMessageBuilderContext); 1443 cMessageBuilderContext = klass; 1444} 1445 1446/* 1447 * call-seq: 1448 * MessageBuilderContext.new(file_builder, name) => context 1449 * 1450 * Create a new message builder context around the given message descriptor and 1451 * builder context. This class is intended to serve as a DSL context to be used 1452 * with #instance_eval. 1453 */ 1454VALUE MessageBuilderContext_initialize(VALUE _self, 1455 VALUE _file_builder, 1456 VALUE name) { 1457 DEFINE_SELF(MessageBuilderContext, self, _self); 1458 FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder); 1459 google_protobuf_FileDescriptorProto* file_proto = file_builder->file_proto; 1460 1461 self->file_builder = _file_builder; 1462 self->msg_proto = google_protobuf_FileDescriptorProto_add_message_type( 1463 file_proto, file_builder->arena); 1464 1465 google_protobuf_DescriptorProto_set_name( 1466 self->msg_proto, FileBuilderContext_strdup(_file_builder, name)); 1467 1468 return Qnil; 1469} 1470 1471static void msgdef_add_field(VALUE msgbuilder_rb, upb_label_t label, VALUE name, 1472 VALUE type, VALUE number, VALUE type_class, 1473 VALUE options, int oneof_index, 1474 bool proto3_optional) { 1475 DEFINE_SELF(MessageBuilderContext, self, msgbuilder_rb); 1476 FileBuilderContext* file_context = 1477 ruby_to_FileBuilderContext(self->file_builder); 1478 google_protobuf_FieldDescriptorProto* field_proto; 1479 VALUE name_str; 1480 1481 field_proto = google_protobuf_DescriptorProto_add_field(self->msg_proto, 1482 file_context->arena); 1483 1484 Check_Type(name, T_SYMBOL); 1485 name_str = rb_id2str(SYM2ID(name)); 1486 1487 google_protobuf_FieldDescriptorProto_set_name( 1488 field_proto, FileBuilderContext_strdup(self->file_builder, name_str)); 1489 google_protobuf_FieldDescriptorProto_set_number(field_proto, NUM2INT(number)); 1490 google_protobuf_FieldDescriptorProto_set_label(field_proto, (int)label); 1491 google_protobuf_FieldDescriptorProto_set_type( 1492 field_proto, (int)ruby_to_descriptortype(type)); 1493 1494 if (proto3_optional) { 1495 google_protobuf_FieldDescriptorProto_set_proto3_optional(field_proto, true); 1496 } 1497 1498 if (type_class != Qnil) { 1499 Check_Type(type_class, T_STRING); 1500 1501 // Make it an absolute type name by prepending a dot. 1502 type_class = rb_str_append(rb_str_new2("."), type_class); 1503 google_protobuf_FieldDescriptorProto_set_type_name( 1504 field_proto, FileBuilderContext_strdup(self->file_builder, type_class)); 1505 } 1506 1507 if (options != Qnil) { 1508 Check_Type(options, T_HASH); 1509 1510 if (rb_funcall(options, rb_intern("key?"), 1, 1511 ID2SYM(rb_intern("default"))) == Qtrue) { 1512 VALUE default_value = 1513 rb_hash_lookup(options, ID2SYM(rb_intern("default"))); 1514 1515 /* Call #to_s since all defaults are strings in the descriptor. */ 1516 default_value = rb_funcall(default_value, rb_intern("to_s"), 0); 1517 1518 google_protobuf_FieldDescriptorProto_set_default_value( 1519 field_proto, 1520 FileBuilderContext_strdup(self->file_builder, default_value)); 1521 } 1522 } 1523 1524 if (oneof_index >= 0) { 1525 google_protobuf_FieldDescriptorProto_set_oneof_index(field_proto, 1526 oneof_index); 1527 } 1528} 1529 1530static VALUE make_mapentry(VALUE _message_builder, VALUE types, int argc, 1531 VALUE* argv) { 1532 DEFINE_SELF(MessageBuilderContext, message_builder, _message_builder); 1533 VALUE type_class = rb_ary_entry(types, 2); 1534 FileBuilderContext* file_context = 1535 ruby_to_FileBuilderContext(message_builder->file_builder); 1536 google_protobuf_MessageOptions* options = 1537 google_protobuf_DescriptorProto_mutable_options( 1538 message_builder->msg_proto, file_context->arena); 1539 1540 google_protobuf_MessageOptions_set_map_entry(options, true); 1541 1542 // optional <type> key = 1; 1543 rb_funcall(_message_builder, rb_intern("optional"), 3, 1544 ID2SYM(rb_intern("key")), rb_ary_entry(types, 0), INT2NUM(1)); 1545 1546 // optional <type> value = 2; 1547 if (type_class == Qnil) { 1548 rb_funcall(_message_builder, rb_intern("optional"), 3, 1549 ID2SYM(rb_intern("value")), rb_ary_entry(types, 1), INT2NUM(2)); 1550 } else { 1551 rb_funcall(_message_builder, rb_intern("optional"), 4, 1552 ID2SYM(rb_intern("value")), rb_ary_entry(types, 1), INT2NUM(2), 1553 type_class); 1554 } 1555 1556 return Qnil; 1557} 1558 1559/* 1560 * call-seq: 1561 * MessageBuilderContext.optional(name, type, number, type_class = nil, 1562 * options = nil) 1563 * 1564 * Defines a new optional field on this message type with the given type, tag 1565 * number, and type class (for message and enum fields). The type must be a Ruby 1566 * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a 1567 * string, if present (as accepted by FieldDescriptor#submsg_name=). 1568 */ 1569VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) { 1570 VALUE name, type, number; 1571 VALUE type_class, options = Qnil; 1572 1573 rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options); 1574 1575 // Allow passing (name, type, number, options) or 1576 // (name, type, number, type_class, options) 1577 if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) { 1578 options = type_class; 1579 type_class = Qnil; 1580 } 1581 1582 msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class, 1583 options, -1, false); 1584 1585 return Qnil; 1586} 1587 1588/* 1589 * call-seq: 1590 * MessageBuilderContext.proto3_optional(name, type, number, 1591 * type_class = nil, options = nil) 1592 * 1593 * Defines a true proto3 optional field (that tracks presence) on this message 1594 * type with the given type, tag number, and type class (for message and enum 1595 * fields). The type must be a Ruby symbol (as accepted by 1596 * FieldDescriptor#type=) and the type_class must be a string, if present (as 1597 * accepted by FieldDescriptor#submsg_name=). 1598 */ 1599VALUE MessageBuilderContext_proto3_optional(int argc, VALUE* argv, 1600 VALUE _self) { 1601 VALUE name, type, number; 1602 VALUE type_class, options = Qnil; 1603 1604 rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options); 1605 1606 // Allow passing (name, type, number, options) or 1607 // (name, type, number, type_class, options) 1608 if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) { 1609 options = type_class; 1610 type_class = Qnil; 1611 } 1612 1613 msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class, 1614 options, -1, true); 1615 1616 return Qnil; 1617} 1618 1619/* 1620 * call-seq: 1621 * MessageBuilderContext.required(name, type, number, type_class = nil, 1622 * options = nil) 1623 * 1624 * Defines a new required field on this message type with the given type, tag 1625 * number, and type class (for message and enum fields). The type must be a Ruby 1626 * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a 1627 * string, if present (as accepted by FieldDescriptor#submsg_name=). 1628 * 1629 * Proto3 does not have required fields, but this method exists for 1630 * completeness. Any attempt to add a message type with required fields to a 1631 * pool will currently result in an error. 1632 */ 1633VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) { 1634 VALUE name, type, number; 1635 VALUE type_class, options = Qnil; 1636 1637 rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options); 1638 1639 // Allow passing (name, type, number, options) or 1640 // (name, type, number, type_class, options) 1641 if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) { 1642 options = type_class; 1643 type_class = Qnil; 1644 } 1645 1646 msgdef_add_field(_self, UPB_LABEL_REQUIRED, name, type, number, type_class, 1647 options, -1, false); 1648 1649 return Qnil; 1650} 1651 1652/* 1653 * call-seq: 1654 * MessageBuilderContext.repeated(name, type, number, type_class = nil) 1655 * 1656 * Defines a new repeated field on this message type with the given type, tag 1657 * number, and type class (for message and enum fields). The type must be a Ruby 1658 * symbol (as accepted by FieldDescriptor#type=) and the type_class must be a 1659 * string, if present (as accepted by FieldDescriptor#submsg_name=). 1660 */ 1661VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) { 1662 VALUE name, type, number, type_class; 1663 1664 if (argc < 3) { 1665 rb_raise(rb_eArgError, "Expected at least 3 arguments."); 1666 } 1667 name = argv[0]; 1668 type = argv[1]; 1669 number = argv[2]; 1670 type_class = (argc > 3) ? argv[3] : Qnil; 1671 1672 msgdef_add_field(_self, UPB_LABEL_REPEATED, name, type, number, type_class, 1673 Qnil, -1, false); 1674 1675 return Qnil; 1676} 1677 1678/* 1679 * call-seq: 1680 * MessageBuilderContext.map(name, key_type, value_type, number, 1681 * value_type_class = nil) 1682 * 1683 * Defines a new map field on this message type with the given key and value 1684 * types, tag number, and type class (for message and enum value types). The key 1685 * type must be :int32/:uint32/:int64/:uint64, :bool, or :string. The value type 1686 * type must be a Ruby symbol (as accepted by FieldDescriptor#type=) and the 1687 * type_class must be a string, if present (as accepted by 1688 * FieldDescriptor#submsg_name=). 1689 */ 1690VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) { 1691 DEFINE_SELF(MessageBuilderContext, self, _self); 1692 VALUE name, key_type, value_type, number, type_class; 1693 VALUE mapentry_desc_name; 1694 FileBuilderContext* file_builder; 1695 upb_strview msg_name; 1696 1697 if (argc < 4) { 1698 rb_raise(rb_eArgError, "Expected at least 4 arguments."); 1699 } 1700 name = argv[0]; 1701 key_type = argv[1]; 1702 value_type = argv[2]; 1703 number = argv[3]; 1704 type_class = (argc > 4) ? argv[4] : Qnil; 1705 1706 // Validate the key type. We can't accept enums, messages, or floats/doubles 1707 // as map keys. (We exclude these explicitly, and the field-descriptor setter 1708 // below then ensures that the type is one of the remaining valid options.) 1709 if (SYM2ID(key_type) == rb_intern("float") || 1710 SYM2ID(key_type) == rb_intern("double") || 1711 SYM2ID(key_type) == rb_intern("enum") || 1712 SYM2ID(key_type) == rb_intern("message")) { 1713 rb_raise(rb_eArgError, 1714 "Cannot add a map field with a float, double, enum, or message " 1715 "type."); 1716 } 1717 1718 file_builder = ruby_to_FileBuilderContext(self->file_builder); 1719 1720 // TODO(haberman): remove this restriction, maps are supported in proto2. 1721 if (upb_strview_eql( 1722 google_protobuf_FileDescriptorProto_syntax(file_builder->file_proto), 1723 upb_strview_makez("proto2"))) { 1724 rb_raise(rb_eArgError, 1725 "Cannot add a native map field using proto2 syntax."); 1726 } 1727 1728 // Create a new message descriptor for the map entry message, and create a 1729 // repeated submessage field here with that type. 1730 msg_name = google_protobuf_DescriptorProto_name(self->msg_proto); 1731 mapentry_desc_name = rb_str_new(msg_name.data, msg_name.size); 1732 mapentry_desc_name = rb_str_cat2(mapentry_desc_name, "_MapEntry_"); 1733 mapentry_desc_name = 1734 rb_str_cat2(mapentry_desc_name, rb_id2name(SYM2ID(name))); 1735 1736 { 1737 // message <msgname>_MapEntry_ { /* ... */ } 1738 VALUE args[1] = {mapentry_desc_name}; 1739 VALUE types = rb_ary_new3(3, key_type, value_type, type_class); 1740 rb_block_call(self->file_builder, rb_intern("add_message"), 1, args, 1741 make_mapentry, types); 1742 } 1743 1744 // If this file is in a package, we need to qualify the map entry type. 1745 if (google_protobuf_FileDescriptorProto_has_package(file_builder->file_proto)) { 1746 upb_strview package_view = 1747 google_protobuf_FileDescriptorProto_package(file_builder->file_proto); 1748 VALUE package = rb_str_new(package_view.data, package_view.size); 1749 package = rb_str_cat2(package, "."); 1750 mapentry_desc_name = rb_str_concat(package, mapentry_desc_name); 1751 } 1752 1753 // repeated MapEntry <name> = <number>; 1754 rb_funcall(_self, rb_intern("repeated"), 4, name, 1755 ID2SYM(rb_intern("message")), number, mapentry_desc_name); 1756 1757 return Qnil; 1758} 1759 1760/* 1761 * call-seq: 1762 * MessageBuilderContext.oneof(name, &block) => nil 1763 * 1764 * Creates a new OneofDescriptor with the given name, creates a 1765 * OneofBuilderContext attached to that OneofDescriptor, evaluates the given 1766 * block in the context of that OneofBuilderContext with #instance_eval, and 1767 * then adds the oneof to the message. 1768 * 1769 * This is the recommended, idiomatic way to build oneof definitions. 1770 */ 1771VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) { 1772 DEFINE_SELF(MessageBuilderContext, self, _self); 1773 size_t oneof_count; 1774 FileBuilderContext* file_context = 1775 ruby_to_FileBuilderContext(self->file_builder); 1776 google_protobuf_OneofDescriptorProto* oneof_proto; 1777 1778 // Existing oneof_count becomes oneof_index. 1779 google_protobuf_DescriptorProto_oneof_decl(self->msg_proto, &oneof_count); 1780 1781 // Create oneof_proto and set its name. 1782 oneof_proto = google_protobuf_DescriptorProto_add_oneof_decl( 1783 self->msg_proto, file_context->arena); 1784 google_protobuf_OneofDescriptorProto_set_name( 1785 oneof_proto, FileBuilderContext_strdup_sym(self->file_builder, name)); 1786 1787 // Evaluate the block with the builder as argument. 1788 { 1789 VALUE args[2] = { INT2NUM(oneof_count), _self }; 1790 VALUE ctx = rb_class_new_instance(2, args, cOneofBuilderContext); 1791 VALUE block = rb_block_proc(); 1792 rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block); 1793 } 1794 1795 return Qnil; 1796} 1797 1798void MessageBuilderContext_add_synthetic_oneofs(VALUE _self) { 1799 DEFINE_SELF(MessageBuilderContext, self, _self); 1800 FileBuilderContext* file_context = 1801 ruby_to_FileBuilderContext(self->file_builder); 1802 size_t field_count, oneof_count; 1803 google_protobuf_FieldDescriptorProto** fields = 1804 google_protobuf_DescriptorProto_mutable_field(self->msg_proto, &field_count); 1805 const google_protobuf_OneofDescriptorProto*const* oneofs = 1806 google_protobuf_DescriptorProto_oneof_decl(self->msg_proto, &oneof_count); 1807 VALUE names = rb_hash_new(); 1808 VALUE underscore = rb_str_new2("_"); 1809 size_t i; 1810 1811 // We have to build a set of all names, to ensure that synthetic oneofs are 1812 // not creating conflicts. 1813 for (i = 0; i < field_count; i++) { 1814 upb_strview name = google_protobuf_FieldDescriptorProto_name(fields[i]); 1815 rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue); 1816 } 1817 for (i = 0; i < oneof_count; i++) { 1818 upb_strview name = google_protobuf_OneofDescriptorProto_name(oneofs[i]); 1819 rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue); 1820 } 1821 1822 for (i = 0; i < field_count; i++) { 1823 google_protobuf_OneofDescriptorProto* oneof_proto; 1824 VALUE oneof_name; 1825 upb_strview field_name; 1826 1827 if (!google_protobuf_FieldDescriptorProto_proto3_optional(fields[i])) { 1828 continue; 1829 } 1830 1831 // Prepend '_' until we are no longer conflicting. 1832 field_name = google_protobuf_FieldDescriptorProto_name(fields[i]); 1833 oneof_name = rb_str_new(field_name.data, field_name.size); 1834 while (rb_hash_lookup(names, oneof_name) != Qnil) { 1835 oneof_name = rb_str_plus(underscore, oneof_name); 1836 } 1837 1838 rb_hash_aset(names, oneof_name, Qtrue); 1839 google_protobuf_FieldDescriptorProto_set_oneof_index(fields[i], 1840 oneof_count++); 1841 oneof_proto = google_protobuf_DescriptorProto_add_oneof_decl( 1842 self->msg_proto, file_context->arena); 1843 google_protobuf_OneofDescriptorProto_set_name( 1844 oneof_proto, FileBuilderContext_strdup(self->file_builder, oneof_name)); 1845 } 1846} 1847 1848// ----------------------------------------------------------------------------- 1849// OneofBuilderContext. 1850// ----------------------------------------------------------------------------- 1851 1852DEFINE_CLASS(OneofBuilderContext, 1853 "Google::Protobuf::Internal::OneofBuilderContext"); 1854 1855void OneofBuilderContext_mark(void* _self) { 1856 OneofBuilderContext* self = _self; 1857 rb_gc_mark(self->message_builder); 1858} 1859 1860void OneofBuilderContext_free(void* _self) { 1861 xfree(_self); 1862} 1863 1864VALUE OneofBuilderContext_alloc(VALUE klass) { 1865 OneofBuilderContext* self = ALLOC(OneofBuilderContext); 1866 VALUE ret = TypedData_Wrap_Struct( 1867 klass, &_OneofBuilderContext_type, self); 1868 self->oneof_index = 0; 1869 self->message_builder = Qnil; 1870 return ret; 1871} 1872 1873void OneofBuilderContext_register(VALUE module) { 1874 VALUE klass = rb_define_class_under( 1875 module, "OneofBuilderContext", rb_cObject); 1876 rb_define_alloc_func(klass, OneofBuilderContext_alloc); 1877 rb_define_method(klass, "initialize", 1878 OneofBuilderContext_initialize, 2); 1879 rb_define_method(klass, "optional", OneofBuilderContext_optional, -1); 1880 rb_gc_register_address(&cOneofBuilderContext); 1881 cOneofBuilderContext = klass; 1882} 1883 1884/* 1885 * call-seq: 1886 * OneofBuilderContext.new(oneof_index, message_builder) => context 1887 * 1888 * Create a new oneof builder context around the given oneof descriptor and 1889 * builder context. This class is intended to serve as a DSL context to be used 1890 * with #instance_eval. 1891 */ 1892VALUE OneofBuilderContext_initialize(VALUE _self, 1893 VALUE oneof_index, 1894 VALUE message_builder) { 1895 DEFINE_SELF(OneofBuilderContext, self, _self); 1896 self->oneof_index = NUM2INT(oneof_index); 1897 self->message_builder = message_builder; 1898 return Qnil; 1899} 1900 1901/* 1902 * call-seq: 1903 * OneofBuilderContext.optional(name, type, number, type_class = nil, 1904 * default_value = nil) 1905 * 1906 * Defines a new optional field in this oneof with the given type, tag number, 1907 * and type class (for message and enum fields). The type must be a Ruby symbol 1908 * (as accepted by FieldDescriptor#type=) and the type_class must be a string, 1909 * if present (as accepted by FieldDescriptor#submsg_name=). 1910 */ 1911VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) { 1912 DEFINE_SELF(OneofBuilderContext, self, _self); 1913 VALUE name, type, number; 1914 VALUE type_class, options = Qnil; 1915 1916 rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options); 1917 1918 msgdef_add_field(self->message_builder, UPB_LABEL_OPTIONAL, name, type, 1919 number, type_class, options, self->oneof_index, false); 1920 1921 return Qnil; 1922} 1923 1924// ----------------------------------------------------------------------------- 1925// EnumBuilderContext. 1926// ----------------------------------------------------------------------------- 1927 1928DEFINE_CLASS(EnumBuilderContext, 1929 "Google::Protobuf::Internal::EnumBuilderContext"); 1930 1931void EnumBuilderContext_mark(void* _self) { 1932 EnumBuilderContext* self = _self; 1933 rb_gc_mark(self->file_builder); 1934} 1935 1936void EnumBuilderContext_free(void* _self) { 1937 xfree(_self); 1938} 1939 1940VALUE EnumBuilderContext_alloc(VALUE klass) { 1941 EnumBuilderContext* self = ALLOC(EnumBuilderContext); 1942 VALUE ret = TypedData_Wrap_Struct( 1943 klass, &_EnumBuilderContext_type, self); 1944 self->enum_proto = NULL; 1945 self->file_builder = Qnil; 1946 return ret; 1947} 1948 1949void EnumBuilderContext_register(VALUE module) { 1950 VALUE klass = rb_define_class_under( 1951 module, "EnumBuilderContext", rb_cObject); 1952 rb_define_alloc_func(klass, EnumBuilderContext_alloc); 1953 rb_define_method(klass, "initialize", EnumBuilderContext_initialize, 2); 1954 rb_define_method(klass, "value", EnumBuilderContext_value, 2); 1955 rb_gc_register_address(&cEnumBuilderContext); 1956 cEnumBuilderContext = klass; 1957} 1958 1959/* 1960 * call-seq: 1961 * EnumBuilderContext.new(file_builder) => context 1962 * 1963 * Create a new builder context around the given enum descriptor. This class is 1964 * intended to serve as a DSL context to be used with #instance_eval. 1965 */ 1966VALUE EnumBuilderContext_initialize(VALUE _self, VALUE _file_builder, 1967 VALUE name) { 1968 DEFINE_SELF(EnumBuilderContext, self, _self); 1969 FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder); 1970 google_protobuf_FileDescriptorProto* file_proto = file_builder->file_proto; 1971 1972 self->file_builder = _file_builder; 1973 self->enum_proto = google_protobuf_FileDescriptorProto_add_enum_type( 1974 file_proto, file_builder->arena); 1975 1976 google_protobuf_EnumDescriptorProto_set_name( 1977 self->enum_proto, FileBuilderContext_strdup(_file_builder, name)); 1978 1979 return Qnil; 1980} 1981 1982/* 1983 * call-seq: 1984 * EnumBuilder.add_value(name, number) 1985 * 1986 * Adds the given name => number mapping to the enum type. Name must be a Ruby 1987 * symbol. 1988 */ 1989VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) { 1990 DEFINE_SELF(EnumBuilderContext, self, _self); 1991 FileBuilderContext* file_builder = 1992 ruby_to_FileBuilderContext(self->file_builder); 1993 google_protobuf_EnumValueDescriptorProto* enum_value; 1994 1995 enum_value = google_protobuf_EnumDescriptorProto_add_value( 1996 self->enum_proto, file_builder->arena); 1997 1998 google_protobuf_EnumValueDescriptorProto_set_name( 1999 enum_value, FileBuilderContext_strdup_sym(self->file_builder, name)); 2000 google_protobuf_EnumValueDescriptorProto_set_number(enum_value, 2001 NUM2INT(number)); 2002 2003 return Qnil; 2004} 2005 2006 2007// ----------------------------------------------------------------------------- 2008// FileBuilderContext. 2009// ----------------------------------------------------------------------------- 2010 2011DEFINE_CLASS(FileBuilderContext, 2012 "Google::Protobuf::Internal::FileBuilderContext"); 2013 2014void FileBuilderContext_mark(void* _self) { 2015 FileBuilderContext* self = _self; 2016 rb_gc_mark(self->descriptor_pool); 2017} 2018 2019void FileBuilderContext_free(void* _self) { 2020 FileBuilderContext* self = _self; 2021 upb_arena_free(self->arena); 2022 xfree(self); 2023} 2024 2025upb_strview FileBuilderContext_strdup2(VALUE _self, const char *str) { 2026 DEFINE_SELF(FileBuilderContext, self, _self); 2027 upb_strview ret; 2028 char *data; 2029 2030 ret.size = strlen(str); 2031 data = upb_malloc(upb_arena_alloc(self->arena), ret.size + 1); 2032 ret.data = data; 2033 memcpy(data, str, ret.size); 2034 /* Null-terminate required by rewrite_enum_defaults() above. */ 2035 data[ret.size] = '\0'; 2036 return ret; 2037} 2038 2039upb_strview FileBuilderContext_strdup(VALUE _self, VALUE rb_str) { 2040 return FileBuilderContext_strdup2(_self, get_str(rb_str)); 2041} 2042 2043upb_strview FileBuilderContext_strdup_sym(VALUE _self, VALUE rb_sym) { 2044 Check_Type(rb_sym, T_SYMBOL); 2045 return FileBuilderContext_strdup(_self, rb_id2str(SYM2ID(rb_sym))); 2046} 2047 2048VALUE FileBuilderContext_alloc(VALUE klass) { 2049 FileBuilderContext* self = ALLOC(FileBuilderContext); 2050 VALUE ret = TypedData_Wrap_Struct(klass, &_FileBuilderContext_type, self); 2051 self->arena = upb_arena_new(); 2052 self->file_proto = google_protobuf_FileDescriptorProto_new(self->arena); 2053 self->descriptor_pool = Qnil; 2054 return ret; 2055} 2056 2057void FileBuilderContext_register(VALUE module) { 2058 VALUE klass = rb_define_class_under(module, "FileBuilderContext", rb_cObject); 2059 rb_define_alloc_func(klass, FileBuilderContext_alloc); 2060 rb_define_method(klass, "initialize", FileBuilderContext_initialize, 3); 2061 rb_define_method(klass, "add_message", FileBuilderContext_add_message, 1); 2062 rb_define_method(klass, "add_enum", FileBuilderContext_add_enum, 1); 2063 rb_gc_register_address(&cFileBuilderContext); 2064 cFileBuilderContext = klass; 2065} 2066 2067/* 2068 * call-seq: 2069 * FileBuilderContext.new(descriptor_pool) => context 2070 * 2071 * Create a new file builder context for the given file descriptor and 2072 * builder context. This class is intended to serve as a DSL context to be used 2073 * with #instance_eval. 2074 */ 2075VALUE FileBuilderContext_initialize(VALUE _self, VALUE descriptor_pool, 2076 VALUE name, VALUE options) { 2077 DEFINE_SELF(FileBuilderContext, self, _self); 2078 self->descriptor_pool = descriptor_pool; 2079 2080 google_protobuf_FileDescriptorProto_set_name( 2081 self->file_proto, FileBuilderContext_strdup(_self, name)); 2082 2083 // Default syntax for Ruby is proto3. 2084 google_protobuf_FileDescriptorProto_set_syntax( 2085 self->file_proto, 2086 FileBuilderContext_strdup(_self, rb_str_new2("proto3"))); 2087 2088 if (options != Qnil) { 2089 VALUE syntax; 2090 2091 Check_Type(options, T_HASH); 2092 syntax = rb_hash_lookup2(options, ID2SYM(rb_intern("syntax")), Qnil); 2093 2094 if (syntax != Qnil) { 2095 VALUE syntax_str; 2096 2097 Check_Type(syntax, T_SYMBOL); 2098 syntax_str = rb_id2str(SYM2ID(syntax)); 2099 google_protobuf_FileDescriptorProto_set_syntax( 2100 self->file_proto, FileBuilderContext_strdup(_self, syntax_str)); 2101 } 2102 } 2103 2104 return Qnil; 2105} 2106 2107/* 2108 * call-seq: 2109 * FileBuilderContext.add_message(name, &block) 2110 * 2111 * Creates a new, empty descriptor with the given name, and invokes the block in 2112 * the context of a MessageBuilderContext on that descriptor. The block can then 2113 * call, e.g., MessageBuilderContext#optional and MessageBuilderContext#repeated 2114 * methods to define the message fields. 2115 * 2116 * This is the recommended, idiomatic way to build message definitions. 2117 */ 2118VALUE FileBuilderContext_add_message(VALUE _self, VALUE name) { 2119 VALUE args[2] = { _self, name }; 2120 VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext); 2121 VALUE block = rb_block_proc(); 2122 rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block); 2123 MessageBuilderContext_add_synthetic_oneofs(ctx); 2124 return Qnil; 2125} 2126 2127/* 2128 * call-seq: 2129 * FileBuilderContext.add_enum(name, &block) 2130 * 2131 * Creates a new, empty enum descriptor with the given name, and invokes the 2132 * block in the context of an EnumBuilderContext on that descriptor. The block 2133 * can then call EnumBuilderContext#add_value to define the enum values. 2134 * 2135 * This is the recommended, idiomatic way to build enum definitions. 2136 */ 2137VALUE FileBuilderContext_add_enum(VALUE _self, VALUE name) { 2138 VALUE args[2] = { _self, name }; 2139 VALUE ctx = rb_class_new_instance(2, args, cEnumBuilderContext); 2140 VALUE block = rb_block_proc(); 2141 rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block); 2142 return Qnil; 2143} 2144 2145void FileBuilderContext_build(VALUE _self) { 2146 DEFINE_SELF(FileBuilderContext, self, _self); 2147 DescriptorPool* pool = ruby_to_DescriptorPool(self->descriptor_pool); 2148 upb_status status; 2149 2150 rewrite_enum_defaults(pool->symtab, self->file_proto); 2151 rewrite_names(_self, self->file_proto); 2152 2153 upb_status_clear(&status); 2154 if (!upb_symtab_addfile(pool->symtab, self->file_proto, &status)) { 2155 rb_raise(cTypeError, "Unable to add defs to DescriptorPool: %s", 2156 upb_status_errmsg(&status)); 2157 } 2158} 2159 2160// ----------------------------------------------------------------------------- 2161// Builder. 2162// ----------------------------------------------------------------------------- 2163 2164DEFINE_CLASS(Builder, "Google::Protobuf::Internal::Builder"); 2165 2166void Builder_mark(void* _self) { 2167 Builder* self = _self; 2168 rb_gc_mark(self->descriptor_pool); 2169 rb_gc_mark(self->default_file_builder); 2170} 2171 2172void Builder_free(void* _self) { 2173 xfree(_self); 2174} 2175 2176VALUE Builder_alloc(VALUE klass) { 2177 Builder* self = ALLOC(Builder); 2178 VALUE ret = TypedData_Wrap_Struct( 2179 klass, &_Builder_type, self); 2180 self->descriptor_pool = Qnil; 2181 self->default_file_builder = Qnil; 2182 return ret; 2183} 2184 2185void Builder_register(VALUE module) { 2186 VALUE klass = rb_define_class_under(module, "Builder", rb_cObject); 2187 rb_define_alloc_func(klass, Builder_alloc); 2188 rb_define_method(klass, "initialize", Builder_initialize, 1); 2189 rb_define_method(klass, "add_file", Builder_add_file, -1); 2190 rb_define_method(klass, "add_message", Builder_add_message, 1); 2191 rb_define_method(klass, "add_enum", Builder_add_enum, 1); 2192 rb_gc_register_address(&cBuilder); 2193 cBuilder = klass; 2194} 2195 2196/* 2197 * call-seq: 2198 * Builder.new(descriptor_pool) => builder 2199 * 2200 * Creates a new Builder. A Builder can accumulate a set of new message and enum 2201 * descriptors and atomically register them into a pool in a way that allows for 2202 * (co)recursive type references. 2203 */ 2204VALUE Builder_initialize(VALUE _self, VALUE pool) { 2205 DEFINE_SELF(Builder, self, _self); 2206 self->descriptor_pool = pool; 2207 self->default_file_builder = Qnil; // Created lazily if needed. 2208 return Qnil; 2209} 2210 2211/* 2212 * call-seq: 2213 * Builder.add_file(name, options = nil, &block) 2214 * 2215 * Creates a new, file descriptor with the given name and options and invokes 2216 * the block in the context of a FileBuilderContext on that descriptor. The 2217 * block can then call FileBuilderContext#add_message or 2218 * FileBuilderContext#add_enum to define new messages or enums, respectively. 2219 * 2220 * This is the recommended, idiomatic way to build file descriptors. 2221 */ 2222VALUE Builder_add_file(int argc, VALUE* argv, VALUE _self) { 2223 DEFINE_SELF(Builder, self, _self); 2224 VALUE name, options; 2225 VALUE ctx; 2226 VALUE block; 2227 2228 rb_scan_args(argc, argv, "11", &name, &options); 2229 2230 { 2231 VALUE args[3] = { self->descriptor_pool, name, options }; 2232 ctx = rb_class_new_instance(3, args, cFileBuilderContext); 2233 } 2234 2235 block = rb_block_proc(); 2236 rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block); 2237 FileBuilderContext_build(ctx); 2238 2239 return Qnil; 2240} 2241 2242static VALUE Builder_get_default_file(VALUE _self) { 2243 DEFINE_SELF(Builder, self, _self); 2244 2245 /* Lazily create only if legacy builder-level methods are called. */ 2246 if (self->default_file_builder == Qnil) { 2247 VALUE name = rb_str_new2("ruby_default_file.proto"); 2248 VALUE args [3] = { self->descriptor_pool, name, rb_hash_new() }; 2249 self->default_file_builder = 2250 rb_class_new_instance(3, args, cFileBuilderContext); 2251 } 2252 2253 return self->default_file_builder; 2254} 2255 2256/* 2257 * call-seq: 2258 * Builder.add_message(name, &block) 2259 * 2260 * Old and deprecated way to create a new descriptor. 2261 * See FileBuilderContext.add_message for the recommended way. 2262 * 2263 * Exists for backwards compatibility to allow building descriptor pool for 2264 * files generated by protoc which don't add messages within "add_file" block. 2265 * Descriptors created this way get assigned to a default empty FileDescriptor. 2266 */ 2267VALUE Builder_add_message(VALUE _self, VALUE name) { 2268 VALUE file_builder = Builder_get_default_file(_self); 2269 rb_funcall_with_block(file_builder, rb_intern("add_message"), 1, &name, 2270 rb_block_proc()); 2271 return Qnil; 2272} 2273 2274/* 2275 * call-seq: 2276 * Builder.add_enum(name, &block) 2277 * 2278 * Old and deprecated way to create a new enum descriptor. 2279 * See FileBuilderContext.add_enum for the recommended way. 2280 * 2281 * Exists for backwards compatibility to allow building descriptor pool for 2282 * files generated by protoc which don't add enums within "add_file" block. 2283 * Enum descriptors created this way get assigned to a default empty 2284 * FileDescriptor. 2285 */ 2286VALUE Builder_add_enum(VALUE _self, VALUE name) { 2287 VALUE file_builder = Builder_get_default_file(_self); 2288 rb_funcall_with_block(file_builder, rb_intern("add_enum"), 1, &name, 2289 rb_block_proc()); 2290 return Qnil; 2291} 2292 2293/* This method is hidden from Ruby, and only called directly from 2294 * DescriptorPool_build(). */ 2295VALUE Builder_build(VALUE _self) { 2296 DEFINE_SELF(Builder, self, _self); 2297 2298 if (self->default_file_builder != Qnil) { 2299 FileBuilderContext_build(self->default_file_builder); 2300 self->default_file_builder = Qnil; 2301 } 2302 2303 return Qnil; 2304} 2305 2306static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) { 2307 DEFINE_SELF(DescriptorPool, descriptor_pool, _descriptor_pool); 2308 VALUE key = ULL2NUM((intptr_t)ptr); 2309 VALUE def; 2310 2311 def = rb_hash_aref(descriptor_pool->def_to_descriptor, key); 2312 2313 if (ptr == NULL) { 2314 return Qnil; 2315 } 2316 2317 if (def == Qnil) { 2318 // Lazily create wrapper object. 2319 VALUE args[3] = { c_only_cookie, _descriptor_pool, key }; 2320 def = rb_class_new_instance(3, args, klass); 2321 rb_hash_aset(descriptor_pool->def_to_descriptor, key, def); 2322 2323 // For message defs, we now eagerly get/create descriptors for all 2324 // submessages. We will need these anyway to parse or serialize this 2325 // message type. But more importantly, we must do this now so that 2326 // add_handlers_for_message() (which calls get_msgdef_obj()) does *not* 2327 // need to create a Ruby object or insert into a Ruby Hash. We need to 2328 // avoid triggering GC, which can switch Ruby threads and re-enter our 2329 // C extension from a different thread. This wreaks havoc on our state 2330 // if we were in the middle of building handlers. 2331 if (klass == cDescriptor) { 2332 const upb_msgdef *m = ptr; 2333 upb_msg_field_iter it; 2334 for (upb_msg_field_begin(&it, m); 2335 !upb_msg_field_done(&it); 2336 upb_msg_field_next(&it)) { 2337 const upb_fielddef* f = upb_msg_iter_field(&it); 2338 if (upb_fielddef_issubmsg(f)) { 2339 get_msgdef_obj(_descriptor_pool, upb_fielddef_msgsubdef(f)); 2340 } 2341 } 2342 } 2343 } 2344 2345 return def; 2346} 2347 2348VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def) { 2349 return get_def_obj(descriptor_pool, def, cDescriptor); 2350} 2351 2352VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_enumdef* def) { 2353 return get_def_obj(descriptor_pool, def, cEnumDescriptor); 2354} 2355 2356VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_fielddef* def) { 2357 return get_def_obj(descriptor_pool, def, cFieldDescriptor); 2358} 2359 2360VALUE get_filedef_obj(VALUE descriptor_pool, const upb_filedef* def) { 2361 return get_def_obj(descriptor_pool, def, cFileDescriptor); 2362} 2363 2364VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def) { 2365 return get_def_obj(descriptor_pool, def, cOneofDescriptor); 2366} 2367