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 "convert.h"
32
9
  #include "defs.h"
@@ -34,7 +11,7 @@
34
11
  #include "protobuf.h"
35
12
 
36
13
  // -----------------------------------------------------------------------------
37
- // Basic map operations on top of upb_map.
14
+ // Basic map operations on top of upb_Map.
38
15
  //
39
16
  // Note that we roll our own `Map` container here because, as for
40
17
  // `RepeatedField`, we want a strongly-typed container. This is so that any user
@@ -48,8 +25,8 @@
48
25
  // -----------------------------------------------------------------------------
49
26
 
50
27
  typedef struct {
51
- const upb_map *map; // Can convert to mutable when non-frozen.
52
- upb_fieldtype_t key_type;
28
+ const upb_Map* map; // Can convert to mutable when non-frozen.
29
+ upb_CType key_type;
53
30
  TypeInfo value_type_info;
54
31
  VALUE value_type_class;
55
32
  VALUE arena;
@@ -61,10 +38,12 @@ static void Map_mark(void* _self) {
61
38
  rb_gc_mark(self->arena);
62
39
  }
63
40
 
41
+ static size_t Map_memsize(const void* _self) { return sizeof(Map); }
42
+
64
43
  const rb_data_type_t Map_type = {
65
- "Google::Protobuf::Map",
66
- { Map_mark, RUBY_DEFAULT_FREE, NULL },
67
- .flags = RUBY_TYPED_FREE_IMMEDIATELY,
44
+ "Google::Protobuf::Map",
45
+ {Map_mark, RUBY_DEFAULT_FREE, Map_memsize},
46
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
68
47
  };
69
48
 
70
49
  VALUE cMap;
@@ -84,33 +63,33 @@ static VALUE Map_alloc(VALUE klass) {
84
63
  return TypedData_Wrap_Struct(klass, &Map_type, self);
85
64
  }
86
65
 
87
- VALUE Map_GetRubyWrapper(upb_map* map, upb_fieldtype_t key_type,
66
+ VALUE Map_GetRubyWrapper(const upb_Map* map, upb_CType key_type,
88
67
  TypeInfo value_type, VALUE arena) {
89
68
  PBRUBY_ASSERT(map);
69
+ PBRUBY_ASSERT(arena != Qnil);
90
70
 
91
71
  VALUE val = ObjectCache_Get(map);
92
72
 
93
73
  if (val == Qnil) {
94
74
  val = Map_alloc(cMap);
95
75
  Map* self;
96
- ObjectCache_Add(map, val);
97
76
  TypedData_Get_Struct(val, Map, &Map_type, self);
98
77
  self->map = map;
99
78
  self->arena = arena;
100
79
  self->key_type = key_type;
101
80
  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;
81
+ if (self->value_type_info.type == kUpb_CType_Message) {
82
+ const upb_MessageDef* val_m = self->value_type_info.def.msgdef;
104
83
  self->value_type_class = Descriptor_DefToClass(val_m);
105
84
  }
85
+ return ObjectCache_TryAdd(map, val);
106
86
  }
107
-
108
87
  return val;
109
88
  }
110
89
 
111
- static VALUE Map_new_this_type(Map *from) {
90
+ static VALUE Map_new_this_type(Map* from) {
112
91
  VALUE arena_rb = Arena_new();
113
- upb_map* map = upb_map_new(Arena_get(arena_rb), from->key_type,
92
+ upb_Map* map = upb_Map_New(Arena_get(arena_rb), from->key_type,
114
93
  from->value_type_info.type);
115
94
  VALUE ret =
116
95
  Map_GetRubyWrapper(map, from->key_type, from->value_type_info, arena_rb);
@@ -125,22 +104,22 @@ static TypeInfo Map_keyinfo(Map* self) {
125
104
  return ret;
126
105
  }
127
106
 
128
- static upb_map *Map_GetMutable(VALUE _self) {
129
- rb_check_frozen(_self);
130
- return (upb_map*)ruby_to_Map(_self)->map;
107
+ static upb_Map* Map_GetMutable(VALUE _self) {
108
+ const upb_Map* map = ruby_to_Map(_self)->map;
109
+ Protobuf_CheckNotFrozen(_self, upb_Map_IsFrozen(map));
110
+ return (upb_Map*)map;
131
111
  }
132
112
 
133
- VALUE Map_CreateHash(const upb_map* map, upb_fieldtype_t key_type,
113
+ VALUE Map_CreateHash(const upb_Map* map, upb_CType key_type,
134
114
  TypeInfo val_info) {
135
115
  VALUE hash = rb_hash_new();
136
- size_t iter = UPB_MAP_BEGIN;
137
116
  TypeInfo key_info = TypeInfo_from_type(key_type);
138
117
 
139
118
  if (!map) return hash;
140
119
 
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);
120
+ size_t iter = kUpb_Map_Begin;
121
+ upb_MessageValue key, val;
122
+ while (upb_Map_Next(map, &key, &val, &iter)) {
144
123
  VALUE key_val = Convert_UpbToRuby(key, key_info, Qnil);
145
124
  VALUE val_val = Scalar_CreateHash(val, val_info);
146
125
  rb_hash_aset(hash, key_val, val_val);
@@ -152,25 +131,25 @@ VALUE Map_CreateHash(const upb_map* map, upb_fieldtype_t key_type,
152
131
  VALUE Map_deep_copy(VALUE obj) {
153
132
  Map* self = ruby_to_Map(obj);
154
133
  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);
134
+ upb_Arena* arena = Arena_get(new_arena_rb);
135
+ upb_Map* new_map =
136
+ upb_Map_New(arena, self->key_type, self->value_type_info.type);
137
+ size_t iter = kUpb_Map_Begin;
138
+ upb_MessageValue key, val;
139
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
140
+ upb_MessageValue val_copy =
141
+ Msgval_DeepCopy(val, self->value_type_info, arena);
142
+ upb_Map_Set(new_map, key, val_copy, arena);
164
143
  }
165
144
 
166
145
  return Map_GetRubyWrapper(new_map, self->key_type, self->value_type_info,
167
146
  new_arena_rb);
168
147
  }
169
148
 
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);
149
+ const upb_Map* Map_GetUpbMap(VALUE val, const upb_FieldDef* field,
150
+ upb_Arena* arena) {
151
+ const upb_FieldDef* key_field = map_field_key(field);
152
+ const upb_FieldDef* value_field = map_field_value(field);
174
153
  TypeInfo value_type_info = TypeInfo_get(value_field);
175
154
  Map* self;
176
155
 
@@ -180,7 +159,7 @@ const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef* field,
180
159
  }
181
160
 
182
161
  self = ruby_to_Map(val);
183
- if (self->key_type != upb_fielddef_type(key_field)) {
162
+ if (self->key_type != upb_FieldDef_CType(key_field)) {
184
163
  rb_raise(cTypeError, "Map key type does not match field's key type");
185
164
  }
186
165
  if (self->value_type_info.type != value_type_info.type) {
@@ -194,16 +173,15 @@ const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef* field,
194
173
  return self->map;
195
174
  }
196
175
 
197
- void Map_Inspect(StringBuilder* b, const upb_map* map, upb_fieldtype_t key_type,
176
+ void Map_Inspect(StringBuilder* b, const upb_Map* map, upb_CType key_type,
198
177
  TypeInfo val_type) {
199
178
  bool first = true;
200
179
  TypeInfo key_type_info = {key_type};
201
180
  StringBuilder_Printf(b, "{");
202
181
  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);
182
+ size_t iter = kUpb_Map_Begin;
183
+ upb_MessageValue key, val;
184
+ while (upb_Map_Next(map, &key, &val, &iter)) {
207
185
  if (first) {
208
186
  first = false;
209
187
  } else {
@@ -219,10 +197,12 @@ void Map_Inspect(StringBuilder* b, const upb_map* map, upb_fieldtype_t key_type,
219
197
 
220
198
  static int merge_into_self_callback(VALUE key, VALUE val, VALUE _self) {
221
199
  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);
200
+ upb_Arena* arena = Arena_get(self->arena);
201
+ upb_MessageValue key_val =
202
+ Convert_RubyToUpb(key, "", Map_keyinfo(self), arena);
203
+ upb_MessageValue val_val =
204
+ Convert_RubyToUpb(val, "", self->value_type_info, arena);
205
+ upb_Map_Set(Map_GetMutable(_self), key_val, val_val, arena);
226
206
  return ST_CONTINUE;
227
207
  }
228
208
 
@@ -234,9 +214,8 @@ static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
234
214
  RTYPEDDATA_TYPE(hashmap) == &Map_type) {
235
215
  Map* self = ruby_to_Map(_self);
236
216
  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;
217
+ upb_Arena* arena = Arena_get(self->arena);
218
+ upb_Map* self_map = Map_GetMutable(_self);
240
219
 
241
220
  Arena_fuse(other->arena, arena);
242
221
 
@@ -246,10 +225,10 @@ static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
246
225
  rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types");
247
226
  }
248
227
 
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);
228
+ size_t iter = kUpb_Map_Begin;
229
+ upb_MessageValue key, val;
230
+ while (upb_Map_Next(other->map, &key, &val, &iter)) {
231
+ upb_Map_Set(self_map, key, val, arena);
253
232
  }
254
233
  } else {
255
234
  rb_raise(rb_eArgError, "Unknown type merging into Map");
@@ -305,22 +284,24 @@ static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
305
284
 
306
285
  // Check that the key type is an allowed type.
307
286
  switch (self->key_type) {
308
- case UPB_TYPE_INT32:
309
- case UPB_TYPE_INT64:
310
- case UPB_TYPE_UINT32:
311
- case UPB_TYPE_UINT64:
312
- case UPB_TYPE_BOOL:
313
- case UPB_TYPE_STRING:
314
- case UPB_TYPE_BYTES:
287
+ case kUpb_CType_Int32:
288
+ case kUpb_CType_Int64:
289
+ case kUpb_CType_UInt32:
290
+ case kUpb_CType_UInt64:
291
+ case kUpb_CType_Bool:
292
+ case kUpb_CType_String:
293
+ case kUpb_CType_Bytes:
315
294
  // These are OK.
316
295
  break;
317
296
  default:
318
297
  rb_raise(rb_eArgError, "Invalid key type for map.");
319
298
  }
320
299
 
321
- self->map = upb_map_new(Arena_get(self->arena), self->key_type,
300
+ self->map = upb_Map_New(Arena_get(self->arena), self->key_type,
322
301
  self->value_type_info.type);
323
- ObjectCache_Add(self->map, _self);
302
+ VALUE stored = ObjectCache_TryAdd(self->map, _self);
303
+ (void)stored;
304
+ PBRUBY_ASSERT(stored == _self);
324
305
 
325
306
  if (init_arg != Qnil) {
326
307
  Map_merge_into_self(_self, init_arg);
@@ -339,11 +320,10 @@ static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
339
320
  */
340
321
  static VALUE Map_each(VALUE _self) {
341
322
  Map* self = ruby_to_Map(_self);
342
- size_t iter = UPB_MAP_BEGIN;
323
+ size_t iter = kUpb_Map_Begin;
324
+ upb_MessageValue key, val;
343
325
 
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);
326
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
347
327
  VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
348
328
  VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
349
329
  rb_yield_values(2, key_val, val_val);
@@ -360,11 +340,11 @@ static VALUE Map_each(VALUE _self) {
360
340
  */
361
341
  static VALUE Map_keys(VALUE _self) {
362
342
  Map* self = ruby_to_Map(_self);
363
- size_t iter = UPB_MAP_BEGIN;
343
+ size_t iter = kUpb_Map_Begin;
364
344
  VALUE ret = rb_ary_new();
345
+ upb_MessageValue key, val;
365
346
 
366
- while (upb_mapiter_next(self->map, &iter)) {
367
- upb_msgval key = upb_mapiter_key(self->map, iter);
347
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
368
348
  VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
369
349
  rb_ary_push(ret, key_val);
370
350
  }
@@ -380,11 +360,11 @@ static VALUE Map_keys(VALUE _self) {
380
360
  */
381
361
  static VALUE Map_values(VALUE _self) {
382
362
  Map* self = ruby_to_Map(_self);
383
- size_t iter = UPB_MAP_BEGIN;
363
+ size_t iter = kUpb_Map_Begin;
384
364
  VALUE ret = rb_ary_new();
365
+ upb_MessageValue key, val;
385
366
 
386
- while (upb_mapiter_next(self->map, &iter)) {
387
- upb_msgval val = upb_mapiter_value(self->map, iter);
367
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
388
368
  VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
389
369
  rb_ary_push(ret, val_val);
390
370
  }
@@ -401,10 +381,11 @@ static VALUE Map_values(VALUE _self) {
401
381
  */
402
382
  static VALUE Map_index(VALUE _self, VALUE key) {
403
383
  Map* self = ruby_to_Map(_self);
404
- upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
405
- upb_msgval val;
384
+ upb_MessageValue key_upb =
385
+ Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
386
+ upb_MessageValue val;
406
387
 
407
- if (upb_map_get(self->map, key_upb, &val)) {
388
+ if (upb_Map_Get(self->map, key_upb, &val)) {
408
389
  return Convert_UpbToRuby(val, self->value_type_info, self->arena);
409
390
  } else {
410
391
  return Qnil;
@@ -421,11 +402,13 @@ static VALUE Map_index(VALUE _self, VALUE key) {
421
402
  */
422
403
  static VALUE Map_index_set(VALUE _self, VALUE key, VALUE val) {
423
404
  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);
405
+ upb_Arena* arena = Arena_get(self->arena);
406
+ upb_MessageValue key_upb =
407
+ Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
408
+ upb_MessageValue val_upb =
409
+ Convert_RubyToUpb(val, "", self->value_type_info, arena);
427
410
 
428
- upb_map_set(Map_GetMutable(_self), key_upb, val_upb, arena);
411
+ upb_Map_Set(Map_GetMutable(_self), key_upb, val_upb, arena);
429
412
 
430
413
  return val;
431
414
  }
@@ -439,9 +422,10 @@ static VALUE Map_index_set(VALUE _self, VALUE key, VALUE val) {
439
422
  */
440
423
  static VALUE Map_has_key(VALUE _self, VALUE key) {
441
424
  Map* self = ruby_to_Map(_self);
442
- upb_msgval key_upb = Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
425
+ upb_MessageValue key_upb =
426
+ Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
443
427
 
444
- if (upb_map_get(self->map, key_upb, NULL)) {
428
+ if (upb_Map_Get(self->map, key_upb, NULL)) {
445
429
  return Qtrue;
446
430
  } else {
447
431
  return Qfalse;
@@ -456,24 +440,18 @@ static VALUE Map_has_key(VALUE _self, VALUE key) {
456
440
  * nil if none was present. Throws an exception if the key is of the wrong type.
457
441
  */
458
442
  static VALUE Map_delete(VALUE _self, VALUE key) {
443
+ upb_Map* map = Map_GetMutable(_self);
459
444
  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;
463
445
 
464
- rb_check_frozen(_self);
446
+ upb_MessageValue key_upb =
447
+ Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
448
+ upb_MessageValue val_upb;
465
449
 
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);
450
+ if (upb_Map_Delete(map, key_upb, &val_upb)) {
451
+ return Convert_UpbToRuby(val_upb, self->value_type_info, self->arena);
470
452
  } else {
471
- ret = Qnil;
453
+ return Qnil;
472
454
  }
473
-
474
- upb_map_delete(Map_GetMutable(_self), key_upb);
475
-
476
- return ret;
477
455
  }
478
456
 
479
457
  /*
@@ -483,7 +461,7 @@ static VALUE Map_delete(VALUE _self, VALUE key) {
483
461
  * Removes all entries from the map.
484
462
  */
485
463
  static VALUE Map_clear(VALUE _self) {
486
- upb_map_clear(Map_GetMutable(_self));
464
+ upb_Map_Clear(Map_GetMutable(_self));
487
465
  return Qnil;
488
466
  }
489
467
 
@@ -495,7 +473,7 @@ static VALUE Map_clear(VALUE _self) {
495
473
  */
496
474
  static VALUE Map_length(VALUE _self) {
497
475
  Map* self = ruby_to_Map(_self);
498
- return ULL2NUM(upb_map_size(self->map));
476
+ return ULL2NUM(upb_Map_Size(self->map));
499
477
  }
500
478
 
501
479
  /*
@@ -509,16 +487,15 @@ static VALUE Map_dup(VALUE _self) {
509
487
  Map* self = ruby_to_Map(_self);
510
488
  VALUE new_map_rb = Map_new_this_type(self);
511
489
  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);
490
+ size_t iter = kUpb_Map_Begin;
491
+ upb_Arena* arena = Arena_get(new_self->arena);
492
+ upb_Map* new_map = Map_GetMutable(new_map_rb);
515
493
 
516
494
  Arena_fuse(self->arena, arena);
517
495
 
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);
496
+ upb_MessageValue key, val;
497
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
498
+ upb_Map_Set(new_map, key, val, arena);
522
499
  }
523
500
 
524
501
  return new_map_rb;
@@ -559,18 +536,17 @@ VALUE Map_eq(VALUE _self, VALUE _other) {
559
536
  self->value_type_class != other->value_type_class) {
560
537
  return Qfalse;
561
538
  }
562
- if (upb_map_size(self->map) != upb_map_size(other->map)) {
539
+ if (upb_Map_Size(self->map) != upb_Map_Size(other->map)) {
563
540
  return Qfalse;
564
541
  }
565
542
 
566
543
  // For each member of self, check that an equal member exists at the same key
567
544
  // in other.
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)) {
545
+ size_t iter = kUpb_Map_Begin;
546
+ upb_MessageValue key, val;
547
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
548
+ upb_MessageValue other_val;
549
+ if (!upb_Map_Get(other->map, key, &other_val)) {
574
550
  // Not present in other map.
575
551
  return Qfalse;
576
552
  }
@@ -585,20 +561,81 @@ VALUE Map_eq(VALUE _self, VALUE _other) {
585
561
 
586
562
  /*
587
563
  * call-seq:
588
- * Message.freeze => self
564
+ * Map.frozen? => bool
565
+ *
566
+ * Returns true if the map is frozen in either Ruby or the underlying
567
+ * representation. Freezes the Ruby map object if it is not already frozen in
568
+ * Ruby but it is frozen in the underlying representation.
569
+ */
570
+ VALUE Map_frozen(VALUE _self) {
571
+ Map* self = ruby_to_Map(_self);
572
+ if (!upb_Map_IsFrozen(self->map)) {
573
+ PBRUBY_ASSERT(!RB_OBJ_FROZEN(_self));
574
+ return Qfalse;
575
+ }
576
+
577
+ // Lazily freeze the Ruby wrapper.
578
+ if (!RB_OBJ_FROZEN(_self)) RB_OBJ_FREEZE(_self);
579
+ return Qtrue;
580
+ }
581
+
582
+ /*
583
+ * call-seq:
584
+ * Map.freeze => self
589
585
  *
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.
586
+ * Freezes the map object. We have to intercept this so we can freeze the
587
+ * underlying representation, not just the Ruby wrapper.
592
588
  */
593
- static VALUE Map_freeze(VALUE _self) {
589
+ VALUE Map_freeze(VALUE _self) {
594
590
  Map* self = ruby_to_Map(_self);
595
- if (!RB_OBJ_FROZEN(_self)) {
596
- Arena_Pin(self->arena, _self);
597
- RB_OBJ_FREEZE(_self);
591
+ if (RB_OBJ_FROZEN(_self)) {
592
+ PBRUBY_ASSERT(upb_Map_IsFrozen(self->map));
593
+ return _self;
598
594
  }
595
+
596
+ if (!upb_Map_IsFrozen(self->map)) {
597
+ if (self->value_type_info.type == kUpb_CType_Message) {
598
+ upb_Map_Freeze(
599
+ Map_GetMutable(_self),
600
+ upb_MessageDef_MiniTable(self->value_type_info.def.msgdef));
601
+ } else {
602
+ upb_Map_Freeze(Map_GetMutable(_self), NULL);
603
+ }
604
+ }
605
+
606
+ RB_OBJ_FREEZE(_self);
607
+
599
608
  return _self;
600
609
  }
601
610
 
611
+ VALUE Map_EmptyFrozen(const upb_FieldDef* f) {
612
+ PBRUBY_ASSERT(upb_FieldDef_IsMap(f));
613
+ VALUE val = ObjectCache_Get(f);
614
+
615
+ if (val == Qnil) {
616
+ const upb_FieldDef* key_f = map_field_key(f);
617
+ const upb_FieldDef* val_f = map_field_value(f);
618
+ upb_CType key_type = upb_FieldDef_CType(key_f);
619
+ TypeInfo value_type_info = TypeInfo_get(val_f);
620
+ val = Map_alloc(cMap);
621
+ Map* self;
622
+ TypedData_Get_Struct(val, Map, &Map_type, self);
623
+ self->arena = Arena_new();
624
+ self->map =
625
+ upb_Map_New(Arena_get(self->arena), key_type, value_type_info.type);
626
+ self->key_type = key_type;
627
+ self->value_type_info = value_type_info;
628
+ if (self->value_type_info.type == kUpb_CType_Message) {
629
+ const upb_MessageDef* val_m = value_type_info.def.msgdef;
630
+ self->value_type_class = Descriptor_DefToClass(val_m);
631
+ }
632
+ return ObjectCache_TryAdd(f, Map_freeze(val));
633
+ }
634
+ PBRUBY_ASSERT(RB_OBJ_FROZEN(val));
635
+ PBRUBY_ASSERT(upb_Map_IsFrozen(ruby_to_Map(val)->map));
636
+ return val;
637
+ }
638
+
602
639
  /*
603
640
  * call-seq:
604
641
  * Map.hash => hash_value
@@ -609,11 +646,10 @@ VALUE Map_hash(VALUE _self) {
609
646
  Map* self = ruby_to_Map(_self);
610
647
  uint64_t hash = 0;
611
648
 
612
- size_t iter = UPB_MAP_BEGIN;
649
+ size_t iter = kUpb_Map_Begin;
613
650
  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);
651
+ upb_MessageValue key, val;
652
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
617
653
  hash = Msgval_GetHash(key, key_info, hash);
618
654
  hash = Msgval_GetHash(val, self->value_type_info, hash);
619
655
  }
@@ -686,6 +722,7 @@ void Map_register(VALUE module) {
686
722
  rb_define_method(klass, "clone", Map_dup, 0);
687
723
  rb_define_method(klass, "==", Map_eq, 1);
688
724
  rb_define_method(klass, "freeze", Map_freeze, 0);
725
+ rb_define_method(klass, "frozen?", Map_frozen, 0);
689
726
  rb_define_method(klass, "hash", Map_hash, 0);
690
727
  rb_define_method(klass, "to_h", Map_to_h, 0);
691
728
  rb_define_method(klass, "inspect", Map_inspect, 0);
@@ -1,59 +1,37 @@
1
1
  // Protocol Buffers - Google's data interchange format
2
2
  // Copyright 2008 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
  #ifndef RUBY_PROTOBUF_MAP_H_
32
9
  #define RUBY_PROTOBUF_MAP_H_
33
10
 
34
- #include <ruby/ruby.h>
35
-
36
11
  #include "protobuf.h"
37
12
  #include "ruby-upb.h"
38
13
 
14
+ // Returns a frozen sentinel Ruby wrapper object for an empty upb_Map with the
15
+ // key and value types specified by the field. Creates one if it doesn't exist.
16
+ VALUE Map_EmptyFrozen(const upb_FieldDef* f);
17
+
39
18
  // Returns a Ruby wrapper object for the given map, which will be created if
40
19
  // one does not exist already.
41
- VALUE Map_GetRubyWrapper(upb_map *map, upb_fieldtype_t key_type,
20
+ VALUE Map_GetRubyWrapper(const upb_Map *map, upb_CType key_type,
42
21
  TypeInfo value_type, VALUE arena);
43
22
 
44
- // Gets the underlying upb_map for this Ruby map object, which must have
23
+ // Gets the underlying upb_Map for this Ruby map object, which must have
45
24
  // key/value type that match |field|. If this is not a map or the type doesn't
46
25
  // match, raises an exception.
47
- const upb_map *Map_GetUpbMap(VALUE val, const upb_fielddef *field,
48
- upb_arena *arena);
26
+ const upb_Map *Map_GetUpbMap(VALUE val, const upb_FieldDef *field,
27
+ upb_Arena *arena);
49
28
 
50
29
  // Implements #inspect for this map by appending its contents to |b|.
51
- void Map_Inspect(StringBuilder *b, const upb_map *map, upb_fieldtype_t key_type,
30
+ void Map_Inspect(StringBuilder *b, const upb_Map *map, upb_CType key_type,
52
31
  TypeInfo val_type);
53
32
 
54
33
  // Returns a new Hash object containing the contents of this Map.
55
- VALUE Map_CreateHash(const upb_map* map, upb_fieldtype_t key_type,
56
- TypeInfo val_info);
34
+ VALUE Map_CreateHash(const upb_Map *map, upb_CType key_type, TypeInfo val_info);
57
35
 
58
36
  // Returns a deep copy of this Map object.
59
37
  VALUE Map_deep_copy(VALUE obj);
@@ -64,4 +42,7 @@ extern VALUE cMap;
64
42
  // Call at startup to register all types in this module.
65
43
  void Map_register(VALUE module);
66
44
 
45
+ // Recursively freeze map
46
+ VALUE Map_freeze(VALUE _self);
47
+
67
48
  #endif // RUBY_PROTOBUF_MAP_H_