google-protobuf 3.21.2 → 4.29.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 (71) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/Rakefile +3 -0
  3. data/ext/google/protobuf_c/convert.c +67 -86
  4. data/ext/google/protobuf_c/convert.h +3 -28
  5. data/ext/google/protobuf_c/defs.c +538 -77
  6. data/ext/google/protobuf_c/defs.h +3 -28
  7. data/ext/google/protobuf_c/extconf.rb +4 -4
  8. data/ext/google/protobuf_c/glue.c +72 -0
  9. data/ext/google/protobuf_c/map.c +114 -85
  10. data/ext/google/protobuf_c/map.h +12 -30
  11. data/ext/google/protobuf_c/message.c +264 -238
  12. data/ext/google/protobuf_c/message.h +11 -33
  13. data/ext/google/protobuf_c/protobuf.c +63 -187
  14. data/ext/google/protobuf_c/protobuf.h +27 -39
  15. data/ext/google/protobuf_c/repeated_field.c +72 -38
  16. data/ext/google/protobuf_c/repeated_field.h +11 -29
  17. data/ext/google/protobuf_c/ruby-upb.c +13783 -8236
  18. data/ext/google/protobuf_c/ruby-upb.h +14077 -4495
  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 +467 -0
  25. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +20 -7
  26. data/ext/google/protobuf_c/wrap_memcpy.c +3 -26
  27. data/lib/google/protobuf/any_pb.rb +6 -8
  28. data/lib/google/protobuf/api_pb.rb +6 -26
  29. data/lib/google/protobuf/descriptor_pb.rb +23 -226
  30. data/lib/google/protobuf/duration_pb.rb +6 -8
  31. data/lib/google/protobuf/empty_pb.rb +6 -6
  32. data/lib/google/protobuf/ffi/descriptor.rb +165 -0
  33. data/lib/google/protobuf/ffi/descriptor_pool.rb +77 -0
  34. data/lib/google/protobuf/ffi/enum_descriptor.rb +173 -0
  35. data/lib/google/protobuf/ffi/ffi.rb +215 -0
  36. data/lib/google/protobuf/ffi/field_descriptor.rb +330 -0
  37. data/lib/google/protobuf/ffi/file_descriptor.rb +49 -0
  38. data/lib/google/protobuf/ffi/internal/arena.rb +60 -0
  39. data/lib/google/protobuf/ffi/internal/convert.rb +296 -0
  40. data/lib/google/protobuf/ffi/internal/pointer_helper.rb +35 -0
  41. data/lib/google/protobuf/ffi/internal/type_safety.rb +25 -0
  42. data/lib/google/protobuf/ffi/map.rb +433 -0
  43. data/lib/google/protobuf/ffi/message.rb +785 -0
  44. data/lib/google/protobuf/ffi/method_descriptor.rb +114 -0
  45. data/lib/google/protobuf/ffi/object_cache.rb +30 -0
  46. data/lib/google/protobuf/ffi/oneof_descriptor.rb +97 -0
  47. data/lib/google/protobuf/ffi/repeated_field.rb +411 -0
  48. data/lib/google/protobuf/ffi/service_descriptor.rb +107 -0
  49. data/lib/google/protobuf/field_mask_pb.rb +6 -7
  50. data/lib/google/protobuf/internal/object_cache.rb +99 -0
  51. data/lib/google/protobuf/message_exts.rb +8 -26
  52. data/lib/google/protobuf/plugin_pb.rb +25 -0
  53. data/lib/google/protobuf/repeated_field.rb +7 -31
  54. data/lib/google/protobuf/source_context_pb.rb +6 -7
  55. data/lib/google/protobuf/struct_pb.rb +6 -23
  56. data/lib/google/protobuf/timestamp_pb.rb +6 -8
  57. data/lib/google/protobuf/type_pb.rb +6 -71
  58. data/lib/google/protobuf/well_known_types.rb +5 -34
  59. data/lib/google/protobuf/wrappers_pb.rb +6 -31
  60. data/lib/google/protobuf.rb +27 -45
  61. data/lib/google/protobuf_ffi.rb +51 -0
  62. data/lib/google/protobuf_native.rb +19 -0
  63. data/lib/google/tasks/ffi.rake +100 -0
  64. metadata +92 -16
  65. data/ext/google/protobuf_c/third_party/utf8_range/naive.c +0 -92
  66. data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +0 -157
  67. data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +0 -170
  68. data/lib/google/protobuf/descriptor_dsl.rb +0 -465
  69. data/tests/basic.rb +0 -739
  70. data/tests/generated_code_test.rb +0 -23
  71. data/tests/stress.rb +0 -38
@@ -1,38 +1,13 @@
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_DEFS_H_
32
9
  #define RUBY_PROTOBUF_DEFS_H_
33
10
 
34
- #include <ruby/ruby.h>
35
-
36
11
  #include "protobuf.h"
37
12
  #include "ruby-upb.h"
38
13
 
@@ -6,23 +6,23 @@ ext_name = "google/protobuf_c"
6
6
 
7
7
  dir_config(ext_name)
8
8
 
9
- if RUBY_PLATFORM =~ /darwin/ || RUBY_PLATFORM =~ /linux/
9
+ if RUBY_PLATFORM =~ /darwin/ || RUBY_PLATFORM =~ /linux/ || RUBY_PLATFORM =~ /freebsd/
10
10
  $CFLAGS += " -std=gnu99 -O3 -DNDEBUG -fvisibility=hidden -Wall -Wsign-compare -Wno-declaration-after-statement"
11
11
  else
12
12
  $CFLAGS += " -std=gnu99 -O3 -DNDEBUG"
13
13
  end
14
14
 
15
-
16
15
  if RUBY_PLATFORM =~ /linux/
17
16
  # Instruct the linker to point memcpy calls at our __wrap_memcpy wrapper.
18
17
  $LDFLAGS += " -Wl,-wrap,memcpy"
19
18
  end
20
19
 
21
20
  $VPATH << "$(srcdir)/third_party/utf8_range"
22
- $INCFLAGS << "$(srcdir)/third_party/utf8_range"
21
+ $INCFLAGS += " -I$(srcdir)/third_party/utf8_range"
23
22
 
24
23
  $srcs = ["protobuf.c", "convert.c", "defs.c", "message.c",
25
24
  "repeated_field.c", "map.c", "ruby-upb.c", "wrap_memcpy.c",
26
- "naive.c", "range2-neon.c", "range2-sse.c"]
25
+ "utf8_range.c", "shared_convert.c",
26
+ "shared_message.c"]
27
27
 
28
28
  create_makefile(ext_name)
@@ -0,0 +1,72 @@
1
+ // Protocol Buffers - Google's data interchange format
2
+ // Copyright 2023 Google Inc. All rights reserved.
3
+ //
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
7
+
8
+ // -----------------------------------------------------------------------------
9
+ // Exposing inlined UPB functions. Strictly free of dependencies on
10
+ // Ruby interpreter internals.
11
+
12
+ #include "ruby-upb.h"
13
+
14
+ upb_Arena* Arena_create() { return upb_Arena_Init(NULL, 0, &upb_alloc_global); }
15
+
16
+ google_protobuf_FileDescriptorProto* FileDescriptorProto_parse(
17
+ const char* serialized_file_proto, size_t length, upb_Arena* arena) {
18
+ return google_protobuf_FileDescriptorProto_parse(serialized_file_proto,
19
+ length, arena);
20
+ }
21
+
22
+ char* EnumDescriptor_serialized_options(const upb_EnumDef* enumdef,
23
+ size_t* size, upb_Arena* arena) {
24
+ const google_protobuf_EnumOptions* opts = upb_EnumDef_Options(enumdef);
25
+ char* serialized = google_protobuf_EnumOptions_serialize(opts, arena, size);
26
+ return serialized;
27
+ }
28
+
29
+ char* FileDescriptor_serialized_options(const upb_FileDef* filedef,
30
+ size_t* size, upb_Arena* arena) {
31
+ const google_protobuf_FileOptions* opts = upb_FileDef_Options(filedef);
32
+ char* serialized = google_protobuf_FileOptions_serialize(opts, arena, size);
33
+ return serialized;
34
+ }
35
+
36
+ char* Descriptor_serialized_options(const upb_MessageDef* msgdef, size_t* size,
37
+ upb_Arena* arena) {
38
+ const google_protobuf_MessageOptions* opts = upb_MessageDef_Options(msgdef);
39
+ char* serialized =
40
+ google_protobuf_MessageOptions_serialize(opts, arena, size);
41
+ return serialized;
42
+ }
43
+
44
+ char* OneOfDescriptor_serialized_options(const upb_OneofDef* oneofdef,
45
+ size_t* size, upb_Arena* arena) {
46
+ const google_protobuf_OneofOptions* opts = upb_OneofDef_Options(oneofdef);
47
+ char* serialized = google_protobuf_OneofOptions_serialize(opts, arena, size);
48
+ return serialized;
49
+ }
50
+
51
+ char* FieldDescriptor_serialized_options(const upb_FieldDef* fielddef,
52
+ size_t* size, upb_Arena* arena) {
53
+ const google_protobuf_FieldOptions* opts = upb_FieldDef_Options(fielddef);
54
+ char* serialized = google_protobuf_FieldOptions_serialize(opts, arena, size);
55
+ return serialized;
56
+ }
57
+
58
+ char* ServiceDescriptor_serialized_options(const upb_ServiceDef* servicedef,
59
+ size_t* size, upb_Arena* arena) {
60
+ const google_protobuf_ServiceOptions* opts =
61
+ upb_ServiceDef_Options(servicedef);
62
+ char* serialized =
63
+ google_protobuf_ServiceOptions_serialize(opts, arena, size);
64
+ return serialized;
65
+ }
66
+
67
+ char* MethodDescriptor_serialized_options(const upb_MethodDef* methoddef,
68
+ size_t* size, upb_Arena* arena) {
69
+ const google_protobuf_MethodOptions* opts = upb_MethodDef_Options(methoddef);
70
+ char* serialized = google_protobuf_MethodOptions_serialize(opts, arena, size);
71
+ return serialized;
72
+ }
@@ -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");
@@ -323,7 +299,9 @@ static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
323
299
 
324
300
  self->map = upb_Map_New(Arena_get(self->arena), self->key_type,
325
301
  self->value_type_info.type);
326
- ObjectCache_Add(self->map, _self);
302
+ VALUE stored = ObjectCache_TryAdd(self->map, _self);
303
+ (void)stored;
304
+ PBRUBY_ASSERT(stored == _self);
327
305
 
328
306
  if (init_arg != Qnil) {
329
307
  Map_merge_into_self(_self, init_arg);
@@ -343,10 +321,9 @@ static VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
343
321
  static VALUE Map_each(VALUE _self) {
344
322
  Map* self = ruby_to_Map(_self);
345
323
  size_t iter = kUpb_Map_Begin;
324
+ upb_MessageValue key, val;
346
325
 
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);
326
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
350
327
  VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
351
328
  VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
352
329
  rb_yield_values(2, key_val, val_val);
@@ -365,9 +342,9 @@ static VALUE Map_keys(VALUE _self) {
365
342
  Map* self = ruby_to_Map(_self);
366
343
  size_t iter = kUpb_Map_Begin;
367
344
  VALUE ret = rb_ary_new();
345
+ upb_MessageValue key, val;
368
346
 
369
- while (upb_MapIterator_Next(self->map, &iter)) {
370
- upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
347
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
371
348
  VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
372
349
  rb_ary_push(ret, key_val);
373
350
  }
@@ -385,9 +362,9 @@ static VALUE Map_values(VALUE _self) {
385
362
  Map* self = ruby_to_Map(_self);
386
363
  size_t iter = kUpb_Map_Begin;
387
364
  VALUE ret = rb_ary_new();
365
+ upb_MessageValue key, val;
388
366
 
389
- while (upb_MapIterator_Next(self->map, &iter)) {
390
- upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
367
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
391
368
  VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
392
369
  rb_ary_push(ret, val_val);
393
370
  }
@@ -463,25 +440,18 @@ static VALUE Map_has_key(VALUE _self, VALUE key) {
463
440
  * nil if none was present. Throws an exception if the key is of the wrong type.
464
441
  */
465
442
  static VALUE Map_delete(VALUE _self, VALUE key) {
443
+ upb_Map* map = Map_GetMutable(_self);
466
444
  Map* self = ruby_to_Map(_self);
445
+
467
446
  upb_MessageValue key_upb =
468
447
  Convert_RubyToUpb(key, "", Map_keyinfo(self), NULL);
469
448
  upb_MessageValue val_upb;
470
- VALUE ret;
471
449
 
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);
450
+ if (upb_Map_Delete(map, key_upb, &val_upb)) {
451
+ return Convert_UpbToRuby(val_upb, self->value_type_info, self->arena);
478
452
  } else {
479
- ret = Qnil;
453
+ return Qnil;
480
454
  }
481
-
482
- upb_Map_Delete(Map_GetMutable(_self), key_upb);
483
-
484
- return ret;
485
455
  }
486
456
 
487
457
  /*
@@ -523,9 +493,8 @@ static VALUE Map_dup(VALUE _self) {
523
493
 
524
494
  Arena_fuse(self->arena, arena);
525
495
 
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);
496
+ upb_MessageValue key, val;
497
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
529
498
  upb_Map_Set(new_map, key, val, arena);
530
499
  }
531
500
 
@@ -574,9 +543,8 @@ VALUE Map_eq(VALUE _self, VALUE _other) {
574
543
  // For each member of self, check that an equal member exists at the same key
575
544
  // in other.
576
545
  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);
546
+ upb_MessageValue key, val;
547
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
580
548
  upb_MessageValue other_val;
581
549
  if (!upb_Map_Get(other->map, key, &other_val)) {
582
550
  // Not present in other map.
@@ -593,20 +561,81 @@ VALUE Map_eq(VALUE _self, VALUE _other) {
593
561
 
594
562
  /*
595
563
  * call-seq:
596
- * 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
597
585
  *
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.
586
+ * Freezes the map object. We have to intercept this so we can freeze the
587
+ * underlying representation, not just the Ruby wrapper.
600
588
  */
601
- static VALUE Map_freeze(VALUE _self) {
589
+ VALUE Map_freeze(VALUE _self) {
602
590
  Map* self = ruby_to_Map(_self);
603
- if (!RB_OBJ_FROZEN(_self)) {
604
- Arena_Pin(self->arena, _self);
605
- RB_OBJ_FREEZE(_self);
591
+ if (RB_OBJ_FROZEN(_self)) {
592
+ PBRUBY_ASSERT(upb_Map_IsFrozen(self->map));
593
+ return _self;
606
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
+
607
608
  return _self;
608
609
  }
609
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
+
610
639
  /*
611
640
  * call-seq:
612
641
  * Map.hash => hash_value
@@ -619,9 +648,8 @@ VALUE Map_hash(VALUE _self) {
619
648
 
620
649
  size_t iter = kUpb_Map_Begin;
621
650
  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);
651
+ upb_MessageValue key, val;
652
+ while (upb_Map_Next(self->map, &key, &val, &iter)) {
625
653
  hash = Msgval_GetHash(key, key_info, hash);
626
654
  hash = Msgval_GetHash(val, self->value_type_info, hash);
627
655
  }
@@ -694,6 +722,7 @@ void Map_register(VALUE module) {
694
722
  rb_define_method(klass, "clone", Map_dup, 0);
695
723
  rb_define_method(klass, "==", Map_eq, 1);
696
724
  rb_define_method(klass, "freeze", Map_freeze, 0);
725
+ rb_define_method(klass, "frozen?", Map_frozen, 0);
697
726
  rb_define_method(klass, "hash", Map_hash, 0);
698
727
  rb_define_method(klass, "to_h", Map_to_h, 0);
699
728
  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_