google-protobuf 3.6.1 → 3.9.1

Sign up to get free protection for your applications and to get access to all the features.

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
  }