google-protobuf 3.19.1 → 4.30.2

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