google-protobuf 3.21.0 → 4.28.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

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 +537 -75
  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 +250 -234
  12. data/ext/google/protobuf_c/message.h +11 -33
  13. data/ext/google/protobuf_c/protobuf.c +63 -185
  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 +14513 -9003
  18. data/ext/google/protobuf_c/ruby-upb.h +13990 -4496
  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 +210 -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 +781 -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_