google-protobuf 3.20.0 → 4.34.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/Rakefile +3 -0
  3. data/ext/google/protobuf_c/convert.c +60 -86
  4. data/ext/google/protobuf_c/convert.h +3 -28
  5. data/ext/google/protobuf_c/defs.c +961 -157
  6. data/ext/google/protobuf_c/defs.h +3 -28
  7. data/ext/google/protobuf_c/extconf.rb +21 -11
  8. data/ext/google/protobuf_c/glue.c +135 -0
  9. data/ext/google/protobuf_c/map.c +187 -121
  10. data/ext/google/protobuf_c/map.h +12 -30
  11. data/ext/google/protobuf_c/message.c +354 -294
  12. data/ext/google/protobuf_c/message.h +11 -33
  13. data/ext/google/protobuf_c/protobuf.c +65 -188
  14. data/ext/google/protobuf_c/protobuf.h +21 -41
  15. data/ext/google/protobuf_c/repeated_field.c +145 -74
  16. data/ext/google/protobuf_c/repeated_field.h +11 -29
  17. data/ext/google/protobuf_c/ruby-upb.c +15734 -8866
  18. data/ext/google/protobuf_c/ruby-upb.h +16769 -4511
  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 +1 -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 +20 -7
  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/lib/google/protobuf/any_pb.rb +6 -8
  29. data/lib/google/protobuf/api_pb.rb +6 -26
  30. data/lib/google/protobuf/descriptor_pb.rb +27 -226
  31. data/lib/google/protobuf/duration_pb.rb +6 -8
  32. data/lib/google/protobuf/empty_pb.rb +6 -6
  33. data/lib/google/protobuf/ffi/descriptor.rb +175 -0
  34. data/lib/google/protobuf/ffi/descriptor_pool.rb +83 -0
  35. data/lib/google/protobuf/ffi/enum_descriptor.rb +183 -0
  36. data/lib/google/protobuf/ffi/ffi.rb +213 -0
  37. data/lib/google/protobuf/ffi/field_descriptor.rb +346 -0
  38. data/lib/google/protobuf/ffi/file_descriptor.rb +85 -0
  39. data/lib/google/protobuf/ffi/internal/arena.rb +60 -0
  40. data/lib/google/protobuf/ffi/internal/convert.rb +292 -0
  41. data/lib/google/protobuf/ffi/internal/pointer_helper.rb +36 -0
  42. data/lib/google/protobuf/ffi/internal/type_safety.rb +25 -0
  43. data/lib/google/protobuf/ffi/map.rb +433 -0
  44. data/lib/google/protobuf/ffi/message.rb +783 -0
  45. data/lib/google/protobuf/ffi/method_descriptor.rb +124 -0
  46. data/lib/google/protobuf/ffi/object_cache.rb +30 -0
  47. data/lib/google/protobuf/ffi/oneof_descriptor.rb +107 -0
  48. data/lib/google/protobuf/ffi/repeated_field.rb +411 -0
  49. data/lib/google/protobuf/ffi/service_descriptor.rb +117 -0
  50. data/lib/google/protobuf/field_mask_pb.rb +6 -7
  51. data/lib/google/protobuf/internal/object_cache.rb +99 -0
  52. data/lib/google/protobuf/message_exts.rb +12 -26
  53. data/lib/google/protobuf/plugin_pb.rb +25 -0
  54. data/lib/google/protobuf/repeated_field.rb +22 -33
  55. data/lib/google/protobuf/source_context_pb.rb +6 -7
  56. data/lib/google/protobuf/struct_pb.rb +6 -23
  57. data/lib/google/protobuf/timestamp_pb.rb +6 -8
  58. data/lib/google/protobuf/type_pb.rb +6 -71
  59. data/lib/google/protobuf/well_known_types.rb +5 -34
  60. data/lib/google/protobuf/wrappers_pb.rb +6 -31
  61. data/lib/google/protobuf.rb +27 -45
  62. data/lib/google/protobuf_ffi.rb +52 -0
  63. data/lib/google/protobuf_native.rb +19 -0
  64. data/lib/google/tasks/ffi.rake +100 -0
  65. metadata +103 -32
  66. data/ext/google/protobuf_c/third_party/utf8_range/naive.c +0 -92
  67. data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +0 -157
  68. data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +0 -170
  69. data/ext/google/protobuf_c/wrap_memcpy.c +0 -52
  70. data/lib/google/protobuf/descriptor_dsl.rb +0 -465
  71. data/tests/basic.rb +0 -670
  72. data/tests/generated_code_test.rb +0 -23
  73. 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"
@@ -61,9 +38,11 @@ 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
44
  "Google::Protobuf::Map",
66
- {Map_mark, RUBY_DEFAULT_FREE, NULL},
45
+ {Map_mark, RUBY_DEFAULT_FREE, Map_memsize},
67
46
  .flags = RUBY_TYPED_FREE_IMMEDIATELY,
68
47
  };
69
48
 
@@ -84,16 +63,16 @@ 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_CType key_type, TypeInfo value_type,
88
- VALUE arena) {
66
+ VALUE Map_GetRubyWrapper(const upb_Map* map, upb_CType key_type,
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;
@@ -103,8 +82,8 @@ VALUE Map_GetRubyWrapper(upb_Map* map, upb_CType key_type, TypeInfo value_type,
103
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
 
@@ -126,21 +105,21 @@ static TypeInfo Map_keyinfo(Map* self) {
126
105
  }
127
106
 
128
107
  static upb_Map* Map_GetMutable(VALUE _self) {
129
- rb_check_frozen(_self);
130
- return (upb_Map*)ruby_to_Map(_self)->map;
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
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 = kUpb_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_MapIterator_Next(map, &iter)) {
142
- upb_MessageValue key = upb_MapIterator_Key(map, iter);
143
- upb_MessageValue val = upb_MapIterator_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);
@@ -156,9 +135,8 @@ VALUE Map_deep_copy(VALUE obj) {
156
135
  upb_Map* new_map =
157
136
  upb_Map_New(arena, self->key_type, self->value_type_info.type);
158
137
  size_t iter = kUpb_Map_Begin;
159
- while (upb_MapIterator_Next(self->map, &iter)) {
160
- upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
161
- upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
138
+ upb_MessageValue key, val;
139
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
162
140
  upb_MessageValue val_copy =
163
141
  Msgval_DeepCopy(val, self->value_type_info, arena);
164
142
  upb_Map_Set(new_map, key, val_copy, arena);
@@ -202,9 +180,8 @@ void Map_Inspect(StringBuilder* b, const upb_Map* map, upb_CType key_type,
202
180
  StringBuilder_Printf(b, "{");
203
181
  if (map) {
204
182
  size_t iter = kUpb_Map_Begin;
205
- while (upb_MapIterator_Next(map, &iter)) {
206
- upb_MessageValue key = upb_MapIterator_Key(map, iter);
207
- upb_MessageValue val = upb_MapIterator_Value(map, iter);
183
+ upb_MessageValue key, val;
184
+ while (upb_Map_Next(map, &key, &val, &iter)) {
208
185
  if (first) {
209
186
  first = false;
210
187
  } else {
@@ -238,8 +215,7 @@ static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
238
215
  Map* self = ruby_to_Map(_self);
239
216
  Map* other = ruby_to_Map(hashmap);
240
217
  upb_Arena* arena = Arena_get(self->arena);
241
- upb_Message* self_msg = Map_GetMutable(_self);
242
- size_t iter = kUpb_Map_Begin;
218
+ upb_Map* self_map = Map_GetMutable(_self);
243
219
 
244
220
  Arena_fuse(other->arena, arena);
245
221
 
@@ -249,10 +225,10 @@ static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
249
225
  rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types");
250
226
  }
251
227
 
252
- while (upb_MapIterator_Next(other->map, &iter)) {
253
- upb_MessageValue key = upb_MapIterator_Key(other->map, iter);
254
- upb_MessageValue val = upb_MapIterator_Value(other->map, iter);
255
- 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);
256
232
  }
257
233
  } else {
258
234
  rb_raise(rb_eArgError, "Unknown type merging into Map");
@@ -260,10 +236,15 @@ static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
260
236
  return _self;
261
237
  }
262
238
 
239
+ /**
240
+ * ruby-doc: Map
241
+ *
242
+ * This class represents a Protobuf Map. It is largely automatically transformed
243
+ * to and from a Ruby hash.
244
+ */
245
+
263
246
  /*
264
- * call-seq:
265
- * Map.new(key_type, value_type, value_typeclass = nil, init_hashmap = {})
266
- * => new map
247
+ * ruby-doc: Map#initialize
267
248
  *
268
249
  * Allocates a new Map container. This constructor may be called with 2, 3, or 4
269
250
  * arguments. The first two arguments are always present and are symbols (taking
@@ -289,6 +270,13 @@ static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
289
270
  * shallow-copied into the new Map: the original map is unmodified, but
290
271
  * references to underlying objects will be shared if the value type is a
291
272
  * message type.
273
+ *
274
+ * @param key_type [Symbol]
275
+ * @param value_type [Symbol]
276
+ * @param value_typeclass [Class<AbstractMessage>,Module]
277
+ * @paramdefault value_typeclass nil
278
+ * @param init_hashmap [Hash,Map]
279
+ * @paramdefault init_hashmap {}
292
280
  */
293
281
  static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
294
282
  Map* self = ruby_to_Map(_self);
@@ -323,7 +311,9 @@ static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
323
311
 
324
312
  self->map = upb_Map_New(Arena_get(self->arena), self->key_type,
325
313
  self->value_type_info.type);
326
- ObjectCache_Add(self->map, _self);
314
+ VALUE stored = ObjectCache_TryAdd(self->map, _self);
315
+ (void)stored;
316
+ PBRUBY_ASSERT(stored == _self);
327
317
 
328
318
  if (init_arg != Qnil) {
329
319
  Map_merge_into_self(_self, init_arg);
@@ -333,20 +323,21 @@ static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
333
323
  }
334
324
 
335
325
  /*
336
- * call-seq:
337
- * Map.each(&block)
326
+ * ruby-doc: Map#each
338
327
  *
339
328
  * Invokes &block on each |key, value| pair in the map, in unspecified order.
340
329
  * Note that Map also includes Enumerable; map thus acts like a normal Ruby
341
330
  * sequence.
331
+ *
332
+ * @yield [Object, Object]
333
+ * @return [nil]
342
334
  */
343
335
  static VALUE Map_each(VALUE _self) {
344
336
  Map* self = ruby_to_Map(_self);
345
337
  size_t iter = kUpb_Map_Begin;
338
+ upb_MessageValue key, val;
346
339
 
347
- while (upb_MapIterator_Next(self->map, &iter)) {
348
- upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
349
- upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
340
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
350
341
  VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
351
342
  VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
352
343
  rb_yield_values(2, key_val, val_val);
@@ -356,18 +347,19 @@ static VALUE Map_each(VALUE _self) {
356
347
  }
357
348
 
358
349
  /*
359
- * call-seq:
360
- * Map.keys => [list_of_keys]
350
+ * ruby-doc: Map#keys
361
351
  *
362
352
  * Returns the list of keys contained in the map, in unspecified order.
353
+ *
354
+ * @return [Array<Object>]
363
355
  */
364
356
  static VALUE Map_keys(VALUE _self) {
365
357
  Map* self = ruby_to_Map(_self);
366
358
  size_t iter = kUpb_Map_Begin;
367
359
  VALUE ret = rb_ary_new();
360
+ upb_MessageValue key, val;
368
361
 
369
- while (upb_MapIterator_Next(self->map, &iter)) {
370
- upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
362
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
371
363
  VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
372
364
  rb_ary_push(ret, key_val);
373
365
  }
@@ -376,18 +368,19 @@ static VALUE Map_keys(VALUE _self) {
376
368
  }
377
369
 
378
370
  /*
379
- * call-seq:
380
- * Map.values => [list_of_values]
371
+ * ruby-doc: Map#values
381
372
  *
382
373
  * Returns the list of values contained in the map, in unspecified order.
374
+ *
375
+ * @return [Array<Object>]
383
376
  */
384
377
  static VALUE Map_values(VALUE _self) {
385
378
  Map* self = ruby_to_Map(_self);
386
379
  size_t iter = kUpb_Map_Begin;
387
380
  VALUE ret = rb_ary_new();
381
+ upb_MessageValue key, val;
388
382
 
389
- while (upb_MapIterator_Next(self->map, &iter)) {
390
- upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
383
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
391
384
  VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
392
385
  rb_ary_push(ret, val_val);
393
386
  }
@@ -396,11 +389,13 @@ static VALUE Map_values(VALUE _self) {
396
389
  }
397
390
 
398
391
  /*
399
- * call-seq:
400
- * Map.[](key) => value
392
+ * ruby-doc: Map#[]
401
393
  *
402
394
  * Accesses the element at the given key. Throws an exception if the key type is
403
395
  * incorrect. Returns nil when the key is not present in the map.
396
+ *
397
+ * @param key [Object]
398
+ * @return [Object]
404
399
  */
405
400
  static VALUE Map_index(VALUE _self, VALUE key) {
406
401
  Map* self = ruby_to_Map(_self);
@@ -416,12 +411,15 @@ static VALUE Map_index(VALUE _self, VALUE key) {
416
411
  }
417
412
 
418
413
  /*
419
- * call-seq:
420
- * Map.[]=(key, value) => value
414
+ * ruby-doc: Map#[]=
421
415
  *
422
416
  * Inserts or overwrites the value at the given key with the given new value.
423
417
  * Throws an exception if the key type is incorrect. Returns the new value that
424
418
  * was just inserted.
419
+ *
420
+ * @param key [Object]
421
+ * @param value [Object]
422
+ * @return [Object]
425
423
  */
426
424
  static VALUE Map_index_set(VALUE _self, VALUE key, VALUE val) {
427
425
  Map* self = ruby_to_Map(_self);
@@ -437,11 +435,13 @@ static VALUE Map_index_set(VALUE _self, VALUE key, VALUE val) {
437
435
  }
438
436
 
439
437
  /*
440
- * call-seq:
441
- * Map.has_key?(key) => bool
438
+ * ruby-doc: Map#has_key?
442
439
  *
443
440
  * Returns true if the given key is present in the map. Throws an exception if
444
441
  * the key has the wrong type.
442
+ *
443
+ * @param key [Object]
444
+ * @return [Boolean]
445
445
  */
446
446
  static VALUE Map_has_key(VALUE _self, VALUE key) {
447
447
  Map* self = ruby_to_Map(_self);
@@ -456,39 +456,35 @@ static VALUE Map_has_key(VALUE _self, VALUE key) {
456
456
  }
457
457
 
458
458
  /*
459
- * call-seq:
460
- * Map.delete(key) => old_value
459
+ * ruby-doc: Map#delete
461
460
  *
462
461
  * Deletes the value at the given key, if any, returning either the old value or
463
462
  * nil if none was present. Throws an exception if the key is of the wrong type.
463
+ *
464
+ * @param key [Object]
465
+ * @return [Object]
464
466
  */
465
467
  static VALUE Map_delete(VALUE _self, VALUE key) {
468
+ upb_Map* map = Map_GetMutable(_self);
466
469
  Map* self = ruby_to_Map(_self);
470
+
467
471
  upb_MessageValue key_upb =
468
472
  Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
469
473
  upb_MessageValue val_upb;
470
- VALUE ret;
471
474
 
472
- rb_check_frozen(_self);
473
-
474
- // TODO(haberman): make upb_Map_Delete() also capable of returning the deleted
475
- // value.
476
- if (upb_Map_Get(self->map, key_upb, &val_upb)) {
477
- ret = Convert_UpbToRuby(val_upb, self->value_type_info, self->arena);
475
+ if (upb_Map_Delete(map, key_upb, &val_upb)) {
476
+ return Convert_UpbToRuby(val_upb, self->value_type_info, self->arena);
478
477
  } else {
479
- ret = Qnil;
478
+ return Qnil;
480
479
  }
481
-
482
- upb_Map_Delete(Map_GetMutable(_self), key_upb);
483
-
484
- return ret;
485
480
  }
486
481
 
487
482
  /*
488
- * call-seq:
489
- * Map.clear
483
+ * ruby-doc: Map#clear
490
484
  *
491
485
  * Removes all entries from the map.
486
+ *
487
+ * @return [nil]
492
488
  */
493
489
  static VALUE Map_clear(VALUE _self) {
494
490
  upb_Map_Clear(Map_GetMutable(_self));
@@ -496,10 +492,11 @@ static VALUE Map_clear(VALUE _self) {
496
492
  }
497
493
 
498
494
  /*
499
- * call-seq:
500
- * Map.length
495
+ * ruby-doc: Map#length
501
496
  *
502
497
  * Returns the number of entries (key-value pairs) in the map.
498
+ *
499
+ * @return [Integer]
503
500
  */
504
501
  static VALUE Map_length(VALUE _self) {
505
502
  Map* self = ruby_to_Map(_self);
@@ -507,11 +504,12 @@ static VALUE Map_length(VALUE _self) {
507
504
  }
508
505
 
509
506
  /*
510
- * call-seq:
511
- * Map.dup => new_map
507
+ * ruby-doc: Map#dup
512
508
  *
513
509
  * Duplicates this map with a shallow copy. References to all non-primitive
514
510
  * element objects (e.g., submessages) are shared.
511
+ *
512
+ * @return [Map]
515
513
  */
516
514
  static VALUE Map_dup(VALUE _self) {
517
515
  Map* self = ruby_to_Map(_self);
@@ -523,9 +521,8 @@ static VALUE Map_dup(VALUE _self) {
523
521
 
524
522
  Arena_fuse(self->arena, arena);
525
523
 
526
- while (upb_MapIterator_Next(self->map, &iter)) {
527
- upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
528
- upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
524
+ upb_MessageValue key, val;
525
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
529
526
  upb_Map_Set(new_map, key, val, arena);
530
527
  }
531
528
 
@@ -533,8 +530,7 @@ static VALUE Map_dup(VALUE _self) {
533
530
  }
534
531
 
535
532
  /*
536
- * call-seq:
537
- * Map.==(other) => boolean
533
+ * ruby-doc: Map#==
538
534
  *
539
535
  * Compares this map to another. Maps are equal if they have identical key sets,
540
536
  * and for each key, the values in both maps compare equal. Elements are
@@ -544,6 +540,9 @@ static VALUE Map_dup(VALUE _self) {
544
540
  * Maps with dissimilar key types or value types/typeclasses are never equal,
545
541
  * even if value comparison (for example, between integers and floats) would
546
542
  * have otherwise indicated that every element has equal value.
543
+ *
544
+ * @param other [Map]
545
+ * @return [Boolean]
547
546
  */
548
547
  VALUE Map_eq(VALUE _self, VALUE _other) {
549
548
  Map* self = ruby_to_Map(_self);
@@ -574,9 +573,8 @@ VALUE Map_eq(VALUE _self, VALUE _other) {
574
573
  // For each member of self, check that an equal member exists at the same key
575
574
  // in other.
576
575
  size_t iter = kUpb_Map_Begin;
577
- while (upb_MapIterator_Next(self->map, &iter)) {
578
- upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
579
- upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
576
+ upb_MessageValue key, val;
577
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
580
578
  upb_MessageValue other_val;
581
579
  if (!upb_Map_Get(other->map, key, &other_val)) {
582
580
  // Not present in other map.
@@ -592,26 +590,90 @@ VALUE Map_eq(VALUE _self, VALUE _other) {
592
590
  }
593
591
 
594
592
  /*
595
- * call-seq:
596
- * Message.freeze => self
593
+ * ruby-doc: Map#frozen?
594
+ *
595
+ * Returns true if the map is frozen in either Ruby or the underlying
596
+ * representation. Freezes the Ruby map object if it is not already frozen in
597
+ * Ruby but it is frozen in the underlying representation.
598
+ *
599
+ * @return [Boolean]
600
+ */
601
+ VALUE Map_frozen(VALUE _self) {
602
+ Map* self = ruby_to_Map(_self);
603
+ if (!upb_Map_IsFrozen(self->map)) {
604
+ PBRUBY_ASSERT(!RB_OBJ_FROZEN(_self));
605
+ return Qfalse;
606
+ }
607
+
608
+ // Lazily freeze the Ruby wrapper.
609
+ if (!RB_OBJ_FROZEN(_self)) RB_OBJ_FREEZE(_self);
610
+ return Qtrue;
611
+ }
612
+
613
+ /*
614
+ * ruby-doc: Map#freeze
597
615
  *
598
- * Freezes the message object. We have to intercept this so we can pin the
599
- * Ruby object into memory so we don't forget it's frozen.
616
+ * Freezes the map object. We have to intercept this so we can freeze the
617
+ * underlying representation, not just the Ruby wrapper.
618
+ *
619
+ * @return [self]
600
620
  */
601
- static VALUE Map_freeze(VALUE _self) {
621
+ VALUE Map_freeze(VALUE _self) {
602
622
  Map* self = ruby_to_Map(_self);
603
- if (!RB_OBJ_FROZEN(_self)) {
604
- Arena_Pin(self->arena, _self);
605
- RB_OBJ_FREEZE(_self);
623
+ if (RB_OBJ_FROZEN(_self)) {
624
+ PBRUBY_ASSERT(upb_Map_IsFrozen(self->map));
625
+ return _self;
626
+ }
627
+
628
+ if (!upb_Map_IsFrozen(self->map)) {
629
+ if (self->value_type_info.type == kUpb_CType_Message) {
630
+ upb_Map_Freeze(
631
+ Map_GetMutable(_self),
632
+ upb_MessageDef_MiniTable(self->value_type_info.def.msgdef));
633
+ } else {
634
+ upb_Map_Freeze(Map_GetMutable(_self), NULL);
635
+ }
606
636
  }
637
+
638
+ RB_OBJ_FREEZE(_self);
639
+
607
640
  return _self;
608
641
  }
609
642
 
643
+ VALUE Map_EmptyFrozen(const upb_FieldDef* f) {
644
+ PBRUBY_ASSERT(upb_FieldDef_IsMap(f));
645
+ VALUE val = ObjectCache_Get(f);
646
+
647
+ if (val == Qnil) {
648
+ const upb_FieldDef* key_f = map_field_key(f);
649
+ const upb_FieldDef* val_f = map_field_value(f);
650
+ upb_CType key_type = upb_FieldDef_CType(key_f);
651
+ TypeInfo value_type_info = TypeInfo_get(val_f);
652
+ val = Map_alloc(cMap);
653
+ Map* self;
654
+ TypedData_Get_Struct(val, Map, &Map_type, self);
655
+ self->arena = Arena_new();
656
+ self->map =
657
+ upb_Map_New(Arena_get(self->arena), key_type, value_type_info.type);
658
+ self->key_type = key_type;
659
+ self->value_type_info = value_type_info;
660
+ if (self->value_type_info.type == kUpb_CType_Message) {
661
+ const upb_MessageDef* val_m = value_type_info.def.msgdef;
662
+ self->value_type_class = Descriptor_DefToClass(val_m);
663
+ }
664
+ return ObjectCache_TryAdd(f, Map_freeze(val));
665
+ }
666
+ PBRUBY_ASSERT(RB_OBJ_FROZEN(val));
667
+ PBRUBY_ASSERT(upb_Map_IsFrozen(ruby_to_Map(val)->map));
668
+ return val;
669
+ }
670
+
610
671
  /*
611
- * call-seq:
612
- * Map.hash => hash_value
672
+ * ruby-doc: Map#hash
613
673
  *
614
674
  * Returns a hash value based on this map's contents.
675
+ *
676
+ * @return [Integer]
615
677
  */
616
678
  VALUE Map_hash(VALUE _self) {
617
679
  Map* self = ruby_to_Map(_self);
@@ -619,21 +681,21 @@ VALUE Map_hash(VALUE _self) {
619
681
 
620
682
  size_t iter = kUpb_Map_Begin;
621
683
  TypeInfo key_info = {self->key_type};
622
- while (upb_MapIterator_Next(self->map, &iter)) {
623
- upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
624
- upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
625
- hash = Msgval_GetHash(key, key_info, hash);
626
- hash = Msgval_GetHash(val, self->value_type_info, hash);
684
+ upb_MessageValue key, val;
685
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
686
+ hash += Msgval_GetHash(key, key_info, 0);
687
+ hash += Msgval_GetHash(val, self->value_type_info, 0);
627
688
  }
628
689
 
629
690
  return LL2NUM(hash);
630
691
  }
631
692
 
632
693
  /*
633
- * call-seq:
634
- * Map.to_h => {}
694
+ * ruby-doc: Map#to_h
635
695
  *
636
696
  * Returns a Ruby Hash object containing all the values within the map
697
+ *
698
+ * @return [Hash]
637
699
  */
638
700
  VALUE Map_to_h(VALUE _self) {
639
701
  Map* self = ruby_to_Map(_self);
@@ -641,12 +703,13 @@ VALUE Map_to_h(VALUE _self) {
641
703
  }
642
704
 
643
705
  /*
644
- * call-seq:
645
- * Map.inspect => string
706
+ * ruby-doc: Map#inspect
646
707
  *
647
708
  * Returns a string representing this map's elements. It will be formatted as
648
709
  * "{key => value, key => value, ...}", with each key and value string
649
710
  * representation computed by its own #inspect method.
711
+ *
712
+ * @return [String]
650
713
  */
651
714
  VALUE Map_inspect(VALUE _self) {
652
715
  Map* self = ruby_to_Map(_self);
@@ -659,13 +722,15 @@ VALUE Map_inspect(VALUE _self) {
659
722
  }
660
723
 
661
724
  /*
662
- * call-seq:
663
- * Map.merge(other_map) => map
725
+ * ruby-doc: Map#merge
664
726
  *
665
727
  * Copies key/value pairs from other_map into a copy of this map. If a key is
666
728
  * set in other_map and this map, the value from other_map overwrites the value
667
729
  * in the new copy of this map. Returns the new copy of this map with merged
668
730
  * contents.
731
+ *
732
+ * @param other_map [Map]
733
+ * @return [Map]
669
734
  */
670
735
  static VALUE Map_merge(VALUE _self, VALUE hashmap) {
671
736
  VALUE dupped = Map_dup(_self);
@@ -694,6 +759,7 @@ void Map_register(VALUE module) {
694
759
  rb_define_method(klass, "clone", Map_dup, 0);
695
760
  rb_define_method(klass, "==", Map_eq, 1);
696
761
  rb_define_method(klass, "freeze", Map_freeze, 0);
762
+ rb_define_method(klass, "frozen?", Map_frozen, 0);
697
763
  rb_define_method(klass, "hash", Map_hash, 0);
698
764
  rb_define_method(klass, "to_h", Map_to_h, 0);
699
765
  rb_define_method(klass, "inspect", Map_inspect, 0);
@@ -1,45 +1,24 @@
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_CType key_type, TypeInfo value_type,
42
- VALUE arena);
20
+ VALUE Map_GetRubyWrapper(const upb_Map *map, upb_CType key_type,
21
+ TypeInfo value_type, VALUE arena);
43
22
 
44
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
@@ -63,4 +42,7 @@ extern VALUE cMap;
63
42
  // Call at startup to register all types in this module.
64
43
  void Map_register(VALUE module);
65
44
 
45
+ // Recursively freeze map
46
+ VALUE Map_freeze(VALUE _self);
47
+
66
48
  #endif // RUBY_PROTOBUF_MAP_H_