google-protobuf 3.22.3 → 4.27.3

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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/ext/google/protobuf_c/Rakefile +3 -0
  3. data/ext/google/protobuf_c/convert.c +28 -72
  4. data/ext/google/protobuf_c/convert.h +3 -28
  5. data/ext/google/protobuf_c/defs.c +534 -72
  6. data/ext/google/protobuf_c/defs.h +3 -28
  7. data/ext/google/protobuf_c/extconf.rb +2 -1
  8. data/ext/google/protobuf_c/glue.c +72 -0
  9. data/ext/google/protobuf_c/map.c +28 -36
  10. data/ext/google/protobuf_c/map.h +6 -28
  11. data/ext/google/protobuf_c/message.c +101 -148
  12. data/ext/google/protobuf_c/message.h +10 -32
  13. data/ext/google/protobuf_c/protobuf.c +53 -177
  14. data/ext/google/protobuf_c/protobuf.h +24 -32
  15. data/ext/google/protobuf_c/repeated_field.c +23 -33
  16. data/ext/google/protobuf_c/repeated_field.h +6 -28
  17. data/ext/google/protobuf_c/ruby-upb.c +12741 -10337
  18. data/ext/google/protobuf_c/ruby-upb.h +8911 -5235
  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/utf8_range.c +467 -0
  24. data/ext/google/protobuf_c/third_party/utf8_range/utf8_range.h +9 -8
  25. data/ext/google/protobuf_c/wrap_memcpy.c +3 -26
  26. data/lib/google/protobuf/any_pb.rb +6 -8
  27. data/lib/google/protobuf/api_pb.rb +6 -26
  28. data/lib/google/protobuf/descriptor_pb.rb +20 -252
  29. data/lib/google/protobuf/duration_pb.rb +6 -8
  30. data/lib/google/protobuf/empty_pb.rb +6 -6
  31. data/lib/google/protobuf/ffi/descriptor.rb +166 -0
  32. data/lib/google/protobuf/ffi/descriptor_pool.rb +77 -0
  33. data/lib/google/protobuf/ffi/enum_descriptor.rb +173 -0
  34. data/lib/google/protobuf/ffi/ffi.rb +210 -0
  35. data/lib/google/protobuf/ffi/field_descriptor.rb +330 -0
  36. data/lib/google/protobuf/ffi/file_descriptor.rb +49 -0
  37. data/lib/google/protobuf/ffi/internal/arena.rb +66 -0
  38. data/lib/google/protobuf/ffi/internal/convert.rb +289 -0
  39. data/lib/google/protobuf/ffi/internal/pointer_helper.rb +35 -0
  40. data/lib/google/protobuf/ffi/internal/type_safety.rb +25 -0
  41. data/lib/google/protobuf/ffi/map.rb +409 -0
  42. data/lib/google/protobuf/ffi/message.rb +659 -0
  43. data/lib/google/protobuf/ffi/method_descriptor.rb +114 -0
  44. data/lib/google/protobuf/ffi/object_cache.rb +30 -0
  45. data/lib/google/protobuf/ffi/oneof_descriptor.rb +97 -0
  46. data/lib/google/protobuf/ffi/repeated_field.rb +385 -0
  47. data/lib/google/protobuf/ffi/service_descriptor.rb +107 -0
  48. data/lib/google/protobuf/field_mask_pb.rb +6 -7
  49. data/lib/google/protobuf/internal/object_cache.rb +99 -0
  50. data/lib/google/protobuf/message_exts.rb +3 -26
  51. data/lib/google/protobuf/plugin_pb.rb +6 -31
  52. data/lib/google/protobuf/repeated_field.rb +7 -31
  53. data/lib/google/protobuf/source_context_pb.rb +6 -7
  54. data/lib/google/protobuf/struct_pb.rb +6 -23
  55. data/lib/google/protobuf/timestamp_pb.rb +6 -8
  56. data/lib/google/protobuf/type_pb.rb +6 -71
  57. data/lib/google/protobuf/well_known_types.rb +5 -34
  58. data/lib/google/protobuf/wrappers_pb.rb +6 -31
  59. data/lib/google/protobuf.rb +27 -45
  60. data/lib/google/protobuf_ffi.rb +51 -0
  61. data/lib/google/protobuf_native.rb +19 -0
  62. data/lib/google/tasks/ffi.rake +100 -0
  63. metadata +89 -8
  64. data/ext/google/protobuf_c/third_party/utf8_range/naive.c +0 -92
  65. data/ext/google/protobuf_c/third_party/utf8_range/range2-neon.c +0 -157
  66. data/ext/google/protobuf_c/third_party/utf8_range/range2-sse.c +0 -170
  67. data/lib/google/protobuf/descriptor_dsl.rb +0 -465
@@ -1,170 +0,0 @@
1
- /*
2
- * Process 2x16 bytes in each iteration.
3
- * Comments removed for brevity. See range-sse.c for details.
4
- */
5
- #ifdef __SSE4_1__
6
-
7
- #include <stdio.h>
8
- #include <stdint.h>
9
- #include <x86intrin.h>
10
-
11
- int utf8_naive(const unsigned char *data, int len);
12
-
13
- static const int8_t _first_len_tbl[] = {
14
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3,
15
- };
16
-
17
- static const int8_t _first_range_tbl[] = {
18
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8,
19
- };
20
-
21
- static const int8_t _range_min_tbl[] = {
22
- 0x00, 0x80, 0x80, 0x80, 0xA0, 0x80, 0x90, 0x80,
23
- 0xC2, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
24
- };
25
- static const int8_t _range_max_tbl[] = {
26
- 0x7F, 0xBF, 0xBF, 0xBF, 0xBF, 0x9F, 0xBF, 0x8F,
27
- 0xF4, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
28
- };
29
-
30
- static const int8_t _df_ee_tbl[] = {
31
- 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
32
- };
33
- static const int8_t _ef_fe_tbl[] = {
34
- 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
35
- };
36
-
37
- /* Return 0 on success, -1 on error */
38
- int utf8_range2(const unsigned char *data, int len)
39
- {
40
- if (len >= 32) {
41
- __m128i prev_input = _mm_set1_epi8(0);
42
- __m128i prev_first_len = _mm_set1_epi8(0);
43
-
44
- const __m128i first_len_tbl =
45
- _mm_loadu_si128((const __m128i *)_first_len_tbl);
46
- const __m128i first_range_tbl =
47
- _mm_loadu_si128((const __m128i *)_first_range_tbl);
48
- const __m128i range_min_tbl =
49
- _mm_loadu_si128((const __m128i *)_range_min_tbl);
50
- const __m128i range_max_tbl =
51
- _mm_loadu_si128((const __m128i *)_range_max_tbl);
52
- const __m128i df_ee_tbl =
53
- _mm_loadu_si128((const __m128i *)_df_ee_tbl);
54
- const __m128i ef_fe_tbl =
55
- _mm_loadu_si128((const __m128i *)_ef_fe_tbl);
56
-
57
- __m128i error = _mm_set1_epi8(0);
58
-
59
- while (len >= 32) {
60
- /***************************** block 1 ****************************/
61
- const __m128i input_a = _mm_loadu_si128((const __m128i *)data);
62
-
63
- __m128i high_nibbles =
64
- _mm_and_si128(_mm_srli_epi16(input_a, 4), _mm_set1_epi8(0x0F));
65
-
66
- __m128i first_len_a = _mm_shuffle_epi8(first_len_tbl, high_nibbles);
67
-
68
- __m128i range_a = _mm_shuffle_epi8(first_range_tbl, high_nibbles);
69
-
70
- range_a = _mm_or_si128(
71
- range_a, _mm_alignr_epi8(first_len_a, prev_first_len, 15));
72
-
73
- __m128i tmp;
74
- tmp = _mm_alignr_epi8(first_len_a, prev_first_len, 14);
75
- tmp = _mm_subs_epu8(tmp, _mm_set1_epi8(1));
76
- range_a = _mm_or_si128(range_a, tmp);
77
-
78
- tmp = _mm_alignr_epi8(first_len_a, prev_first_len, 13);
79
- tmp = _mm_subs_epu8(tmp, _mm_set1_epi8(2));
80
- range_a = _mm_or_si128(range_a, tmp);
81
-
82
- __m128i shift1, pos, range2;
83
- shift1 = _mm_alignr_epi8(input_a, prev_input, 15);
84
- pos = _mm_sub_epi8(shift1, _mm_set1_epi8(0xEF));
85
- tmp = _mm_subs_epu8(pos, _mm_set1_epi8(0xF0));
86
- range2 = _mm_shuffle_epi8(df_ee_tbl, tmp);
87
- tmp = _mm_adds_epu8(pos, _mm_set1_epi8(0x70));
88
- range2 = _mm_add_epi8(range2, _mm_shuffle_epi8(ef_fe_tbl, tmp));
89
-
90
- range_a = _mm_add_epi8(range_a, range2);
91
-
92
- __m128i minv = _mm_shuffle_epi8(range_min_tbl, range_a);
93
- __m128i maxv = _mm_shuffle_epi8(range_max_tbl, range_a);
94
-
95
- tmp = _mm_or_si128(
96
- _mm_cmplt_epi8(input_a, minv),
97
- _mm_cmpgt_epi8(input_a, maxv)
98
- );
99
- error = _mm_or_si128(error, tmp);
100
-
101
- /***************************** block 2 ****************************/
102
- const __m128i input_b = _mm_loadu_si128((const __m128i *)(data+16));
103
-
104
- high_nibbles =
105
- _mm_and_si128(_mm_srli_epi16(input_b, 4), _mm_set1_epi8(0x0F));
106
-
107
- __m128i first_len_b = _mm_shuffle_epi8(first_len_tbl, high_nibbles);
108
-
109
- __m128i range_b = _mm_shuffle_epi8(first_range_tbl, high_nibbles);
110
-
111
- range_b = _mm_or_si128(
112
- range_b, _mm_alignr_epi8(first_len_b, first_len_a, 15));
113
-
114
-
115
- tmp = _mm_alignr_epi8(first_len_b, first_len_a, 14);
116
- tmp = _mm_subs_epu8(tmp, _mm_set1_epi8(1));
117
- range_b = _mm_or_si128(range_b, tmp);
118
-
119
- tmp = _mm_alignr_epi8(first_len_b, first_len_a, 13);
120
- tmp = _mm_subs_epu8(tmp, _mm_set1_epi8(2));
121
- range_b = _mm_or_si128(range_b, tmp);
122
-
123
- shift1 = _mm_alignr_epi8(input_b, input_a, 15);
124
- pos = _mm_sub_epi8(shift1, _mm_set1_epi8(0xEF));
125
- tmp = _mm_subs_epu8(pos, _mm_set1_epi8(0xF0));
126
- range2 = _mm_shuffle_epi8(df_ee_tbl, tmp);
127
- tmp = _mm_adds_epu8(pos, _mm_set1_epi8(0x70));
128
- range2 = _mm_add_epi8(range2, _mm_shuffle_epi8(ef_fe_tbl, tmp));
129
-
130
- range_b = _mm_add_epi8(range_b, range2);
131
-
132
- minv = _mm_shuffle_epi8(range_min_tbl, range_b);
133
- maxv = _mm_shuffle_epi8(range_max_tbl, range_b);
134
-
135
-
136
- tmp = _mm_or_si128(
137
- _mm_cmplt_epi8(input_b, minv),
138
- _mm_cmpgt_epi8(input_b, maxv)
139
- );
140
- error = _mm_or_si128(error, tmp);
141
-
142
- /************************ next iteration **************************/
143
- prev_input = input_b;
144
- prev_first_len = first_len_b;
145
-
146
- data += 32;
147
- len -= 32;
148
- }
149
-
150
- if (!_mm_testz_si128(error, error))
151
- return -1;
152
-
153
- int32_t token4 = _mm_extract_epi32(prev_input, 3);
154
- const int8_t *token = (const int8_t *)&token4;
155
- int lookahead = 0;
156
- if (token[3] > (int8_t)0xBF)
157
- lookahead = 1;
158
- else if (token[2] > (int8_t)0xBF)
159
- lookahead = 2;
160
- else if (token[1] > (int8_t)0xBF)
161
- lookahead = 3;
162
-
163
- data -= lookahead;
164
- len += lookahead;
165
- }
166
-
167
- return utf8_naive(data, len);
168
- }
169
-
170
- #endif
@@ -1,465 +0,0 @@
1
- #!/usr/bin/ruby
2
- #
3
- # Code that implements the DSL for defining proto messages.
4
-
5
- # Suppress warning: loading in progress, circular require considered harmful.
6
- # This circular require is intentional to avoid missing dependency.
7
- begin
8
- old_verbose, $VERBOSE = $VERBOSE, nil
9
- require 'google/protobuf/descriptor_pb'
10
- ensure
11
- $VERBOSE = old_verbose
12
- end
13
-
14
- module Google
15
- module Protobuf
16
- module Internal
17
- class AtomicCounter
18
- def initialize
19
- @n = 0
20
- @mu = Mutex.new
21
- end
22
-
23
- def get_and_increment
24
- n = @n
25
- @mu.synchronize {
26
- @n += 1
27
- }
28
- return n
29
- end
30
- end
31
-
32
- class Builder
33
- @@file_number = AtomicCounter.new
34
-
35
- def initialize(pool)
36
- @pool = pool
37
- @default_file = nil # Constructed lazily
38
- end
39
-
40
- def add_file(name, options={}, &block)
41
- builder = FileBuilder.new(@pool, name, options)
42
- builder.instance_eval(&block)
43
- internal_add_file(builder)
44
- end
45
-
46
- def add_message(name, &block)
47
- internal_default_file.add_message(name, &block)
48
- end
49
-
50
- def add_enum(name, &block)
51
- internal_default_file.add_enum(name, &block)
52
- end
53
-
54
- # ---- Internal methods, not part of the DSL ----
55
-
56
- def build
57
- if @default_file
58
- internal_add_file(@default_file)
59
- end
60
- end
61
-
62
- private def internal_add_file(file_builder)
63
- proto = file_builder.build
64
- serialized = Google::Protobuf::FileDescriptorProto.encode(proto)
65
- @pool.add_serialized_file(serialized)
66
- end
67
-
68
- private def internal_default_file
69
- number = @@file_number.get_and_increment
70
- filename = "ruby_default_file#{number}.proto"
71
- @default_file ||= FileBuilder.new(@pool, filename)
72
- end
73
- end
74
-
75
- class FileBuilder
76
- def initialize(pool, name, options={})
77
- @pool = pool
78
- @file_proto = Google::Protobuf::FileDescriptorProto.new(
79
- name: name,
80
- syntax: options.fetch(:syntax, "proto3")
81
- )
82
- end
83
-
84
- def add_message(name, &block)
85
- builder = MessageBuilder.new(name, self, @file_proto)
86
- builder.instance_eval(&block)
87
- builder.internal_add_synthetic_oneofs
88
- end
89
-
90
- def add_enum(name, &block)
91
- EnumBuilder.new(name, @file_proto).instance_eval(&block)
92
- end
93
-
94
- # ---- Internal methods, not part of the DSL ----
95
-
96
- # These methods fix up the file descriptor to account for differences
97
- # between the DSL and FileDescriptorProto.
98
-
99
- # The DSL can omit a package name; here we infer what the package is if
100
- # was not specified.
101
- def infer_package(names)
102
- # Package is longest common prefix ending in '.', if any.
103
- if not names.empty?
104
- min, max = names.minmax
105
- last_common_dot = nil
106
- min.size.times { |i|
107
- if min[i] != max[i] then break end
108
- if min[i] == "." then last_common_dot = i end
109
- }
110
- if last_common_dot
111
- return min.slice(0, last_common_dot)
112
- end
113
- end
114
-
115
- nil
116
- end
117
-
118
- def rewrite_enum_default(field)
119
- if field.type != :TYPE_ENUM or !field.has_default_value? or !field.has_type_name?
120
- return
121
- end
122
-
123
- value = field.default_value
124
- type_name = field.type_name
125
-
126
- if value.empty? or value[0].ord < "0".ord or value[0].ord > "9".ord
127
- return
128
- end
129
-
130
- if type_name.empty? || type_name[0] != "."
131
- return
132
- end
133
-
134
- type_name = type_name[1..-1]
135
- as_int = Integer(value) rescue return
136
-
137
- enum_desc = @pool.lookup(type_name)
138
- if enum_desc.is_a?(Google::Protobuf::EnumDescriptor)
139
- # Enum was defined in a previous file.
140
- name = enum_desc.lookup_value(as_int)
141
- if name
142
- # Update the default value in the proto.
143
- field.default_value = name
144
- end
145
- else
146
- # See if enum was defined in this file.
147
- @file_proto.enum_type.each { |enum_proto|
148
- if enum_proto.name == type_name
149
- enum_proto.value.each { |enum_value_proto|
150
- if enum_value_proto.number == as_int
151
- # Update the default value in the proto.
152
- field.default_value = enum_value_proto.name
153
- return
154
- end
155
- }
156
- # We found the right enum, but no value matched.
157
- return
158
- end
159
- }
160
- end
161
- end
162
-
163
- # Historically we allowed enum defaults to be specified as a number.
164
- # In retrospect this was a mistake as descriptors require defaults to
165
- # be specified as a label. This can make a difference if multiple
166
- # labels have the same number.
167
- #
168
- # Here we do a pass over all enum defaults and rewrite numeric defaults
169
- # by looking up their labels. This is complicated by the fact that the
170
- # enum definition can live in either the symtab or the file_proto.
171
- #
172
- # We take advantage of the fact that this is called *before* enums or
173
- # messages are nested in other messages, so we only have to iterate
174
- # one level deep.
175
- def rewrite_enum_defaults
176
- @file_proto.message_type.each { |msg|
177
- msg.field.each { |field|
178
- rewrite_enum_default(field)
179
- }
180
- }
181
- end
182
-
183
- # We have to do some relatively complicated logic here for backward
184
- # compatibility.
185
- #
186
- # In descriptor.proto, messages are nested inside other messages if that is
187
- # what the original .proto file looks like. For example, suppose we have this
188
- # foo.proto:
189
- #
190
- # package foo;
191
- # message Bar {
192
- # message Baz {}
193
- # }
194
- #
195
- # The descriptor for this must look like this:
196
- #
197
- # file {
198
- # name: "test.proto"
199
- # package: "foo"
200
- # message_type {
201
- # name: "Bar"
202
- # nested_type {
203
- # name: "Baz"
204
- # }
205
- # }
206
- # }
207
- #
208
- # However, the Ruby generated code has always generated messages in a flat,
209
- # non-nested way:
210
- #
211
- # Google::Protobuf::DescriptorPool.generated_pool.build do
212
- # add_message "foo.Bar" do
213
- # end
214
- # add_message "foo.Bar.Baz" do
215
- # end
216
- # end
217
- #
218
- # Here we need to do a translation where we turn this generated code into the
219
- # above descriptor. We need to infer that "foo" is the package name, and not
220
- # a message itself. */
221
-
222
- def split_parent_name(msg_or_enum)
223
- name = msg_or_enum.name
224
- idx = name.rindex(?.)
225
- if idx
226
- return name[0...idx], name[idx+1..-1]
227
- else
228
- return nil, name
229
- end
230
- end
231
-
232
- def get_parent_msg(msgs_by_name, name, parent_name)
233
- parent_msg = msgs_by_name[parent_name]
234
- if parent_msg.nil?
235
- raise "To define name #{name}, there must be a message named #{parent_name} to enclose it"
236
- end
237
- return parent_msg
238
- end
239
-
240
- def fix_nesting
241
- # Calculate and update package.
242
- msgs_by_name = @file_proto.message_type.map { |msg| [msg.name, msg] }.to_h
243
- enum_names = @file_proto.enum_type.map { |enum_proto| enum_proto.name }
244
-
245
- package = infer_package(msgs_by_name.keys + enum_names)
246
- if package
247
- @file_proto.package = package
248
- end
249
-
250
- # Update nesting based on package.
251
- final_msgs = Google::Protobuf::RepeatedField.new(:message, Google::Protobuf::DescriptorProto)
252
- final_enums = Google::Protobuf::RepeatedField.new(:message, Google::Protobuf::EnumDescriptorProto)
253
-
254
- # Note: We don't iterate over msgs_by_name.values because we want to
255
- # preserve order as listed in the DSL.
256
- @file_proto.message_type.each { |msg|
257
- parent_name, msg.name = split_parent_name(msg)
258
- if parent_name == package
259
- final_msgs << msg
260
- else
261
- get_parent_msg(msgs_by_name, msg.name, parent_name).nested_type << msg
262
- end
263
- }
264
-
265
- @file_proto.enum_type.each { |enum|
266
- parent_name, enum.name = split_parent_name(enum)
267
- if parent_name == package
268
- final_enums << enum
269
- else
270
- get_parent_msg(msgs_by_name, enum.name, parent_name).enum_type << enum
271
- end
272
- }
273
-
274
- @file_proto.message_type = final_msgs
275
- @file_proto.enum_type = final_enums
276
- end
277
-
278
- def internal_file_proto
279
- @file_proto
280
- end
281
-
282
- def build
283
- rewrite_enum_defaults
284
- fix_nesting
285
- return @file_proto
286
- end
287
- end
288
-
289
- class MessageBuilder
290
- def initialize(name, file_builder, file_proto)
291
- @file_builder = file_builder
292
- @msg_proto = Google::Protobuf::DescriptorProto.new(
293
- :name => name
294
- )
295
- file_proto.message_type << @msg_proto
296
- end
297
-
298
- def optional(name, type, number, type_class=nil, options=nil)
299
- internal_add_field(:LABEL_OPTIONAL, name, type, number, type_class, options)
300
- end
301
-
302
- def proto3_optional(name, type, number, type_class=nil, options=nil)
303
- internal_add_field(:LABEL_OPTIONAL, name, type, number, type_class, options,
304
- proto3_optional: true)
305
- end
306
-
307
- def required(name, type, number, type_class=nil, options=nil)
308
- internal_add_field(:LABEL_REQUIRED, name, type, number, type_class, options)
309
- end
310
-
311
- def repeated(name, type, number, type_class = nil, options=nil)
312
- internal_add_field(:LABEL_REPEATED, name, type, number, type_class, options)
313
- end
314
-
315
- def oneof(name, &block)
316
- OneofBuilder.new(name, self).instance_eval(&block)
317
- end
318
-
319
- # Defines a new map field on this message type with the given key and
320
- # value types, tag number, and type class (for message and enum value
321
- # types). The key type must be :int32/:uint32/:int64/:uint64, :bool, or
322
- # :string. The value type type must be a Ruby symbol (as accepted by
323
- # FieldDescriptor#type=) and the type_class must be a string, if
324
- # present (as accepted by FieldDescriptor#submsg_name=).
325
- def map(name, key_type, value_type, number, value_type_class = nil)
326
- if key_type == :float or key_type == :double or key_type == :enum or
327
- key_type == :message
328
- raise ArgError, "Not an acceptable key type: " + key_type
329
- end
330
- entry_name = "#{@msg_proto.name}_MapEntry_#{name}"
331
-
332
- @file_builder.add_message entry_name do
333
- optional :key, key_type, 1
334
- optional :value, value_type, 2, value_type_class
335
- end
336
- options = @file_builder.internal_file_proto.message_type.last.options ||= MessageOptions.new
337
- options.map_entry = true
338
- repeated name, :message, number, entry_name
339
- end
340
-
341
- # ---- Internal methods, not part of the DSL ----
342
-
343
- def internal_add_synthetic_oneofs
344
- # We have to build a set of all names, to ensure that synthetic oneofs
345
- # are not creating conflicts
346
- names = {}
347
- @msg_proto.field.each { |field| names[field.name] = true }
348
- @msg_proto.oneof_decl.each { |oneof| names[oneof.name] = true }
349
-
350
- @msg_proto.field.each { |field|
351
- if field.proto3_optional
352
- # Prepend '_' until we are no longer conflicting.
353
- oneof_name = field.name
354
- while names[oneof_name]
355
- oneof_name = "_" + oneof_name
356
- end
357
- names[oneof_name] = true
358
- field.oneof_index = @msg_proto.oneof_decl.size
359
- @msg_proto.oneof_decl << Google::Protobuf::OneofDescriptorProto.new(
360
- name: oneof_name
361
- )
362
- end
363
- }
364
- end
365
-
366
- def internal_add_field(label, name, type, number, type_class, options,
367
- oneof_index: nil, proto3_optional: false)
368
- # Allow passing either:
369
- # - (name, type, number, options) or
370
- # - (name, type, number, type_class, options)
371
- if options.nil? and type_class.instance_of?(Hash)
372
- options = type_class;
373
- type_class = nil;
374
- end
375
-
376
- field_proto = Google::Protobuf::FieldDescriptorProto.new(
377
- :label => label,
378
- :name => name,
379
- :type => ("TYPE_" + type.to_s.upcase).to_sym,
380
- :number => number
381
- )
382
-
383
- if type_class
384
- # Make it an absolute type name by prepending a dot.
385
- field_proto.type_name = "." + type_class
386
- end
387
-
388
- if oneof_index
389
- field_proto.oneof_index = oneof_index
390
- end
391
-
392
- if proto3_optional
393
- field_proto.proto3_optional = true
394
- end
395
-
396
- if options
397
- if options.key?(:default)
398
- default = options[:default]
399
- if !default.instance_of?(String)
400
- # Call #to_s since all defaults are strings in the descriptor.
401
- default = default.to_s
402
- end
403
- # XXX: we should be C-escaping bytes defaults.
404
- field_proto.default_value = default.dup.force_encoding("UTF-8")
405
- end
406
- if options.key?(:json_name)
407
- field_proto.json_name = options[:json_name]
408
- end
409
- end
410
-
411
- @msg_proto.field << field_proto
412
- end
413
-
414
- def internal_msg_proto
415
- @msg_proto
416
- end
417
- end
418
-
419
- class OneofBuilder
420
- def initialize(name, msg_builder)
421
- @msg_builder = msg_builder
422
- oneof_proto = Google::Protobuf::OneofDescriptorProto.new(
423
- :name => name
424
- )
425
- msg_proto = msg_builder.internal_msg_proto
426
- @oneof_index = msg_proto.oneof_decl.size
427
- msg_proto.oneof_decl << oneof_proto
428
- end
429
-
430
- def optional(name, type, number, type_class=nil, options=nil)
431
- @msg_builder.internal_add_field(
432
- :LABEL_OPTIONAL, name, type, number, type_class, options,
433
- oneof_index: @oneof_index)
434
- end
435
- end
436
-
437
- class EnumBuilder
438
- def initialize(name, file_proto)
439
- @enum_proto = Google::Protobuf::EnumDescriptorProto.new(
440
- :name => name
441
- )
442
- file_proto.enum_type << @enum_proto
443
- end
444
-
445
- def value(name, number)
446
- enum_value_proto = Google::Protobuf::EnumValueDescriptorProto.new(
447
- name: name,
448
- number: number
449
- )
450
- @enum_proto.value << enum_value_proto
451
- end
452
- end
453
-
454
- end
455
-
456
- # Re-open the class (the rest of the class is implemented in C)
457
- class DescriptorPool
458
- def build(&block)
459
- builder = Internal::Builder.new(self)
460
- builder.instance_eval(&block)
461
- builder.build
462
- end
463
- end
464
- end
465
- end