@@ -44,7 +44,7 @@ static VALUE rb_str_maybe_null(const char* s) {
44
44
}
45
45
return rb_str_new2 (s );
46
46
}
47
-
47
+ static ID options_instancevar_interned ;
48
48
// -----------------------------------------------------------------------------
49
49
// DescriptorPool.
50
50
// -----------------------------------------------------------------------------
@@ -192,6 +192,7 @@ static void DescriptorPool_register(VALUE module) {
192
192
193
193
rb_gc_register_address (& generated_pool );
194
194
generated_pool = rb_class_new_instance (0 , NULL , klass );
195
+ options_instancevar_interned = rb_intern ("options" );
195
196
}
196
197
197
198
// -----------------------------------------------------------------------------
@@ -226,6 +227,35 @@ static Descriptor* ruby_to_Descriptor(VALUE val) {
226
227
return ret ;
227
228
}
228
229
230
+ // Decode and return a frozen instance of a Descriptor Option for the given pool
231
+ static VALUE decode_options (VALUE self , const char * option_type , int size ,
232
+ const char * bytes , VALUE descriptor_pool ) {
233
+ VALUE options_rb = rb_ivar_get (self , options_instancevar_interned );
234
+ if (options_rb != Qnil ) {
235
+ return options_rb ;
236
+ }
237
+
238
+ static const char * prefix = "google.protobuf." ;
239
+ char fullname
240
+ [/*strlen(prefix)*/ 16 +
241
+ /*strln(longest option type supported e.g. "MessageOptions")*/ 14 +
242
+ /*null terminator*/ 1 ];
243
+
244
+ snprintf (fullname , sizeof (fullname ), "%s%s" , prefix , option_type );
245
+ const upb_MessageDef * msgdef = upb_DefPool_FindMessageByName (
246
+ ruby_to_DescriptorPool (descriptor_pool )-> symtab , fullname );
247
+ if (!msgdef ) {
248
+ rb_raise (rb_eRuntimeError , "Cannot find %s in DescriptorPool" , option_type );
249
+ }
250
+
251
+ VALUE desc_rb = get_msgdef_obj (descriptor_pool , msgdef );
252
+ const Descriptor * desc = ruby_to_Descriptor (desc_rb );
253
+
254
+ options_rb = Message_decode_bytes (size , bytes , 0 , desc -> klass , true);
255
+ rb_ivar_set (self , options_instancevar_interned , options_rb );
256
+ return options_rb ;
257
+ }
258
+
229
259
/*
230
260
* call-seq:
231
261
* Descriptor.new => descriptor
@@ -374,6 +404,26 @@ static VALUE Descriptor_msgclass(VALUE _self) {
374
404
return self -> klass ;
375
405
}
376
406
407
+ /*
408
+ * call-seq:
409
+ * Descriptor.options => options
410
+ *
411
+ * Returns the `MessageOptions` for this `Descriptor`.
412
+ */
413
+ static VALUE Descriptor_options (VALUE _self ) {
414
+ Descriptor * self = ruby_to_Descriptor (_self );
415
+ const google_protobuf_MessageOptions * opts =
416
+ upb_MessageDef_Options (self -> msgdef );
417
+ upb_Arena * arena = upb_Arena_New ();
418
+ size_t size ;
419
+ char * serialized =
420
+ google_protobuf_MessageOptions_serialize (opts , arena , & size );
421
+ VALUE message_options = decode_options (_self , "MessageOptions" , size ,
422
+ serialized , self -> descriptor_pool );
423
+ upb_Arena_Free (arena );
424
+ return message_options ;
425
+ }
426
+
377
427
static void Descriptor_register (VALUE module ) {
378
428
VALUE klass = rb_define_class_under (module , "Descriptor" , rb_cObject );
379
429
rb_define_alloc_func (klass , Descriptor_alloc );
@@ -385,6 +435,7 @@ static void Descriptor_register(VALUE module) {
385
435
rb_define_method (klass , "msgclass" , Descriptor_msgclass , 0 );
386
436
rb_define_method (klass , "name" , Descriptor_name , 0 );
387
437
rb_define_method (klass , "file_descriptor" , Descriptor_file_descriptor , 0 );
438
+ rb_define_method (klass , "options" , Descriptor_options , 0 );
388
439
rb_include_module (klass , rb_mEnumerable );
389
440
rb_gc_register_address (& cDescriptor );
390
441
cDescriptor = klass ;
@@ -484,12 +535,31 @@ static VALUE FileDescriptor_syntax(VALUE _self) {
484
535
}
485
536
}
486
537
538
+ /*
539
+ * call-seq:
540
+ * FileDescriptor.options => options
541
+ *
542
+ * Returns the `FileOptions` for this `FileDescriptor`.
543
+ */
544
+ static VALUE FileDescriptor_options (VALUE _self ) {
545
+ FileDescriptor * self = ruby_to_FileDescriptor (_self );
546
+ const google_protobuf_FileOptions * opts = upb_FileDef_Options (self -> filedef );
547
+ upb_Arena * arena = upb_Arena_New ();
548
+ size_t size ;
549
+ char * serialized = google_protobuf_FileOptions_serialize (opts , arena , & size );
550
+ VALUE file_options = decode_options (_self , "FileOptions" , size , serialized ,
551
+ self -> descriptor_pool );
552
+ upb_Arena_Free (arena );
553
+ return file_options ;
554
+ }
555
+
487
556
static void FileDescriptor_register (VALUE module ) {
488
557
VALUE klass = rb_define_class_under (module , "FileDescriptor" , rb_cObject );
489
558
rb_define_alloc_func (klass , FileDescriptor_alloc );
490
559
rb_define_method (klass , "initialize" , FileDescriptor_initialize , 3 );
491
560
rb_define_method (klass , "name" , FileDescriptor_name , 0 );
492
561
rb_define_method (klass , "syntax" , FileDescriptor_syntax , 0 );
562
+ rb_define_method (klass , "options" , FileDescriptor_options , 0 );
493
563
rb_gc_register_address (& cFileDescriptor );
494
564
cFileDescriptor = klass ;
495
565
}
@@ -540,7 +610,7 @@ static VALUE FieldDescriptor_alloc(VALUE klass) {
540
610
541
611
/*
542
612
* call-seq:
543
- * EnumDescriptor .new(c_only_cookie, pool, ptr) => EnumDescriptor
613
+ * FieldDescriptor .new(c_only_cookie, pool, ptr) => FieldDescriptor
544
614
*
545
615
* Creates a descriptor wrapper object. May only be called from C.
546
616
*/
@@ -841,6 +911,25 @@ static VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
841
911
return Qnil ;
842
912
}
843
913
914
+ /*
915
+ * call-seq:
916
+ * FieldDescriptor.options => options
917
+ *
918
+ * Returns the `FieldOptions` for this `FieldDescriptor`.
919
+ */
920
+ static VALUE FieldDescriptor_options (VALUE _self ) {
921
+ FieldDescriptor * self = ruby_to_FieldDescriptor (_self );
922
+ const google_protobuf_FieldOptions * opts =
923
+ upb_FieldDef_Options (self -> fielddef );
924
+ upb_Arena * arena = upb_Arena_New ();
925
+ size_t size ;
926
+ char * serialized = google_protobuf_FieldOptions_serialize (opts , arena , & size );
927
+ VALUE field_options = decode_options (_self , "FieldOptions" , size , serialized ,
928
+ self -> descriptor_pool );
929
+ upb_Arena_Free (arena );
930
+ return field_options ;
931
+ }
932
+
844
933
static void FieldDescriptor_register (VALUE module ) {
845
934
VALUE klass = rb_define_class_under (module , "FieldDescriptor" , rb_cObject );
846
935
rb_define_alloc_func (klass , FieldDescriptor_alloc );
@@ -857,6 +946,7 @@ static void FieldDescriptor_register(VALUE module) {
857
946
rb_define_method (klass , "clear" , FieldDescriptor_clear , 1 );
858
947
rb_define_method (klass , "get" , FieldDescriptor_get , 1 );
859
948
rb_define_method (klass , "set" , FieldDescriptor_set , 2 );
949
+ rb_define_method (klass , "options" , FieldDescriptor_options , 0 );
860
950
rb_gc_register_address (& cFieldDescriptor );
861
951
cFieldDescriptor = klass ;
862
952
}
@@ -956,12 +1046,32 @@ static VALUE OneofDescriptor_each(VALUE _self) {
956
1046
return Qnil ;
957
1047
}
958
1048
1049
+ /*
1050
+ * call-seq:
1051
+ * OneofDescriptor.options => options
1052
+ *
1053
+ * Returns the `OneofOptions` for this `OneofDescriptor`.
1054
+ */
1055
+ static VALUE OneOfDescriptor_options (VALUE _self ) {
1056
+ OneofDescriptor * self = ruby_to_OneofDescriptor (_self );
1057
+ const google_protobuf_OneofOptions * opts =
1058
+ upb_OneofDef_Options (self -> oneofdef );
1059
+ upb_Arena * arena = upb_Arena_New ();
1060
+ size_t size ;
1061
+ char * serialized = google_protobuf_OneofOptions_serialize (opts , arena , & size );
1062
+ VALUE oneof_options = decode_options (_self , "OneofOptions" , size , serialized ,
1063
+ self -> descriptor_pool );
1064
+ upb_Arena_Free (arena );
1065
+ return oneof_options ;
1066
+ }
1067
+
959
1068
static void OneofDescriptor_register (VALUE module ) {
960
1069
VALUE klass = rb_define_class_under (module , "OneofDescriptor" , rb_cObject );
961
1070
rb_define_alloc_func (klass , OneofDescriptor_alloc );
962
1071
rb_define_method (klass , "initialize" , OneofDescriptor_initialize , 3 );
963
1072
rb_define_method (klass , "name" , OneofDescriptor_name , 0 );
964
1073
rb_define_method (klass , "each" , OneofDescriptor_each , 0 );
1074
+ rb_define_method (klass , "options" , OneOfDescriptor_options , 0 );
965
1075
rb_include_module (klass , rb_mEnumerable );
966
1076
rb_gc_register_address (& cOneofDescriptor );
967
1077
cOneofDescriptor = klass ;
@@ -1131,6 +1241,24 @@ static VALUE EnumDescriptor_enummodule(VALUE _self) {
1131
1241
return self -> module ;
1132
1242
}
1133
1243
1244
+ /*
1245
+ * call-seq:
1246
+ * EnumDescriptor.options => options
1247
+ *
1248
+ * Returns the `EnumOptions` for this `EnumDescriptor`.
1249
+ */
1250
+ static VALUE EnumDescriptor_options (VALUE _self ) {
1251
+ EnumDescriptor * self = ruby_to_EnumDescriptor (_self );
1252
+ const google_protobuf_EnumOptions * opts = upb_EnumDef_Options (self -> enumdef );
1253
+ upb_Arena * arena = upb_Arena_New ();
1254
+ size_t size ;
1255
+ char * serialized = google_protobuf_EnumOptions_serialize (opts , arena , & size );
1256
+ VALUE enum_options = decode_options (_self , "EnumOptions" , size , serialized ,
1257
+ self -> descriptor_pool );
1258
+ upb_Arena_Free (arena );
1259
+ return enum_options ;
1260
+ }
1261
+
1134
1262
static void EnumDescriptor_register (VALUE module ) {
1135
1263
VALUE klass = rb_define_class_under (module , "EnumDescriptor" , rb_cObject );
1136
1264
rb_define_alloc_func (klass , EnumDescriptor_alloc );
@@ -1141,6 +1269,7 @@ static void EnumDescriptor_register(VALUE module) {
1141
1269
rb_define_method (klass , "each" , EnumDescriptor_each , 0 );
1142
1270
rb_define_method (klass , "enummodule" , EnumDescriptor_enummodule , 0 );
1143
1271
rb_define_method (klass , "file_descriptor" , EnumDescriptor_file_descriptor , 0 );
1272
+ rb_define_method (klass , "options" , EnumDescriptor_options , 0 );
1144
1273
rb_include_module (klass , rb_mEnumerable );
1145
1274
rb_gc_register_address (& cEnumDescriptor );
1146
1275
cEnumDescriptor = klass ;
0 commit comments