google-protobuf 3.6.1 → 3.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of google-protobuf might be problematic. Click here for more details.

@@ -2,7 +2,11 @@
2
2
 
3
3
  require 'mkmf'
4
4
 
5
- unless RUBY_PLATFORM =~ /mswin|mingw/
5
+ if RUBY_PLATFORM =~ /darwin/ || RUBY_PLATFORM =~ /linux/
6
+ # XOPEN_SOURCE needed for strptime:
7
+ # https://stackoverflow.com/questions/35234152/strptime-giving-implicit-declaration-and-undefined-reference
8
+ $CFLAGS += " -std=c99 -O3 -DNDEBUG -D_XOPEN_SOURCE=700"
9
+ else
6
10
  $CFLAGS += " -std=c99 -O3 -DNDEBUG"
7
11
  end
8
12
 
@@ -82,7 +82,7 @@ static VALUE table_key(Map* self, VALUE key,
82
82
  case UPB_TYPE_INT64:
83
83
  case UPB_TYPE_UINT32:
84
84
  case UPB_TYPE_UINT64:
85
- native_slot_set(self->key_type, Qnil, buf, key);
85
+ native_slot_set("", self->key_type, Qnil, buf, key);
86
86
  *out_key = buf;
87
87
  *out_length = native_slot_size(self->key_type);
88
88
  break;
@@ -386,6 +386,8 @@ VALUE Map_index(VALUE _self, VALUE key) {
386
386
  * was just inserted.
387
387
  */
388
388
  VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) {
389
+ rb_check_frozen(_self);
390
+
389
391
  Map* self = ruby_to_Map(_self);
390
392
 
391
393
  char keybuf[TABLE_KEY_BUF_LENGTH];
@@ -396,7 +398,7 @@ VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) {
396
398
  key = table_key(self, key, keybuf, &keyval, &length);
397
399
 
398
400
  mem = value_memory(&v);
399
- native_slot_set(self->value_type, self->value_type_class, mem, value);
401
+ native_slot_set("", self->value_type, self->value_type_class, mem, value);
400
402
 
401
403
  // Replace any existing value by issuing a 'remove' operation first.
402
404
  upb_strtable_remove2(&self->table, keyval, length, NULL);
@@ -438,6 +440,8 @@ VALUE Map_has_key(VALUE _self, VALUE key) {
438
440
  * nil if none was present. Throws an exception if the key is of the wrong type.
439
441
  */
440
442
  VALUE Map_delete(VALUE _self, VALUE key) {
443
+ rb_check_frozen(_self);
444
+
441
445
  Map* self = ruby_to_Map(_self);
442
446
 
443
447
  char keybuf[TABLE_KEY_BUF_LENGTH];
@@ -461,6 +465,8 @@ VALUE Map_delete(VALUE _self, VALUE key) {
461
465
  * Removes all entries from the map.
462
466
  */
463
467
  VALUE Map_clear(VALUE _self) {
468
+ rb_check_frozen(_self);
469
+
464
470
  Map* self = ruby_to_Map(_self);
465
471
 
466
472
  // Uninit and reinit the table -- this is faster than iterating and doing a
@@ -841,7 +847,6 @@ void Map_register(VALUE module) {
841
847
  rb_define_method(klass, "dup", Map_dup, 0);
842
848
  rb_define_method(klass, "==", Map_eq, 1);
843
849
  rb_define_method(klass, "hash", Map_hash, 0);
844
- rb_define_method(klass, "to_hash", Map_to_h, 0);
845
850
  rb_define_method(klass, "to_h", Map_to_h, 0);
846
851
  rb_define_method(klass, "inspect", Map_inspect, 0);
847
852
  rb_define_method(klass, "merge", Map_merge, 1);
@@ -79,7 +79,7 @@ VALUE Message_alloc(VALUE klass) {
79
79
  return ret;
80
80
  }
81
81
 
82
- static VALUE which_oneof_field(MessageHeader* self, const upb_oneofdef* o) {
82
+ static const upb_fielddef* which_oneof_field(MessageHeader* self, const upb_oneofdef* o) {
83
83
  upb_oneof_iter it;
84
84
  size_t case_ofs;
85
85
  uint32_t oneof_case;
@@ -88,7 +88,7 @@ static VALUE which_oneof_field(MessageHeader* self, const upb_oneofdef* o) {
88
88
 
89
89
  // If no fields in the oneof, always nil.
90
90
  if (upb_oneofdef_numfields(o) == 0) {
91
- return Qnil;
91
+ return NULL;
92
92
  }
93
93
  // Grab the first field in the oneof so we can get its layout info to find the
94
94
  // oneof_case field.
@@ -103,22 +103,165 @@ static VALUE which_oneof_field(MessageHeader* self, const upb_oneofdef* o) {
103
103
  oneof_case = *((uint32_t*)((char*)Message_data(self) + case_ofs));
104
104
 
105
105
  if (oneof_case == ONEOF_CASE_NONE) {
106
- return Qnil;
106
+ return NULL;
107
107
  }
108
108
 
109
109
  // oneof_case is a field index, so find that field.
110
110
  f = upb_oneofdef_itof(o, oneof_case);
111
111
  assert(f != NULL);
112
112
 
113
- return ID2SYM(rb_intern(upb_fielddef_name(f)));
113
+ return f;
114
+ }
115
+
116
+ enum {
117
+ METHOD_UNKNOWN = 0,
118
+ METHOD_GETTER = 1,
119
+ METHOD_SETTER = 2,
120
+ METHOD_CLEAR = 3,
121
+ METHOD_PRESENCE = 4,
122
+ METHOD_ENUM_GETTER = 5,
123
+ METHOD_WRAPPER_GETTER = 6,
124
+ METHOD_WRAPPER_SETTER = 7
125
+ };
126
+
127
+ // Check if the field is a well known wrapper type
128
+ static bool is_wrapper_type_field(const upb_fielddef* field) {
129
+ char* field_type_name = rb_class2name(field_type_class(field));
130
+
131
+ return strcmp(field_type_name, "Google::Protobuf::DoubleValue") == 0 ||
132
+ strcmp(field_type_name, "Google::Protobuf::FloatValue") == 0 ||
133
+ strcmp(field_type_name, "Google::Protobuf::Int32Value") == 0 ||
134
+ strcmp(field_type_name, "Google::Protobuf::Int64Value") == 0 ||
135
+ strcmp(field_type_name, "Google::Protobuf::UInt32Value") == 0 ||
136
+ strcmp(field_type_name, "Google::Protobuf::UInt64Value") == 0 ||
137
+ strcmp(field_type_name, "Google::Protobuf::BoolValue") == 0 ||
138
+ strcmp(field_type_name, "Google::Protobuf::StringValue") == 0 ||
139
+ strcmp(field_type_name, "Google::Protobuf::BytesValue") == 0;
140
+ }
141
+
142
+ // Get a new Ruby wrapper type and set the initial value
143
+ static VALUE ruby_wrapper_type(const upb_fielddef* field, const VALUE* value) {
144
+ if (is_wrapper_type_field(field) && value != Qnil) {
145
+ VALUE hash = rb_hash_new();
146
+ rb_hash_aset(hash, rb_str_new2("value"), value);
147
+ VALUE args[1] = { hash };
148
+ return rb_class_new_instance(1, args, field_type_class(field));
149
+ }
150
+ return Qnil;
151
+ }
152
+
153
+ static int extract_method_call(VALUE method_name, MessageHeader* self,
154
+ const upb_fielddef **f, const upb_oneofdef **o) {
155
+ Check_Type(method_name, T_SYMBOL);
156
+
157
+ VALUE method_str = rb_id2str(SYM2ID(method_name));
158
+ char* name = RSTRING_PTR(method_str);
159
+ size_t name_len = RSTRING_LEN(method_str);
160
+ int accessor_type;
161
+ const upb_oneofdef* test_o;
162
+ const upb_fielddef* test_f;
163
+
164
+ if (name[name_len - 1] == '=') {
165
+ accessor_type = METHOD_SETTER;
166
+ name_len--;
167
+ // We want to ensure if the proto has something named clear_foo or has_foo?,
168
+ // we don't strip the prefix.
169
+ } else if (strncmp("clear_", name, 6) == 0 &&
170
+ !upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len,
171
+ &test_f, &test_o)) {
172
+ accessor_type = METHOD_CLEAR;
173
+ name = name + 6;
174
+ name_len = name_len - 6;
175
+ } else if (strncmp("has_", name, 4) == 0 && name[name_len - 1] == '?' &&
176
+ !upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len,
177
+ &test_f, &test_o)) {
178
+ accessor_type = METHOD_PRESENCE;
179
+ name = name + 4;
180
+ name_len = name_len - 5;
181
+ } else {
182
+ accessor_type = METHOD_GETTER;
183
+ }
184
+
185
+ bool has_field = upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len,
186
+ &test_f, &test_o);
187
+
188
+ // Look for wrapper type accessor of the form <field_name>_as_value
189
+ if (!has_field &&
190
+ (accessor_type == METHOD_GETTER || accessor_type == METHOD_SETTER) &&
191
+ name_len > 9 && strncmp(name + name_len - 9, "_as_value", 9) == 0) {
192
+ // Find the field name
193
+ char wrapper_field_name[name_len - 8];
194
+ strncpy(wrapper_field_name, name, name_len - 9);
195
+ wrapper_field_name[name_len - 7] = '\0';
196
+
197
+ // Check if field exists and is a wrapper type
198
+ const upb_oneofdef* test_o_wrapper;
199
+ const upb_fielddef* test_f_wrapper;
200
+ if (upb_msgdef_lookupname(self->descriptor->msgdef, wrapper_field_name, name_len - 9,
201
+ &test_f_wrapper, &test_o_wrapper) &&
202
+ upb_fielddef_type(test_f_wrapper) == UPB_TYPE_MESSAGE &&
203
+ is_wrapper_type_field(test_f_wrapper)) {
204
+ // It does exist!
205
+ has_field = true;
206
+ if (accessor_type == METHOD_SETTER) {
207
+ accessor_type = METHOD_WRAPPER_SETTER;
208
+ } else {
209
+ accessor_type = METHOD_WRAPPER_GETTER;
210
+ }
211
+ test_o = test_o_wrapper;
212
+ test_f = test_f_wrapper;
213
+ }
214
+ }
215
+
216
+ // Look for enum accessor of the form <enum_name>_const
217
+ if (!has_field && accessor_type == METHOD_GETTER &&
218
+ name_len > 6 && strncmp(name + name_len - 6, "_const", 6) == 0) {
219
+
220
+ // Find enum field name
221
+ char enum_name[name_len - 5];
222
+ strncpy(enum_name, name, name_len - 6);
223
+ enum_name[name_len - 4] = '\0';
224
+
225
+ // Check if enum field exists
226
+ const upb_oneofdef* test_o_enum;
227
+ const upb_fielddef* test_f_enum;
228
+ if (upb_msgdef_lookupname(self->descriptor->msgdef, enum_name, name_len - 6,
229
+ &test_f_enum, &test_o_enum) &&
230
+ upb_fielddef_type(test_f_enum) == UPB_TYPE_ENUM) {
231
+ // It does exist!
232
+ has_field = true;
233
+ accessor_type = METHOD_ENUM_GETTER;
234
+ test_o = test_o_enum;
235
+ test_f = test_f_enum;
236
+ }
237
+ }
238
+
239
+ // Verify the name corresponds to a oneof or field in this message.
240
+ if (!has_field) {
241
+ return METHOD_UNKNOWN;
242
+ }
243
+
244
+ // Method calls like 'has_foo?' are not allowed if field "foo" does not have
245
+ // a hasbit (e.g. repeated fields or non-message type fields for proto3
246
+ // syntax).
247
+ if (accessor_type == METHOD_PRESENCE && test_f != NULL &&
248
+ !upb_fielddef_haspresence(test_f)) {
249
+ return METHOD_UNKNOWN;
250
+ }
251
+
252
+ *o = test_o;
253
+ *f = test_f;
254
+ return accessor_type;
114
255
  }
115
256
 
116
257
  /*
117
258
  * call-seq:
118
259
  * Message.method_missing(*args)
119
260
  *
120
- * Provides accessors and setters for message fields according to their field
121
- * names. For any field whose name does not conflict with a built-in method, an
261
+ * Provides accessors and setters and methods to clear and check for presence of
262
+ * message fields according to their field names.
263
+ *
264
+ * For any field whose name does not conflict with a built-in method, an
122
265
  * accessor is provided with the same name as the field, and a setter is
123
266
  * provided with the name of the field plus the '=' suffix. Thus, given a
124
267
  * message instance 'msg' with field 'foo', the following code is valid:
@@ -129,13 +272,17 @@ static VALUE which_oneof_field(MessageHeader* self, const upb_oneofdef* o) {
129
272
  * This method also provides read-only accessors for oneofs. If a oneof exists
130
273
  * with name 'my_oneof', then msg.my_oneof will return a Ruby symbol equal to
131
274
  * the name of the field in that oneof that is currently set, or nil if none.
275
+ *
276
+ * It also provides methods of the form 'clear_fieldname' to clear the value
277
+ * of the field 'fieldname'. For basic data types, this will set the default
278
+ * value of the field.
279
+ *
280
+ * Additionally, it provides methods of the form 'has_fieldname?', which returns
281
+ * true if the field 'fieldname' is set in the message object, else false. For
282
+ * 'proto3' syntax, calling this for a basic type field will result in an error.
132
283
  */
133
284
  VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
134
285
  MessageHeader* self;
135
- VALUE method_name, method_str;
136
- char* name;
137
- size_t name_len;
138
- bool setter;
139
286
  const upb_oneofdef* o;
140
287
  const upb_fielddef* f;
141
288
 
@@ -143,54 +290,84 @@ VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
143
290
  if (argc < 1) {
144
291
  rb_raise(rb_eArgError, "Expected method name as first argument.");
145
292
  }
146
- method_name = argv[0];
147
- if (!SYMBOL_P(method_name)) {
148
- rb_raise(rb_eArgError, "Expected symbol as method name.");
149
- }
150
- method_str = rb_id2str(SYM2ID(method_name));
151
- name = RSTRING_PTR(method_str);
152
- name_len = RSTRING_LEN(method_str);
153
- setter = false;
154
-
155
- // Setters have names that end in '='.
156
- if (name[name_len - 1] == '=') {
157
- setter = true;
158
- name_len--;
159
- }
160
293
 
161
- // See if this name corresponds to either a oneof or field in this message.
162
- if (!upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len, &f,
163
- &o)) {
294
+ int accessor_type = extract_method_call(argv[0], self, &f, &o);
295
+ if (accessor_type == METHOD_UNKNOWN || (o == NULL && f == NULL) ) {
164
296
  return rb_call_super(argc, argv);
297
+ } else if (accessor_type == METHOD_SETTER || accessor_type == METHOD_WRAPPER_SETTER) {
298
+ if (argc != 2) {
299
+ rb_raise(rb_eArgError, "Expected 2 arguments, received %d", argc);
300
+ }
301
+ rb_check_frozen(_self);
302
+ } else if (argc != 1) {
303
+ rb_raise(rb_eArgError, "Expected 1 argument, received %d", argc);
165
304
  }
166
305
 
306
+ // Return which of the oneof fields are set
167
307
  if (o != NULL) {
168
- // This is a oneof -- return which field inside the oneof is set.
169
- if (setter) {
308
+ if (accessor_type == METHOD_SETTER) {
170
309
  rb_raise(rb_eRuntimeError, "Oneof accessors are read-only.");
171
310
  }
172
- return which_oneof_field(self, o);
173
- } else {
174
- // This is a field -- get or set the field's value.
175
- assert(f);
176
- if (setter) {
177
- if (argc < 2) {
178
- rb_raise(rb_eArgError, "No value provided to setter.");
311
+
312
+ const upb_fielddef* oneof_field = which_oneof_field(self, o);
313
+ if (accessor_type == METHOD_PRESENCE) {
314
+ return oneof_field == NULL ? Qfalse : Qtrue;
315
+ } else if (accessor_type == METHOD_CLEAR) {
316
+ if (oneof_field != NULL) {
317
+ layout_clear(self->descriptor->layout, Message_data(self), oneof_field);
179
318
  }
180
- layout_set(self->descriptor->layout, Message_data(self), f, argv[1]);
181
319
  return Qnil;
182
320
  } else {
183
- return layout_get(self->descriptor->layout, Message_data(self), f);
321
+ // METHOD_ACCESSOR
322
+ return oneof_field == NULL ? Qnil :
323
+ ID2SYM(rb_intern(upb_fielddef_name(oneof_field)));
324
+ }
325
+ // Otherwise we're operating on a single proto field
326
+ } else if (accessor_type == METHOD_SETTER) {
327
+ layout_set(self->descriptor->layout, Message_data(self), f, argv[1]);
328
+ return Qnil;
329
+ } else if (accessor_type == METHOD_CLEAR) {
330
+ layout_clear(self->descriptor->layout, Message_data(self), f);
331
+ return Qnil;
332
+ } else if (accessor_type == METHOD_PRESENCE) {
333
+ return layout_has(self->descriptor->layout, Message_data(self), f);
334
+ } else if (accessor_type == METHOD_WRAPPER_GETTER) {
335
+ VALUE value = layout_get(self->descriptor->layout, Message_data(self), f);
336
+ if (value != Qnil) {
337
+ value = rb_funcall(value, rb_intern("value"), 0);
184
338
  }
339
+ return value;
340
+ } else if (accessor_type == METHOD_WRAPPER_SETTER) {
341
+ VALUE wrapper = ruby_wrapper_type(f, argv[1]);
342
+ layout_set(self->descriptor->layout, Message_data(self), f, wrapper);
343
+ return Qnil;
344
+ } else if (accessor_type == METHOD_ENUM_GETTER) {
345
+ VALUE enum_type = field_type_class(f);
346
+ VALUE method = rb_intern("const_get");
347
+ VALUE raw_value = layout_get(self->descriptor->layout, Message_data(self), f);
348
+
349
+ // Map repeated fields to a new type with ints
350
+ if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
351
+ int array_size = FIX2INT(rb_funcall(raw_value, rb_intern("length"), 0));
352
+ VALUE array_args[1] = { ID2SYM(rb_intern("int64")) };
353
+ VALUE array = rb_class_new_instance(1, array_args, CLASS_OF(raw_value));
354
+ for (int i = 0; i < array_size; i++) {
355
+ VALUE entry = rb_funcall(enum_type, method, 1, rb_funcall(raw_value,
356
+ rb_intern("at"), 1, INT2NUM(i)));
357
+ rb_funcall(array, rb_intern("push"), 1, entry);
358
+ }
359
+ return array;
360
+ }
361
+ // Convert the value for singular fields
362
+ return rb_funcall(enum_type, method, 1, raw_value);
363
+ } else {
364
+ return layout_get(self->descriptor->layout, Message_data(self), f);
185
365
  }
186
366
  }
187
367
 
368
+
188
369
  VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
189
370
  MessageHeader* self;
190
- VALUE method_name, method_str;
191
- char* name;
192
- size_t name_len;
193
- bool setter;
194
371
  const upb_oneofdef* o;
195
372
  const upb_fielddef* f;
196
373
 
@@ -198,30 +375,15 @@ VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
198
375
  if (argc < 1) {
199
376
  rb_raise(rb_eArgError, "Expected method name as first argument.");
200
377
  }
201
- method_name = argv[0];
202
- if (!SYMBOL_P(method_name)) {
203
- rb_raise(rb_eArgError, "Expected symbol as method name.");
204
- }
205
- method_str = rb_id2str(SYM2ID(method_name));
206
- name = RSTRING_PTR(method_str);
207
- name_len = RSTRING_LEN(method_str);
208
- setter = false;
209
-
210
- // Setters have names that end in '='.
211
- if (name[name_len - 1] == '=') {
212
- setter = true;
213
- name_len--;
214
- }
215
378
 
216
- // See if this name corresponds to either a oneof or field in this message.
217
- if (!upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len, &f,
218
- &o)) {
379
+ int accessor_type = extract_method_call(argv[0], self, &f, &o);
380
+ if (accessor_type == METHOD_UNKNOWN) {
219
381
  return rb_call_super(argc, argv);
382
+ } else if (o != NULL) {
383
+ return accessor_type == METHOD_SETTER ? Qfalse : Qtrue;
384
+ } else {
385
+ return Qtrue;
220
386
  }
221
- if (o != NULL) {
222
- return setter ? Qfalse : Qtrue;
223
- }
224
- return Qtrue;
225
387
  }
226
388
 
227
389
  VALUE create_submsg_from_hash(const upb_fielddef *f, VALUE hash) {
@@ -256,12 +418,17 @@ int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
256
418
  "Unknown field name '%s' in initialization map entry.", name);
257
419
  }
258
420
 
421
+ if (TYPE(val) == T_NIL) {
422
+ return 0;
423
+ }
424
+
259
425
  if (is_map_field(f)) {
260
426
  VALUE map;
261
427
 
262
428
  if (TYPE(val) != T_HASH) {
263
429
  rb_raise(rb_eArgError,
264
- "Expected Hash object as initializer value for map field '%s'.", name);
430
+ "Expected Hash object as initializer value for map field '%s' (given %s).",
431
+ name, rb_class2name(CLASS_OF(val)));
265
432
  }
266
433
  map = layout_get(self->descriptor->layout, Message_data(self), f);
267
434
  Map_merge_into_self(map, val);
@@ -270,7 +437,8 @@ int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
270
437
 
271
438
  if (TYPE(val) != T_ARRAY) {
272
439
  rb_raise(rb_eArgError,
273
- "Expected array as initializer value for repeated field '%s'.", name);
440
+ "Expected array as initializer value for repeated field '%s' (given %s).",
441
+ name, rb_class2name(CLASS_OF(val)));
274
442
  }
275
443
  ary = layout_get(self->descriptor->layout, Message_data(self), f);
276
444
  for (int i = 0; i < RARRAY_LEN(val); i++) {
@@ -440,13 +608,25 @@ VALUE Message_to_h(VALUE _self) {
440
608
  !upb_msg_field_done(&it);
441
609
  upb_msg_field_next(&it)) {
442
610
  const upb_fielddef* field = upb_msg_iter_field(&it);
611
+
612
+ // For proto2, do not include fields which are not set.
613
+ if (upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2 &&
614
+ field_contains_hasbit(self->descriptor->layout, field) &&
615
+ !layout_has(self->descriptor->layout, Message_data(self), field)) {
616
+ continue;
617
+ }
618
+
443
619
  VALUE msg_value = layout_get(self->descriptor->layout, Message_data(self),
444
620
  field);
445
621
  VALUE msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
446
- if (upb_fielddef_ismap(field)) {
622
+ if (is_map_field(field)) {
447
623
  msg_value = Map_to_h(msg_value);
448
624
  } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
449
625
  msg_value = RepeatedField_to_ary(msg_value);
626
+ if (upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2 &&
627
+ RARRAY_LEN(msg_value) == 0) {
628
+ continue;
629
+ }
450
630
 
451
631
  if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
452
632
  for (int i = 0; i < RARRAY_LEN(msg_value); i++) {
@@ -454,6 +634,7 @@ VALUE Message_to_h(VALUE _self) {
454
634
  rb_ary_store(msg_value, i, Message_to_h(elem));
455
635
  }
456
636
  }
637
+
457
638
  } else if (msg_value != Qnil &&
458
639
  upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
459
640
  msg_value = Message_to_h(msg_value);
@@ -553,15 +734,16 @@ VALUE build_class_from_descriptor(Descriptor* desc) {
553
734
  // Also define #clone so that we don't inherit Object#clone.
554
735
  rb_define_method(klass, "clone", Message_dup, 0);
555
736
  rb_define_method(klass, "==", Message_eq, 1);
737
+ rb_define_method(klass, "eql?", Message_eq, 1);
556
738
  rb_define_method(klass, "hash", Message_hash, 0);
557
739
  rb_define_method(klass, "to_h", Message_to_h, 0);
558
- rb_define_method(klass, "to_hash", Message_to_h, 0);
559
740
  rb_define_method(klass, "inspect", Message_inspect, 0);
741
+ rb_define_method(klass, "to_s", Message_inspect, 0);
560
742
  rb_define_method(klass, "[]", Message_index, 1);
561
743
  rb_define_method(klass, "[]=", Message_index_set, 2);
562
744
  rb_define_singleton_method(klass, "decode", Message_decode, 1);
563
745
  rb_define_singleton_method(klass, "encode", Message_encode, 1);
564
- rb_define_singleton_method(klass, "decode_json", Message_decode_json, 1);
746
+ rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1);
565
747
  rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
566
748
  rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
567
749
 
@@ -631,10 +813,9 @@ VALUE build_module_from_enumdesc(EnumDescriptor* enumdesc) {
631
813
  const char* name = upb_enum_iter_name(&it);
632
814
  int32_t value = upb_enum_iter_number(&it);
633
815
  if (name[0] < 'A' || name[0] > 'Z') {
634
- rb_raise(rb_eTypeError,
635
- "Enum value '%s' does not start with an uppercase letter "
636
- "as is required for Ruby constants.",
637
- name);
816
+ rb_warn("Enum value '%s' does not start with an uppercase letter "
817
+ "as is required for Ruby constants.",
818
+ name);
638
819
  }
639
820
  rb_define_const(mod, name, INT2NUM(value));
640
821
  }