google-protobuf 3.8.0 → 3.19.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.

Potentially problematic release.


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

Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/convert.c +348 -0
  3. data/ext/google/protobuf_c/convert.h +72 -0
  4. data/ext/google/protobuf_c/defs.c +610 -1583
  5. data/ext/google/protobuf_c/defs.h +107 -0
  6. data/ext/google/protobuf_c/extconf.rb +4 -7
  7. data/ext/google/protobuf_c/map.c +315 -476
  8. data/ext/google/protobuf_c/map.h +67 -0
  9. data/ext/google/protobuf_c/message.c +928 -448
  10. data/ext/google/protobuf_c/message.h +101 -0
  11. data/ext/google/protobuf_c/protobuf.c +400 -51
  12. data/ext/google/protobuf_c/protobuf.h +47 -545
  13. data/ext/google/protobuf_c/repeated_field.c +311 -312
  14. data/ext/google/protobuf_c/repeated_field.h +63 -0
  15. data/ext/google/protobuf_c/ruby-upb.c +9171 -0
  16. data/ext/google/protobuf_c/ruby-upb.h +4704 -0
  17. data/lib/google/protobuf/any_pb.rb +1 -1
  18. data/lib/google/protobuf/api_pb.rb +4 -3
  19. data/lib/google/protobuf/descriptor_dsl.rb +458 -0
  20. data/lib/google/protobuf/descriptor_pb.rb +268 -0
  21. data/lib/google/protobuf/duration_pb.rb +1 -1
  22. data/lib/google/protobuf/empty_pb.rb +1 -1
  23. data/lib/google/protobuf/field_mask_pb.rb +1 -1
  24. data/lib/google/protobuf/source_context_pb.rb +1 -1
  25. data/lib/google/protobuf/struct_pb.rb +4 -4
  26. data/lib/google/protobuf/timestamp_pb.rb +1 -1
  27. data/lib/google/protobuf/type_pb.rb +9 -8
  28. data/lib/google/protobuf/well_known_types.rb +13 -2
  29. data/lib/google/protobuf/wrappers_pb.rb +9 -9
  30. data/lib/google/protobuf.rb +2 -0
  31. data/tests/basic.rb +329 -70
  32. data/tests/generated_code_test.rb +0 -0
  33. data/tests/stress.rb +1 -1
  34. metadata +21 -28
  35. data/ext/google/protobuf_c/encode_decode.c +0 -1614
  36. data/ext/google/protobuf_c/storage.c +0 -1062
  37. data/ext/google/protobuf_c/upb.c +0 -17480
  38. data/ext/google/protobuf_c/upb.h +0 -10641
@@ -28,167 +28,233 @@
28
28
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
29
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
30
 
31
+ #include "convert.h"
32
+ #include "defs.h"
33
+ #include "message.h"
31
34
  #include "protobuf.h"
32
35
 
33
36
  // -----------------------------------------------------------------------------
34
- // Basic map operations on top of upb's strtable.
37
+ // Basic map operations on top of upb_map.
35
38
  //
36
39
  // Note that we roll our own `Map` container here because, as for
37
40
  // `RepeatedField`, we want a strongly-typed container. This is so that any user
38
41
  // errors due to incorrect map key or value types are raised as close as
39
42
  // possible to the error site, rather than at some deferred point (e.g.,
40
43
  // serialization).
41
- //
42
- // We build our `Map` on top of upb_strtable so that we're able to take
43
- // advantage of the native_slot storage abstraction, as RepeatedField does.
44
- // (This is not quite a perfect mapping -- see the key conversions below -- but
45
- // gives us full support and error-checking for all value types for free.)
46
44
  // -----------------------------------------------------------------------------
47
45
 
48
- // Map values are stored using the native_slot abstraction (as with repeated
49
- // field values), but keys are a bit special. Since we use a strtable, we need
50
- // to store keys as sequences of bytes such that equality of those bytes maps
51
- // one-to-one to equality of keys. We store strings directly (i.e., they map to
52
- // their own bytes) and integers as native integers (using the native_slot
53
- // abstraction).
54
-
55
- // Note that there is another tradeoff here in keeping string keys as native
56
- // strings rather than Ruby strings: traversing the Map requires conversion to
57
- // Ruby string values on every traversal, potentially creating more garbage. We
58
- // should consider ways to cache a Ruby version of the key if this becomes an
59
- // issue later.
60
-
61
- // Forms a key to use with the underlying strtable from a Ruby key value. |buf|
62
- // must point to TABLE_KEY_BUF_LENGTH bytes of temporary space, used to
63
- // construct a key byte sequence if needed. |out_key| and |out_length| provide
64
- // the resulting key data/length.
65
- #define TABLE_KEY_BUF_LENGTH 8 // sizeof(uint64_t)
66
- static VALUE table_key(Map* self, VALUE key,
67
- char* buf,
68
- const char** out_key,
69
- size_t* out_length) {
70
- switch (self->key_type) {
71
- case UPB_TYPE_BYTES:
72
- case UPB_TYPE_STRING:
73
- // Strings: use string content directly.
74
- Check_Type(key, T_STRING);
75
- key = native_slot_encode_and_freeze_string(self->key_type, key);
76
- *out_key = RSTRING_PTR(key);
77
- *out_length = RSTRING_LEN(key);
78
- break;
79
-
80
- case UPB_TYPE_BOOL:
81
- case UPB_TYPE_INT32:
82
- case UPB_TYPE_INT64:
83
- case UPB_TYPE_UINT32:
84
- case UPB_TYPE_UINT64:
85
- native_slot_set("", self->key_type, Qnil, buf, key);
86
- *out_key = buf;
87
- *out_length = native_slot_size(self->key_type);
88
- break;
89
-
90
- default:
91
- // Map constructor should not allow a Map with another key type to be
92
- // constructed.
93
- assert(false);
94
- break;
95
- }
96
-
97
- return key;
98
- }
99
-
100
- static VALUE table_key_to_ruby(Map* self, const char* buf, size_t length) {
101
- switch (self->key_type) {
102
- case UPB_TYPE_BYTES:
103
- case UPB_TYPE_STRING: {
104
- VALUE ret = rb_str_new(buf, length);
105
- rb_enc_associate(ret,
106
- (self->key_type == UPB_TYPE_BYTES) ?
107
- kRubyString8bitEncoding : kRubyStringUtf8Encoding);
108
- return ret;
109
- }
110
-
111
- case UPB_TYPE_BOOL:
112
- case UPB_TYPE_INT32:
113
- case UPB_TYPE_INT64:
114
- case UPB_TYPE_UINT32:
115
- case UPB_TYPE_UINT64:
116
- return native_slot_get(self->key_type, Qnil, buf);
117
-
118
- default:
119
- assert(false);
120
- return Qnil;
121
- }
122
- }
123
-
124
- static void* value_memory(upb_value* v) {
125
- return (void*)(&v->val);
126
- }
127
-
128
46
  // -----------------------------------------------------------------------------
129
47
  // Map container type.
130
48
  // -----------------------------------------------------------------------------
131
49
 
50
+ typedef struct {
51
+ const upb_map *map; // Can convert to mutable when non-frozen.
52
+ upb_fieldtype_t key_type;
53
+ TypeInfo value_type_info;
54
+ VALUE value_type_class;
55
+ VALUE arena;
56
+ } Map;
57
+
58
+ static void Map_mark(void* _self) {
59
+ Map* self = _self;
60
+ rb_gc_mark(self->value_type_class);
61
+ rb_gc_mark(self->arena);
62
+ }
63
+
132
64
  const rb_data_type_t Map_type = {
133
65
  "Google::Protobuf::Map",
134
- { Map_mark, Map_free, NULL },
66
+ { Map_mark, RUBY_DEFAULT_FREE, NULL },
67
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
135
68
  };
136
69
 
137
70
  VALUE cMap;
138
71
 
139
- Map* ruby_to_Map(VALUE _self) {
72
+ static Map* ruby_to_Map(VALUE _self) {
140
73
  Map* self;
141
74
  TypedData_Get_Struct(_self, Map, &Map_type, self);
142
75
  return self;
143
76
  }
144
77
 
145
- void Map_mark(void* _self) {
146
- Map* self = _self;
78
+ static VALUE Map_alloc(VALUE klass) {
79
+ Map* self = ALLOC(Map);
80
+ self->map = NULL;
81
+ self->value_type_class = Qnil;
82
+ self->value_type_info.def.msgdef = NULL;
83
+ self->arena = Qnil;
84
+ return TypedData_Wrap_Struct(klass, &Map_type, self);
85
+ }
147
86
 
148
- rb_gc_mark(self->value_type_class);
149
- rb_gc_mark(self->parse_frame);
150
-
151
- if (self->value_type == UPB_TYPE_STRING ||
152
- self->value_type == UPB_TYPE_BYTES ||
153
- self->value_type == UPB_TYPE_MESSAGE) {
154
- upb_strtable_iter it;
155
- for (upb_strtable_begin(&it, &self->table);
156
- !upb_strtable_done(&it);
157
- upb_strtable_next(&it)) {
158
- upb_value v = upb_strtable_iter_value(&it);
159
- void* mem = value_memory(&v);
160
- native_slot_mark(self->value_type, mem);
87
+ VALUE Map_GetRubyWrapper(upb_map* map, upb_fieldtype_t key_type,
88
+ TypeInfo value_type, VALUE arena) {
89
+ PBRUBY_ASSERT(map);
90
+
91
+ VALUE val = ObjectCache_Get(map);
92
+
93
+ if (val == Qnil) {
94
+ val = Map_alloc(cMap);
95
+ Map* self;
96
+ ObjectCache_Add(map, val);
97
+ TypedData_Get_Struct(val, Map, &Map_type, self);
98
+ self->map = map;
99
+ self->arena = arena;
100
+ self->key_type = key_type;
101
+ self->value_type_info = value_type;
102
+ if (self->value_type_info.type == UPB_TYPE_MESSAGE) {
103
+ const upb_msgdef *val_m = self->value_type_info.def.msgdef;
104
+ self->value_type_class = Descriptor_DefToClass(val_m);
161
105
  }
162
106
  }
107
+
108
+ return val;
163
109
  }
164
110
 
165
- void Map_free(void* _self) {
166
- Map* self = _self;
167
- upb_strtable_uninit(&self->table);
168
- xfree(self);
111
+ static VALUE Map_new_this_type(Map *from) {
112
+ VALUE arena_rb = Arena_new();
113
+ upb_map* map = upb_map_new(Arena_get(arena_rb), from->key_type,
114
+ from->value_type_info.type);
115
+ VALUE ret =
116
+ Map_GetRubyWrapper(map, from->key_type, from->value_type_info, arena_rb);
117
+ PBRUBY_ASSERT(ruby_to_Map(ret)->value_type_class == from->value_type_class);
118
+ return ret;
169
119
  }
170
120
 
171
- VALUE Map_alloc(VALUE klass) {
172
- Map* self = ALLOC(Map);
173
- memset(self, 0, sizeof(Map));
174
- self->value_type_class = Qnil;
175
- return TypedData_Wrap_Struct(klass, &Map_type, self);
121
+ static TypeInfo Map_keyinfo(Map* self) {
122
+ TypeInfo ret;
123
+ ret.type = self->key_type;
124
+ ret.def.msgdef = NULL;
125
+ return ret;
176
126
  }
177
127
 
178
- VALUE Map_set_frame(VALUE map, VALUE val) {
179
- Map* self = ruby_to_Map(map);
180
- self->parse_frame = val;
181
- return val;
128
+ static upb_map *Map_GetMutable(VALUE _self) {
129
+ rb_check_frozen(_self);
130
+ return (upb_map*)ruby_to_Map(_self)->map;
182
131
  }
183
132
 
184
- static bool needs_typeclass(upb_fieldtype_t type) {
185
- switch (type) {
186
- case UPB_TYPE_MESSAGE:
187
- case UPB_TYPE_ENUM:
188
- return true;
189
- default:
190
- return false;
133
+ VALUE Map_CreateHash(const upb_map* map, upb_fieldtype_t key_type,
134
+ TypeInfo val_info) {
135
+ VALUE hash = rb_hash_new();
136
+ size_t iter = UPB_MAP_BEGIN;
137
+ TypeInfo key_info = TypeInfo_from_type(key_type);
138
+
139
+ if (!map) return hash;
140
+
141
+ while (upb_mapiter_next(map, &iter)) {
142
+ upb_msgval key = upb_mapiter_key(map, iter);
143
+ upb_msgval val = upb_mapiter_value(map, iter);
144
+ VALUE key_val = Convert_UpbToRuby(key, key_info, Qnil);
145
+ VALUE val_val = Scalar_CreateHash(val, val_info);
146
+ rb_hash_aset(hash, key_val, val_val);
147
+ }
148
+
149
+ return hash;
150
+ }
151
+
152
+ VALUE Map_deep_copy(VALUE obj) {
153
+ Map* self = ruby_to_Map(obj);
154
+ VALUE new_arena_rb = Arena_new();
155
+ upb_arena *arena = Arena_get(new_arena_rb);
156
+ upb_map* new_map =
157
+ upb_map_new(arena, self->key_type, self->value_type_info.type);
158
+ size_t iter = UPB_MAP_BEGIN;
159
+ while (upb_mapiter_next(self->map, &iter)) {
160
+ upb_msgval key = upb_mapiter_key(self->map, iter);
161
+ upb_msgval val = upb_mapiter_value(self->map, iter);
162
+ upb_msgval val_copy = Msgval_DeepCopy(val, self->value_type_info, arena);
163
+ upb_map_set(new_map, key, val_copy, arena);
164
+ }
165
+
166
+ return Map_GetRubyWrapper(new_map, self->key_type, self->value_type_info,
167
+ new_arena_rb);
168
+ }
169
+
170
+ const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef* field,
171
+ upb_arena* arena) {
172
+ const upb_fielddef* key_field = map_field_key(field);
173
+ const upb_fielddef* value_field = map_field_value(field);
174
+ TypeInfo value_type_info = TypeInfo_get(value_field);
175
+ Map* self;
176
+
177
+ if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
178
+ RTYPEDDATA_TYPE(val) != &Map_type) {
179
+ rb_raise(cTypeError, "Expected Map instance");
180
+ }
181
+
182
+ self = ruby_to_Map(val);
183
+ if (self->key_type != upb_fielddef_type(key_field)) {
184
+ rb_raise(cTypeError, "Map key type does not match field's key type");
185
+ }
186
+ if (self->value_type_info.type != value_type_info.type) {
187
+ rb_raise(cTypeError, "Map value type does not match field's value type");
188
+ }
189
+ if (self->value_type_info.def.msgdef != value_type_info.def.msgdef) {
190
+ rb_raise(cTypeError, "Map value type has wrong message/enum class");
191
+ }
192
+
193
+ Arena_fuse(self->arena, arena);
194
+ return self->map;
195
+ }
196
+
197
+ void Map_Inspect(StringBuilder* b, const upb_map* map, upb_fieldtype_t key_type,
198
+ TypeInfo val_type) {
199
+ bool first = true;
200
+ TypeInfo key_type_info = {key_type};
201
+ StringBuilder_Printf(b, "{");
202
+ if (map) {
203
+ size_t iter = UPB_MAP_BEGIN;
204
+ while (upb_mapiter_next(map, &iter)) {
205
+ upb_msgval key = upb_mapiter_key(map, iter);
206
+ upb_msgval val = upb_mapiter_value(map, iter);
207
+ if (first) {
208
+ first = false;
209
+ } else {
210
+ StringBuilder_Printf(b, ", ");
211
+ }
212
+ StringBuilder_PrintMsgval(b, key, key_type_info);
213
+ StringBuilder_Printf(b, "=>");
214
+ StringBuilder_PrintMsgval(b, val, val_type);
215
+ }
216
+ }
217
+ StringBuilder_Printf(b, "}");
218
+ }
219
+
220
+ static int merge_into_self_callback(VALUE key, VALUE val, VALUE _self) {
221
+ Map* self = ruby_to_Map(_self);
222
+ upb_arena *arena = Arena_get(self->arena);
223
+ upb_msgval key_val = Convert_RubyToUpb(key, "", Map_keyinfo(self), arena);
224
+ upb_msgval val_val = Convert_RubyToUpb(val, "", self->value_type_info, arena);
225
+ upb_map_set(Map_GetMutable(_self), key_val, val_val, arena);
226
+ return ST_CONTINUE;
227
+ }
228
+
229
+ // Used only internally -- shared by #merge and #initialize.
230
+ static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
231
+ if (TYPE(hashmap) == T_HASH) {
232
+ rb_hash_foreach(hashmap, merge_into_self_callback, _self);
233
+ } else if (RB_TYPE_P(hashmap, T_DATA) && RTYPEDDATA_P(hashmap) &&
234
+ RTYPEDDATA_TYPE(hashmap) == &Map_type) {
235
+ Map* self = ruby_to_Map(_self);
236
+ Map* other = ruby_to_Map(hashmap);
237
+ upb_arena *arena = Arena_get(self->arena);
238
+ upb_msg *self_msg = Map_GetMutable(_self);
239
+ size_t iter = UPB_MAP_BEGIN;
240
+
241
+ Arena_fuse(other->arena, arena);
242
+
243
+ if (self->key_type != other->key_type ||
244
+ self->value_type_info.type != other->value_type_info.type ||
245
+ self->value_type_class != other->value_type_class) {
246
+ rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types");
247
+ }
248
+
249
+ while (upb_mapiter_next(other->map, &iter)) {
250
+ upb_msgval key = upb_mapiter_key(other->map, iter);
251
+ upb_msgval val = upb_mapiter_value(other->map, iter);
252
+ upb_map_set(self_msg, key, val, arena);
253
+ }
254
+ } else {
255
+ rb_raise(rb_eArgError, "Unknown type merging into Map");
191
256
  }
257
+ return _self;
192
258
  }
193
259
 
194
260
  /*
@@ -221,9 +287,9 @@ static bool needs_typeclass(upb_fieldtype_t type) {
221
287
  * references to underlying objects will be shared if the value type is a
222
288
  * message type.
223
289
  */
224
- VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
290
+ static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
225
291
  Map* self = ruby_to_Map(_self);
226
- int init_value_arg;
292
+ VALUE init_arg;
227
293
 
228
294
  // We take either two args (:key_type, :value_type), three args (:key_type,
229
295
  // :value_type, "ValueMessageType"), or four args (the above plus an initial
@@ -233,8 +299,9 @@ VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
233
299
  }
234
300
 
235
301
  self->key_type = ruby_to_fieldtype(argv[0]);
236
- self->value_type = ruby_to_fieldtype(argv[1]);
237
- self->parse_frame = Qnil;
302
+ self->value_type_info =
303
+ TypeInfo_FromClass(argc, argv, 1, &self->value_type_class, &init_arg);
304
+ self->arena = Arena_new();
238
305
 
239
306
  // Check that the key type is an allowed type.
240
307
  switch (self->key_type) {
@@ -251,21 +318,12 @@ VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
251
318
  rb_raise(rb_eArgError, "Invalid key type for map.");
252
319
  }
253
320
 
254
- init_value_arg = 2;
255
- if (needs_typeclass(self->value_type) && argc > 2) {
256
- self->value_type_class = argv[2];
257
- validate_type_class(self->value_type, self->value_type_class);
258
- init_value_arg = 3;
259
- }
321
+ self->map = upb_map_new(Arena_get(self->arena), self->key_type,
322
+ self->value_type_info.type);
323
+ ObjectCache_Add(self->map, _self);
260
324
 
261
- // Table value type is always UINT64: this ensures enough space to store the
262
- // native_slot value.
263
- if (!upb_strtable_init(&self->table, UPB_CTYPE_UINT64)) {
264
- rb_raise(rb_eRuntimeError, "Could not allocate table.");
265
- }
266
-
267
- if (argc > init_value_arg) {
268
- Map_merge_into_self(_self, argv[init_value_arg]);
325
+ if (init_arg != Qnil) {
326
+ Map_merge_into_self(_self, init_arg);
269
327
  }
270
328
 
271
329
  return Qnil;
@@ -279,24 +337,16 @@ VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
279
337
  * Note that Map also includes Enumerable; map thus acts like a normal Ruby
280
338
  * sequence.
281
339
  */
282
- VALUE Map_each(VALUE _self) {
340
+ static VALUE Map_each(VALUE _self) {
283
341
  Map* self = ruby_to_Map(_self);
284
-
285
- upb_strtable_iter it;
286
- for (upb_strtable_begin(&it, &self->table);
287
- !upb_strtable_done(&it);
288
- upb_strtable_next(&it)) {
289
-
290
- VALUE key = table_key_to_ruby(
291
- self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it));
292
-
293
- upb_value v = upb_strtable_iter_value(&it);
294
- void* mem = value_memory(&v);
295
- VALUE value = native_slot_get(self->value_type,
296
- self->value_type_class,
297
- mem);
298
-
299
- rb_yield_values(2, key, value);
342
+ size_t iter = UPB_MAP_BEGIN;
343
+
344
+ while (upb_mapiter_next(self->map, &iter)) {
345
+ upb_msgval key = upb_mapiter_key(self->map, iter);
346
+ upb_msgval val = upb_mapiter_value(self->map, iter);
347
+ VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
348
+ VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
349
+ rb_yield_values(2, key_val, val_val);
300
350
  }
301
351
 
302
352
  return Qnil;
@@ -308,19 +358,15 @@ VALUE Map_each(VALUE _self) {
308
358
  *
309
359
  * Returns the list of keys contained in the map, in unspecified order.
310
360
  */
311
- VALUE Map_keys(VALUE _self) {
361
+ static VALUE Map_keys(VALUE _self) {
312
362
  Map* self = ruby_to_Map(_self);
313
-
363
+ size_t iter = UPB_MAP_BEGIN;
314
364
  VALUE ret = rb_ary_new();
315
- upb_strtable_iter it;
316
- for (upb_strtable_begin(&it, &self->table);
317
- !upb_strtable_done(&it);
318
- upb_strtable_next(&it)) {
319
365
 
320
- VALUE key = table_key_to_ruby(
321
- self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it));
322
-
323
- rb_ary_push(ret, key);
366
+ while (upb_mapiter_next(self->map, &iter)) {
367
+ upb_msgval key = upb_mapiter_key(self->map, iter);
368
+ VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
369
+ rb_ary_push(ret, key_val);
324
370
  }
325
371
 
326
372
  return ret;
@@ -332,22 +378,15 @@ VALUE Map_keys(VALUE _self) {
332
378
  *
333
379
  * Returns the list of values contained in the map, in unspecified order.
334
380
  */
335
- VALUE Map_values(VALUE _self) {
381
+ static VALUE Map_values(VALUE _self) {
336
382
  Map* self = ruby_to_Map(_self);
337
-
383
+ size_t iter = UPB_MAP_BEGIN;
338
384
  VALUE ret = rb_ary_new();
339
- upb_strtable_iter it;
340
- for (upb_strtable_begin(&it, &self->table);
341
- !upb_strtable_done(&it);
342
- upb_strtable_next(&it)) {
343
-
344
- upb_value v = upb_strtable_iter_value(&it);
345
- void* mem = value_memory(&v);
346
- VALUE value = native_slot_get(self->value_type,
347
- self->value_type_class,
348
- mem);
349
-
350
- rb_ary_push(ret, value);
385
+
386
+ while (upb_mapiter_next(self->map, &iter)) {
387
+ upb_msgval val = upb_mapiter_value(self->map, iter);
388
+ VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
389
+ rb_ary_push(ret, val_val);
351
390
  }
352
391
 
353
392
  return ret;
@@ -360,18 +399,13 @@ VALUE Map_values(VALUE _self) {
360
399
  * Accesses the element at the given key. Throws an exception if the key type is
361
400
  * incorrect. Returns nil when the key is not present in the map.
362
401
  */
363
- VALUE Map_index(VALUE _self, VALUE key) {
402
+ static VALUE Map_index(VALUE _self, VALUE key) {
364
403
  Map* self = ruby_to_Map(_self);
404
+ upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
405
+ upb_msgval val;
365
406
 
366
- char keybuf[TABLE_KEY_BUF_LENGTH];
367
- const char* keyval = NULL;
368
- size_t length = 0;
369
- upb_value v;
370
- key = table_key(self, key, keybuf, &keyval, &length);
371
-
372
- if (upb_strtable_lookup2(&self->table, keyval, length, &v)) {
373
- void* mem = value_memory(&v);
374
- return native_slot_get(self->value_type, self->value_type_class, mem);
407
+ if (upb_map_get(self->map, key_upb, &val)) {
408
+ return Convert_UpbToRuby(val, self->value_type_info, self->arena);
375
409
  } else {
376
410
  return Qnil;
377
411
  }
@@ -385,29 +419,15 @@ VALUE Map_index(VALUE _self, VALUE key) {
385
419
  * Throws an exception if the key type is incorrect. Returns the new value that
386
420
  * was just inserted.
387
421
  */
388
- VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) {
389
- rb_check_frozen(_self);
390
-
422
+ static VALUE Map_index_set(VALUE _self, VALUE key, VALUE val) {
391
423
  Map* self = ruby_to_Map(_self);
424
+ upb_arena *arena = Arena_get(self->arena);
425
+ upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
426
+ upb_msgval val_upb = Convert_RubyToUpb(val, "", self->value_type_info, arena);
392
427
 
393
- char keybuf[TABLE_KEY_BUF_LENGTH];
394
- const char* keyval = NULL;
395
- size_t length = 0;
396
- upb_value v;
397
- void* mem;
398
- key = table_key(self, key, keybuf, &keyval, &length);
399
-
400
- mem = value_memory(&v);
401
- native_slot_set("", self->value_type, self->value_type_class, mem, value);
428
+ upb_map_set(Map_GetMutable(_self), key_upb, val_upb, arena);
402
429
 
403
- // Replace any existing value by issuing a 'remove' operation first.
404
- upb_strtable_remove2(&self->table, keyval, length, NULL);
405
- if (!upb_strtable_insert2(&self->table, keyval, length, v)) {
406
- rb_raise(rb_eRuntimeError, "Could not insert into table");
407
- }
408
-
409
- // Ruby hashmap's :[]= method also returns the inserted value.
410
- return value;
430
+ return val;
411
431
  }
412
432
 
413
433
  /*
@@ -417,15 +437,11 @@ VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) {
417
437
  * Returns true if the given key is present in the map. Throws an exception if
418
438
  * the key has the wrong type.
419
439
  */
420
- VALUE Map_has_key(VALUE _self, VALUE key) {
440
+ static VALUE Map_has_key(VALUE _self, VALUE key) {
421
441
  Map* self = ruby_to_Map(_self);
442
+ upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
422
443
 
423
- char keybuf[TABLE_KEY_BUF_LENGTH];
424
- const char* keyval = NULL;
425
- size_t length = 0;
426
- key = table_key(self, key, keybuf, &keyval, &length);
427
-
428
- if (upb_strtable_lookup2(&self->table, keyval, length, NULL)) {
444
+ if (upb_map_get(self->map, key_upb, NULL)) {
429
445
  return Qtrue;
430
446
  } else {
431
447
  return Qfalse;
@@ -439,23 +455,25 @@ VALUE Map_has_key(VALUE _self, VALUE key) {
439
455
  * Deletes the value at the given key, if any, returning either the old value or
440
456
  * nil if none was present. Throws an exception if the key is of the wrong type.
441
457
  */
442
- VALUE Map_delete(VALUE _self, VALUE key) {
443
- rb_check_frozen(_self);
444
-
458
+ static VALUE Map_delete(VALUE _self, VALUE key) {
445
459
  Map* self = ruby_to_Map(_self);
460
+ upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
461
+ upb_msgval val_upb;
462
+ VALUE ret;
446
463
 
447
- char keybuf[TABLE_KEY_BUF_LENGTH];
448
- const char* keyval = NULL;
449
- size_t length = 0;
450
- upb_value v;
451
- key = table_key(self, key, keybuf, &keyval, &length);
464
+ rb_check_frozen(_self);
452
465
 
453
- if (upb_strtable_remove2(&self->table, keyval, length, &v)) {
454
- void* mem = value_memory(&v);
455
- return native_slot_get(self->value_type, self->value_type_class, mem);
466
+ // TODO(haberman): make upb_map_delete() also capable of returning the deleted
467
+ // value.
468
+ if (upb_map_get(self->map, key_upb, &val_upb)) {
469
+ ret = Convert_UpbToRuby(val_upb, self->value_type_info, self->arena);
456
470
  } else {
457
- return Qnil;
471
+ ret = Qnil;
458
472
  }
473
+
474
+ upb_map_delete(Map_GetMutable(_self), key_upb);
475
+
476
+ return ret;
459
477
  }
460
478
 
461
479
  /*
@@ -464,17 +482,8 @@ VALUE Map_delete(VALUE _self, VALUE key) {
464
482
  *
465
483
  * Removes all entries from the map.
466
484
  */
467
- VALUE Map_clear(VALUE _self) {
468
- rb_check_frozen(_self);
469
-
470
- Map* self = ruby_to_Map(_self);
471
-
472
- // Uninit and reinit the table -- this is faster than iterating and doing a
473
- // delete-lookup on each key.
474
- upb_strtable_uninit(&self->table);
475
- if (!upb_strtable_init(&self->table, UPB_CTYPE_INT64)) {
476
- rb_raise(rb_eRuntimeError, "Unable to re-initialize table");
477
- }
485
+ static VALUE Map_clear(VALUE _self) {
486
+ upb_map_clear(Map_GetMutable(_self));
478
487
  return Qnil;
479
488
  }
480
489
 
@@ -484,24 +493,9 @@ VALUE Map_clear(VALUE _self) {
484
493
  *
485
494
  * Returns the number of entries (key-value pairs) in the map.
486
495
  */
487
- VALUE Map_length(VALUE _self) {
496
+ static VALUE Map_length(VALUE _self) {
488
497
  Map* self = ruby_to_Map(_self);
489
- return ULL2NUM(upb_strtable_count(&self->table));
490
- }
491
-
492
- static VALUE Map_new_this_type(VALUE _self) {
493
- Map* self = ruby_to_Map(_self);
494
- VALUE new_map = Qnil;
495
- VALUE key_type = fieldtype_to_ruby(self->key_type);
496
- VALUE value_type = fieldtype_to_ruby(self->value_type);
497
- if (self->value_type_class != Qnil) {
498
- new_map = rb_funcall(CLASS_OF(_self), rb_intern("new"), 3,
499
- key_type, value_type, self->value_type_class);
500
- } else {
501
- new_map = rb_funcall(CLASS_OF(_self), rb_intern("new"), 2,
502
- key_type, value_type);
503
- }
504
- return new_map;
498
+ return ULL2NUM(upb_map_size(self->map));
505
499
  }
506
500
 
507
501
  /*
@@ -511,59 +505,23 @@ static VALUE Map_new_this_type(VALUE _self) {
511
505
  * Duplicates this map with a shallow copy. References to all non-primitive
512
506
  * element objects (e.g., submessages) are shared.
513
507
  */
514
- VALUE Map_dup(VALUE _self) {
515
- Map* self = ruby_to_Map(_self);
516
- VALUE new_map = Map_new_this_type(_self);
517
- Map* new_self = ruby_to_Map(new_map);
518
-
519
- upb_strtable_iter it;
520
- for (upb_strtable_begin(&it, &self->table);
521
- !upb_strtable_done(&it);
522
- upb_strtable_next(&it)) {
523
-
524
- upb_value v = upb_strtable_iter_value(&it);
525
- void* mem = value_memory(&v);
526
- upb_value dup;
527
- void* dup_mem = value_memory(&dup);
528
- native_slot_dup(self->value_type, dup_mem, mem);
529
-
530
- if (!upb_strtable_insert2(&new_self->table,
531
- upb_strtable_iter_key(&it),
532
- upb_strtable_iter_keylength(&it),
533
- dup)) {
534
- rb_raise(rb_eRuntimeError, "Error inserting value into new table");
535
- }
536
- }
537
-
538
- return new_map;
539
- }
540
-
541
- // Used by Google::Protobuf.deep_copy but not exposed directly.
542
- VALUE Map_deep_copy(VALUE _self) {
508
+ static VALUE Map_dup(VALUE _self) {
543
509
  Map* self = ruby_to_Map(_self);
544
- VALUE new_map = Map_new_this_type(_self);
545
- Map* new_self = ruby_to_Map(new_map);
546
-
547
- upb_strtable_iter it;
548
- for (upb_strtable_begin(&it, &self->table);
549
- !upb_strtable_done(&it);
550
- upb_strtable_next(&it)) {
551
-
552
- upb_value v = upb_strtable_iter_value(&it);
553
- void* mem = value_memory(&v);
554
- upb_value dup;
555
- void* dup_mem = value_memory(&dup);
556
- native_slot_deep_copy(self->value_type, dup_mem, mem);
557
-
558
- if (!upb_strtable_insert2(&new_self->table,
559
- upb_strtable_iter_key(&it),
560
- upb_strtable_iter_keylength(&it),
561
- dup)) {
562
- rb_raise(rb_eRuntimeError, "Error inserting value into new table");
563
- }
510
+ VALUE new_map_rb = Map_new_this_type(self);
511
+ Map* new_self = ruby_to_Map(new_map_rb);
512
+ size_t iter = UPB_MAP_BEGIN;
513
+ upb_arena *arena = Arena_get(new_self->arena);
514
+ upb_map *new_map = Map_GetMutable(new_map_rb);
515
+
516
+ Arena_fuse(self->arena, arena);
517
+
518
+ while (upb_mapiter_next(self->map, &iter)) {
519
+ upb_msgval key = upb_mapiter_key(self->map, iter);
520
+ upb_msgval val = upb_mapiter_value(self->map, iter);
521
+ upb_map_set(new_map, key, val, arena);
564
522
  }
565
523
 
566
- return new_map;
524
+ return new_map_rb;
567
525
  }
568
526
 
569
527
  /*
@@ -582,12 +540,11 @@ VALUE Map_deep_copy(VALUE _self) {
582
540
  VALUE Map_eq(VALUE _self, VALUE _other) {
583
541
  Map* self = ruby_to_Map(_self);
584
542
  Map* other;
585
- upb_strtable_iter it;
586
543
 
587
544
  // Allow comparisons to Ruby hashmaps by converting to a temporary Map
588
545
  // instance. Slow, but workable.
589
546
  if (TYPE(_other) == T_HASH) {
590
- VALUE other_map = Map_new_this_type(_self);
547
+ VALUE other_map = Map_new_this_type(self);
591
548
  Map_merge_into_self(other_map, _other);
592
549
  _other = other_map;
593
550
  }
@@ -598,35 +555,27 @@ VALUE Map_eq(VALUE _self, VALUE _other) {
598
555
  return Qtrue;
599
556
  }
600
557
  if (self->key_type != other->key_type ||
601
- self->value_type != other->value_type ||
558
+ self->value_type_info.type != other->value_type_info.type ||
602
559
  self->value_type_class != other->value_type_class) {
603
560
  return Qfalse;
604
561
  }
605
- if (upb_strtable_count(&self->table) != upb_strtable_count(&other->table)) {
562
+ if (upb_map_size(self->map) != upb_map_size(other->map)) {
606
563
  return Qfalse;
607
564
  }
608
565
 
609
566
  // For each member of self, check that an equal member exists at the same key
610
567
  // in other.
611
- for (upb_strtable_begin(&it, &self->table);
612
- !upb_strtable_done(&it);
613
- upb_strtable_next(&it)) {
614
-
615
- upb_value v = upb_strtable_iter_value(&it);
616
- void* mem = value_memory(&v);
617
- upb_value other_v;
618
- void* other_mem = value_memory(&other_v);
619
-
620
- if (!upb_strtable_lookup2(&other->table,
621
- upb_strtable_iter_key(&it),
622
- upb_strtable_iter_keylength(&it),
623
- &other_v)) {
568
+ size_t iter = UPB_MAP_BEGIN;
569
+ while (upb_mapiter_next(self->map, &iter)) {
570
+ upb_msgval key = upb_mapiter_key(self->map, iter);
571
+ upb_msgval val = upb_mapiter_value(self->map, iter);
572
+ upb_msgval other_val;
573
+ if (!upb_map_get(other->map, key, &other_val)) {
624
574
  // Not present in other map.
625
575
  return Qfalse;
626
576
  }
627
-
628
- if (!native_slot_eq(self->value_type, mem, other_mem)) {
629
- // Present, but value not equal.
577
+ if (!Msgval_IsEqual(val, other_val, self->value_type_info)) {
578
+ // Present but different value.
630
579
  return Qfalse;
631
580
  }
632
581
  }
@@ -634,6 +583,22 @@ VALUE Map_eq(VALUE _self, VALUE _other) {
634
583
  return Qtrue;
635
584
  }
636
585
 
586
+ /*
587
+ * call-seq:
588
+ * Message.freeze => self
589
+ *
590
+ * Freezes the message object. We have to intercept this so we can pin the
591
+ * Ruby object into memory so we don't forget it's frozen.
592
+ */
593
+ static VALUE Map_freeze(VALUE _self) {
594
+ Map* self = ruby_to_Map(_self);
595
+ if (!RB_OBJ_FROZEN(_self)) {
596
+ Arena_Pin(self->arena, _self);
597
+ RB_OBJ_FREEZE(_self);
598
+ }
599
+ return _self;
600
+ }
601
+
637
602
  /*
638
603
  * call-seq:
639
604
  * Map.hash => hash_value
@@ -642,28 +607,18 @@ VALUE Map_eq(VALUE _self, VALUE _other) {
642
607
  */
643
608
  VALUE Map_hash(VALUE _self) {
644
609
  Map* self = ruby_to_Map(_self);
645
-
646
- st_index_t h = rb_hash_start(0);
647
- VALUE hash_sym = rb_intern("hash");
648
-
649
- upb_strtable_iter it;
650
- for (upb_strtable_begin(&it, &self->table);
651
- !upb_strtable_done(&it);
652
- upb_strtable_next(&it)) {
653
- VALUE key = table_key_to_ruby(
654
- self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it));
655
-
656
- upb_value v = upb_strtable_iter_value(&it);
657
- void* mem = value_memory(&v);
658
- VALUE value = native_slot_get(self->value_type,
659
- self->value_type_class,
660
- mem);
661
-
662
- h = rb_hash_uint(h, NUM2LONG(rb_funcall(key, hash_sym, 0)));
663
- h = rb_hash_uint(h, NUM2LONG(rb_funcall(value, hash_sym, 0)));
610
+ uint64_t hash = 0;
611
+
612
+ size_t iter = UPB_MAP_BEGIN;
613
+ TypeInfo key_info = {self->key_type};
614
+ while (upb_mapiter_next(self->map, &iter)) {
615
+ upb_msgval key = upb_mapiter_key(self->map, iter);
616
+ upb_msgval val = upb_mapiter_value(self->map, iter);
617
+ hash = Msgval_GetHash(key, key_info, hash);
618
+ hash = Msgval_GetHash(val, self->value_type_info, hash);
664
619
  }
665
620
 
666
- return INT2FIX(h);
621
+ return LL2NUM(hash);
667
622
  }
668
623
 
669
624
  /*
@@ -674,25 +629,7 @@ VALUE Map_hash(VALUE _self) {
674
629
  */
675
630
  VALUE Map_to_h(VALUE _self) {
676
631
  Map* self = ruby_to_Map(_self);
677
- VALUE hash = rb_hash_new();
678
- upb_strtable_iter it;
679
- for (upb_strtable_begin(&it, &self->table);
680
- !upb_strtable_done(&it);
681
- upb_strtable_next(&it)) {
682
- VALUE key = table_key_to_ruby(
683
- self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it));
684
- upb_value v = upb_strtable_iter_value(&it);
685
- void* mem = value_memory(&v);
686
- VALUE value = native_slot_get(self->value_type,
687
- self->value_type_class,
688
- mem);
689
-
690
- if (self->value_type == UPB_TYPE_MESSAGE) {
691
- value = Message_to_h(value);
692
- }
693
- rb_hash_aset(hash, key, value);
694
- }
695
- return hash;
632
+ return Map_CreateHash(self->map, self->key_type, self->value_type_info);
696
633
  }
697
634
 
698
635
  /*
@@ -706,36 +643,11 @@ VALUE Map_to_h(VALUE _self) {
706
643
  VALUE Map_inspect(VALUE _self) {
707
644
  Map* self = ruby_to_Map(_self);
708
645
 
709
- VALUE str = rb_str_new2("{");
710
-
711
- bool first = true;
712
- VALUE inspect_sym = rb_intern("inspect");
713
-
714
- upb_strtable_iter it;
715
- for (upb_strtable_begin(&it, &self->table);
716
- !upb_strtable_done(&it);
717
- upb_strtable_next(&it)) {
718
- VALUE key = table_key_to_ruby(
719
- self, upb_strtable_iter_key(&it), upb_strtable_iter_keylength(&it));
720
-
721
- upb_value v = upb_strtable_iter_value(&it);
722
- void* mem = value_memory(&v);
723
- VALUE value = native_slot_get(self->value_type,
724
- self->value_type_class,
725
- mem);
726
-
727
- if (!first) {
728
- str = rb_str_cat2(str, ", ");
729
- } else {
730
- first = false;
731
- }
732
- str = rb_str_append(str, rb_funcall(key, inspect_sym, 0));
733
- str = rb_str_cat2(str, "=>");
734
- str = rb_str_append(str, rb_funcall(value, inspect_sym, 0));
735
- }
736
-
737
- str = rb_str_cat2(str, "}");
738
- return str;
646
+ StringBuilder* builder = StringBuilder_New();
647
+ Map_Inspect(builder, self->map, self->key_type, self->value_type_info);
648
+ VALUE ret = StringBuilder_ToRubyString(builder);
649
+ StringBuilder_Free(builder);
650
+ return ret;
739
651
  }
740
652
 
741
653
  /*
@@ -747,87 +659,11 @@ VALUE Map_inspect(VALUE _self) {
747
659
  * in the new copy of this map. Returns the new copy of this map with merged
748
660
  * contents.
749
661
  */
750
- VALUE Map_merge(VALUE _self, VALUE hashmap) {
662
+ static VALUE Map_merge(VALUE _self, VALUE hashmap) {
751
663
  VALUE dupped = Map_dup(_self);
752
664
  return Map_merge_into_self(dupped, hashmap);
753
665
  }
754
666
 
755
- static int merge_into_self_callback(VALUE key, VALUE value, VALUE self) {
756
- Map_index_set(self, key, value);
757
- return ST_CONTINUE;
758
- }
759
-
760
- // Used only internally -- shared by #merge and #initialize.
761
- VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
762
- if (TYPE(hashmap) == T_HASH) {
763
- rb_hash_foreach(hashmap, merge_into_self_callback, _self);
764
- } else if (RB_TYPE_P(hashmap, T_DATA) && RTYPEDDATA_P(hashmap) &&
765
- RTYPEDDATA_TYPE(hashmap) == &Map_type) {
766
-
767
- Map* self = ruby_to_Map(_self);
768
- Map* other = ruby_to_Map(hashmap);
769
- upb_strtable_iter it;
770
-
771
- if (self->key_type != other->key_type ||
772
- self->value_type != other->value_type ||
773
- self->value_type_class != other->value_type_class) {
774
- rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types");
775
- }
776
-
777
- for (upb_strtable_begin(&it, &other->table);
778
- !upb_strtable_done(&it);
779
- upb_strtable_next(&it)) {
780
-
781
- // Replace any existing value by issuing a 'remove' operation first.
782
- upb_value v;
783
- upb_value oldv;
784
- upb_strtable_remove2(&self->table,
785
- upb_strtable_iter_key(&it),
786
- upb_strtable_iter_keylength(&it),
787
- &oldv);
788
-
789
- v = upb_strtable_iter_value(&it);
790
- upb_strtable_insert2(&self->table,
791
- upb_strtable_iter_key(&it),
792
- upb_strtable_iter_keylength(&it),
793
- v);
794
- }
795
- } else {
796
- rb_raise(rb_eArgError, "Unknown type merging into Map");
797
- }
798
- return _self;
799
- }
800
-
801
- // Internal method: map iterator initialization (used for serialization).
802
- void Map_begin(VALUE _self, Map_iter* iter) {
803
- Map* self = ruby_to_Map(_self);
804
- iter->self = self;
805
- upb_strtable_begin(&iter->it, &self->table);
806
- }
807
-
808
- void Map_next(Map_iter* iter) {
809
- upb_strtable_next(&iter->it);
810
- }
811
-
812
- bool Map_done(Map_iter* iter) {
813
- return upb_strtable_done(&iter->it);
814
- }
815
-
816
- VALUE Map_iter_key(Map_iter* iter) {
817
- return table_key_to_ruby(
818
- iter->self,
819
- upb_strtable_iter_key(&iter->it),
820
- upb_strtable_iter_keylength(&iter->it));
821
- }
822
-
823
- VALUE Map_iter_value(Map_iter* iter) {
824
- upb_value v = upb_strtable_iter_value(&iter->it);
825
- void* mem = value_memory(&v);
826
- return native_slot_get(iter->self->value_type,
827
- iter->self->value_type_class,
828
- mem);
829
- }
830
-
831
667
  void Map_register(VALUE module) {
832
668
  VALUE klass = rb_define_class_under(module, "Map", rb_cObject);
833
669
  rb_define_alloc_func(klass, Map_alloc);
@@ -844,10 +680,13 @@ void Map_register(VALUE module) {
844
680
  rb_define_method(klass, "delete", Map_delete, 1);
845
681
  rb_define_method(klass, "clear", Map_clear, 0);
846
682
  rb_define_method(klass, "length", Map_length, 0);
683
+ rb_define_method(klass, "size", Map_length, 0);
847
684
  rb_define_method(klass, "dup", Map_dup, 0);
685
+ // Also define #clone so that we don't inherit Object#clone.
686
+ rb_define_method(klass, "clone", Map_dup, 0);
848
687
  rb_define_method(klass, "==", Map_eq, 1);
688
+ rb_define_method(klass, "freeze", Map_freeze, 0);
849
689
  rb_define_method(klass, "hash", Map_hash, 0);
850
- rb_define_method(klass, "to_hash", Map_to_h, 0);
851
690
  rb_define_method(klass, "to_h", Map_to_h, 0);
852
691
  rb_define_method(klass, "inspect", Map_inspect, 0);
853
692
  rb_define_method(klass, "merge", Map_merge, 1);