google-protobuf 3.19.1 → 3.25.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.

Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/Rakefile +3 -0
  3. data/ext/google/protobuf_c/convert.c +121 -155
  4. data/ext/google/protobuf_c/convert.h +15 -37
  5. data/ext/google/protobuf_c/defs.c +362 -243
  6. data/ext/google/protobuf_c/defs.h +22 -47
  7. data/ext/google/protobuf_c/extconf.rb +13 -5
  8. data/ext/google/protobuf_c/glue.c +56 -0
  9. data/ext/google/protobuf_c/map.c +129 -137
  10. data/ext/google/protobuf_c/map.h +13 -36
  11. data/ext/google/protobuf_c/message.c +486 -389
  12. data/ext/google/protobuf_c/message.h +32 -47
  13. data/ext/google/protobuf_c/protobuf.c +101 -228
  14. data/ext/google/protobuf_c/protobuf.h +37 -42
  15. data/ext/google/protobuf_c/repeated_field.c +110 -113
  16. data/ext/google/protobuf_c/repeated_field.h +12 -34
  17. data/ext/google/protobuf_c/ruby-upb.c +12236 -6993
  18. data/ext/google/protobuf_c/ruby-upb.h +12127 -3787
  19. data/ext/google/protobuf_c/shared_convert.c +64 -0
  20. data/ext/google/protobuf_c/shared_convert.h +26 -0
  21. data/ext/google/protobuf_c/shared_message.c +65 -0
  22. data/ext/google/protobuf_c/shared_message.h +25 -0
  23. data/ext/google/protobuf_c/third_party/utf8_range/LICENSE +22 -0
  24. data/ext/google/protobuf_c/third_party/utf8_range/naive.c +92 -0
  25. data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +157 -0
  26. data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +170 -0
  27. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +21 -0
  28. data/ext/google/protobuf_c/wrap_memcpy.c +7 -29
  29. data/lib/google/protobuf/any_pb.rb +24 -5
  30. data/lib/google/protobuf/api_pb.rb +26 -23
  31. data/lib/google/protobuf/descriptor_dsl.rb +8 -1
  32. data/lib/google/protobuf/descriptor_pb.rb +43 -225
  33. data/lib/google/protobuf/duration_pb.rb +24 -5
  34. data/lib/google/protobuf/empty_pb.rb +24 -3
  35. data/lib/google/protobuf/ffi/descriptor.rb +165 -0
  36. data/lib/google/protobuf/ffi/descriptor_pool.rb +75 -0
  37. data/lib/google/protobuf/ffi/enum_descriptor.rb +171 -0
  38. data/lib/google/protobuf/ffi/ffi.rb +213 -0
  39. data/lib/google/protobuf/ffi/field_descriptor.rb +319 -0
  40. data/lib/google/protobuf/ffi/file_descriptor.rb +59 -0
  41. data/lib/google/protobuf/ffi/internal/arena.rb +66 -0
  42. data/lib/google/protobuf/ffi/internal/convert.rb +305 -0
  43. data/lib/google/protobuf/ffi/internal/pointer_helper.rb +35 -0
  44. data/lib/google/protobuf/ffi/internal/type_safety.rb +25 -0
  45. data/lib/google/protobuf/ffi/map.rb +407 -0
  46. data/lib/google/protobuf/ffi/message.rb +662 -0
  47. data/lib/google/protobuf/ffi/object_cache.rb +30 -0
  48. data/lib/google/protobuf/ffi/oneof_descriptor.rb +95 -0
  49. data/lib/google/protobuf/ffi/repeated_field.rb +383 -0
  50. data/lib/google/protobuf/field_mask_pb.rb +24 -4
  51. data/lib/google/protobuf/message_exts.rb +10 -28
  52. data/lib/google/protobuf/object_cache.rb +97 -0
  53. data/lib/google/protobuf/plugin_pb.rb +47 -0
  54. data/lib/google/protobuf/repeated_field.rb +18 -28
  55. data/lib/google/protobuf/source_context_pb.rb +24 -4
  56. data/lib/google/protobuf/struct_pb.rb +24 -20
  57. data/lib/google/protobuf/timestamp_pb.rb +24 -5
  58. data/lib/google/protobuf/type_pb.rb +26 -68
  59. data/lib/google/protobuf/well_known_types.rb +16 -40
  60. data/lib/google/protobuf/wrappers_pb.rb +24 -28
  61. data/lib/google/protobuf.rb +32 -50
  62. data/lib/google/protobuf_ffi.rb +50 -0
  63. data/lib/google/protobuf_native.rb +20 -0
  64. data/lib/google/tasks/ffi.rake +102 -0
  65. metadata +82 -20
  66. data/tests/basic.rb +0 -640
  67. data/tests/generated_code_test.rb +0 -23
  68. data/tests/stress.rb +0 -38
@@ -1,32 +1,9 @@
1
1
  // Protocol Buffers - Google's data interchange format
2
2
  // Copyright 2014 Google Inc. All rights reserved.
3
- // https://developers.google.com/protocol-buffers/
4
3
  //
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.
4
+ // Use of this source code is governed by a BSD-style
5
+ // license that can be found in the LICENSE file or at
6
+ // https://developers.google.com/open-source/licenses/bsd
30
7
 
31
8
  #include "message.h"
32
9
 
@@ -35,12 +12,14 @@
35
12
  #include "map.h"
36
13
  #include "protobuf.h"
37
14
  #include "repeated_field.h"
15
+ #include "shared_message.h"
38
16
 
39
17
  static VALUE cParseError = Qnil;
18
+ static VALUE cAbstractMessage = Qnil;
40
19
  static ID descriptor_instancevar_interned;
41
20
 
42
21
  static VALUE initialize_rb_class_with_no_args(VALUE klass) {
43
- return rb_funcall(klass, rb_intern("new"), 0);
22
+ return rb_funcall(klass, rb_intern("new"), 0);
44
23
  }
45
24
 
46
25
  VALUE MessageOrEnum_GetDescriptor(VALUE klass) {
@@ -52,20 +31,23 @@ VALUE MessageOrEnum_GetDescriptor(VALUE klass) {
52
31
  // -----------------------------------------------------------------------------
53
32
 
54
33
  typedef struct {
34
+ // IMPORTANT: WB_PROTECTED objects must only use the RB_OBJ_WRITE()
35
+ // macro to update VALUE references, as to trigger write barriers.
55
36
  VALUE arena;
56
- const upb_msg* msg; // Can get as mutable when non-frozen.
57
- const upb_msgdef* msgdef; // kept alive by self.class.descriptor reference.
37
+ const upb_Message* msg; // Can get as mutable when non-frozen.
38
+ const upb_MessageDef*
39
+ msgdef; // kept alive by self.class.descriptor reference.
58
40
  } Message;
59
41
 
60
42
  static void Message_mark(void* _self) {
61
- Message* self = (Message *)_self;
43
+ Message* self = (Message*)_self;
62
44
  rb_gc_mark(self->arena);
63
45
  }
64
46
 
65
47
  static rb_data_type_t Message_type = {
66
- "Message",
67
- { Message_mark, RUBY_DEFAULT_FREE, NULL },
68
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
48
+ "Google::Protobuf::Message",
49
+ {Message_mark, RUBY_DEFAULT_FREE, NULL},
50
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
69
51
  };
70
52
 
71
53
  static Message* ruby_to_Message(VALUE msg_rb) {
@@ -89,22 +71,24 @@ static VALUE Message_alloc(VALUE klass) {
89
71
  return ret;
90
72
  }
91
73
 
92
- const upb_msg *Message_Get(VALUE msg_rb, const upb_msgdef **m) {
74
+ const upb_Message* Message_Get(VALUE msg_rb, const upb_MessageDef** m) {
93
75
  Message* msg = ruby_to_Message(msg_rb);
94
76
  if (m) *m = msg->msgdef;
95
77
  return msg->msg;
96
78
  }
97
79
 
98
- upb_msg *Message_GetMutable(VALUE msg_rb, const upb_msgdef **m) {
80
+ upb_Message* Message_GetMutable(VALUE msg_rb, const upb_MessageDef** m) {
99
81
  rb_check_frozen(msg_rb);
100
- return (upb_msg*)Message_Get(msg_rb, m);
82
+ return (upb_Message*)Message_Get(msg_rb, m);
101
83
  }
102
84
 
103
- void Message_InitPtr(VALUE self_, upb_msg *msg, VALUE arena) {
85
+ void Message_InitPtr(VALUE self_, upb_Message* msg, VALUE arena) {
104
86
  Message* self = ruby_to_Message(self_);
105
87
  self->msg = msg;
106
- self->arena = arena;
107
- ObjectCache_Add(msg, self_);
88
+ RB_OBJ_WRITE(self_, &self->arena, arena);
89
+ VALUE stored = ObjectCache_TryAdd(msg, self_);
90
+ (void)stored;
91
+ PBRUBY_ASSERT(stored == self_);
108
92
  }
109
93
 
110
94
  VALUE Message_GetArena(VALUE msg_rb) {
@@ -119,7 +103,8 @@ void Message_CheckClass(VALUE klass) {
119
103
  }
120
104
  }
121
105
 
122
- VALUE Message_GetRubyWrapper(upb_msg* msg, const upb_msgdef* m, VALUE arena) {
106
+ VALUE Message_GetRubyWrapper(upb_Message* msg, const upb_MessageDef* m,
107
+ VALUE arena) {
123
108
  if (msg == NULL) return Qnil;
124
109
 
125
110
  VALUE val = ObjectCache_Get(msg);
@@ -133,17 +118,18 @@ VALUE Message_GetRubyWrapper(upb_msg* msg, const upb_msgdef* m, VALUE arena) {
133
118
  return val;
134
119
  }
135
120
 
136
- void Message_PrintMessage(StringBuilder* b, const upb_msg* msg,
137
- const upb_msgdef* m) {
121
+ void Message_PrintMessage(StringBuilder* b, const upb_Message* msg,
122
+ const upb_MessageDef* m) {
138
123
  bool first = true;
139
- int n = upb_msgdef_fieldcount(m);
124
+ int n = upb_MessageDef_FieldCount(m);
140
125
  VALUE klass = Descriptor_DefToClass(m);
141
126
  StringBuilder_Printf(b, "<%s: ", rb_class2name(klass));
142
127
 
143
128
  for (int i = 0; i < n; i++) {
144
- const upb_fielddef* field = upb_msgdef_field(m, i);
129
+ const upb_FieldDef* field = upb_MessageDef_Field(m, i);
145
130
 
146
- if (upb_fielddef_haspresence(field) && !upb_msg_has(msg, field)) {
131
+ if (upb_FieldDef_HasPresence(field) &&
132
+ !upb_Message_HasFieldByDef(msg, field)) {
147
133
  continue;
148
134
  }
149
135
 
@@ -153,17 +139,17 @@ void Message_PrintMessage(StringBuilder* b, const upb_msg* msg,
153
139
  first = false;
154
140
  }
155
141
 
156
- upb_msgval msgval = upb_msg_get(msg, field);
142
+ upb_MessageValue msgval = upb_Message_GetFieldByDef(msg, field);
157
143
 
158
- StringBuilder_Printf(b, "%s: ", upb_fielddef_name(field));
144
+ StringBuilder_Printf(b, "%s: ", upb_FieldDef_Name(field));
159
145
 
160
- if (upb_fielddef_ismap(field)) {
161
- const upb_msgdef* entry_m = upb_fielddef_msgsubdef(field);
162
- const upb_fielddef* key_f = upb_msgdef_itof(entry_m, 1);
163
- const upb_fielddef* val_f = upb_msgdef_itof(entry_m, 2);
146
+ if (upb_FieldDef_IsMap(field)) {
147
+ const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(field);
148
+ const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry_m, 1);
149
+ const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
164
150
  TypeInfo val_info = TypeInfo_get(val_f);
165
- Map_Inspect(b, msgval.map_val, upb_fielddef_type(key_f), val_info);
166
- } else if (upb_fielddef_isseq(field)) {
151
+ Map_Inspect(b, msgval.map_val, upb_FieldDef_CType(key_f), val_info);
152
+ } else if (upb_FieldDef_IsRepeated(field)) {
167
153
  RepeatedField_Inspect(b, msgval.array_val, TypeInfo_get(field));
168
154
  } else {
169
155
  StringBuilder_PrintMsgval(b, msgval, TypeInfo_get(field));
@@ -187,14 +173,31 @@ enum {
187
173
  };
188
174
 
189
175
  // Check if the field is a well known wrapper type
190
- static bool IsWrapper(const upb_fielddef* f) {
191
- return upb_fielddef_issubmsg(f) &&
192
- upb_msgdef_iswrapper(upb_fielddef_msgsubdef(f));
176
+ static bool IsWrapper(const upb_MessageDef* m) {
177
+ if (!m) return false;
178
+ switch (upb_MessageDef_WellKnownType(m)) {
179
+ case kUpb_WellKnown_DoubleValue:
180
+ case kUpb_WellKnown_FloatValue:
181
+ case kUpb_WellKnown_Int64Value:
182
+ case kUpb_WellKnown_UInt64Value:
183
+ case kUpb_WellKnown_Int32Value:
184
+ case kUpb_WellKnown_UInt32Value:
185
+ case kUpb_WellKnown_StringValue:
186
+ case kUpb_WellKnown_BytesValue:
187
+ case kUpb_WellKnown_BoolValue:
188
+ return true;
189
+ default:
190
+ return false;
191
+ }
193
192
  }
194
193
 
195
- static bool Match(const upb_msgdef* m, const char* name, const upb_fielddef** f,
196
- const upb_oneofdef** o, const char* prefix,
197
- const char* suffix) {
194
+ static bool IsFieldWrapper(const upb_FieldDef* f) {
195
+ return IsWrapper(upb_FieldDef_MessageSubDef(f));
196
+ }
197
+
198
+ static bool Match(const upb_MessageDef* m, const char* name,
199
+ const upb_FieldDef** f, const upb_OneofDef** o,
200
+ const char* prefix, const char* suffix) {
198
201
  size_t sp = strlen(prefix);
199
202
  size_t ss = strlen(suffix);
200
203
  size_t sn = strlen(name);
@@ -206,12 +209,12 @@ static bool Match(const upb_msgdef* m, const char* name, const upb_fielddef** f,
206
209
  return false;
207
210
  }
208
211
 
209
- return upb_msgdef_lookupname(m, name + sp, sn - sp - ss, f, o);
212
+ return upb_MessageDef_FindByNameWithSize(m, name + sp, sn - sp - ss, f, o);
210
213
  }
211
214
 
212
215
  static int extract_method_call(VALUE method_name, Message* self,
213
- const upb_fielddef** f, const upb_oneofdef** o) {
214
- const upb_msgdef* m = self->msgdef;
216
+ const upb_FieldDef** f, const upb_OneofDef** o) {
217
+ const upb_MessageDef* m = self->msgdef;
215
218
  const char* name;
216
219
 
217
220
  Check_Type(method_name, T_SYMBOL);
@@ -221,156 +224,153 @@ static int extract_method_call(VALUE method_name, Message* self,
221
224
  if (Match(m, name, f, o, "", "=")) return METHOD_SETTER;
222
225
  if (Match(m, name, f, o, "clear_", "")) return METHOD_CLEAR;
223
226
  if (Match(m, name, f, o, "has_", "?") &&
224
- (*o || (*f && upb_fielddef_haspresence(*f)))) {
225
- // Disallow oneof hazzers for proto3.
226
- // TODO(haberman): remove this test when we are enabling oneof hazzers for
227
- // proto3.
228
- if (*f && !upb_fielddef_issubmsg(*f) &&
229
- upb_fielddef_realcontainingoneof(*f) &&
230
- upb_msgdef_syntax(upb_fielddef_containingtype(*f)) !=
231
- UPB_SYNTAX_PROTO2) {
232
- return METHOD_UNKNOWN;
233
- }
227
+ (*o || (*f && upb_FieldDef_HasPresence(*f)))) {
234
228
  return METHOD_PRESENCE;
235
229
  }
236
- if (Match(m, name, f, o, "", "_as_value") && *f && !upb_fielddef_isseq(*f) &&
237
- IsWrapper(*f)) {
230
+ if (Match(m, name, f, o, "", "_as_value") && *f &&
231
+ !upb_FieldDef_IsRepeated(*f) && IsFieldWrapper(*f)) {
238
232
  return METHOD_WRAPPER_GETTER;
239
233
  }
240
- if (Match(m, name, f, o, "", "_as_value=") && *f && !upb_fielddef_isseq(*f) &&
241
- IsWrapper(*f)) {
234
+ if (Match(m, name, f, o, "", "_as_value=") && *f &&
235
+ !upb_FieldDef_IsRepeated(*f) && IsFieldWrapper(*f)) {
242
236
  return METHOD_WRAPPER_SETTER;
243
237
  }
244
238
  if (Match(m, name, f, o, "", "_const") && *f &&
245
- upb_fielddef_type(*f) == UPB_TYPE_ENUM) {
239
+ upb_FieldDef_CType(*f) == kUpb_CType_Enum) {
246
240
  return METHOD_ENUM_GETTER;
247
241
  }
248
242
 
249
243
  return METHOD_UNKNOWN;
250
244
  }
251
245
 
252
- static VALUE Message_oneof_accessor(VALUE _self, const upb_oneofdef* o,
246
+ static VALUE Message_oneof_accessor(VALUE _self, const upb_OneofDef* o,
253
247
  int accessor_type) {
254
248
  Message* self = ruby_to_Message(_self);
255
- const upb_fielddef* oneof_field = upb_msg_whichoneof(self->msg, o);
249
+ const upb_FieldDef* oneof_field = upb_Message_WhichOneof(self->msg, o);
256
250
 
257
251
  switch (accessor_type) {
258
252
  case METHOD_PRESENCE:
259
253
  return oneof_field == NULL ? Qfalse : Qtrue;
260
254
  case METHOD_CLEAR:
261
255
  if (oneof_field != NULL) {
262
- upb_msg_clearfield(Message_GetMutable(_self, NULL), oneof_field);
256
+ upb_Message_ClearFieldByDef(Message_GetMutable(_self, NULL),
257
+ oneof_field);
263
258
  }
264
259
  return Qnil;
265
260
  case METHOD_GETTER:
266
261
  return oneof_field == NULL
267
262
  ? Qnil
268
- : ID2SYM(rb_intern(upb_fielddef_name(oneof_field)));
263
+ : ID2SYM(rb_intern(upb_FieldDef_Name(oneof_field)));
269
264
  case METHOD_SETTER:
270
265
  rb_raise(rb_eRuntimeError, "Oneof accessors are read-only.");
271
266
  }
272
267
  rb_raise(rb_eRuntimeError, "Invalid access of oneof field.");
273
268
  }
274
269
 
275
- static void Message_setfield(upb_msg* msg, const upb_fielddef* f, VALUE val,
276
- upb_arena* arena) {
277
- upb_msgval msgval;
278
- if (upb_fielddef_ismap(f)) {
270
+ static void Message_setfield(upb_Message* msg, const upb_FieldDef* f, VALUE val,
271
+ upb_Arena* arena) {
272
+ upb_MessageValue msgval;
273
+ if (upb_FieldDef_IsMap(f)) {
279
274
  msgval.map_val = Map_GetUpbMap(val, f, arena);
280
- } else if (upb_fielddef_isseq(f)) {
275
+ } else if (upb_FieldDef_IsRepeated(f)) {
281
276
  msgval.array_val = RepeatedField_GetUpbArray(val, f, arena);
282
277
  } else {
283
278
  if (val == Qnil &&
284
- (upb_fielddef_issubmsg(f) || upb_fielddef_realcontainingoneof(f))) {
285
- upb_msg_clearfield(msg, f);
279
+ (upb_FieldDef_IsSubMessage(f) || upb_FieldDef_RealContainingOneof(f))) {
280
+ upb_Message_ClearFieldByDef(msg, f);
286
281
  return;
287
282
  }
288
283
  msgval =
289
- Convert_RubyToUpb(val, upb_fielddef_name(f), TypeInfo_get(f), arena);
284
+ Convert_RubyToUpb(val, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
290
285
  }
291
- upb_msg_set(msg, f, msgval, arena);
286
+ upb_Message_SetFieldByDef(msg, f, msgval, arena);
292
287
  }
293
288
 
294
- VALUE Message_getfield(VALUE _self, const upb_fielddef* f) {
289
+ VALUE Message_getfield(VALUE _self, const upb_FieldDef* f) {
295
290
  Message* self = ruby_to_Message(_self);
296
- // This is a special-case: upb_msg_mutable() for map & array are logically
291
+ // This is a special-case: upb_Message_Mutable() for map & array are logically
297
292
  // const (they will not change what is serialized) but physically
298
293
  // non-const, as they do allocate a repeated field or map. The logical
299
294
  // constness means it's ok to do even if the message is frozen.
300
- upb_msg *msg = (upb_msg*)self->msg;
301
- upb_arena *arena = Arena_get(self->arena);
302
- if (upb_fielddef_ismap(f)) {
303
- upb_map *map = upb_msg_mutable(msg, f, arena).map;
304
- const upb_fielddef *key_f = map_field_key(f);
305
- const upb_fielddef *val_f = map_field_value(f);
306
- upb_fieldtype_t key_type = upb_fielddef_type(key_f);
295
+ upb_Message* msg = (upb_Message*)self->msg;
296
+ upb_Arena* arena = Arena_get(self->arena);
297
+ if (upb_FieldDef_IsMap(f)) {
298
+ upb_Map* map = upb_Message_Mutable(msg, f, arena).map;
299
+ const upb_FieldDef* key_f = map_field_key(f);
300
+ const upb_FieldDef* val_f = map_field_value(f);
301
+ upb_CType key_type = upb_FieldDef_CType(key_f);
307
302
  TypeInfo value_type_info = TypeInfo_get(val_f);
308
303
  return Map_GetRubyWrapper(map, key_type, value_type_info, self->arena);
309
- } else if (upb_fielddef_isseq(f)) {
310
- upb_array *arr = upb_msg_mutable(msg, f, arena).array;
304
+ } else if (upb_FieldDef_IsRepeated(f)) {
305
+ upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
311
306
  return RepeatedField_GetRubyWrapper(arr, TypeInfo_get(f), self->arena);
312
- } else if (upb_fielddef_issubmsg(f)) {
313
- if (!upb_msg_has(self->msg, f)) return Qnil;
314
- upb_msg *submsg = upb_msg_mutable(msg, f, arena).msg;
315
- const upb_msgdef *m = upb_fielddef_msgsubdef(f);
307
+ } else if (upb_FieldDef_IsSubMessage(f)) {
308
+ if (!upb_Message_HasFieldByDef(self->msg, f)) return Qnil;
309
+ upb_Message* submsg = upb_Message_Mutable(msg, f, arena).msg;
310
+ const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
316
311
  return Message_GetRubyWrapper(submsg, m, self->arena);
317
312
  } else {
318
- upb_msgval msgval = upb_msg_get(self->msg, f);
313
+ upb_MessageValue msgval = upb_Message_GetFieldByDef(self->msg, f);
319
314
  return Convert_UpbToRuby(msgval, TypeInfo_get(f), self->arena);
320
315
  }
321
316
  }
322
317
 
323
- static VALUE Message_field_accessor(VALUE _self, const upb_fielddef* f,
318
+ static VALUE Message_field_accessor(VALUE _self, const upb_FieldDef* f,
324
319
  int accessor_type, int argc, VALUE* argv) {
325
- upb_arena *arena = Arena_get(Message_GetArena(_self));
320
+ upb_Arena* arena = Arena_get(Message_GetArena(_self));
326
321
 
327
322
  switch (accessor_type) {
328
323
  case METHOD_SETTER:
329
324
  Message_setfield(Message_GetMutable(_self, NULL), f, argv[1], arena);
330
325
  return Qnil;
331
326
  case METHOD_CLEAR:
332
- upb_msg_clearfield(Message_GetMutable(_self, NULL), f);
327
+ upb_Message_ClearFieldByDef(Message_GetMutable(_self, NULL), f);
333
328
  return Qnil;
334
329
  case METHOD_PRESENCE:
335
- if (!upb_fielddef_haspresence(f)) {
330
+ if (!upb_FieldDef_HasPresence(f)) {
336
331
  rb_raise(rb_eRuntimeError, "Field does not have presence.");
337
332
  }
338
- return upb_msg_has(Message_Get(_self, NULL), f);
333
+ return upb_Message_HasFieldByDef(Message_Get(_self, NULL), f);
339
334
  case METHOD_WRAPPER_GETTER: {
340
335
  Message* self = ruby_to_Message(_self);
341
- if (upb_msg_has(self->msg, f)) {
342
- PBRUBY_ASSERT(upb_fielddef_issubmsg(f) && !upb_fielddef_isseq(f));
343
- upb_msgval wrapper = upb_msg_get(self->msg, f);
344
- const upb_msgdef *wrapper_m = upb_fielddef_msgsubdef(f);
345
- const upb_fielddef *value_f = upb_msgdef_itof(wrapper_m, 1);
346
- upb_msgval value = upb_msg_get(wrapper.msg_val, value_f);
336
+ if (upb_Message_HasFieldByDef(self->msg, f)) {
337
+ PBRUBY_ASSERT(upb_FieldDef_IsSubMessage(f) &&
338
+ !upb_FieldDef_IsRepeated(f));
339
+ upb_MessageValue wrapper = upb_Message_GetFieldByDef(self->msg, f);
340
+ const upb_MessageDef* wrapper_m = upb_FieldDef_MessageSubDef(f);
341
+ const upb_FieldDef* value_f =
342
+ upb_MessageDef_FindFieldByNumber(wrapper_m, 1);
343
+ upb_MessageValue value =
344
+ upb_Message_GetFieldByDef(wrapper.msg_val, value_f);
347
345
  return Convert_UpbToRuby(value, TypeInfo_get(value_f), self->arena);
348
346
  } else {
349
347
  return Qnil;
350
348
  }
351
349
  }
352
350
  case METHOD_WRAPPER_SETTER: {
353
- upb_msg *msg = Message_GetMutable(_self, NULL);
351
+ upb_Message* msg = Message_GetMutable(_self, NULL);
354
352
  if (argv[1] == Qnil) {
355
- upb_msg_clearfield(msg, f);
353
+ upb_Message_ClearFieldByDef(msg, f);
356
354
  } else {
357
- const upb_fielddef *val_f = upb_msgdef_itof(upb_fielddef_msgsubdef(f), 1);
358
- upb_msgval msgval = Convert_RubyToUpb(argv[1], upb_fielddef_name(f),
359
- TypeInfo_get(val_f), arena);
360
- upb_msg *wrapper = upb_msg_mutable(msg, f, arena).msg;
361
- upb_msg_set(wrapper, val_f, msgval, arena);
355
+ const upb_FieldDef* val_f =
356
+ upb_MessageDef_FindFieldByNumber(upb_FieldDef_MessageSubDef(f), 1);
357
+ upb_MessageValue msgval = Convert_RubyToUpb(
358
+ argv[1], upb_FieldDef_Name(f), TypeInfo_get(val_f), arena);
359
+ upb_Message* wrapper = upb_Message_Mutable(msg, f, arena).msg;
360
+ upb_Message_SetFieldByDef(wrapper, val_f, msgval, arena);
362
361
  }
363
362
  return Qnil;
364
363
  }
365
364
  case METHOD_ENUM_GETTER: {
366
- upb_msgval msgval = upb_msg_get(Message_Get(_self, NULL), f);
365
+ upb_MessageValue msgval =
366
+ upb_Message_GetFieldByDef(Message_Get(_self, NULL), f);
367
367
 
368
- if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
368
+ if (upb_FieldDef_Label(f) == kUpb_Label_Repeated) {
369
369
  // Map repeated fields to a new type with ints
370
370
  VALUE arr = rb_ary_new();
371
- size_t i, n = upb_array_size(msgval.array_val);
371
+ size_t i, n = upb_Array_Size(msgval.array_val);
372
372
  for (i = 0; i < n; i++) {
373
- upb_msgval elem = upb_array_get(msgval.array_val, i);
373
+ upb_MessageValue elem = upb_Array_Get(msgval.array_val, i);
374
374
  rb_ary_push(arr, INT2NUM(elem.int32_val));
375
375
  }
376
376
  return arr;
@@ -415,8 +415,8 @@ static VALUE Message_field_accessor(VALUE _self, const upb_fielddef* f,
415
415
  */
416
416
  static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
417
417
  Message* self = ruby_to_Message(_self);
418
- const upb_oneofdef* o;
419
- const upb_fielddef* f;
418
+ const upb_OneofDef* o;
419
+ const upb_FieldDef* f;
420
420
  int accessor_type;
421
421
 
422
422
  if (argc < 1) {
@@ -453,8 +453,8 @@ static VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
453
453
 
454
454
  static VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
455
455
  Message* self = ruby_to_Message(_self);
456
- const upb_oneofdef* o;
457
- const upb_fielddef* f;
456
+ const upb_OneofDef* o;
457
+ const upb_FieldDef* f;
458
458
  int accessor_type;
459
459
 
460
460
  if (argc < 1) {
@@ -472,53 +472,55 @@ static VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
472
472
  }
473
473
  }
474
474
 
475
- void Message_InitFromValue(upb_msg* msg, const upb_msgdef* m, VALUE val,
476
- upb_arena* arena);
475
+ void Message_InitFromValue(upb_Message* msg, const upb_MessageDef* m, VALUE val,
476
+ upb_Arena* arena);
477
477
 
478
478
  typedef struct {
479
- upb_map *map;
479
+ upb_Map* map;
480
480
  TypeInfo key_type;
481
481
  TypeInfo val_type;
482
- upb_arena *arena;
482
+ upb_Arena* arena;
483
483
  } MapInit;
484
484
 
485
485
  static int Map_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
486
- MapInit *map_init = (MapInit*)_self;
487
- upb_msgval k, v;
486
+ MapInit* map_init = (MapInit*)_self;
487
+ upb_MessageValue k, v;
488
488
  k = Convert_RubyToUpb(key, "", map_init->key_type, NULL);
489
489
 
490
- if (map_init->val_type.type == UPB_TYPE_MESSAGE && TYPE(val) == T_HASH) {
491
- upb_msg *msg = upb_msg_new(map_init->val_type.def.msgdef, map_init->arena);
490
+ if (map_init->val_type.type == kUpb_CType_Message && TYPE(val) == T_HASH) {
491
+ upb_MiniTable* t = upb_MessageDef_MiniTable(map_init->val_type.def.msgdef);
492
+ upb_Message* msg = upb_Message_New(t, map_init->arena);
492
493
  Message_InitFromValue(msg, map_init->val_type.def.msgdef, val,
493
494
  map_init->arena);
494
495
  v.msg_val = msg;
495
496
  } else {
496
497
  v = Convert_RubyToUpb(val, "", map_init->val_type, map_init->arena);
497
498
  }
498
- upb_map_set(map_init->map, k, v, map_init->arena);
499
+ upb_Map_Set(map_init->map, k, v, map_init->arena);
499
500
  return ST_CONTINUE;
500
501
  }
501
502
 
502
- static void Map_InitFromValue(upb_map* map, const upb_fielddef* f, VALUE val,
503
- upb_arena* arena) {
504
- const upb_msgdef* entry_m = upb_fielddef_msgsubdef(f);
505
- const upb_fielddef* key_f = upb_msgdef_itof(entry_m, 1);
506
- const upb_fielddef* val_f = upb_msgdef_itof(entry_m, 2);
503
+ static void Map_InitFromValue(upb_Map* map, const upb_FieldDef* f, VALUE val,
504
+ upb_Arena* arena) {
505
+ const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(f);
506
+ const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry_m, 1);
507
+ const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
507
508
  if (TYPE(val) != T_HASH) {
508
509
  rb_raise(rb_eArgError,
509
510
  "Expected Hash object as initializer value for map field '%s' "
510
511
  "(given %s).",
511
- upb_fielddef_name(f), rb_class2name(CLASS_OF(val)));
512
+ upb_FieldDef_Name(f), rb_class2name(CLASS_OF(val)));
512
513
  }
513
514
  MapInit map_init = {map, TypeInfo_get(key_f), TypeInfo_get(val_f), arena};
514
515
  rb_hash_foreach(val, Map_initialize_kwarg, (VALUE)&map_init);
515
516
  }
516
517
 
517
- static upb_msgval MessageValue_FromValue(VALUE val, TypeInfo info,
518
- upb_arena* arena) {
519
- if (info.type == UPB_TYPE_MESSAGE) {
520
- upb_msgval msgval;
521
- upb_msg* msg = upb_msg_new(info.def.msgdef, arena);
518
+ static upb_MessageValue MessageValue_FromValue(VALUE val, TypeInfo info,
519
+ upb_Arena* arena) {
520
+ if (info.type == kUpb_CType_Message) {
521
+ upb_MessageValue msgval;
522
+ upb_MiniTable* t = upb_MessageDef_MiniTable(info.def.msgdef);
523
+ upb_Message* msg = upb_Message_New(t, arena);
522
524
  Message_InitFromValue(msg, info.def.msgdef, val, arena);
523
525
  msgval.msg_val = msg;
524
526
  return msgval;
@@ -527,61 +529,62 @@ static upb_msgval MessageValue_FromValue(VALUE val, TypeInfo info,
527
529
  }
528
530
  }
529
531
 
530
- static void RepeatedField_InitFromValue(upb_array* arr, const upb_fielddef* f,
531
- VALUE val, upb_arena* arena) {
532
+ static void RepeatedField_InitFromValue(upb_Array* arr, const upb_FieldDef* f,
533
+ VALUE val, upb_Arena* arena) {
532
534
  TypeInfo type_info = TypeInfo_get(f);
533
535
 
534
536
  if (TYPE(val) != T_ARRAY) {
535
537
  rb_raise(rb_eArgError,
536
- "Expected array as initializer value for repeated field '%s' (given %s).",
537
- upb_fielddef_name(f), rb_class2name(CLASS_OF(val)));
538
+ "Expected array as initializer value for repeated field '%s' "
539
+ "(given %s).",
540
+ upb_FieldDef_Name(f), rb_class2name(CLASS_OF(val)));
538
541
  }
539
542
 
540
543
  for (int i = 0; i < RARRAY_LEN(val); i++) {
541
544
  VALUE entry = rb_ary_entry(val, i);
542
- upb_msgval msgval;
543
- if (upb_fielddef_issubmsg(f) && TYPE(entry) == T_HASH) {
545
+ upb_MessageValue msgval;
546
+ if (upb_FieldDef_IsSubMessage(f) && TYPE(entry) == T_HASH) {
544
547
  msgval = MessageValue_FromValue(entry, type_info, arena);
545
548
  } else {
546
- msgval = Convert_RubyToUpb(entry, upb_fielddef_name(f), type_info, arena);
549
+ msgval = Convert_RubyToUpb(entry, upb_FieldDef_Name(f), type_info, arena);
547
550
  }
548
- upb_array_append(arr, msgval, arena);
551
+ upb_Array_Append(arr, msgval, arena);
549
552
  }
550
553
  }
551
554
 
552
- static void Message_InitFieldFromValue(upb_msg* msg, const upb_fielddef* f,
553
- VALUE val, upb_arena* arena) {
555
+ static void Message_InitFieldFromValue(upb_Message* msg, const upb_FieldDef* f,
556
+ VALUE val, upb_Arena* arena) {
554
557
  if (TYPE(val) == T_NIL) return;
555
558
 
556
- if (upb_fielddef_ismap(f)) {
557
- upb_map *map = upb_msg_mutable(msg, f, arena).map;
559
+ if (upb_FieldDef_IsMap(f)) {
560
+ upb_Map* map = upb_Message_Mutable(msg, f, arena).map;
558
561
  Map_InitFromValue(map, f, val, arena);
559
- } else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
560
- upb_array *arr = upb_msg_mutable(msg, f, arena).array;
562
+ } else if (upb_FieldDef_Label(f) == kUpb_Label_Repeated) {
563
+ upb_Array* arr = upb_Message_Mutable(msg, f, arena).array;
561
564
  RepeatedField_InitFromValue(arr, f, val, arena);
562
- } else if (upb_fielddef_issubmsg(f)) {
565
+ } else if (upb_FieldDef_IsSubMessage(f)) {
563
566
  if (TYPE(val) == T_HASH) {
564
- upb_msg *submsg = upb_msg_mutable(msg, f, arena).msg;
565
- Message_InitFromValue(submsg, upb_fielddef_msgsubdef(f), val, arena);
567
+ upb_Message* submsg = upb_Message_Mutable(msg, f, arena).msg;
568
+ Message_InitFromValue(submsg, upb_FieldDef_MessageSubDef(f), val, arena);
566
569
  } else {
567
570
  Message_setfield(msg, f, val, arena);
568
571
  }
569
572
  } else {
570
- upb_msgval msgval =
571
- Convert_RubyToUpb(val, upb_fielddef_name(f), TypeInfo_get(f), arena);
572
- upb_msg_set(msg, f, msgval, arena);
573
+ upb_MessageValue msgval =
574
+ Convert_RubyToUpb(val, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
575
+ upb_Message_SetFieldByDef(msg, f, msgval, arena);
573
576
  }
574
577
  }
575
578
 
576
579
  typedef struct {
577
- upb_msg *msg;
578
- const upb_msgdef *msgdef;
579
- upb_arena *arena;
580
+ upb_Message* msg;
581
+ const upb_MessageDef* msgdef;
582
+ upb_Arena* arena;
580
583
  } MsgInit;
581
584
 
582
585
  static int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
583
- MsgInit *msg_init = (MsgInit*)_self;
584
- const char *name;
586
+ MsgInit* msg_init = (MsgInit*)_self;
587
+ const char* name;
585
588
 
586
589
  if (TYPE(key) == T_STRING) {
587
590
  name = RSTRING_PTR(key);
@@ -589,10 +592,12 @@ static int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
589
592
  name = RSTRING_PTR(rb_id2str(SYM2ID(key)));
590
593
  } else {
591
594
  rb_raise(rb_eArgError,
592
- "Expected string or symbols as hash keys when initializing proto from hash.");
595
+ "Expected string or symbols as hash keys when initializing proto "
596
+ "from hash.");
593
597
  }
594
598
 
595
- const upb_fielddef* f = upb_msgdef_ntofz(msg_init->msgdef, name);
599
+ const upb_FieldDef* f =
600
+ upb_MessageDef_FindFieldByName(msg_init->msgdef, name);
596
601
 
597
602
  if (f == NULL) {
598
603
  rb_raise(rb_eArgError,
@@ -603,8 +608,8 @@ static int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
603
608
  return ST_CONTINUE;
604
609
  }
605
610
 
606
- void Message_InitFromValue(upb_msg* msg, const upb_msgdef* m, VALUE val,
607
- upb_arena* arena) {
611
+ void Message_InitFromValue(upb_Message* msg, const upb_MessageDef* m, VALUE val,
612
+ upb_Arena* arena) {
608
613
  MsgInit msg_init = {msg, m, arena};
609
614
  if (TYPE(val) == T_HASH) {
610
615
  rb_hash_foreach(val, Message_initialize_kwarg, (VALUE)&msg_init);
@@ -629,8 +634,9 @@ void Message_InitFromValue(upb_msg* msg, const upb_msgdef* m, VALUE val,
629
634
  static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
630
635
  Message* self = ruby_to_Message(_self);
631
636
  VALUE arena_rb = Arena_new();
632
- upb_arena *arena = Arena_get(arena_rb);
633
- upb_msg *msg = upb_msg_new(self->msgdef, arena);
637
+ upb_Arena* arena = Arena_get(arena_rb);
638
+ upb_MiniTable* t = upb_MessageDef_MiniTable(self->msgdef);
639
+ upb_Message* msg = upb_Message_New(t, arena);
634
640
 
635
641
  Message_InitPtr(_self, msg, arena_rb);
636
642
 
@@ -640,7 +646,7 @@ static VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
640
646
  if (argc != 1) {
641
647
  rb_raise(rb_eArgError, "Expected 0 or 1 arguments.");
642
648
  }
643
- Message_InitFromValue((upb_msg*)self->msg, self->msgdef, argv[0], arena);
649
+ Message_InitFromValue((upb_Message*)self->msg, self->msgdef, argv[0], arena);
644
650
  return Qnil;
645
651
  }
646
652
 
@@ -654,35 +660,25 @@ static VALUE Message_dup(VALUE _self) {
654
660
  Message* self = ruby_to_Message(_self);
655
661
  VALUE new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
656
662
  Message* new_msg_self = ruby_to_Message(new_msg);
657
- size_t size = upb_msgdef_layout(self->msgdef)->size;
663
+ size_t size = upb_MessageDef_MiniTable(self->msgdef)->size;
658
664
 
659
- // TODO(copy unknown fields?)
660
- // TODO(use official upb msg copy function)
661
- memcpy((upb_msg*)new_msg_self->msg, self->msg, size);
665
+ // TODO
666
+ // TODO
667
+ memcpy((upb_Message*)new_msg_self->msg, self->msg, size);
662
668
  Arena_fuse(self->arena, Arena_get(new_msg_self->arena));
663
669
  return new_msg;
664
670
  }
665
671
 
666
672
  // Support function for Message_eq, and also used by other #eq functions.
667
- bool Message_Equal(const upb_msg *m1, const upb_msg *m2, const upb_msgdef *m) {
668
- if (m1 == m2) return true;
669
-
670
- size_t size1, size2;
671
- int encode_opts = UPB_ENCODE_SKIPUNKNOWN | UPB_ENCODE_DETERMINISTIC;
672
- upb_arena *arena_tmp = upb_arena_new();
673
- const upb_msglayout *layout = upb_msgdef_layout(m);
674
-
675
- // Compare deterministically serialized payloads with no unknown fields.
676
- char *data1 = upb_encode_ex(m1, layout, encode_opts, arena_tmp, &size1);
677
- char *data2 = upb_encode_ex(m2, layout, encode_opts, arena_tmp, &size2);
678
-
679
- if (data1 && data2) {
680
- bool ret = (size1 == size2) && (memcmp(data1, data2, size1) == 0);
681
- upb_arena_free(arena_tmp);
682
- return ret;
673
+ bool Message_Equal(const upb_Message* m1, const upb_Message* m2,
674
+ const upb_MessageDef* m) {
675
+ upb_Status status;
676
+ upb_Status_Clear(&status);
677
+ bool return_value = shared_Message_Equal(m1, m2, m, &status);
678
+ if (upb_Status_IsOk(&status)) {
679
+ return return_value;
683
680
  } else {
684
- upb_arena_free(arena_tmp);
685
- rb_raise(cParseError, "Error comparing messages");
681
+ rb_raise(cParseError, upb_Status_ErrorMessage(&status));
686
682
  }
687
683
  }
688
684
 
@@ -705,23 +701,15 @@ static VALUE Message_eq(VALUE _self, VALUE _other) {
705
701
  return Message_Equal(self->msg, other->msg, self->msgdef) ? Qtrue : Qfalse;
706
702
  }
707
703
 
708
- uint64_t Message_Hash(const upb_msg* msg, const upb_msgdef* m, uint64_t seed) {
709
- upb_arena *arena = upb_arena_new();
710
- const char *data;
711
- size_t size;
712
-
713
- // Hash a deterministically serialized payloads with no unknown fields.
714
- data = upb_encode_ex(msg, upb_msgdef_layout(m),
715
- UPB_ENCODE_SKIPUNKNOWN | UPB_ENCODE_DETERMINISTIC, arena,
716
- &size);
717
-
718
- if (data) {
719
- uint64_t ret = Wyhash(data, size, seed, kWyhashSalt);
720
- upb_arena_free(arena);
721
- return ret;
704
+ uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
705
+ uint64_t seed) {
706
+ upb_Status status;
707
+ upb_Status_Clear(&status);
708
+ uint64_t return_value = shared_Message_Hash(msg, m, seed, &status);
709
+ if (upb_Status_IsOk(&status)) {
710
+ return return_value;
722
711
  } else {
723
- upb_arena_free(arena);
724
- rb_raise(cParseError, "Error calculating hash");
712
+ rb_raise(cParseError, upb_Status_ErrorMessage(&status));
725
713
  }
726
714
  }
727
715
 
@@ -759,13 +747,13 @@ static VALUE Message_inspect(VALUE _self) {
759
747
 
760
748
  // Support functions for Message_to_h //////////////////////////////////////////
761
749
 
762
- static VALUE RepeatedField_CreateArray(const upb_array* arr,
750
+ static VALUE RepeatedField_CreateArray(const upb_Array* arr,
763
751
  TypeInfo type_info) {
764
- int size = arr ? upb_array_size(arr) : 0;
752
+ int size = arr ? upb_Array_Size(arr) : 0;
765
753
  VALUE ary = rb_ary_new2(size);
766
754
 
767
755
  for (int i = 0; i < size; i++) {
768
- upb_msgval msgval = upb_array_get(arr, i);
756
+ upb_MessageValue msgval = upb_Array_Get(arr, i);
769
757
  VALUE val = Scalar_CreateHash(msgval, type_info);
770
758
  rb_ary_push(ary, val);
771
759
  }
@@ -773,54 +761,56 @@ static VALUE RepeatedField_CreateArray(const upb_array* arr,
773
761
  return ary;
774
762
  }
775
763
 
776
- static VALUE Message_CreateHash(const upb_msg *msg, const upb_msgdef *m) {
764
+ static VALUE Message_CreateHash(const upb_Message* msg,
765
+ const upb_MessageDef* m) {
777
766
  if (!msg) return Qnil;
778
767
 
779
768
  VALUE hash = rb_hash_new();
780
- int n = upb_msgdef_fieldcount(m);
769
+ int n = upb_MessageDef_FieldCount(m);
781
770
  bool is_proto2;
782
771
 
783
772
  // We currently have a few behaviors that are specific to proto2.
784
773
  // This is unfortunate, we should key behaviors off field attributes (like
785
774
  // whether a field has presence), not proto2 vs. proto3. We should see if we
786
775
  // can change this without breaking users.
787
- is_proto2 = upb_msgdef_syntax(m) == UPB_SYNTAX_PROTO2;
776
+ is_proto2 = upb_MessageDef_Syntax(m) == kUpb_Syntax_Proto2;
788
777
 
789
778
  for (int i = 0; i < n; i++) {
790
- const upb_fielddef* field = upb_msgdef_field(m, i);
779
+ const upb_FieldDef* field = upb_MessageDef_Field(m, i);
791
780
  TypeInfo type_info = TypeInfo_get(field);
792
- upb_msgval msgval;
781
+ upb_MessageValue msgval;
793
782
  VALUE msg_value;
794
783
  VALUE msg_key;
795
784
 
796
- if (!is_proto2 && upb_fielddef_issubmsg(field) &&
797
- !upb_fielddef_isseq(field) && !upb_msg_has(msg, field)) {
785
+ if (!is_proto2 && upb_FieldDef_IsSubMessage(field) &&
786
+ !upb_FieldDef_IsRepeated(field) &&
787
+ !upb_Message_HasFieldByDef(msg, field)) {
798
788
  // TODO: Legacy behavior, remove when we fix the is_proto2 differences.
799
- msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
789
+ msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
800
790
  rb_hash_aset(hash, msg_key, Qnil);
801
791
  continue;
802
792
  }
803
793
 
804
794
  // Do not include fields that are not present (oneof or optional fields).
805
- if (is_proto2 && upb_fielddef_haspresence(field) &&
806
- !upb_msg_has(msg, field)) {
795
+ if (is_proto2 && upb_FieldDef_HasPresence(field) &&
796
+ !upb_Message_HasFieldByDef(msg, field)) {
807
797
  continue;
808
798
  }
809
799
 
810
- msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
811
- msgval = upb_msg_get(msg, field);
800
+ msg_key = ID2SYM(rb_intern(upb_FieldDef_Name(field)));
801
+ msgval = upb_Message_GetFieldByDef(msg, field);
812
802
 
813
803
  // Proto2 omits empty map/repeated filds also.
814
804
 
815
- if (upb_fielddef_ismap(field)) {
816
- const upb_msgdef *entry_m = upb_fielddef_msgsubdef(field);
817
- const upb_fielddef *key_f = upb_msgdef_itof(entry_m, 1);
818
- const upb_fielddef *val_f = upb_msgdef_itof(entry_m, 2);
819
- upb_fieldtype_t key_type = upb_fielddef_type(key_f);
805
+ if (upb_FieldDef_IsMap(field)) {
806
+ const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(field);
807
+ const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry_m, 1);
808
+ const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
809
+ upb_CType key_type = upb_FieldDef_CType(key_f);
820
810
  msg_value = Map_CreateHash(msgval.map_val, key_type, TypeInfo_get(val_f));
821
- } else if (upb_fielddef_isseq(field)) {
811
+ } else if (upb_FieldDef_IsRepeated(field)) {
822
812
  if (is_proto2 &&
823
- (!msgval.array_val || upb_array_size(msgval.array_val) == 0)) {
813
+ (!msgval.array_val || upb_Array_Size(msgval.array_val) == 0)) {
824
814
  continue;
825
815
  }
826
816
  msg_value = RepeatedField_CreateArray(msgval.array_val, type_info);
@@ -834,8 +824,8 @@ static VALUE Message_CreateHash(const upb_msg *msg, const upb_msgdef *m) {
834
824
  return hash;
835
825
  }
836
826
 
837
- VALUE Scalar_CreateHash(upb_msgval msgval, TypeInfo type_info) {
838
- if (type_info.type == UPB_TYPE_MESSAGE) {
827
+ VALUE Scalar_CreateHash(upb_MessageValue msgval, TypeInfo type_info) {
828
+ if (type_info.type == kUpb_CType_Message) {
839
829
  return Message_CreateHash(msgval.msg_val, type_info.def.msgdef);
840
830
  } else {
841
831
  return Convert_UpbToRuby(msgval, type_info, Qnil);
@@ -869,6 +859,32 @@ static VALUE Message_freeze(VALUE _self) {
869
859
  return _self;
870
860
  }
871
861
 
862
+ /*
863
+ * Deep freezes the message object recursively.
864
+ * Internal use only.
865
+ */
866
+ VALUE Message_internal_deep_freeze(VALUE _self) {
867
+ Message* self = ruby_to_Message(_self);
868
+ Message_freeze(_self);
869
+
870
+ int n = upb_MessageDef_FieldCount(self->msgdef);
871
+ for (int i = 0; i < n; i++) {
872
+ const upb_FieldDef* f = upb_MessageDef_Field(self->msgdef, i);
873
+ VALUE field = Message_getfield(_self, f);
874
+
875
+ if (field != Qnil) {
876
+ if (upb_FieldDef_IsMap(f)) {
877
+ Map_internal_deep_freeze(field);
878
+ } else if (upb_FieldDef_IsRepeated(f)) {
879
+ RepeatedField_internal_deep_freeze(field);
880
+ } else if (upb_FieldDef_IsSubMessage(f)) {
881
+ Message_internal_deep_freeze(field);
882
+ }
883
+ }
884
+ }
885
+ return _self;
886
+ }
887
+
872
888
  /*
873
889
  * call-seq:
874
890
  * Message.[](index) => value
@@ -878,10 +894,10 @@ static VALUE Message_freeze(VALUE _self) {
878
894
  */
879
895
  static VALUE Message_index(VALUE _self, VALUE field_name) {
880
896
  Message* self = ruby_to_Message(_self);
881
- const upb_fielddef* field;
897
+ const upb_FieldDef* field;
882
898
 
883
899
  Check_Type(field_name, T_STRING);
884
- field = upb_msgdef_ntofz(self->msgdef, RSTRING_PTR(field_name));
900
+ field = upb_MessageDef_FindFieldByName(self->msgdef, RSTRING_PTR(field_name));
885
901
 
886
902
  if (field == NULL) {
887
903
  return Qnil;
@@ -899,45 +915,80 @@ static VALUE Message_index(VALUE _self, VALUE field_name) {
899
915
  */
900
916
  static VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
901
917
  Message* self = ruby_to_Message(_self);
902
- const upb_fielddef* f;
903
- upb_msgval val;
904
- upb_arena *arena = Arena_get(self->arena);
918
+ const upb_FieldDef* f;
919
+ upb_MessageValue val;
920
+ upb_Arena* arena = Arena_get(self->arena);
905
921
 
906
922
  Check_Type(field_name, T_STRING);
907
- f = upb_msgdef_ntofz(self->msgdef, RSTRING_PTR(field_name));
923
+ f = upb_MessageDef_FindFieldByName(self->msgdef, RSTRING_PTR(field_name));
908
924
 
909
925
  if (f == NULL) {
910
926
  rb_raise(rb_eArgError, "Unknown field: %s", RSTRING_PTR(field_name));
911
927
  }
912
928
 
913
- val = Convert_RubyToUpb(value, upb_fielddef_name(f), TypeInfo_get(f), arena);
914
- upb_msg_set(Message_GetMutable(_self, NULL), f, val, arena);
929
+ val = Convert_RubyToUpb(value, upb_FieldDef_Name(f), TypeInfo_get(f), arena);
930
+ upb_Message_SetFieldByDef(Message_GetMutable(_self, NULL), f, val, arena);
915
931
 
916
932
  return Qnil;
917
933
  }
918
934
 
919
935
  /*
920
936
  * call-seq:
921
- * MessageClass.decode(data) => message
937
+ * MessageClass.decode(data, options) => message
922
938
  *
923
939
  * Decodes the given data (as a string containing bytes in protocol buffers wire
924
- * format) under the interpretration given by this message class's definition
940
+ * format) under the interpretation given by this message class's definition
925
941
  * and returns a message object with the corresponding field values.
942
+ * @param options [Hash] options for the decoder
943
+ * recursion_limit: set to maximum decoding depth for message (default is 64)
926
944
  */
927
- static VALUE Message_decode(VALUE klass, VALUE data) {
945
+ static VALUE Message_decode(int argc, VALUE* argv, VALUE klass) {
946
+ VALUE data = argv[0];
947
+ int options = 0;
948
+
949
+ if (argc < 1 || argc > 2) {
950
+ rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
951
+ }
952
+
953
+ if (argc == 2) {
954
+ VALUE hash_args = argv[1];
955
+ if (TYPE(hash_args) != T_HASH) {
956
+ rb_raise(rb_eArgError, "Expected hash arguments.");
957
+ }
958
+
959
+ VALUE depth =
960
+ rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
961
+
962
+ if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
963
+ options |= upb_DecodeOptions_MaxDepth(FIX2INT(depth));
964
+ }
965
+ }
966
+
928
967
  if (TYPE(data) != T_STRING) {
929
968
  rb_raise(rb_eArgError, "Expected string for binary protobuf data.");
930
969
  }
931
970
 
971
+ return Message_decode_bytes(RSTRING_LEN(data), RSTRING_PTR(data), options,
972
+ klass, /*freeze*/ false);
973
+ }
974
+
975
+ VALUE Message_decode_bytes(int size, const char* bytes, int options,
976
+ VALUE klass, bool freeze) {
932
977
  VALUE msg_rb = initialize_rb_class_with_no_args(klass);
933
978
  Message* msg = ruby_to_Message(msg_rb);
934
979
 
935
- if (!upb_decode(RSTRING_PTR(data), RSTRING_LEN(data), (upb_msg*)msg->msg,
936
- upb_msgdef_layout(msg->msgdef),
937
- Arena_get(msg->arena))) {
980
+ const upb_FileDef* file = upb_MessageDef_File(msg->msgdef);
981
+ const upb_ExtensionRegistry* extreg =
982
+ upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
983
+ upb_DecodeStatus status = upb_Decode(bytes, size, (upb_Message*)msg->msg,
984
+ upb_MessageDef_MiniTable(msg->msgdef),
985
+ extreg, options, Arena_get(msg->arena));
986
+ if (status != kUpb_DecodeStatus_Ok) {
938
987
  rb_raise(cParseError, "Error occurred during parsing");
939
988
  }
940
-
989
+ if (freeze) {
990
+ Message_internal_deep_freeze(msg_rb);
991
+ }
941
992
  return msg_rb;
942
993
  }
943
994
 
@@ -956,10 +1007,10 @@ static VALUE Message_decode(VALUE klass, VALUE data) {
956
1007
  static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
957
1008
  VALUE data = argv[0];
958
1009
  int options = 0;
959
- upb_status status;
1010
+ upb_Status status;
960
1011
 
961
- // TODO(haberman): use this message's pool instead.
962
- const upb_symtab *symtab = DescriptorPool_GetSymtab(generated_pool);
1012
+ // TODO: use this message's pool instead.
1013
+ const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
963
1014
 
964
1015
  if (argc < 1 || argc > 2) {
965
1016
  rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
@@ -971,8 +1022,9 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
971
1022
  rb_raise(rb_eArgError, "Expected hash arguments.");
972
1023
  }
973
1024
 
974
- if (RTEST(rb_hash_lookup2( hash_args, ID2SYM(rb_intern("ignore_unknown_fields")), Qfalse))) {
975
- options |= UPB_JSONDEC_IGNOREUNKNOWN;
1025
+ if (RTEST(rb_hash_lookup2(
1026
+ hash_args, ID2SYM(rb_intern("ignore_unknown_fields")), Qfalse))) {
1027
+ options |= upb_JsonDecode_IgnoreUnknown;
976
1028
  }
977
1029
  }
978
1030
 
@@ -980,7 +1032,7 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
980
1032
  rb_raise(rb_eArgError, "Expected string for JSON data.");
981
1033
  }
982
1034
 
983
- // TODO(cfallin): Check and respect string encoding. If not UTF-8, we need to
1035
+ // TODO: Check and respect string encoding. If not UTF-8, we need to
984
1036
  // convert, because string handlers pass data directly to message string
985
1037
  // fields.
986
1038
 
@@ -988,16 +1040,16 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
988
1040
  Message* msg = ruby_to_Message(msg_rb);
989
1041
 
990
1042
  // We don't allow users to decode a wrapper type directly.
991
- if (upb_msgdef_iswrapper(msg->msgdef)) {
1043
+ if (IsWrapper(msg->msgdef)) {
992
1044
  rb_raise(rb_eRuntimeError, "Cannot parse a wrapper directly.");
993
1045
  }
994
1046
 
995
- upb_status_clear(&status);
996
- if (!upb_json_decode(RSTRING_PTR(data), RSTRING_LEN(data), (upb_msg*)msg->msg,
997
- msg->msgdef, symtab, options,
998
- Arena_get(msg->arena), &status)) {
1047
+ upb_Status_Clear(&status);
1048
+ if (!upb_JsonDecode(RSTRING_PTR(data), RSTRING_LEN(data),
1049
+ (upb_Message*)msg->msg, msg->msgdef, symtab, options,
1050
+ Arena_get(msg->arena), &status)) {
999
1051
  rb_raise(cParseError, "Error occurred during parsing: %s",
1000
- upb_status_errmsg(&status));
1052
+ upb_Status_ErrorMessage(&status));
1001
1053
  }
1002
1054
 
1003
1055
  return msg_rb;
@@ -1005,32 +1057,53 @@ static VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass) {
1005
1057
 
1006
1058
  /*
1007
1059
  * call-seq:
1008
- * MessageClass.encode(msg) => bytes
1060
+ * MessageClass.encode(msg, options) => bytes
1009
1061
  *
1010
1062
  * Encodes the given message object to its serialized form in protocol buffers
1011
1063
  * wire format.
1064
+ * @param options [Hash] options for the encoder
1065
+ * recursion_limit: set to maximum encoding depth for message (default is 64)
1012
1066
  */
1013
- static VALUE Message_encode(VALUE klass, VALUE msg_rb) {
1014
- Message* msg = ruby_to_Message(msg_rb);
1015
- const char *data;
1067
+ static VALUE Message_encode(int argc, VALUE* argv, VALUE klass) {
1068
+ Message* msg = ruby_to_Message(argv[0]);
1069
+ int options = 0;
1070
+ char* data;
1016
1071
  size_t size;
1017
1072
 
1018
- if (CLASS_OF(msg_rb) != klass) {
1073
+ if (CLASS_OF(argv[0]) != klass) {
1019
1074
  rb_raise(rb_eArgError, "Message of wrong type.");
1020
1075
  }
1021
1076
 
1022
- upb_arena *arena = upb_arena_new();
1077
+ if (argc < 1 || argc > 2) {
1078
+ rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
1079
+ }
1080
+
1081
+ if (argc == 2) {
1082
+ VALUE hash_args = argv[1];
1083
+ if (TYPE(hash_args) != T_HASH) {
1084
+ rb_raise(rb_eArgError, "Expected hash arguments.");
1085
+ }
1086
+ VALUE depth =
1087
+ rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
1088
+
1089
+ if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
1090
+ options |= upb_DecodeOptions_MaxDepth(FIX2INT(depth));
1091
+ }
1092
+ }
1093
+
1094
+ upb_Arena* arena = upb_Arena_New();
1023
1095
 
1024
- data = upb_encode(msg->msg, upb_msgdef_layout(msg->msgdef), arena,
1025
- &size);
1096
+ upb_EncodeStatus status =
1097
+ upb_Encode(msg->msg, upb_MessageDef_MiniTable(msg->msgdef), options,
1098
+ arena, &data, &size);
1026
1099
 
1027
- if (data) {
1100
+ if (status == kUpb_EncodeStatus_Ok) {
1028
1101
  VALUE ret = rb_str_new(data, size);
1029
1102
  rb_enc_associate(ret, rb_ascii8bit_encoding());
1030
- upb_arena_free(arena);
1103
+ upb_Arena_Free(arena);
1031
1104
  return ret;
1032
1105
  } else {
1033
- upb_arena_free(arena);
1106
+ upb_Arena_Free(arena);
1034
1107
  rb_raise(rb_eRuntimeError, "Exceeded maximum depth (possibly cycle)");
1035
1108
  }
1036
1109
  }
@@ -1041,18 +1114,19 @@ static VALUE Message_encode(VALUE klass, VALUE msg_rb) {
1041
1114
  *
1042
1115
  * Encodes the given message object into its serialized JSON representation.
1043
1116
  * @param options [Hash] options for the decoder
1044
- * preserve_proto_fieldnames: set true to use original fieldnames (default is to camelCase)
1045
- * emit_defaults: set true to emit 0/false values (default is to omit them)
1117
+ * preserve_proto_fieldnames: set true to use original fieldnames (default is
1118
+ * to camelCase) emit_defaults: set true to emit 0/false values (default is to
1119
+ * omit them)
1046
1120
  */
1047
1121
  static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
1048
1122
  Message* msg = ruby_to_Message(argv[0]);
1049
1123
  int options = 0;
1050
1124
  char buf[1024];
1051
1125
  size_t size;
1052
- upb_status status;
1126
+ upb_Status status;
1053
1127
 
1054
- // TODO(haberman): use this message's pool instead.
1055
- const upb_symtab *symtab = DescriptorPool_GetSymtab(generated_pool);
1128
+ // TODO: use this message's pool instead.
1129
+ const upb_DefPool* symtab = DescriptorPool_GetSymtab(generated_pool);
1056
1130
 
1057
1131
  if (argc < 1 || argc > 2) {
1058
1132
  rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
@@ -1061,35 +1135,46 @@ static VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
1061
1135
  if (argc == 2) {
1062
1136
  VALUE hash_args = argv[1];
1063
1137
  if (TYPE(hash_args) != T_HASH) {
1064
- rb_raise(rb_eArgError, "Expected hash arguments.");
1138
+ if (RTEST(rb_funcall(hash_args, rb_intern("respond_to?"), 1,
1139
+ rb_str_new2("to_h")))) {
1140
+ hash_args = rb_funcall(hash_args, rb_intern("to_h"), 0);
1141
+ } else {
1142
+ rb_raise(rb_eArgError, "Expected hash arguments.");
1143
+ }
1065
1144
  }
1066
1145
 
1067
1146
  if (RTEST(rb_hash_lookup2(hash_args,
1068
1147
  ID2SYM(rb_intern("preserve_proto_fieldnames")),
1069
1148
  Qfalse))) {
1070
- options |= UPB_JSONENC_PROTONAMES;
1149
+ options |= upb_JsonEncode_UseProtoNames;
1071
1150
  }
1072
1151
 
1073
1152
  if (RTEST(rb_hash_lookup2(hash_args, ID2SYM(rb_intern("emit_defaults")),
1074
1153
  Qfalse))) {
1075
- options |= UPB_JSONENC_EMITDEFAULTS;
1154
+ options |= upb_JsonEncode_EmitDefaults;
1155
+ }
1156
+
1157
+ if (RTEST(rb_hash_lookup2(hash_args,
1158
+ ID2SYM(rb_intern("format_enums_as_integers")),
1159
+ Qfalse))) {
1160
+ options |= upb_JsonEncode_FormatEnumsAsIntegers;
1076
1161
  }
1077
1162
  }
1078
1163
 
1079
- upb_status_clear(&status);
1080
- size = upb_json_encode(msg->msg, msg->msgdef, symtab, options, buf,
1081
- sizeof(buf), &status);
1164
+ upb_Status_Clear(&status);
1165
+ size = upb_JsonEncode(msg->msg, msg->msgdef, symtab, options, buf,
1166
+ sizeof(buf), &status);
1082
1167
 
1083
- if (!upb_ok(&status)) {
1168
+ if (!upb_Status_IsOk(&status)) {
1084
1169
  rb_raise(cParseError, "Error occurred during encoding: %s",
1085
- upb_status_errmsg(&status));
1170
+ upb_Status_ErrorMessage(&status));
1086
1171
  }
1087
1172
 
1088
1173
  VALUE ret;
1089
1174
  if (size >= sizeof(buf)) {
1090
1175
  char* buf2 = malloc(size + 1);
1091
- upb_json_encode(msg->msg, msg->msgdef, symtab, options, buf2, size + 1,
1092
- &status);
1176
+ upb_JsonEncode(msg->msg, msg->msgdef, symtab, options, buf2, size + 1,
1177
+ &status);
1093
1178
  ret = rb_str_new(buf2, size);
1094
1179
  free(buf2);
1095
1180
  } else {
@@ -1112,10 +1197,10 @@ static VALUE Message_descriptor(VALUE klass) {
1112
1197
  }
1113
1198
 
1114
1199
  VALUE build_class_from_descriptor(VALUE descriptor) {
1115
- const char *name;
1200
+ const char* name;
1116
1201
  VALUE klass;
1117
1202
 
1118
- name = upb_msgdef_fullname(Descriptor_GetMsgDef(descriptor));
1203
+ name = upb_MessageDef_FullName(Descriptor_GetMsgDef(descriptor));
1119
1204
  if (name == NULL) {
1120
1205
  rb_raise(rb_eRuntimeError, "Descriptor does not have assigned name.");
1121
1206
  }
@@ -1123,38 +1208,8 @@ VALUE build_class_from_descriptor(VALUE descriptor) {
1123
1208
  klass = rb_define_class_id(
1124
1209
  // Docs say this parameter is ignored. User will assign return value to
1125
1210
  // their own toplevel constant class name.
1126
- rb_intern("Message"),
1127
- rb_cObject);
1211
+ rb_intern("Message"), cAbstractMessage);
1128
1212
  rb_ivar_set(klass, descriptor_instancevar_interned, descriptor);
1129
- rb_define_alloc_func(klass, Message_alloc);
1130
- rb_require("google/protobuf/message_exts");
1131
- rb_include_module(klass, rb_eval_string("::Google::Protobuf::MessageExts"));
1132
- rb_extend_object(
1133
- klass, rb_eval_string("::Google::Protobuf::MessageExts::ClassMethods"));
1134
-
1135
- rb_define_method(klass, "method_missing",
1136
- Message_method_missing, -1);
1137
- rb_define_method(klass, "respond_to_missing?",
1138
- Message_respond_to_missing, -1);
1139
- rb_define_method(klass, "initialize", Message_initialize, -1);
1140
- rb_define_method(klass, "dup", Message_dup, 0);
1141
- // Also define #clone so that we don't inherit Object#clone.
1142
- rb_define_method(klass, "clone", Message_dup, 0);
1143
- rb_define_method(klass, "==", Message_eq, 1);
1144
- rb_define_method(klass, "eql?", Message_eq, 1);
1145
- rb_define_method(klass, "freeze", Message_freeze, 0);
1146
- rb_define_method(klass, "hash", Message_hash, 0);
1147
- rb_define_method(klass, "to_h", Message_to_h, 0);
1148
- rb_define_method(klass, "inspect", Message_inspect, 0);
1149
- rb_define_method(klass, "to_s", Message_inspect, 0);
1150
- rb_define_method(klass, "[]", Message_index, 1);
1151
- rb_define_method(klass, "[]=", Message_index_set, 2);
1152
- rb_define_singleton_method(klass, "decode", Message_decode, 1);
1153
- rb_define_singleton_method(klass, "encode", Message_encode, 1);
1154
- rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1);
1155
- rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
1156
- rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
1157
-
1158
1213
  return klass;
1159
1214
  }
1160
1215
 
@@ -1168,13 +1223,12 @@ VALUE build_class_from_descriptor(VALUE descriptor) {
1168
1223
  static VALUE enum_lookup(VALUE self, VALUE number) {
1169
1224
  int32_t num = NUM2INT(number);
1170
1225
  VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
1171
- const upb_enumdef *e = EnumDescriptor_GetEnumDef(desc);
1172
-
1173
- const char* name = upb_enumdef_iton(e, num);
1174
- if (name == NULL) {
1175
- return Qnil;
1226
+ const upb_EnumDef* e = EnumDescriptor_GetEnumDef(desc);
1227
+ const upb_EnumValueDef* ev = upb_EnumDef_FindValueByNumber(e, num);
1228
+ if (ev) {
1229
+ return ID2SYM(rb_intern(upb_EnumValueDef_Name(ev)));
1176
1230
  } else {
1177
- return ID2SYM(rb_intern(name));
1231
+ return Qnil;
1178
1232
  }
1179
1233
  }
1180
1234
 
@@ -1188,14 +1242,12 @@ static VALUE enum_lookup(VALUE self, VALUE number) {
1188
1242
  static VALUE enum_resolve(VALUE self, VALUE sym) {
1189
1243
  const char* name = rb_id2name(SYM2ID(sym));
1190
1244
  VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
1191
- const upb_enumdef *e = EnumDescriptor_GetEnumDef(desc);
1192
-
1193
- int32_t num = 0;
1194
- bool found = upb_enumdef_ntoiz(e, name, &num);
1195
- if (!found) {
1196
- return Qnil;
1245
+ const upb_EnumDef* e = EnumDescriptor_GetEnumDef(desc);
1246
+ const upb_EnumValueDef* ev = upb_EnumDef_FindValueByName(e, name);
1247
+ if (ev) {
1248
+ return INT2NUM(upb_EnumValueDef_Number(ev));
1197
1249
  } else {
1198
- return INT2NUM(num);
1250
+ return Qnil;
1199
1251
  }
1200
1252
  }
1201
1253
 
@@ -1211,21 +1263,28 @@ static VALUE enum_descriptor(VALUE self) {
1211
1263
  }
1212
1264
 
1213
1265
  VALUE build_module_from_enumdesc(VALUE _enumdesc) {
1214
- const upb_enumdef *e = EnumDescriptor_GetEnumDef(_enumdesc);
1215
- VALUE mod = rb_define_module_id(rb_intern(upb_enumdef_fullname(e)));
1216
-
1217
- upb_enum_iter it;
1218
- for (upb_enum_begin(&it, e);
1219
- !upb_enum_done(&it);
1220
- upb_enum_next(&it)) {
1221
- const char* name = upb_enum_iter_name(&it);
1222
- int32_t value = upb_enum_iter_number(&it);
1266
+ const upb_EnumDef* e = EnumDescriptor_GetEnumDef(_enumdesc);
1267
+ VALUE mod = rb_define_module_id(rb_intern(upb_EnumDef_FullName(e)));
1268
+
1269
+ int n = upb_EnumDef_ValueCount(e);
1270
+ for (int i = 0; i < n; i++) {
1271
+ const upb_EnumValueDef* ev = upb_EnumDef_Value(e, i);
1272
+ upb_Arena* arena = upb_Arena_New();
1273
+ const char* src_name = upb_EnumValueDef_Name(ev);
1274
+ char* name = upb_strdup2(src_name, strlen(src_name), arena);
1275
+ int32_t value = upb_EnumValueDef_Number(ev);
1223
1276
  if (name[0] < 'A' || name[0] > 'Z') {
1224
- rb_warn("Enum value '%s' does not start with an uppercase letter "
1225
- "as is required for Ruby constants.",
1226
- name);
1277
+ if (name[0] >= 'a' && name[0] <= 'z') {
1278
+ name[0] -= 32; // auto capitalize
1279
+ } else {
1280
+ rb_warn(
1281
+ "Enum value '%s' does not start with an uppercase letter "
1282
+ "as is required for Ruby constants.",
1283
+ name);
1284
+ }
1227
1285
  }
1228
1286
  rb_define_const(mod, name, INT2NUM(value));
1287
+ upb_Arena_Free(arena);
1229
1288
  }
1230
1289
 
1231
1290
  rb_define_singleton_method(mod, "lookup", enum_lookup, 1);
@@ -1236,81 +1295,88 @@ VALUE build_module_from_enumdesc(VALUE _enumdesc) {
1236
1295
  return mod;
1237
1296
  }
1238
1297
 
1239
- // Internal only; used by Google::Protobuf.deep_copy.
1240
- upb_msg* Message_deep_copy(const upb_msg* msg, const upb_msgdef* m,
1241
- upb_arena *arena) {
1298
+ // Internal to the library; used by Google::Protobuf.deep_copy.
1299
+ upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
1300
+ upb_Arena* arena) {
1242
1301
  // Serialize and parse.
1243
- upb_arena *tmp_arena = upb_arena_new();
1244
- const upb_msglayout *layout = upb_msgdef_layout(m);
1302
+ upb_Arena* tmp_arena = upb_Arena_New();
1303
+ const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
1245
1304
  size_t size;
1246
1305
 
1247
- char* data = upb_encode_ex(msg, layout, 0, tmp_arena, &size);
1248
- upb_msg* new_msg = upb_msg_new(m, arena);
1249
-
1250
- if (!data || !upb_decode(data, size, new_msg, layout, arena)) {
1251
- upb_arena_free(tmp_arena);
1306
+ upb_Message* new_msg = upb_Message_New(layout, arena);
1307
+ char* data;
1308
+
1309
+ const upb_FileDef* file = upb_MessageDef_File(m);
1310
+ const upb_ExtensionRegistry* extreg =
1311
+ upb_DefPool_ExtensionRegistry(upb_FileDef_Pool(file));
1312
+ if (upb_Encode(msg, layout, 0, tmp_arena, &data, &size) !=
1313
+ kUpb_EncodeStatus_Ok ||
1314
+ upb_Decode(data, size, new_msg, layout, extreg, 0, arena) !=
1315
+ kUpb_DecodeStatus_Ok) {
1316
+ upb_Arena_Free(tmp_arena);
1252
1317
  rb_raise(cParseError, "Error occurred copying proto");
1253
1318
  }
1254
1319
 
1255
- upb_arena_free(tmp_arena);
1320
+ upb_Arena_Free(tmp_arena);
1256
1321
  return new_msg;
1257
1322
  }
1258
1323
 
1259
- const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m,
1260
- const char* name, upb_arena* arena) {
1324
+ const upb_Message* Message_GetUpbMessage(VALUE value, const upb_MessageDef* m,
1325
+ const char* name, upb_Arena* arena) {
1261
1326
  if (value == Qnil) {
1262
1327
  rb_raise(cTypeError, "nil message not allowed here.");
1263
1328
  }
1264
1329
 
1265
1330
  VALUE klass = CLASS_OF(value);
1266
1331
  VALUE desc_rb = rb_ivar_get(klass, descriptor_instancevar_interned);
1267
- const upb_msgdef* val_m =
1332
+ const upb_MessageDef* val_m =
1268
1333
  desc_rb == Qnil ? NULL : Descriptor_GetMsgDef(desc_rb);
1269
1334
 
1270
1335
  if (val_m != m) {
1271
1336
  // Check for possible implicit conversions
1272
1337
  // TODO: hash conversion?
1273
1338
 
1274
- switch (upb_msgdef_wellknowntype(m)) {
1275
- case UPB_WELLKNOWN_TIMESTAMP: {
1339
+ switch (upb_MessageDef_WellKnownType(m)) {
1340
+ case kUpb_WellKnown_Timestamp: {
1276
1341
  // Time -> Google::Protobuf::Timestamp
1277
- upb_msg *msg = upb_msg_new(m, arena);
1278
- upb_msgval sec, nsec;
1342
+ const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
1343
+ upb_Message* msg = upb_Message_New(t, arena);
1344
+ upb_MessageValue sec, nsec;
1279
1345
  struct timespec time;
1280
- const upb_fielddef *sec_f = upb_msgdef_itof(m, 1);
1281
- const upb_fielddef *nsec_f = upb_msgdef_itof(m, 2);
1346
+ const upb_FieldDef* sec_f = upb_MessageDef_FindFieldByNumber(m, 1);
1347
+ const upb_FieldDef* nsec_f = upb_MessageDef_FindFieldByNumber(m, 2);
1282
1348
 
1283
1349
  if (!rb_obj_is_kind_of(value, rb_cTime)) goto badtype;
1284
1350
 
1285
1351
  time = rb_time_timespec(value);
1286
1352
  sec.int64_val = time.tv_sec;
1287
1353
  nsec.int32_val = time.tv_nsec;
1288
- upb_msg_set(msg, sec_f, sec, arena);
1289
- upb_msg_set(msg, nsec_f, nsec, arena);
1354
+ upb_Message_SetFieldByDef(msg, sec_f, sec, arena);
1355
+ upb_Message_SetFieldByDef(msg, nsec_f, nsec, arena);
1290
1356
  return msg;
1291
1357
  }
1292
- case UPB_WELLKNOWN_DURATION: {
1358
+ case kUpb_WellKnown_Duration: {
1293
1359
  // Numeric -> Google::Protobuf::Duration
1294
- upb_msg *msg = upb_msg_new(m, arena);
1295
- upb_msgval sec, nsec;
1296
- const upb_fielddef *sec_f = upb_msgdef_itof(m, 1);
1297
- const upb_fielddef *nsec_f = upb_msgdef_itof(m, 2);
1360
+ const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
1361
+ upb_Message* msg = upb_Message_New(t, arena);
1362
+ upb_MessageValue sec, nsec;
1363
+ const upb_FieldDef* sec_f = upb_MessageDef_FindFieldByNumber(m, 1);
1364
+ const upb_FieldDef* nsec_f = upb_MessageDef_FindFieldByNumber(m, 2);
1298
1365
 
1299
1366
  if (!rb_obj_is_kind_of(value, rb_cNumeric)) goto badtype;
1300
1367
 
1301
1368
  sec.int64_val = NUM2LL(value);
1302
1369
  nsec.int32_val = round((NUM2DBL(value) - NUM2LL(value)) * 1000000000);
1303
- upb_msg_set(msg, sec_f, sec, arena);
1304
- upb_msg_set(msg, nsec_f, nsec, arena);
1370
+ upb_Message_SetFieldByDef(msg, sec_f, sec, arena);
1371
+ upb_Message_SetFieldByDef(msg, nsec_f, nsec, arena);
1305
1372
  return msg;
1306
1373
  }
1307
1374
  default:
1308
1375
  badtype:
1309
1376
  rb_raise(cTypeError,
1310
1377
  "Invalid type %s to assign to submessage field '%s'.",
1311
- rb_class2name(CLASS_OF(value)), name);
1378
+ rb_class2name(CLASS_OF(value)), name);
1312
1379
  }
1313
-
1314
1380
  }
1315
1381
 
1316
1382
  Message* self = ruby_to_Message(value);
@@ -1319,11 +1385,42 @@ const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m,
1319
1385
  return self->msg;
1320
1386
  }
1321
1387
 
1388
+ static void Message_define_class(VALUE klass) {
1389
+ rb_define_alloc_func(klass, Message_alloc);
1390
+
1391
+ rb_require("google/protobuf/message_exts");
1392
+ rb_define_method(klass, "method_missing", Message_method_missing, -1);
1393
+ rb_define_method(klass, "respond_to_missing?", Message_respond_to_missing,
1394
+ -1);
1395
+ rb_define_method(klass, "initialize", Message_initialize, -1);
1396
+ rb_define_method(klass, "dup", Message_dup, 0);
1397
+ // Also define #clone so that we don't inherit Object#clone.
1398
+ rb_define_method(klass, "clone", Message_dup, 0);
1399
+ rb_define_method(klass, "==", Message_eq, 1);
1400
+ rb_define_method(klass, "eql?", Message_eq, 1);
1401
+ rb_define_method(klass, "freeze", Message_freeze, 0);
1402
+ rb_define_method(klass, "hash", Message_hash, 0);
1403
+ rb_define_method(klass, "to_h", Message_to_h, 0);
1404
+ rb_define_method(klass, "inspect", Message_inspect, 0);
1405
+ rb_define_method(klass, "to_s", Message_inspect, 0);
1406
+ rb_define_method(klass, "[]", Message_index, 1);
1407
+ rb_define_method(klass, "[]=", Message_index_set, 2);
1408
+ rb_define_singleton_method(klass, "decode", Message_decode, -1);
1409
+ rb_define_singleton_method(klass, "encode", Message_encode, -1);
1410
+ rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1);
1411
+ rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
1412
+ rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
1413
+ }
1414
+
1322
1415
  void Message_register(VALUE protobuf) {
1323
1416
  cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
1417
+ cAbstractMessage =
1418
+ rb_define_class_under(protobuf, "AbstractMessage", rb_cObject);
1419
+ Message_define_class(cAbstractMessage);
1420
+ rb_gc_register_address(&cAbstractMessage);
1324
1421
 
1325
1422
  // Ruby-interned string: "descriptor". We use this identifier to store an
1326
1423
  // instance variable on message classes we create in order to link them back
1327
1424
  // to their descriptors.
1328
- descriptor_instancevar_interned = rb_intern("descriptor");
1425
+ descriptor_instancevar_interned = rb_intern("@descriptor");
1329
1426
  }