google-protobuf 3.8.0 → 3.13.0
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.
Potentially problematic release.
This version of google-protobuf might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/ext/google/protobuf_c/defs.c +942 -833
- data/ext/google/protobuf_c/encode_decode.c +482 -301
- data/ext/google/protobuf_c/extconf.rb +2 -4
- data/ext/google/protobuf_c/map.c +39 -58
- data/ext/google/protobuf_c/message.c +124 -114
- data/ext/google/protobuf_c/protobuf.c +30 -15
- data/ext/google/protobuf_c/protobuf.h +109 -57
- data/ext/google/protobuf_c/repeated_field.c +47 -21
- data/ext/google/protobuf_c/storage.c +305 -169
- data/ext/google/protobuf_c/upb.c +5335 -8998
- data/ext/google/protobuf_c/upb.h +4634 -8498
- data/lib/google/protobuf.rb +70 -0
- data/lib/google/protobuf/any_pb.rb +1 -1
- data/lib/google/protobuf/api_pb.rb +3 -3
- data/lib/google/protobuf/duration_pb.rb +1 -1
- data/lib/google/protobuf/empty_pb.rb +1 -1
- data/lib/google/protobuf/field_mask_pb.rb +1 -1
- data/lib/google/protobuf/source_context_pb.rb +1 -1
- data/lib/google/protobuf/struct_pb.rb +4 -4
- data/lib/google/protobuf/timestamp_pb.rb +1 -1
- data/lib/google/protobuf/type_pb.rb +8 -8
- data/lib/google/protobuf/well_known_types.rb +8 -2
- data/lib/google/protobuf/wrappers_pb.rb +9 -9
- data/tests/basic.rb +229 -67
- data/tests/generated_code_test.rb +0 -0
- data/tests/stress.rb +0 -0
- metadata +17 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 34afa1365c4de64d0a8922c15490b0a0559bd36d87d8fed0e37d42a6e73d7441
|
4
|
+
data.tar.gz: 742745747e3b4f4c5ebe0fdec56071c7482c45fa1ebd32629cdde8863dedcea1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c66aff4b91bc21111a4fa09cd3f562d8cd6a2b9405f5248d7b913a171316aa6b565b5c65c01dbbe8c4ca7e34c98b7fd571b129d3b069ee2dca5b367c633dfeff
|
7
|
+
data.tar.gz: fd938105444fc70d75046efa3b28ab220b44fcf7c3e9e93934db642448f1ae960db8ab7de2af1656deeede09a46ab8b46d87ae24acf6d9e6ce80b654f0f8ecc7
|
@@ -28,6 +28,8 @@
|
|
28
28
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
29
29
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
30
|
|
31
|
+
#include <ctype.h>
|
32
|
+
#include <errno.h>
|
31
33
|
#include "protobuf.h"
|
32
34
|
|
33
35
|
// -----------------------------------------------------------------------------
|
@@ -46,29 +48,290 @@ static VALUE rb_str_maybe_null(const char* s) {
|
|
46
48
|
return rb_str_new2(s);
|
47
49
|
}
|
48
50
|
|
49
|
-
static
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
51
|
+
static void rewrite_enum_default(const upb_symtab* symtab,
|
52
|
+
google_protobuf_FileDescriptorProto* file,
|
53
|
+
google_protobuf_FieldDescriptorProto* field) {
|
54
|
+
upb_strview defaultval;
|
55
|
+
const char *type_name_str;
|
56
|
+
char *end;
|
57
|
+
long val;
|
58
|
+
const upb_enumdef *e;
|
59
|
+
upb_strview type_name;
|
60
|
+
|
61
|
+
/* Look for TYPE_ENUM fields that have a default. */
|
62
|
+
if (google_protobuf_FieldDescriptorProto_type(field) !=
|
63
|
+
google_protobuf_FieldDescriptorProto_TYPE_ENUM ||
|
64
|
+
!google_protobuf_FieldDescriptorProto_has_default_value(field) ||
|
65
|
+
!google_protobuf_FieldDescriptorProto_has_type_name(field)) {
|
66
|
+
return;
|
54
67
|
}
|
55
|
-
return (upb_def*)def;
|
56
|
-
}
|
57
68
|
|
58
|
-
|
59
|
-
|
69
|
+
defaultval = google_protobuf_FieldDescriptorProto_default_value(field);
|
70
|
+
type_name = google_protobuf_FieldDescriptorProto_type_name(field);
|
71
|
+
|
72
|
+
if (defaultval.size == 0 || !isdigit(defaultval.data[0])) {
|
73
|
+
return;
|
74
|
+
}
|
75
|
+
|
76
|
+
if (type_name.size == 0 || type_name.data[0] != '.') {
|
77
|
+
return;
|
78
|
+
}
|
79
|
+
|
80
|
+
type_name_str = type_name.data + 1;
|
81
|
+
|
82
|
+
errno = 0;
|
83
|
+
val = strtol(defaultval.data, &end, 10);
|
84
|
+
|
85
|
+
if (errno != 0 || *end != 0 || val < INT32_MIN || val > INT32_MAX) {
|
86
|
+
return;
|
87
|
+
}
|
88
|
+
|
89
|
+
/* Now find the corresponding enum definition. */
|
90
|
+
e = upb_symtab_lookupenum(symtab, type_name_str);
|
91
|
+
if (e) {
|
92
|
+
/* Look in previously loaded files. */
|
93
|
+
const char *label = upb_enumdef_iton(e, val);
|
94
|
+
if (!label) {
|
95
|
+
return;
|
96
|
+
}
|
97
|
+
google_protobuf_FieldDescriptorProto_set_default_value(
|
98
|
+
field, upb_strview_makez(label));
|
99
|
+
} else {
|
100
|
+
/* Look in enums defined in this file. */
|
101
|
+
const google_protobuf_EnumDescriptorProto* matching_enum = NULL;
|
102
|
+
size_t i, n;
|
103
|
+
const google_protobuf_EnumDescriptorProto* const* enums =
|
104
|
+
google_protobuf_FileDescriptorProto_enum_type(file, &n);
|
105
|
+
const google_protobuf_EnumValueDescriptorProto* const* values;
|
106
|
+
|
107
|
+
for (i = 0; i < n; i++) {
|
108
|
+
if (upb_strview_eql(google_protobuf_EnumDescriptorProto_name(enums[i]),
|
109
|
+
upb_strview_makez(type_name_str))) {
|
110
|
+
matching_enum = enums[i];
|
111
|
+
break;
|
112
|
+
}
|
113
|
+
}
|
114
|
+
|
115
|
+
if (!matching_enum) {
|
116
|
+
return;
|
117
|
+
}
|
118
|
+
|
119
|
+
values = google_protobuf_EnumDescriptorProto_value(matching_enum, &n);
|
120
|
+
for (i = 0; i < n; i++) {
|
121
|
+
if (google_protobuf_EnumValueDescriptorProto_number(values[i]) == val) {
|
122
|
+
google_protobuf_FieldDescriptorProto_set_default_value(
|
123
|
+
field, google_protobuf_EnumValueDescriptorProto_name(values[i]));
|
124
|
+
return;
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
/* We failed to find an enum default. But we'll just leave the enum
|
129
|
+
* untouched and let the normal def-building code catch it. */
|
130
|
+
}
|
60
131
|
}
|
61
132
|
|
62
|
-
|
63
|
-
|
133
|
+
/* Historically we allowed enum defaults to be specified as a number. In
|
134
|
+
* retrospect this was a mistake as descriptors require defaults to be
|
135
|
+
* specified as a label. This can make a difference if multiple labels have the
|
136
|
+
* same number.
|
137
|
+
*
|
138
|
+
* Here we do a pass over all enum defaults and rewrite numeric defaults by
|
139
|
+
* looking up their labels. This is complicated by the fact that the enum
|
140
|
+
* definition can live in either the symtab or the file_proto.
|
141
|
+
* */
|
142
|
+
static void rewrite_enum_defaults(
|
143
|
+
const upb_symtab* symtab, google_protobuf_FileDescriptorProto* file_proto) {
|
144
|
+
size_t i, n;
|
145
|
+
google_protobuf_DescriptorProto** msgs =
|
146
|
+
google_protobuf_FileDescriptorProto_mutable_message_type(file_proto, &n);
|
147
|
+
|
148
|
+
for (i = 0; i < n; i++) {
|
149
|
+
size_t j, m;
|
150
|
+
google_protobuf_FieldDescriptorProto** fields =
|
151
|
+
google_protobuf_DescriptorProto_mutable_field(msgs[i], &m);
|
152
|
+
for (j = 0; j < m; j++) {
|
153
|
+
rewrite_enum_default(symtab, file_proto, fields[j]);
|
154
|
+
}
|
155
|
+
}
|
64
156
|
}
|
65
157
|
|
66
|
-
static
|
67
|
-
|
158
|
+
static void remove_path(upb_strview *name) {
|
159
|
+
const char* last = strrchr(name->data, '.');
|
160
|
+
if (last) {
|
161
|
+
size_t remove = last - name->data + 1;
|
162
|
+
name->data += remove;
|
163
|
+
name->size -= remove;
|
164
|
+
}
|
165
|
+
}
|
166
|
+
|
167
|
+
static void rewrite_nesting(VALUE msg_ent, google_protobuf_DescriptorProto* msg,
|
168
|
+
google_protobuf_DescriptorProto* const* msgs,
|
169
|
+
google_protobuf_EnumDescriptorProto* const* enums,
|
170
|
+
upb_arena *arena) {
|
171
|
+
VALUE submsgs = rb_hash_aref(msg_ent, ID2SYM(rb_intern("msgs")));
|
172
|
+
VALUE enum_pos = rb_hash_aref(msg_ent, ID2SYM(rb_intern("enums")));
|
173
|
+
int submsg_count;
|
174
|
+
int enum_count;
|
175
|
+
int i;
|
176
|
+
google_protobuf_DescriptorProto** msg_msgs;
|
177
|
+
google_protobuf_EnumDescriptorProto** msg_enums;
|
178
|
+
|
179
|
+
Check_Type(submsgs, T_ARRAY);
|
180
|
+
Check_Type(enum_pos, T_ARRAY);
|
181
|
+
|
182
|
+
submsg_count = RARRAY_LEN(submsgs);
|
183
|
+
enum_count = RARRAY_LEN(enum_pos);
|
184
|
+
|
185
|
+
msg_msgs = google_protobuf_DescriptorProto_resize_nested_type(
|
186
|
+
msg, submsg_count, arena);
|
187
|
+
msg_enums =
|
188
|
+
google_protobuf_DescriptorProto_resize_enum_type(msg, enum_count, arena);
|
189
|
+
|
190
|
+
for (i = 0; i < submsg_count; i++) {
|
191
|
+
VALUE submsg_ent = RARRAY_PTR(submsgs)[i];
|
192
|
+
VALUE pos = rb_hash_aref(submsg_ent, ID2SYM(rb_intern("pos")));
|
193
|
+
upb_strview name;
|
194
|
+
|
195
|
+
msg_msgs[i] = msgs[NUM2INT(pos)];
|
196
|
+
name = google_protobuf_DescriptorProto_name(msg_msgs[i]);
|
197
|
+
remove_path(&name);
|
198
|
+
google_protobuf_DescriptorProto_set_name(msg_msgs[i], name);
|
199
|
+
rewrite_nesting(submsg_ent, msg_msgs[i], msgs, enums, arena);
|
200
|
+
}
|
201
|
+
|
202
|
+
for (i = 0; i < enum_count; i++) {
|
203
|
+
VALUE pos = RARRAY_PTR(enum_pos)[i];
|
204
|
+
msg_enums[i] = enums[NUM2INT(pos)];
|
205
|
+
}
|
68
206
|
}
|
69
207
|
|
70
|
-
|
71
|
-
|
208
|
+
/* We have to do some relatively complicated logic here for backward
|
209
|
+
* compatibility.
|
210
|
+
*
|
211
|
+
* In descriptor.proto, messages are nested inside other messages if that is
|
212
|
+
* what the original .proto file looks like. For example, suppose we have this
|
213
|
+
* foo.proto:
|
214
|
+
*
|
215
|
+
* package foo;
|
216
|
+
* message Bar {
|
217
|
+
* message Baz {}
|
218
|
+
* }
|
219
|
+
*
|
220
|
+
* The descriptor for this must look like this:
|
221
|
+
*
|
222
|
+
* file {
|
223
|
+
* name: "test.proto"
|
224
|
+
* package: "foo"
|
225
|
+
* message_type {
|
226
|
+
* name: "Bar"
|
227
|
+
* nested_type {
|
228
|
+
* name: "Baz"
|
229
|
+
* }
|
230
|
+
* }
|
231
|
+
* }
|
232
|
+
*
|
233
|
+
* However, the Ruby generated code has always generated messages in a flat,
|
234
|
+
* non-nested way:
|
235
|
+
*
|
236
|
+
* Google::Protobuf::DescriptorPool.generated_pool.build do
|
237
|
+
* add_message "foo.Bar" do
|
238
|
+
* end
|
239
|
+
* add_message "foo.Bar.Baz" do
|
240
|
+
* end
|
241
|
+
* end
|
242
|
+
*
|
243
|
+
* Here we need to do a translation where we turn this generated code into the
|
244
|
+
* above descriptor. We need to infer that "foo" is the package name, and not
|
245
|
+
* a message itself.
|
246
|
+
*
|
247
|
+
* We delegate to Ruby to compute the transformation, for more concice and
|
248
|
+
* readable code than we can do in C */
|
249
|
+
static void rewrite_names(VALUE _file_builder,
|
250
|
+
google_protobuf_FileDescriptorProto* file_proto) {
|
251
|
+
FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder);
|
252
|
+
upb_arena *arena = file_builder->arena;
|
253
|
+
// Build params (package, msg_names, enum_names).
|
254
|
+
VALUE package = Qnil;
|
255
|
+
VALUE msg_names = rb_ary_new();
|
256
|
+
VALUE enum_names = rb_ary_new();
|
257
|
+
size_t msg_count, enum_count, i;
|
258
|
+
VALUE new_package, nesting, msg_ents, enum_ents;
|
259
|
+
google_protobuf_DescriptorProto** msgs;
|
260
|
+
google_protobuf_EnumDescriptorProto** enums;
|
261
|
+
|
262
|
+
if (google_protobuf_FileDescriptorProto_has_package(file_proto)) {
|
263
|
+
upb_strview package_str =
|
264
|
+
google_protobuf_FileDescriptorProto_package(file_proto);
|
265
|
+
package = rb_str_new(package_str.data, package_str.size);
|
266
|
+
}
|
267
|
+
|
268
|
+
msgs = google_protobuf_FileDescriptorProto_mutable_message_type(file_proto,
|
269
|
+
&msg_count);
|
270
|
+
for (i = 0; i < msg_count; i++) {
|
271
|
+
upb_strview name = google_protobuf_DescriptorProto_name(msgs[i]);
|
272
|
+
rb_ary_push(msg_names, rb_str_new(name.data, name.size));
|
273
|
+
}
|
274
|
+
|
275
|
+
enums = google_protobuf_FileDescriptorProto_mutable_enum_type(file_proto,
|
276
|
+
&enum_count);
|
277
|
+
for (i = 0; i < enum_count; i++) {
|
278
|
+
upb_strview name = google_protobuf_EnumDescriptorProto_name(enums[i]);
|
279
|
+
rb_ary_push(enum_names, rb_str_new(name.data, name.size));
|
280
|
+
}
|
281
|
+
|
282
|
+
{
|
283
|
+
// Call Ruby code to calculate package name and nesting.
|
284
|
+
VALUE args[3] = { package, msg_names, enum_names };
|
285
|
+
VALUE internal = rb_eval_string("Google::Protobuf::Internal");
|
286
|
+
VALUE ret = rb_funcallv(internal, rb_intern("fixup_descriptor"), 3, args);
|
287
|
+
|
288
|
+
new_package = rb_ary_entry(ret, 0);
|
289
|
+
nesting = rb_ary_entry(ret, 1);
|
290
|
+
}
|
291
|
+
|
292
|
+
// Rewrite package and names.
|
293
|
+
if (new_package != Qnil) {
|
294
|
+
upb_strview new_package_str =
|
295
|
+
FileBuilderContext_strdup(_file_builder, new_package);
|
296
|
+
google_protobuf_FileDescriptorProto_set_package(file_proto,
|
297
|
+
new_package_str);
|
298
|
+
}
|
299
|
+
|
300
|
+
for (i = 0; i < msg_count; i++) {
|
301
|
+
upb_strview name = google_protobuf_DescriptorProto_name(msgs[i]);
|
302
|
+
remove_path(&name);
|
303
|
+
google_protobuf_DescriptorProto_set_name(msgs[i], name);
|
304
|
+
}
|
305
|
+
|
306
|
+
for (i = 0; i < enum_count; i++) {
|
307
|
+
upb_strview name = google_protobuf_EnumDescriptorProto_name(enums[i]);
|
308
|
+
remove_path(&name);
|
309
|
+
google_protobuf_EnumDescriptorProto_set_name(enums[i], name);
|
310
|
+
}
|
311
|
+
|
312
|
+
// Rewrite nesting.
|
313
|
+
msg_ents = rb_hash_aref(nesting, ID2SYM(rb_intern("msgs")));
|
314
|
+
enum_ents = rb_hash_aref(nesting, ID2SYM(rb_intern("enums")));
|
315
|
+
|
316
|
+
Check_Type(msg_ents, T_ARRAY);
|
317
|
+
Check_Type(enum_ents, T_ARRAY);
|
318
|
+
|
319
|
+
for (i = 0; i < (size_t)RARRAY_LEN(msg_ents); i++) {
|
320
|
+
VALUE msg_ent = rb_ary_entry(msg_ents, i);
|
321
|
+
VALUE pos = rb_hash_aref(msg_ent, ID2SYM(rb_intern("pos")));
|
322
|
+
msgs[i] = msgs[NUM2INT(pos)];
|
323
|
+
rewrite_nesting(msg_ent, msgs[i], msgs, enums, arena);
|
324
|
+
}
|
325
|
+
|
326
|
+
for (i = 0; i < (size_t)RARRAY_LEN(enum_ents); i++) {
|
327
|
+
VALUE enum_pos = rb_ary_entry(enum_ents, i);
|
328
|
+
enums[i] = enums[NUM2INT(enum_pos)];
|
329
|
+
}
|
330
|
+
|
331
|
+
google_protobuf_FileDescriptorProto_resize_message_type(
|
332
|
+
file_proto, RARRAY_LEN(msg_ents), arena);
|
333
|
+
google_protobuf_FileDescriptorProto_resize_enum_type(
|
334
|
+
file_proto, RARRAY_LEN(enum_ents), arena);
|
72
335
|
}
|
73
336
|
|
74
337
|
// -----------------------------------------------------------------------------
|
@@ -92,16 +355,26 @@ static upb_enumdef* check_enum_notfrozen(const upb_enumdef* def) {
|
|
92
355
|
|
93
356
|
// Global singleton DescriptorPool. The user is free to create others, but this
|
94
357
|
// is used by generated code.
|
95
|
-
VALUE generated_pool;
|
358
|
+
VALUE generated_pool = Qnil;
|
96
359
|
|
97
360
|
DEFINE_CLASS(DescriptorPool, "Google::Protobuf::DescriptorPool");
|
98
361
|
|
99
362
|
void DescriptorPool_mark(void* _self) {
|
363
|
+
DescriptorPool* self = _self;
|
364
|
+
rb_gc_mark(self->def_to_descriptor);
|
100
365
|
}
|
101
366
|
|
102
367
|
void DescriptorPool_free(void* _self) {
|
103
368
|
DescriptorPool* self = _self;
|
369
|
+
|
104
370
|
upb_symtab_free(self->symtab);
|
371
|
+
upb_handlercache_free(self->fill_handler_cache);
|
372
|
+
upb_handlercache_free(self->pb_serialize_handler_cache);
|
373
|
+
upb_handlercache_free(self->json_serialize_handler_cache);
|
374
|
+
upb_handlercache_free(self->json_serialize_handler_preserve_cache);
|
375
|
+
upb_pbcodecache_free(self->fill_method_cache);
|
376
|
+
upb_json_codecache_free(self->json_fill_method_cache);
|
377
|
+
|
105
378
|
xfree(self);
|
106
379
|
}
|
107
380
|
|
@@ -113,15 +386,29 @@ void DescriptorPool_free(void* _self) {
|
|
113
386
|
*/
|
114
387
|
VALUE DescriptorPool_alloc(VALUE klass) {
|
115
388
|
DescriptorPool* self = ALLOC(DescriptorPool);
|
389
|
+
VALUE ret;
|
390
|
+
|
391
|
+
self->def_to_descriptor = Qnil;
|
392
|
+
ret = TypedData_Wrap_Struct(klass, &_DescriptorPool_type, self);
|
393
|
+
|
394
|
+
self->def_to_descriptor = rb_hash_new();
|
116
395
|
self->symtab = upb_symtab_new();
|
117
|
-
|
396
|
+
self->fill_handler_cache =
|
397
|
+
upb_handlercache_new(add_handlers_for_message, (void*)ret);
|
398
|
+
self->pb_serialize_handler_cache = upb_pb_encoder_newcache();
|
399
|
+
self->json_serialize_handler_cache = upb_json_printer_newcache(false);
|
400
|
+
self->json_serialize_handler_preserve_cache =
|
401
|
+
upb_json_printer_newcache(true);
|
402
|
+
self->fill_method_cache = upb_pbcodecache_new(self->fill_handler_cache);
|
403
|
+
self->json_fill_method_cache = upb_json_codecache_new();
|
404
|
+
|
405
|
+
return ret;
|
118
406
|
}
|
119
407
|
|
120
408
|
void DescriptorPool_register(VALUE module) {
|
121
409
|
VALUE klass = rb_define_class_under(
|
122
410
|
module, "DescriptorPool", rb_cObject);
|
123
411
|
rb_define_alloc_func(klass, DescriptorPool_alloc);
|
124
|
-
rb_define_method(klass, "add", DescriptorPool_add, 1);
|
125
412
|
rb_define_method(klass, "build", DescriptorPool_build, -1);
|
126
413
|
rb_define_method(klass, "lookup", DescriptorPool_lookup, 1);
|
127
414
|
rb_define_singleton_method(klass, "generated_pool",
|
@@ -133,44 +420,6 @@ void DescriptorPool_register(VALUE module) {
|
|
133
420
|
generated_pool = rb_class_new_instance(0, NULL, klass);
|
134
421
|
}
|
135
422
|
|
136
|
-
static void add_descriptor_to_pool(DescriptorPool* self,
|
137
|
-
Descriptor* descriptor) {
|
138
|
-
CHECK_UPB(
|
139
|
-
upb_symtab_add(self->symtab, (upb_def**)&descriptor->msgdef, 1,
|
140
|
-
NULL, &status),
|
141
|
-
"Adding Descriptor to DescriptorPool failed");
|
142
|
-
}
|
143
|
-
|
144
|
-
static void add_enumdesc_to_pool(DescriptorPool* self,
|
145
|
-
EnumDescriptor* enumdesc) {
|
146
|
-
CHECK_UPB(
|
147
|
-
upb_symtab_add(self->symtab, (upb_def**)&enumdesc->enumdef, 1,
|
148
|
-
NULL, &status),
|
149
|
-
"Adding EnumDescriptor to DescriptorPool failed");
|
150
|
-
}
|
151
|
-
|
152
|
-
/*
|
153
|
-
* call-seq:
|
154
|
-
* DescriptorPool.add(descriptor)
|
155
|
-
*
|
156
|
-
* Adds the given Descriptor or EnumDescriptor to this pool. All references to
|
157
|
-
* other types in a Descriptor's fields must be resolvable within this pool or
|
158
|
-
* an exception will be raised.
|
159
|
-
*/
|
160
|
-
VALUE DescriptorPool_add(VALUE _self, VALUE def) {
|
161
|
-
DEFINE_SELF(DescriptorPool, self, _self);
|
162
|
-
VALUE def_klass = rb_obj_class(def);
|
163
|
-
if (def_klass == cDescriptor) {
|
164
|
-
add_descriptor_to_pool(self, ruby_to_Descriptor(def));
|
165
|
-
} else if (def_klass == cEnumDescriptor) {
|
166
|
-
add_enumdesc_to_pool(self, ruby_to_EnumDescriptor(def));
|
167
|
-
} else {
|
168
|
-
rb_raise(rb_eArgError,
|
169
|
-
"Second argument must be a Descriptor or EnumDescriptor.");
|
170
|
-
}
|
171
|
-
return Qnil;
|
172
|
-
}
|
173
|
-
|
174
423
|
/*
|
175
424
|
* call-seq:
|
176
425
|
* DescriptorPool.build(&block)
|
@@ -182,10 +431,10 @@ VALUE DescriptorPool_add(VALUE _self, VALUE def) {
|
|
182
431
|
* idiomatic way to define new message and enum types.
|
183
432
|
*/
|
184
433
|
VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self) {
|
185
|
-
VALUE ctx = rb_class_new_instance(
|
434
|
+
VALUE ctx = rb_class_new_instance(1, &_self, cBuilder);
|
186
435
|
VALUE block = rb_block_proc();
|
187
436
|
rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
|
188
|
-
|
437
|
+
Builder_build(ctx);
|
189
438
|
return Qnil;
|
190
439
|
}
|
191
440
|
|
@@ -199,11 +448,20 @@ VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self) {
|
|
199
448
|
VALUE DescriptorPool_lookup(VALUE _self, VALUE name) {
|
200
449
|
DEFINE_SELF(DescriptorPool, self, _self);
|
201
450
|
const char* name_str = get_str(name);
|
202
|
-
const
|
203
|
-
|
204
|
-
|
451
|
+
const upb_msgdef* msgdef;
|
452
|
+
const upb_enumdef* enumdef;
|
453
|
+
|
454
|
+
msgdef = upb_symtab_lookupmsg(self->symtab, name_str);
|
455
|
+
if (msgdef) {
|
456
|
+
return get_msgdef_obj(_self, msgdef);
|
205
457
|
}
|
206
|
-
|
458
|
+
|
459
|
+
enumdef = upb_symtab_lookupenum(self->symtab, name_str);
|
460
|
+
if (enumdef) {
|
461
|
+
return get_enumdef_obj(_self, enumdef);
|
462
|
+
}
|
463
|
+
|
464
|
+
return Qnil;
|
207
465
|
}
|
208
466
|
|
209
467
|
/*
|
@@ -228,36 +486,17 @@ DEFINE_CLASS(Descriptor, "Google::Protobuf::Descriptor");
|
|
228
486
|
void Descriptor_mark(void* _self) {
|
229
487
|
Descriptor* self = _self;
|
230
488
|
rb_gc_mark(self->klass);
|
489
|
+
rb_gc_mark(self->descriptor_pool);
|
490
|
+
if (self->layout && self->layout->empty_template) {
|
491
|
+
layout_mark(self->layout, self->layout->empty_template);
|
492
|
+
}
|
231
493
|
}
|
232
494
|
|
233
495
|
void Descriptor_free(void* _self) {
|
234
496
|
Descriptor* self = _self;
|
235
|
-
upb_msgdef_unref(self->msgdef, &self->msgdef);
|
236
497
|
if (self->layout) {
|
237
498
|
free_layout(self->layout);
|
238
499
|
}
|
239
|
-
if (self->fill_handlers) {
|
240
|
-
upb_handlers_unref(self->fill_handlers, &self->fill_handlers);
|
241
|
-
}
|
242
|
-
if (self->fill_method) {
|
243
|
-
upb_pbdecodermethod_unref(self->fill_method, &self->fill_method);
|
244
|
-
}
|
245
|
-
if (self->json_fill_method) {
|
246
|
-
upb_json_parsermethod_unref(self->json_fill_method,
|
247
|
-
&self->json_fill_method);
|
248
|
-
}
|
249
|
-
if (self->pb_serialize_handlers) {
|
250
|
-
upb_handlers_unref(self->pb_serialize_handlers,
|
251
|
-
&self->pb_serialize_handlers);
|
252
|
-
}
|
253
|
-
if (self->json_serialize_handlers) {
|
254
|
-
upb_handlers_unref(self->json_serialize_handlers,
|
255
|
-
&self->json_serialize_handlers);
|
256
|
-
}
|
257
|
-
if (self->json_serialize_handlers_preserve) {
|
258
|
-
upb_handlers_unref(self->json_serialize_handlers_preserve,
|
259
|
-
&self->json_serialize_handlers_preserve);
|
260
|
-
}
|
261
500
|
xfree(self);
|
262
501
|
}
|
263
502
|
|
@@ -273,15 +512,10 @@ void Descriptor_free(void* _self) {
|
|
273
512
|
VALUE Descriptor_alloc(VALUE klass) {
|
274
513
|
Descriptor* self = ALLOC(Descriptor);
|
275
514
|
VALUE ret = TypedData_Wrap_Struct(klass, &_Descriptor_type, self);
|
276
|
-
self->msgdef =
|
515
|
+
self->msgdef = NULL;
|
277
516
|
self->klass = Qnil;
|
517
|
+
self->descriptor_pool = Qnil;
|
278
518
|
self->layout = NULL;
|
279
|
-
self->fill_handlers = NULL;
|
280
|
-
self->fill_method = NULL;
|
281
|
-
self->json_fill_method = NULL;
|
282
|
-
self->pb_serialize_handlers = NULL;
|
283
|
-
self->json_serialize_handlers = NULL;
|
284
|
-
self->json_serialize_handlers_preserve = NULL;
|
285
519
|
return ret;
|
286
520
|
}
|
287
521
|
|
@@ -289,16 +523,13 @@ void Descriptor_register(VALUE module) {
|
|
289
523
|
VALUE klass = rb_define_class_under(
|
290
524
|
module, "Descriptor", rb_cObject);
|
291
525
|
rb_define_alloc_func(klass, Descriptor_alloc);
|
292
|
-
rb_define_method(klass, "initialize", Descriptor_initialize,
|
526
|
+
rb_define_method(klass, "initialize", Descriptor_initialize, 3);
|
293
527
|
rb_define_method(klass, "each", Descriptor_each, 0);
|
294
528
|
rb_define_method(klass, "lookup", Descriptor_lookup, 1);
|
295
|
-
rb_define_method(klass, "add_field", Descriptor_add_field, 1);
|
296
|
-
rb_define_method(klass, "add_oneof", Descriptor_add_oneof, 1);
|
297
529
|
rb_define_method(klass, "each_oneof", Descriptor_each_oneof, 0);
|
298
530
|
rb_define_method(klass, "lookup_oneof", Descriptor_lookup_oneof, 1);
|
299
531
|
rb_define_method(klass, "msgclass", Descriptor_msgclass, 0);
|
300
532
|
rb_define_method(klass, "name", Descriptor_name, 0);
|
301
|
-
rb_define_method(klass, "name=", Descriptor_name_set, 1);
|
302
533
|
rb_define_method(klass, "file_descriptor", Descriptor_file_descriptor, 0);
|
303
534
|
rb_include_module(klass, rb_mEnumerable);
|
304
535
|
rb_gc_register_address(&cDescriptor);
|
@@ -307,19 +538,21 @@ void Descriptor_register(VALUE module) {
|
|
307
538
|
|
308
539
|
/*
|
309
540
|
* call-seq:
|
310
|
-
* Descriptor.new(
|
541
|
+
* Descriptor.new(c_only_cookie, ptr) => Descriptor
|
311
542
|
*
|
312
|
-
*
|
543
|
+
* Creates a descriptor wrapper object. May only be called from C.
|
313
544
|
*/
|
314
|
-
VALUE Descriptor_initialize(VALUE _self, VALUE
|
545
|
+
VALUE Descriptor_initialize(VALUE _self, VALUE cookie,
|
546
|
+
VALUE descriptor_pool, VALUE ptr) {
|
315
547
|
DEFINE_SELF(Descriptor, self, _self);
|
316
548
|
|
317
|
-
|
549
|
+
if (cookie != c_only_cookie) {
|
550
|
+
rb_raise(rb_eRuntimeError,
|
551
|
+
"Descriptor objects may not be created from Ruby.");
|
552
|
+
}
|
318
553
|
|
319
|
-
|
320
|
-
|
321
|
-
"Failed to associate message to file descriptor.");
|
322
|
-
add_def_obj(file_descriptor->filedef, file_descriptor_rb);
|
554
|
+
self->descriptor_pool = descriptor_pool;
|
555
|
+
self->msgdef = (const upb_msgdef*)NUM2ULL(ptr);
|
323
556
|
|
324
557
|
return Qnil;
|
325
558
|
}
|
@@ -332,14 +565,14 @@ VALUE Descriptor_initialize(VALUE _self, VALUE file_descriptor_rb) {
|
|
332
565
|
*/
|
333
566
|
VALUE Descriptor_file_descriptor(VALUE _self) {
|
334
567
|
DEFINE_SELF(Descriptor, self, _self);
|
335
|
-
return
|
568
|
+
return get_filedef_obj(self->descriptor_pool, upb_msgdef_file(self->msgdef));
|
336
569
|
}
|
337
570
|
|
338
571
|
/*
|
339
572
|
* call-seq:
|
340
573
|
* Descriptor.name => name
|
341
574
|
*
|
342
|
-
* Returns the name of this message type as a fully-
|
575
|
+
* Returns the name of this message type as a fully-qualified string (e.g.,
|
343
576
|
* My.Package.MessageType).
|
344
577
|
*/
|
345
578
|
VALUE Descriptor_name(VALUE _self) {
|
@@ -347,23 +580,6 @@ VALUE Descriptor_name(VALUE _self) {
|
|
347
580
|
return rb_str_maybe_null(upb_msgdef_fullname(self->msgdef));
|
348
581
|
}
|
349
582
|
|
350
|
-
/*
|
351
|
-
* call-seq:
|
352
|
-
* Descriptor.name = name
|
353
|
-
*
|
354
|
-
* Assigns a name to this message type. The descriptor must not have been added
|
355
|
-
* to a pool yet.
|
356
|
-
*/
|
357
|
-
VALUE Descriptor_name_set(VALUE _self, VALUE str) {
|
358
|
-
DEFINE_SELF(Descriptor, self, _self);
|
359
|
-
upb_msgdef* mut_def = check_msg_notfrozen(self->msgdef);
|
360
|
-
const char* name = get_str(str);
|
361
|
-
CHECK_UPB(
|
362
|
-
upb_msgdef_setfullname(mut_def, name, &status),
|
363
|
-
"Error setting Descriptor name");
|
364
|
-
return Qnil;
|
365
|
-
}
|
366
|
-
|
367
583
|
/*
|
368
584
|
* call-seq:
|
369
585
|
* Descriptor.each(&block)
|
@@ -378,7 +594,7 @@ VALUE Descriptor_each(VALUE _self) {
|
|
378
594
|
!upb_msg_field_done(&it);
|
379
595
|
upb_msg_field_next(&it)) {
|
380
596
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
381
|
-
VALUE obj =
|
597
|
+
VALUE obj = get_fielddef_obj(self->descriptor_pool, field);
|
382
598
|
rb_yield(obj);
|
383
599
|
}
|
384
600
|
return Qnil;
|
@@ -398,51 +614,7 @@ VALUE Descriptor_lookup(VALUE _self, VALUE name) {
|
|
398
614
|
if (field == NULL) {
|
399
615
|
return Qnil;
|
400
616
|
}
|
401
|
-
return
|
402
|
-
}
|
403
|
-
|
404
|
-
/*
|
405
|
-
* call-seq:
|
406
|
-
* Descriptor.add_field(field) => nil
|
407
|
-
*
|
408
|
-
* Adds the given FieldDescriptor to this message type. This descriptor must not
|
409
|
-
* have been added to a pool yet. Raises an exception if a field with the same
|
410
|
-
* name or number already exists. Sub-type references (e.g. for fields of type
|
411
|
-
* message) are not resolved at this point.
|
412
|
-
*/
|
413
|
-
VALUE Descriptor_add_field(VALUE _self, VALUE obj) {
|
414
|
-
DEFINE_SELF(Descriptor, self, _self);
|
415
|
-
upb_msgdef* mut_def = check_msg_notfrozen(self->msgdef);
|
416
|
-
FieldDescriptor* def = ruby_to_FieldDescriptor(obj);
|
417
|
-
upb_fielddef* mut_field_def = check_field_notfrozen(def->fielddef);
|
418
|
-
CHECK_UPB(
|
419
|
-
upb_msgdef_addfield(mut_def, mut_field_def, NULL, &status),
|
420
|
-
"Adding field to Descriptor failed");
|
421
|
-
add_def_obj(def->fielddef, obj);
|
422
|
-
return Qnil;
|
423
|
-
}
|
424
|
-
|
425
|
-
/*
|
426
|
-
* call-seq:
|
427
|
-
* Descriptor.add_oneof(oneof) => nil
|
428
|
-
*
|
429
|
-
* Adds the given OneofDescriptor to this message type. This descriptor must not
|
430
|
-
* have been added to a pool yet. Raises an exception if a oneof with the same
|
431
|
-
* name already exists, or if any of the oneof's fields' names or numbers
|
432
|
-
* conflict with an existing field in this message type. All fields in the oneof
|
433
|
-
* are added to the message descriptor. Sub-type references (e.g. for fields of
|
434
|
-
* type message) are not resolved at this point.
|
435
|
-
*/
|
436
|
-
VALUE Descriptor_add_oneof(VALUE _self, VALUE obj) {
|
437
|
-
DEFINE_SELF(Descriptor, self, _self);
|
438
|
-
upb_msgdef* mut_def = check_msg_notfrozen(self->msgdef);
|
439
|
-
OneofDescriptor* def = ruby_to_OneofDescriptor(obj);
|
440
|
-
upb_oneofdef* mut_oneof_def = check_oneof_notfrozen(def->oneofdef);
|
441
|
-
CHECK_UPB(
|
442
|
-
upb_msgdef_addoneof(mut_def, mut_oneof_def, NULL, &status),
|
443
|
-
"Adding oneof to Descriptor failed");
|
444
|
-
add_def_obj(def->oneofdef, obj);
|
445
|
-
return Qnil;
|
617
|
+
return get_fielddef_obj(self->descriptor_pool, field);
|
446
618
|
}
|
447
619
|
|
448
620
|
/*
|
@@ -460,7 +632,7 @@ VALUE Descriptor_each_oneof(VALUE _self) {
|
|
460
632
|
!upb_msg_oneof_done(&it);
|
461
633
|
upb_msg_oneof_next(&it)) {
|
462
634
|
const upb_oneofdef* oneof = upb_msg_iter_oneof(&it);
|
463
|
-
VALUE obj =
|
635
|
+
VALUE obj = get_oneofdef_obj(self->descriptor_pool, oneof);
|
464
636
|
rb_yield(obj);
|
465
637
|
}
|
466
638
|
return Qnil;
|
@@ -480,24 +652,19 @@ VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name) {
|
|
480
652
|
if (oneof == NULL) {
|
481
653
|
return Qnil;
|
482
654
|
}
|
483
|
-
return
|
655
|
+
return get_oneofdef_obj(self->descriptor_pool, oneof);
|
484
656
|
}
|
485
657
|
|
486
658
|
/*
|
487
659
|
* call-seq:
|
488
660
|
* Descriptor.msgclass => message_klass
|
489
661
|
*
|
490
|
-
* Returns the Ruby class created for this message type.
|
491
|
-
* message type has been added to a pool.
|
662
|
+
* Returns the Ruby class created for this message type.
|
492
663
|
*/
|
493
664
|
VALUE Descriptor_msgclass(VALUE _self) {
|
494
665
|
DEFINE_SELF(Descriptor, self, _self);
|
495
|
-
if (!upb_def_isfrozen((const upb_def*)self->msgdef)) {
|
496
|
-
rb_raise(rb_eRuntimeError,
|
497
|
-
"Cannot fetch message class from a Descriptor not yet in a pool.");
|
498
|
-
}
|
499
666
|
if (self->klass == Qnil) {
|
500
|
-
self->klass = build_class_from_descriptor(
|
667
|
+
self->klass = build_class_from_descriptor(_self);
|
501
668
|
}
|
502
669
|
return self->klass;
|
503
670
|
}
|
@@ -509,12 +676,20 @@ VALUE Descriptor_msgclass(VALUE _self) {
|
|
509
676
|
DEFINE_CLASS(FileDescriptor, "Google::Protobuf::FileDescriptor");
|
510
677
|
|
511
678
|
void FileDescriptor_mark(void* _self) {
|
679
|
+
FileDescriptor* self = _self;
|
680
|
+
rb_gc_mark(self->descriptor_pool);
|
512
681
|
}
|
513
682
|
|
514
683
|
void FileDescriptor_free(void* _self) {
|
515
|
-
|
516
|
-
|
517
|
-
|
684
|
+
xfree(_self);
|
685
|
+
}
|
686
|
+
|
687
|
+
VALUE FileDescriptor_alloc(VALUE klass) {
|
688
|
+
FileDescriptor* self = ALLOC(FileDescriptor);
|
689
|
+
VALUE ret = TypedData_Wrap_Struct(klass, &_FileDescriptor_type, self);
|
690
|
+
self->descriptor_pool = Qnil;
|
691
|
+
self->filedef = NULL;
|
692
|
+
return ret;
|
518
693
|
}
|
519
694
|
|
520
695
|
/*
|
@@ -524,64 +699,32 @@ void FileDescriptor_free(void* _self) {
|
|
524
699
|
* Returns a new file descriptor. The syntax must be set before it's passed
|
525
700
|
* to a builder.
|
526
701
|
*/
|
527
|
-
VALUE
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
702
|
+
VALUE FileDescriptor_initialize(VALUE _self, VALUE cookie,
|
703
|
+
VALUE descriptor_pool, VALUE ptr) {
|
704
|
+
DEFINE_SELF(FileDescriptor, self, _self);
|
705
|
+
|
706
|
+
if (cookie != c_only_cookie) {
|
707
|
+
rb_raise(rb_eRuntimeError,
|
708
|
+
"Descriptor objects may not be created from Ruby.");
|
709
|
+
}
|
710
|
+
|
711
|
+
self->descriptor_pool = descriptor_pool;
|
712
|
+
self->filedef = (const upb_filedef*)NUM2ULL(ptr);
|
713
|
+
|
714
|
+
return Qnil;
|
533
715
|
}
|
534
716
|
|
535
717
|
void FileDescriptor_register(VALUE module) {
|
536
718
|
VALUE klass = rb_define_class_under(
|
537
719
|
module, "FileDescriptor", rb_cObject);
|
538
720
|
rb_define_alloc_func(klass, FileDescriptor_alloc);
|
539
|
-
rb_define_method(klass, "initialize", FileDescriptor_initialize,
|
721
|
+
rb_define_method(klass, "initialize", FileDescriptor_initialize, 3);
|
540
722
|
rb_define_method(klass, "name", FileDescriptor_name, 0);
|
541
723
|
rb_define_method(klass, "syntax", FileDescriptor_syntax, 0);
|
542
|
-
rb_define_method(klass, "syntax=", FileDescriptor_syntax_set, 1);
|
543
724
|
rb_gc_register_address(&cFileDescriptor);
|
544
725
|
cFileDescriptor = klass;
|
545
726
|
}
|
546
727
|
|
547
|
-
/*
|
548
|
-
* call-seq:
|
549
|
-
* FileDescriptor.new(name, options = nil) => file
|
550
|
-
*
|
551
|
-
* Initializes a new file descriptor with the given file name.
|
552
|
-
* Also accepts an optional "options" hash, specifying other optional
|
553
|
-
* metadata about the file. The options hash currently accepts the following
|
554
|
-
* * "syntax": :proto2 or :proto3 (default: :proto3)
|
555
|
-
*/
|
556
|
-
VALUE FileDescriptor_initialize(int argc, VALUE* argv, VALUE _self) {
|
557
|
-
DEFINE_SELF(FileDescriptor, self, _self);
|
558
|
-
|
559
|
-
VALUE name_rb;
|
560
|
-
VALUE options = Qnil;
|
561
|
-
rb_scan_args(argc, argv, "11", &name_rb, &options);
|
562
|
-
|
563
|
-
if (name_rb != Qnil) {
|
564
|
-
Check_Type(name_rb, T_STRING);
|
565
|
-
const char* name = get_str(name_rb);
|
566
|
-
CHECK_UPB(upb_filedef_setname(self->filedef, name, &status),
|
567
|
-
"Error setting file name");
|
568
|
-
}
|
569
|
-
|
570
|
-
// Default syntax is proto3.
|
571
|
-
VALUE syntax = ID2SYM(rb_intern("proto3"));
|
572
|
-
if (options != Qnil) {
|
573
|
-
Check_Type(options, T_HASH);
|
574
|
-
|
575
|
-
if (rb_funcall(options, rb_intern("key?"), 1,
|
576
|
-
ID2SYM(rb_intern("syntax"))) == Qtrue) {
|
577
|
-
syntax = rb_hash_lookup(options, ID2SYM(rb_intern("syntax")));
|
578
|
-
}
|
579
|
-
}
|
580
|
-
FileDescriptor_syntax_set(_self, syntax);
|
581
|
-
|
582
|
-
return Qnil;
|
583
|
-
}
|
584
|
-
|
585
728
|
/*
|
586
729
|
* call-seq:
|
587
730
|
* FileDescriptor.name => name
|
@@ -613,31 +756,6 @@ VALUE FileDescriptor_syntax(VALUE _self) {
|
|
613
756
|
}
|
614
757
|
}
|
615
758
|
|
616
|
-
/*
|
617
|
-
* call-seq:
|
618
|
-
* FileDescriptor.syntax = version
|
619
|
-
*
|
620
|
-
* Sets this file descriptor's syntax, can be :proto3 or :proto2.
|
621
|
-
*/
|
622
|
-
VALUE FileDescriptor_syntax_set(VALUE _self, VALUE syntax_rb) {
|
623
|
-
DEFINE_SELF(FileDescriptor, self, _self);
|
624
|
-
Check_Type(syntax_rb, T_SYMBOL);
|
625
|
-
|
626
|
-
upb_syntax_t syntax;
|
627
|
-
if (SYM2ID(syntax_rb) == rb_intern("proto3")) {
|
628
|
-
syntax = UPB_SYNTAX_PROTO3;
|
629
|
-
} else if (SYM2ID(syntax_rb) == rb_intern("proto2")) {
|
630
|
-
syntax = UPB_SYNTAX_PROTO2;
|
631
|
-
} else {
|
632
|
-
rb_raise(rb_eArgError, "Expected :proto3 or :proto3, received '%s'",
|
633
|
-
rb_id2name(SYM2ID(syntax_rb)));
|
634
|
-
}
|
635
|
-
|
636
|
-
CHECK_UPB(upb_filedef_setsyntax(self->filedef, syntax, &status),
|
637
|
-
"Error setting file syntax for proto");
|
638
|
-
return Qnil;
|
639
|
-
}
|
640
|
-
|
641
759
|
// -----------------------------------------------------------------------------
|
642
760
|
// FieldDescriptor.
|
643
761
|
// -----------------------------------------------------------------------------
|
@@ -645,12 +763,12 @@ VALUE FileDescriptor_syntax_set(VALUE _self, VALUE syntax_rb) {
|
|
645
763
|
DEFINE_CLASS(FieldDescriptor, "Google::Protobuf::FieldDescriptor");
|
646
764
|
|
647
765
|
void FieldDescriptor_mark(void* _self) {
|
766
|
+
FieldDescriptor* self = _self;
|
767
|
+
rb_gc_mark(self->descriptor_pool);
|
648
768
|
}
|
649
769
|
|
650
770
|
void FieldDescriptor_free(void* _self) {
|
651
|
-
|
652
|
-
upb_fielddef_unref(self->fielddef, &self->fielddef);
|
653
|
-
xfree(self);
|
771
|
+
xfree(_self);
|
654
772
|
}
|
655
773
|
|
656
774
|
/*
|
@@ -663,9 +781,7 @@ void FieldDescriptor_free(void* _self) {
|
|
663
781
|
VALUE FieldDescriptor_alloc(VALUE klass) {
|
664
782
|
FieldDescriptor* self = ALLOC(FieldDescriptor);
|
665
783
|
VALUE ret = TypedData_Wrap_Struct(klass, &_FieldDescriptor_type, self);
|
666
|
-
|
667
|
-
upb_fielddef_setpacked(fielddef, false);
|
668
|
-
self->fielddef = fielddef;
|
784
|
+
self->fielddef = NULL;
|
669
785
|
return ret;
|
670
786
|
}
|
671
787
|
|
@@ -673,18 +789,13 @@ void FieldDescriptor_register(VALUE module) {
|
|
673
789
|
VALUE klass = rb_define_class_under(
|
674
790
|
module, "FieldDescriptor", rb_cObject);
|
675
791
|
rb_define_alloc_func(klass, FieldDescriptor_alloc);
|
792
|
+
rb_define_method(klass, "initialize", FieldDescriptor_initialize, 3);
|
676
793
|
rb_define_method(klass, "name", FieldDescriptor_name, 0);
|
677
|
-
rb_define_method(klass, "name=", FieldDescriptor_name_set, 1);
|
678
794
|
rb_define_method(klass, "type", FieldDescriptor_type, 0);
|
679
|
-
rb_define_method(klass, "type=", FieldDescriptor_type_set, 1);
|
680
795
|
rb_define_method(klass, "default", FieldDescriptor_default, 0);
|
681
|
-
rb_define_method(klass, "default=", FieldDescriptor_default_set, 1);
|
682
796
|
rb_define_method(klass, "label", FieldDescriptor_label, 0);
|
683
|
-
rb_define_method(klass, "label=", FieldDescriptor_label_set, 1);
|
684
797
|
rb_define_method(klass, "number", FieldDescriptor_number, 0);
|
685
|
-
rb_define_method(klass, "number=", FieldDescriptor_number_set, 1);
|
686
798
|
rb_define_method(klass, "submsg_name", FieldDescriptor_submsg_name, 0);
|
687
|
-
rb_define_method(klass, "submsg_name=", FieldDescriptor_submsg_name_set, 1);
|
688
799
|
rb_define_method(klass, "subtype", FieldDescriptor_subtype, 0);
|
689
800
|
rb_define_method(klass, "has?", FieldDescriptor_has, 1);
|
690
801
|
rb_define_method(klass, "clear", FieldDescriptor_clear, 1);
|
@@ -696,29 +807,34 @@ void FieldDescriptor_register(VALUE module) {
|
|
696
807
|
|
697
808
|
/*
|
698
809
|
* call-seq:
|
699
|
-
*
|
810
|
+
* EnumDescriptor.new(c_only_cookie, pool, ptr) => EnumDescriptor
|
700
811
|
*
|
701
|
-
*
|
812
|
+
* Creates a descriptor wrapper object. May only be called from C.
|
702
813
|
*/
|
703
|
-
VALUE
|
814
|
+
VALUE FieldDescriptor_initialize(VALUE _self, VALUE cookie,
|
815
|
+
VALUE descriptor_pool, VALUE ptr) {
|
704
816
|
DEFINE_SELF(FieldDescriptor, self, _self);
|
705
|
-
|
817
|
+
|
818
|
+
if (cookie != c_only_cookie) {
|
819
|
+
rb_raise(rb_eRuntimeError,
|
820
|
+
"Descriptor objects may not be created from Ruby.");
|
821
|
+
}
|
822
|
+
|
823
|
+
self->descriptor_pool = descriptor_pool;
|
824
|
+
self->fielddef = (const upb_fielddef*)NUM2ULL(ptr);
|
825
|
+
|
826
|
+
return Qnil;
|
706
827
|
}
|
707
828
|
|
708
829
|
/*
|
709
830
|
* call-seq:
|
710
|
-
* FieldDescriptor.name
|
831
|
+
* FieldDescriptor.name => name
|
711
832
|
*
|
712
|
-
*
|
713
|
-
* type, if any, is added to a pool.
|
833
|
+
* Returns the name of this field.
|
714
834
|
*/
|
715
|
-
VALUE
|
835
|
+
VALUE FieldDescriptor_name(VALUE _self) {
|
716
836
|
DEFINE_SELF(FieldDescriptor, self, _self);
|
717
|
-
|
718
|
-
const char* name = get_str(str);
|
719
|
-
CHECK_UPB(upb_fielddef_setname(mut_def, name, &status),
|
720
|
-
"Error setting FieldDescriptor name");
|
721
|
-
return Qnil;
|
837
|
+
return rb_str_maybe_null(upb_fielddef_name(self->fielddef));
|
722
838
|
}
|
723
839
|
|
724
840
|
upb_fieldtype_t ruby_to_fieldtype(VALUE type) {
|
@@ -831,6 +947,29 @@ VALUE descriptortype_to_ruby(upb_descriptortype_t type) {
|
|
831
947
|
return Qnil;
|
832
948
|
}
|
833
949
|
|
950
|
+
VALUE ruby_to_label(VALUE label) {
|
951
|
+
upb_label_t upb_label;
|
952
|
+
bool converted = false;
|
953
|
+
|
954
|
+
#define CONVERT(upb, ruby) \
|
955
|
+
if (SYM2ID(label) == rb_intern( # ruby )) { \
|
956
|
+
upb_label = UPB_LABEL_ ## upb; \
|
957
|
+
converted = true; \
|
958
|
+
}
|
959
|
+
|
960
|
+
CONVERT(OPTIONAL, optional);
|
961
|
+
CONVERT(REQUIRED, required);
|
962
|
+
CONVERT(REPEATED, repeated);
|
963
|
+
|
964
|
+
#undef CONVERT
|
965
|
+
|
966
|
+
if (!converted) {
|
967
|
+
rb_raise(rb_eArgError, "Unknown field label.");
|
968
|
+
}
|
969
|
+
|
970
|
+
return upb_label;
|
971
|
+
}
|
972
|
+
|
834
973
|
/*
|
835
974
|
* call-seq:
|
836
975
|
* FieldDescriptor.type => type
|
@@ -843,26 +982,9 @@ VALUE descriptortype_to_ruby(upb_descriptortype_t type) {
|
|
843
982
|
*/
|
844
983
|
VALUE FieldDescriptor_type(VALUE _self) {
|
845
984
|
DEFINE_SELF(FieldDescriptor, self, _self);
|
846
|
-
if (!upb_fielddef_typeisset(self->fielddef)) {
|
847
|
-
return Qnil;
|
848
|
-
}
|
849
985
|
return descriptortype_to_ruby(upb_fielddef_descriptortype(self->fielddef));
|
850
986
|
}
|
851
987
|
|
852
|
-
/*
|
853
|
-
* call-seq:
|
854
|
-
* FieldDescriptor.type = type
|
855
|
-
*
|
856
|
-
* Sets this field's type. Cannot be called if field is part of a message type
|
857
|
-
* already in a pool.
|
858
|
-
*/
|
859
|
-
VALUE FieldDescriptor_type_set(VALUE _self, VALUE type) {
|
860
|
-
DEFINE_SELF(FieldDescriptor, self, _self);
|
861
|
-
upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
|
862
|
-
upb_fielddef_setdescriptortype(mut_def, ruby_to_descriptortype(type));
|
863
|
-
return Qnil;
|
864
|
-
}
|
865
|
-
|
866
988
|
/*
|
867
989
|
* call-seq:
|
868
990
|
* FieldDescriptor.default => default
|
@@ -874,60 +996,6 @@ VALUE FieldDescriptor_default(VALUE _self) {
|
|
874
996
|
return layout_get_default(self->fielddef);
|
875
997
|
}
|
876
998
|
|
877
|
-
/*
|
878
|
-
* call-seq:
|
879
|
-
* FieldDescriptor.default = default
|
880
|
-
*
|
881
|
-
* Sets this field's default value. Raises an exception when calling with
|
882
|
-
* proto syntax 3.
|
883
|
-
*/
|
884
|
-
VALUE FieldDescriptor_default_set(VALUE _self, VALUE default_value) {
|
885
|
-
DEFINE_SELF(FieldDescriptor, self, _self);
|
886
|
-
upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
|
887
|
-
|
888
|
-
switch (upb_fielddef_type(mut_def)) {
|
889
|
-
case UPB_TYPE_FLOAT:
|
890
|
-
upb_fielddef_setdefaultfloat(mut_def, NUM2DBL(default_value));
|
891
|
-
break;
|
892
|
-
case UPB_TYPE_DOUBLE:
|
893
|
-
upb_fielddef_setdefaultdouble(mut_def, NUM2DBL(default_value));
|
894
|
-
break;
|
895
|
-
case UPB_TYPE_BOOL:
|
896
|
-
if (!RB_TYPE_P(default_value, T_TRUE) &&
|
897
|
-
!RB_TYPE_P(default_value, T_FALSE) &&
|
898
|
-
!RB_TYPE_P(default_value, T_NIL)) {
|
899
|
-
rb_raise(cTypeError, "Expected boolean for default value.");
|
900
|
-
}
|
901
|
-
|
902
|
-
upb_fielddef_setdefaultbool(mut_def, RTEST(default_value));
|
903
|
-
break;
|
904
|
-
case UPB_TYPE_ENUM:
|
905
|
-
case UPB_TYPE_INT32:
|
906
|
-
upb_fielddef_setdefaultint32(mut_def, NUM2INT(default_value));
|
907
|
-
break;
|
908
|
-
case UPB_TYPE_INT64:
|
909
|
-
upb_fielddef_setdefaultint64(mut_def, NUM2INT(default_value));
|
910
|
-
break;
|
911
|
-
case UPB_TYPE_UINT32:
|
912
|
-
upb_fielddef_setdefaultuint32(mut_def, NUM2UINT(default_value));
|
913
|
-
break;
|
914
|
-
case UPB_TYPE_UINT64:
|
915
|
-
upb_fielddef_setdefaultuint64(mut_def, NUM2UINT(default_value));
|
916
|
-
break;
|
917
|
-
case UPB_TYPE_STRING:
|
918
|
-
case UPB_TYPE_BYTES:
|
919
|
-
CHECK_UPB(upb_fielddef_setdefaultcstr(mut_def, StringValuePtr(default_value),
|
920
|
-
&status),
|
921
|
-
"Error setting default string");
|
922
|
-
break;
|
923
|
-
default:
|
924
|
-
rb_raise(rb_eArgError, "Defaults not supported on field %s.%s",
|
925
|
-
upb_fielddef_fullname(mut_def), upb_fielddef_name(mut_def));
|
926
|
-
}
|
927
|
-
|
928
|
-
return Qnil;
|
929
|
-
}
|
930
|
-
|
931
999
|
/*
|
932
1000
|
* call-seq:
|
933
1001
|
* FieldDescriptor.label => label
|
@@ -953,44 +1021,6 @@ VALUE FieldDescriptor_label(VALUE _self) {
|
|
953
1021
|
return Qnil;
|
954
1022
|
}
|
955
1023
|
|
956
|
-
/*
|
957
|
-
* call-seq:
|
958
|
-
* FieldDescriptor.label = label
|
959
|
-
*
|
960
|
-
* Sets the label on this field. Cannot be called if field is part of a message
|
961
|
-
* type already in a pool.
|
962
|
-
*/
|
963
|
-
VALUE FieldDescriptor_label_set(VALUE _self, VALUE label) {
|
964
|
-
DEFINE_SELF(FieldDescriptor, self, _self);
|
965
|
-
upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
|
966
|
-
upb_label_t upb_label = -1;
|
967
|
-
bool converted = false;
|
968
|
-
|
969
|
-
if (TYPE(label) != T_SYMBOL) {
|
970
|
-
rb_raise(rb_eArgError, "Expected symbol for field label.");
|
971
|
-
}
|
972
|
-
|
973
|
-
#define CONVERT(upb, ruby) \
|
974
|
-
if (SYM2ID(label) == rb_intern( # ruby )) { \
|
975
|
-
upb_label = UPB_LABEL_ ## upb; \
|
976
|
-
converted = true; \
|
977
|
-
}
|
978
|
-
|
979
|
-
CONVERT(OPTIONAL, optional);
|
980
|
-
CONVERT(REQUIRED, required);
|
981
|
-
CONVERT(REPEATED, repeated);
|
982
|
-
|
983
|
-
#undef CONVERT
|
984
|
-
|
985
|
-
if (!converted) {
|
986
|
-
rb_raise(rb_eArgError, "Unknown field label.");
|
987
|
-
}
|
988
|
-
|
989
|
-
upb_fielddef_setlabel(mut_def, upb_label);
|
990
|
-
|
991
|
-
return Qnil;
|
992
|
-
}
|
993
|
-
|
994
1024
|
/*
|
995
1025
|
* call-seq:
|
996
1026
|
* FieldDescriptor.number => number
|
@@ -1002,21 +1032,6 @@ VALUE FieldDescriptor_number(VALUE _self) {
|
|
1002
1032
|
return INT2NUM(upb_fielddef_number(self->fielddef));
|
1003
1033
|
}
|
1004
1034
|
|
1005
|
-
/*
|
1006
|
-
* call-seq:
|
1007
|
-
* FieldDescriptor.number = number
|
1008
|
-
*
|
1009
|
-
* Sets the tag number for this field. Cannot be called if field is part of a
|
1010
|
-
* message type already in a pool.
|
1011
|
-
*/
|
1012
|
-
VALUE FieldDescriptor_number_set(VALUE _self, VALUE number) {
|
1013
|
-
DEFINE_SELF(FieldDescriptor, self, _self);
|
1014
|
-
upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
|
1015
|
-
CHECK_UPB(upb_fielddef_setnumber(mut_def, NUM2INT(number), &status),
|
1016
|
-
"Error setting field number");
|
1017
|
-
return Qnil;
|
1018
|
-
}
|
1019
|
-
|
1020
1035
|
/*
|
1021
1036
|
* call-seq:
|
1022
1037
|
* FieldDescriptor.submsg_name => submsg_name
|
@@ -1028,32 +1043,16 @@ VALUE FieldDescriptor_number_set(VALUE _self, VALUE number) {
|
|
1028
1043
|
*/
|
1029
1044
|
VALUE FieldDescriptor_submsg_name(VALUE _self) {
|
1030
1045
|
DEFINE_SELF(FieldDescriptor, self, _self);
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
*
|
1041
|
-
* Sets the name of the message or enum type corresponding to this field, if it
|
1042
|
-
* is a message or enum field (respectively). This type name will be resolved
|
1043
|
-
* within the context of the pool to which the containing message type is added.
|
1044
|
-
* Cannot be called on field that are not of message or enum type, or on fields
|
1045
|
-
* that are part of a message type already added to a pool.
|
1046
|
-
*/
|
1047
|
-
VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value) {
|
1048
|
-
DEFINE_SELF(FieldDescriptor, self, _self);
|
1049
|
-
upb_fielddef* mut_def = check_field_notfrozen(self->fielddef);
|
1050
|
-
const char* str = get_str(value);
|
1051
|
-
if (!upb_fielddef_hassubdef(self->fielddef)) {
|
1052
|
-
rb_raise(cTypeError, "FieldDescriptor does not have subdef.");
|
1046
|
+
switch (upb_fielddef_type(self->fielddef)) {
|
1047
|
+
case UPB_TYPE_ENUM:
|
1048
|
+
return rb_str_new2(
|
1049
|
+
upb_enumdef_fullname(upb_fielddef_enumsubdef(self->fielddef)));
|
1050
|
+
case UPB_TYPE_MESSAGE:
|
1051
|
+
return rb_str_new2(
|
1052
|
+
upb_msgdef_fullname(upb_fielddef_msgsubdef(self->fielddef)));
|
1053
|
+
default:
|
1054
|
+
return Qnil;
|
1053
1055
|
}
|
1054
|
-
CHECK_UPB(upb_fielddef_setsubdefname(mut_def, str, &status),
|
1055
|
-
"Error setting submessage name");
|
1056
|
-
return Qnil;
|
1057
1056
|
}
|
1058
1057
|
|
1059
1058
|
/*
|
@@ -1067,16 +1066,16 @@ VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value) {
|
|
1067
1066
|
*/
|
1068
1067
|
VALUE FieldDescriptor_subtype(VALUE _self) {
|
1069
1068
|
DEFINE_SELF(FieldDescriptor, self, _self);
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1069
|
+
switch (upb_fielddef_type(self->fielddef)) {
|
1070
|
+
case UPB_TYPE_ENUM:
|
1071
|
+
return get_enumdef_obj(self->descriptor_pool,
|
1072
|
+
upb_fielddef_enumsubdef(self->fielddef));
|
1073
|
+
case UPB_TYPE_MESSAGE:
|
1074
|
+
return get_msgdef_obj(self->descriptor_pool,
|
1075
|
+
upb_fielddef_msgsubdef(self->fielddef));
|
1076
|
+
default:
|
1077
|
+
return Qnil;
|
1078
1078
|
}
|
1079
|
-
return get_def_obj(def);
|
1080
1079
|
}
|
1081
1080
|
|
1082
1081
|
/*
|
@@ -1101,7 +1100,7 @@ VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb) {
|
|
1101
1100
|
* FieldDescriptor.has?(message) => boolean
|
1102
1101
|
*
|
1103
1102
|
* Returns whether the value is set on the given message. Raises an
|
1104
|
-
* exception when calling
|
1103
|
+
* exception when calling for fields that do not have presence.
|
1105
1104
|
*/
|
1106
1105
|
VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb) {
|
1107
1106
|
DEFINE_SELF(FieldDescriptor, self, _self);
|
@@ -1160,12 +1159,12 @@ VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value) {
|
|
1160
1159
|
DEFINE_CLASS(OneofDescriptor, "Google::Protobuf::OneofDescriptor");
|
1161
1160
|
|
1162
1161
|
void OneofDescriptor_mark(void* _self) {
|
1162
|
+
OneofDescriptor* self = _self;
|
1163
|
+
rb_gc_mark(self->descriptor_pool);
|
1163
1164
|
}
|
1164
1165
|
|
1165
1166
|
void OneofDescriptor_free(void* _self) {
|
1166
|
-
|
1167
|
-
upb_oneofdef_unref(self->oneofdef, &self->oneofdef);
|
1168
|
-
xfree(self);
|
1167
|
+
xfree(_self);
|
1169
1168
|
}
|
1170
1169
|
|
1171
1170
|
/*
|
@@ -1178,7 +1177,8 @@ void OneofDescriptor_free(void* _self) {
|
|
1178
1177
|
VALUE OneofDescriptor_alloc(VALUE klass) {
|
1179
1178
|
OneofDescriptor* self = ALLOC(OneofDescriptor);
|
1180
1179
|
VALUE ret = TypedData_Wrap_Struct(klass, &_OneofDescriptor_type, self);
|
1181
|
-
self->oneofdef =
|
1180
|
+
self->oneofdef = NULL;
|
1181
|
+
self->descriptor_pool = Qnil;
|
1182
1182
|
return ret;
|
1183
1183
|
}
|
1184
1184
|
|
@@ -1186,9 +1186,8 @@ void OneofDescriptor_register(VALUE module) {
|
|
1186
1186
|
VALUE klass = rb_define_class_under(
|
1187
1187
|
module, "OneofDescriptor", rb_cObject);
|
1188
1188
|
rb_define_alloc_func(klass, OneofDescriptor_alloc);
|
1189
|
+
rb_define_method(klass, "initialize", OneofDescriptor_initialize, 3);
|
1189
1190
|
rb_define_method(klass, "name", OneofDescriptor_name, 0);
|
1190
|
-
rb_define_method(klass, "name=", OneofDescriptor_name_set, 1);
|
1191
|
-
rb_define_method(klass, "add_field", OneofDescriptor_add_field, 1);
|
1192
1191
|
rb_define_method(klass, "each", OneofDescriptor_each, 0);
|
1193
1192
|
rb_include_module(klass, rb_mEnumerable);
|
1194
1193
|
rb_gc_register_address(&cOneofDescriptor);
|
@@ -1197,55 +1196,34 @@ void OneofDescriptor_register(VALUE module) {
|
|
1197
1196
|
|
1198
1197
|
/*
|
1199
1198
|
* call-seq:
|
1200
|
-
*
|
1199
|
+
* OneofDescriptor.new(c_only_cookie, pool, ptr) => OneofDescriptor
|
1201
1200
|
*
|
1202
|
-
*
|
1201
|
+
* Creates a descriptor wrapper object. May only be called from C.
|
1203
1202
|
*/
|
1204
|
-
VALUE
|
1203
|
+
VALUE OneofDescriptor_initialize(VALUE _self, VALUE cookie,
|
1204
|
+
VALUE descriptor_pool, VALUE ptr) {
|
1205
1205
|
DEFINE_SELF(OneofDescriptor, self, _self);
|
1206
|
-
return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef));
|
1207
|
-
}
|
1208
1206
|
|
1209
|
-
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
DEFINE_SELF(OneofDescriptor, self, _self);
|
1218
|
-
upb_oneofdef* mut_def = check_oneof_notfrozen(self->oneofdef);
|
1219
|
-
const char* str = get_str(value);
|
1220
|
-
CHECK_UPB(upb_oneofdef_setname(mut_def, str, &status),
|
1221
|
-
"Error setting oneof name");
|
1207
|
+
if (cookie != c_only_cookie) {
|
1208
|
+
rb_raise(rb_eRuntimeError,
|
1209
|
+
"Descriptor objects may not be created from Ruby.");
|
1210
|
+
}
|
1211
|
+
|
1212
|
+
self->descriptor_pool = descriptor_pool;
|
1213
|
+
self->oneofdef = (const upb_oneofdef*)NUM2ULL(ptr);
|
1214
|
+
|
1222
1215
|
return Qnil;
|
1223
1216
|
}
|
1224
1217
|
|
1225
1218
|
/*
|
1226
1219
|
* call-seq:
|
1227
|
-
* OneofDescriptor.
|
1228
|
-
*
|
1229
|
-
* Adds a field to this oneof. The field may have been added to this oneof in
|
1230
|
-
* the past, or the message to which this oneof belongs (if any), but may not
|
1231
|
-
* have already been added to any other oneof or message. Otherwise, an
|
1232
|
-
* exception is raised.
|
1220
|
+
* OneofDescriptor.name => name
|
1233
1221
|
*
|
1234
|
-
*
|
1235
|
-
* the message to which this oneof belongs, if it belongs to one currently, or
|
1236
|
-
* else will be added to any message to which the oneof is later added at the
|
1237
|
-
* time that it is added.
|
1222
|
+
* Returns the name of this oneof.
|
1238
1223
|
*/
|
1239
|
-
VALUE
|
1224
|
+
VALUE OneofDescriptor_name(VALUE _self) {
|
1240
1225
|
DEFINE_SELF(OneofDescriptor, self, _self);
|
1241
|
-
|
1242
|
-
FieldDescriptor* def = ruby_to_FieldDescriptor(obj);
|
1243
|
-
upb_fielddef* mut_field_def = check_field_notfrozen(def->fielddef);
|
1244
|
-
CHECK_UPB(
|
1245
|
-
upb_oneofdef_addfield(mut_def, mut_field_def, NULL, &status),
|
1246
|
-
"Adding field to OneofDescriptor failed");
|
1247
|
-
add_def_obj(def->fielddef, obj);
|
1248
|
-
return Qnil;
|
1226
|
+
return rb_str_maybe_null(upb_oneofdef_name(self->oneofdef));
|
1249
1227
|
}
|
1250
1228
|
|
1251
1229
|
/*
|
@@ -1254,14 +1232,14 @@ VALUE OneofDescriptor_add_field(VALUE _self, VALUE obj) {
|
|
1254
1232
|
*
|
1255
1233
|
* Iterates through fields in this oneof, yielding to the block on each one.
|
1256
1234
|
*/
|
1257
|
-
VALUE OneofDescriptor_each(VALUE _self
|
1235
|
+
VALUE OneofDescriptor_each(VALUE _self) {
|
1258
1236
|
DEFINE_SELF(OneofDescriptor, self, _self);
|
1259
1237
|
upb_oneof_iter it;
|
1260
1238
|
for (upb_oneof_begin(&it, self->oneofdef);
|
1261
1239
|
!upb_oneof_done(&it);
|
1262
1240
|
upb_oneof_next(&it)) {
|
1263
1241
|
const upb_fielddef* f = upb_oneof_iter_field(&it);
|
1264
|
-
VALUE obj =
|
1242
|
+
VALUE obj = get_fielddef_obj(self->descriptor_pool, f);
|
1265
1243
|
rb_yield(obj);
|
1266
1244
|
}
|
1267
1245
|
return Qnil;
|
@@ -1276,38 +1254,49 @@ DEFINE_CLASS(EnumDescriptor, "Google::Protobuf::EnumDescriptor");
|
|
1276
1254
|
void EnumDescriptor_mark(void* _self) {
|
1277
1255
|
EnumDescriptor* self = _self;
|
1278
1256
|
rb_gc_mark(self->module);
|
1257
|
+
rb_gc_mark(self->descriptor_pool);
|
1279
1258
|
}
|
1280
1259
|
|
1281
1260
|
void EnumDescriptor_free(void* _self) {
|
1282
|
-
|
1283
|
-
upb_enumdef_unref(self->enumdef, &self->enumdef);
|
1284
|
-
xfree(self);
|
1261
|
+
xfree(_self);
|
1285
1262
|
}
|
1286
1263
|
|
1287
|
-
/*
|
1288
|
-
* call-seq:
|
1289
|
-
* EnumDescriptor.new => enum_descriptor
|
1290
|
-
*
|
1291
|
-
* Creates a new, empty, enum descriptor. Must be added to a pool before the
|
1292
|
-
* enum type can be used. The enum type may only be modified prior to adding to
|
1293
|
-
* a pool.
|
1294
|
-
*/
|
1295
1264
|
VALUE EnumDescriptor_alloc(VALUE klass) {
|
1296
1265
|
EnumDescriptor* self = ALLOC(EnumDescriptor);
|
1297
1266
|
VALUE ret = TypedData_Wrap_Struct(klass, &_EnumDescriptor_type, self);
|
1298
|
-
self->enumdef =
|
1267
|
+
self->enumdef = NULL;
|
1299
1268
|
self->module = Qnil;
|
1269
|
+
self->descriptor_pool = Qnil;
|
1300
1270
|
return ret;
|
1301
1271
|
}
|
1302
1272
|
|
1273
|
+
/*
|
1274
|
+
* call-seq:
|
1275
|
+
* EnumDescriptor.new(c_only_cookie, ptr) => EnumDescriptor
|
1276
|
+
*
|
1277
|
+
* Creates a descriptor wrapper object. May only be called from C.
|
1278
|
+
*/
|
1279
|
+
VALUE EnumDescriptor_initialize(VALUE _self, VALUE cookie,
|
1280
|
+
VALUE descriptor_pool, VALUE ptr) {
|
1281
|
+
DEFINE_SELF(EnumDescriptor, self, _self);
|
1282
|
+
|
1283
|
+
if (cookie != c_only_cookie) {
|
1284
|
+
rb_raise(rb_eRuntimeError,
|
1285
|
+
"Descriptor objects may not be created from Ruby.");
|
1286
|
+
}
|
1287
|
+
|
1288
|
+
self->descriptor_pool = descriptor_pool;
|
1289
|
+
self->enumdef = (const upb_enumdef*)NUM2ULL(ptr);
|
1290
|
+
|
1291
|
+
return Qnil;
|
1292
|
+
}
|
1293
|
+
|
1303
1294
|
void EnumDescriptor_register(VALUE module) {
|
1304
1295
|
VALUE klass = rb_define_class_under(
|
1305
1296
|
module, "EnumDescriptor", rb_cObject);
|
1306
1297
|
rb_define_alloc_func(klass, EnumDescriptor_alloc);
|
1307
|
-
rb_define_method(klass, "initialize", EnumDescriptor_initialize,
|
1298
|
+
rb_define_method(klass, "initialize", EnumDescriptor_initialize, 3);
|
1308
1299
|
rb_define_method(klass, "name", EnumDescriptor_name, 0);
|
1309
|
-
rb_define_method(klass, "name=", EnumDescriptor_name_set, 1);
|
1310
|
-
rb_define_method(klass, "add_value", EnumDescriptor_add_value, 2);
|
1311
1300
|
rb_define_method(klass, "lookup_name", EnumDescriptor_lookup_name, 1);
|
1312
1301
|
rb_define_method(klass, "lookup_value", EnumDescriptor_lookup_value, 1);
|
1313
1302
|
rb_define_method(klass, "each", EnumDescriptor_each, 0);
|
@@ -1320,31 +1309,14 @@ void EnumDescriptor_register(VALUE module) {
|
|
1320
1309
|
|
1321
1310
|
/*
|
1322
1311
|
* call-seq:
|
1323
|
-
*
|
1324
|
-
*
|
1325
|
-
* Initializes a new descriptor and assigns a file descriptor to it.
|
1326
|
-
*/
|
1327
|
-
VALUE EnumDescriptor_initialize(VALUE _self, VALUE file_descriptor_rb) {
|
1328
|
-
DEFINE_SELF(EnumDescriptor, self, _self);
|
1329
|
-
FileDescriptor* file_descriptor = ruby_to_FileDescriptor(file_descriptor_rb);
|
1330
|
-
CHECK_UPB(
|
1331
|
-
upb_filedef_addenum(file_descriptor->filedef, self->enumdef,
|
1332
|
-
NULL, &status),
|
1333
|
-
"Failed to associate enum to file descriptor.");
|
1334
|
-
add_def_obj(file_descriptor->filedef, file_descriptor_rb);
|
1335
|
-
|
1336
|
-
return Qnil;
|
1337
|
-
}
|
1338
|
-
|
1339
|
-
/*
|
1340
|
-
* call-seq:
|
1341
|
-
* Descriptor.file_descriptor
|
1312
|
+
* EnumDescriptor.file_descriptor
|
1342
1313
|
*
|
1343
1314
|
* Returns the FileDescriptor object this enum belongs to.
|
1344
1315
|
*/
|
1345
1316
|
VALUE EnumDescriptor_file_descriptor(VALUE _self) {
|
1346
1317
|
DEFINE_SELF(EnumDescriptor, self, _self);
|
1347
|
-
return
|
1318
|
+
return get_filedef_obj(self->descriptor_pool,
|
1319
|
+
upb_enumdef_file(self->enumdef));
|
1348
1320
|
}
|
1349
1321
|
|
1350
1322
|
/*
|
@@ -1358,40 +1330,6 @@ VALUE EnumDescriptor_name(VALUE _self) {
|
|
1358
1330
|
return rb_str_maybe_null(upb_enumdef_fullname(self->enumdef));
|
1359
1331
|
}
|
1360
1332
|
|
1361
|
-
/*
|
1362
|
-
* call-seq:
|
1363
|
-
* EnumDescriptor.name = name
|
1364
|
-
*
|
1365
|
-
* Sets the name of this enum type. Cannot be called if the enum type has
|
1366
|
-
* already been added to a pool.
|
1367
|
-
*/
|
1368
|
-
VALUE EnumDescriptor_name_set(VALUE _self, VALUE str) {
|
1369
|
-
DEFINE_SELF(EnumDescriptor, self, _self);
|
1370
|
-
upb_enumdef* mut_def = check_enum_notfrozen(self->enumdef);
|
1371
|
-
const char* name = get_str(str);
|
1372
|
-
CHECK_UPB(upb_enumdef_setfullname(mut_def, name, &status),
|
1373
|
-
"Error setting EnumDescriptor name");
|
1374
|
-
return Qnil;
|
1375
|
-
}
|
1376
|
-
|
1377
|
-
/*
|
1378
|
-
* call-seq:
|
1379
|
-
* EnumDescriptor.add_value(key, value)
|
1380
|
-
*
|
1381
|
-
* Adds a new key => value mapping to this enum type. Key must be given as a
|
1382
|
-
* Ruby symbol. Cannot be called if the enum type has already been added to a
|
1383
|
-
* pool. Will raise an exception if the key or value is already in use.
|
1384
|
-
*/
|
1385
|
-
VALUE EnumDescriptor_add_value(VALUE _self, VALUE name, VALUE number) {
|
1386
|
-
DEFINE_SELF(EnumDescriptor, self, _self);
|
1387
|
-
upb_enumdef* mut_def = check_enum_notfrozen(self->enumdef);
|
1388
|
-
const char* name_str = rb_id2name(SYM2ID(name));
|
1389
|
-
int32_t val = NUM2INT(number);
|
1390
|
-
CHECK_UPB(upb_enumdef_addval(mut_def, name_str, val, &status),
|
1391
|
-
"Error adding value to enum");
|
1392
|
-
return Qnil;
|
1393
|
-
}
|
1394
|
-
|
1395
1333
|
/*
|
1396
1334
|
* call-seq:
|
1397
1335
|
* EnumDescriptor.lookup_name(name) => value
|
@@ -1454,18 +1392,12 @@ VALUE EnumDescriptor_each(VALUE _self) {
|
|
1454
1392
|
* call-seq:
|
1455
1393
|
* EnumDescriptor.enummodule => module
|
1456
1394
|
*
|
1457
|
-
* Returns the Ruby module corresponding to this enum type.
|
1458
|
-
* until the enum descriptor has been added to a pool.
|
1395
|
+
* Returns the Ruby module corresponding to this enum type.
|
1459
1396
|
*/
|
1460
1397
|
VALUE EnumDescriptor_enummodule(VALUE _self) {
|
1461
1398
|
DEFINE_SELF(EnumDescriptor, self, _self);
|
1462
|
-
if (!upb_def_isfrozen((const upb_def*)self->enumdef)) {
|
1463
|
-
rb_raise(rb_eRuntimeError,
|
1464
|
-
"Cannot fetch enum module from an EnumDescriptor not yet "
|
1465
|
-
"in a pool.");
|
1466
|
-
}
|
1467
1399
|
if (self->module == Qnil) {
|
1468
|
-
self->module = build_module_from_enumdesc(
|
1400
|
+
self->module = build_module_from_enumdesc(_self);
|
1469
1401
|
}
|
1470
1402
|
return self->module;
|
1471
1403
|
}
|
@@ -1479,8 +1411,7 @@ DEFINE_CLASS(MessageBuilderContext,
|
|
1479
1411
|
|
1480
1412
|
void MessageBuilderContext_mark(void* _self) {
|
1481
1413
|
MessageBuilderContext* self = _self;
|
1482
|
-
rb_gc_mark(self->
|
1483
|
-
rb_gc_mark(self->builder);
|
1414
|
+
rb_gc_mark(self->file_builder);
|
1484
1415
|
}
|
1485
1416
|
|
1486
1417
|
void MessageBuilderContext_free(void* _self) {
|
@@ -1492,8 +1423,7 @@ VALUE MessageBuilderContext_alloc(VALUE klass) {
|
|
1492
1423
|
MessageBuilderContext* self = ALLOC(MessageBuilderContext);
|
1493
1424
|
VALUE ret = TypedData_Wrap_Struct(
|
1494
1425
|
klass, &_MessageBuilderContext_type, self);
|
1495
|
-
self->
|
1496
|
-
self->builder = Qnil;
|
1426
|
+
self->file_builder = Qnil;
|
1497
1427
|
return ret;
|
1498
1428
|
}
|
1499
1429
|
|
@@ -1504,6 +1434,7 @@ void MessageBuilderContext_register(VALUE module) {
|
|
1504
1434
|
rb_define_method(klass, "initialize",
|
1505
1435
|
MessageBuilderContext_initialize, 2);
|
1506
1436
|
rb_define_method(klass, "optional", MessageBuilderContext_optional, -1);
|
1437
|
+
rb_define_method(klass, "proto3_optional", MessageBuilderContext_proto3_optional, -1);
|
1507
1438
|
rb_define_method(klass, "required", MessageBuilderContext_required, -1);
|
1508
1439
|
rb_define_method(klass, "repeated", MessageBuilderContext_repeated, -1);
|
1509
1440
|
rb_define_method(klass, "map", MessageBuilderContext_map, -1);
|
@@ -1514,65 +1445,115 @@ void MessageBuilderContext_register(VALUE module) {
|
|
1514
1445
|
|
1515
1446
|
/*
|
1516
1447
|
* call-seq:
|
1517
|
-
* MessageBuilderContext.new(
|
1448
|
+
* MessageBuilderContext.new(file_builder, name) => context
|
1518
1449
|
*
|
1519
1450
|
* Create a new message builder context around the given message descriptor and
|
1520
1451
|
* builder context. This class is intended to serve as a DSL context to be used
|
1521
1452
|
* with #instance_eval.
|
1522
1453
|
*/
|
1523
1454
|
VALUE MessageBuilderContext_initialize(VALUE _self,
|
1524
|
-
VALUE
|
1525
|
-
VALUE
|
1455
|
+
VALUE _file_builder,
|
1456
|
+
VALUE name) {
|
1526
1457
|
DEFINE_SELF(MessageBuilderContext, self, _self);
|
1527
|
-
|
1528
|
-
|
1458
|
+
FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder);
|
1459
|
+
google_protobuf_FileDescriptorProto* file_proto = file_builder->file_proto;
|
1460
|
+
|
1461
|
+
self->file_builder = _file_builder;
|
1462
|
+
self->msg_proto = google_protobuf_FileDescriptorProto_add_message_type(
|
1463
|
+
file_proto, file_builder->arena);
|
1464
|
+
|
1465
|
+
google_protobuf_DescriptorProto_set_name(
|
1466
|
+
self->msg_proto, FileBuilderContext_strdup(_file_builder, name));
|
1467
|
+
|
1529
1468
|
return Qnil;
|
1530
1469
|
}
|
1531
1470
|
|
1532
|
-
static
|
1533
|
-
|
1534
|
-
|
1535
|
-
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1471
|
+
static void msgdef_add_field(VALUE msgbuilder_rb, upb_label_t label, VALUE name,
|
1472
|
+
VALUE type, VALUE number, VALUE type_class,
|
1473
|
+
VALUE options, int oneof_index,
|
1474
|
+
bool proto3_optional) {
|
1475
|
+
DEFINE_SELF(MessageBuilderContext, self, msgbuilder_rb);
|
1476
|
+
FileBuilderContext* file_context =
|
1477
|
+
ruby_to_FileBuilderContext(self->file_builder);
|
1478
|
+
google_protobuf_FieldDescriptorProto* field_proto;
|
1479
|
+
VALUE name_str;
|
1480
|
+
|
1481
|
+
field_proto = google_protobuf_DescriptorProto_add_field(self->msg_proto,
|
1482
|
+
file_context->arena);
|
1539
1483
|
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1543
|
-
|
1484
|
+
Check_Type(name, T_SYMBOL);
|
1485
|
+
name_str = rb_id2str(SYM2ID(name));
|
1486
|
+
|
1487
|
+
google_protobuf_FieldDescriptorProto_set_name(
|
1488
|
+
field_proto, FileBuilderContext_strdup(self->file_builder, name_str));
|
1489
|
+
google_protobuf_FieldDescriptorProto_set_number(field_proto, NUM2INT(number));
|
1490
|
+
google_protobuf_FieldDescriptorProto_set_label(field_proto, (int)label);
|
1491
|
+
google_protobuf_FieldDescriptorProto_set_type(
|
1492
|
+
field_proto, (int)ruby_to_descriptortype(type));
|
1493
|
+
|
1494
|
+
if (proto3_optional) {
|
1495
|
+
google_protobuf_FieldDescriptorProto_set_proto3_optional(field_proto, true);
|
1496
|
+
}
|
1544
1497
|
|
1545
1498
|
if (type_class != Qnil) {
|
1546
1499
|
Check_Type(type_class, T_STRING);
|
1547
1500
|
|
1548
1501
|
// Make it an absolute type name by prepending a dot.
|
1549
1502
|
type_class = rb_str_append(rb_str_new2("."), type_class);
|
1550
|
-
|
1503
|
+
google_protobuf_FieldDescriptorProto_set_type_name(
|
1504
|
+
field_proto, FileBuilderContext_strdup(self->file_builder, type_class));
|
1551
1505
|
}
|
1552
1506
|
|
1553
1507
|
if (options != Qnil) {
|
1554
1508
|
Check_Type(options, T_HASH);
|
1555
1509
|
|
1556
1510
|
if (rb_funcall(options, rb_intern("key?"), 1,
|
1557
|
-
|
1558
|
-
|
1559
|
-
|
1560
|
-
rb_raise(rb_eArgError, "Cannot set :default when using proto3 syntax.");
|
1561
|
-
}
|
1511
|
+
ID2SYM(rb_intern("default"))) == Qtrue) {
|
1512
|
+
VALUE default_value =
|
1513
|
+
rb_hash_lookup(options, ID2SYM(rb_intern("default")));
|
1562
1514
|
|
1563
|
-
|
1564
|
-
|
1565
|
-
upb_fielddef_issubmsg((upb_fielddef*)fielddef->fielddef)) {
|
1566
|
-
rb_raise(rb_eArgError, "Cannot set :default on this kind of field.");
|
1567
|
-
}
|
1515
|
+
/* Call #to_s since all defaults are strings in the descriptor. */
|
1516
|
+
default_value = rb_funcall(default_value, rb_intern("to_s"), 0);
|
1568
1517
|
|
1569
|
-
|
1570
|
-
|
1518
|
+
google_protobuf_FieldDescriptorProto_set_default_value(
|
1519
|
+
field_proto,
|
1520
|
+
FileBuilderContext_strdup(self->file_builder, default_value));
|
1571
1521
|
}
|
1572
1522
|
}
|
1573
1523
|
|
1574
|
-
|
1575
|
-
|
1524
|
+
if (oneof_index >= 0) {
|
1525
|
+
google_protobuf_FieldDescriptorProto_set_oneof_index(field_proto,
|
1526
|
+
oneof_index);
|
1527
|
+
}
|
1528
|
+
}
|
1529
|
+
|
1530
|
+
static VALUE make_mapentry(VALUE _message_builder, VALUE types, int argc,
|
1531
|
+
VALUE* argv) {
|
1532
|
+
DEFINE_SELF(MessageBuilderContext, message_builder, _message_builder);
|
1533
|
+
VALUE type_class = rb_ary_entry(types, 2);
|
1534
|
+
FileBuilderContext* file_context =
|
1535
|
+
ruby_to_FileBuilderContext(message_builder->file_builder);
|
1536
|
+
google_protobuf_MessageOptions* options =
|
1537
|
+
google_protobuf_DescriptorProto_mutable_options(
|
1538
|
+
message_builder->msg_proto, file_context->arena);
|
1539
|
+
|
1540
|
+
google_protobuf_MessageOptions_set_map_entry(options, true);
|
1541
|
+
|
1542
|
+
// optional <type> key = 1;
|
1543
|
+
rb_funcall(_message_builder, rb_intern("optional"), 3,
|
1544
|
+
ID2SYM(rb_intern("key")), rb_ary_entry(types, 0), INT2NUM(1));
|
1545
|
+
|
1546
|
+
// optional <type> value = 2;
|
1547
|
+
if (type_class == Qnil) {
|
1548
|
+
rb_funcall(_message_builder, rb_intern("optional"), 3,
|
1549
|
+
ID2SYM(rb_intern("value")), rb_ary_entry(types, 1), INT2NUM(2));
|
1550
|
+
} else {
|
1551
|
+
rb_funcall(_message_builder, rb_intern("optional"), 4,
|
1552
|
+
ID2SYM(rb_intern("value")), rb_ary_entry(types, 1), INT2NUM(2),
|
1553
|
+
type_class);
|
1554
|
+
}
|
1555
|
+
|
1556
|
+
return Qnil;
|
1576
1557
|
}
|
1577
1558
|
|
1578
1559
|
/*
|
@@ -1586,7 +1567,6 @@ static VALUE msgdef_add_field(VALUE msgdef_rb,
|
|
1586
1567
|
* string, if present (as accepted by FieldDescriptor#submsg_name=).
|
1587
1568
|
*/
|
1588
1569
|
VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
|
1589
|
-
DEFINE_SELF(MessageBuilderContext, self, _self);
|
1590
1570
|
VALUE name, type, number;
|
1591
1571
|
VALUE type_class, options = Qnil;
|
1592
1572
|
|
@@ -1599,8 +1579,41 @@ VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
|
|
1599
1579
|
type_class = Qnil;
|
1600
1580
|
}
|
1601
1581
|
|
1602
|
-
|
1603
|
-
|
1582
|
+
msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class,
|
1583
|
+
options, -1, false);
|
1584
|
+
|
1585
|
+
return Qnil;
|
1586
|
+
}
|
1587
|
+
|
1588
|
+
/*
|
1589
|
+
* call-seq:
|
1590
|
+
* MessageBuilderContext.proto3_optional(name, type, number,
|
1591
|
+
* type_class = nil, options = nil)
|
1592
|
+
*
|
1593
|
+
* Defines a true proto3 optional field (that tracks presence) on this message
|
1594
|
+
* type with the given type, tag number, and type class (for message and enum
|
1595
|
+
* fields). The type must be a Ruby symbol (as accepted by
|
1596
|
+
* FieldDescriptor#type=) and the type_class must be a string, if present (as
|
1597
|
+
* accepted by FieldDescriptor#submsg_name=).
|
1598
|
+
*/
|
1599
|
+
VALUE MessageBuilderContext_proto3_optional(int argc, VALUE* argv,
|
1600
|
+
VALUE _self) {
|
1601
|
+
VALUE name, type, number;
|
1602
|
+
VALUE type_class, options = Qnil;
|
1603
|
+
|
1604
|
+
rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
|
1605
|
+
|
1606
|
+
// Allow passing (name, type, number, options) or
|
1607
|
+
// (name, type, number, type_class, options)
|
1608
|
+
if (argc == 4 && RB_TYPE_P(type_class, T_HASH)) {
|
1609
|
+
options = type_class;
|
1610
|
+
type_class = Qnil;
|
1611
|
+
}
|
1612
|
+
|
1613
|
+
msgdef_add_field(_self, UPB_LABEL_OPTIONAL, name, type, number, type_class,
|
1614
|
+
options, -1, true);
|
1615
|
+
|
1616
|
+
return Qnil;
|
1604
1617
|
}
|
1605
1618
|
|
1606
1619
|
/*
|
@@ -1618,7 +1631,6 @@ VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
|
|
1618
1631
|
* pool will currently result in an error.
|
1619
1632
|
*/
|
1620
1633
|
VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) {
|
1621
|
-
DEFINE_SELF(MessageBuilderContext, self, _self);
|
1622
1634
|
VALUE name, type, number;
|
1623
1635
|
VALUE type_class, options = Qnil;
|
1624
1636
|
|
@@ -1631,8 +1643,10 @@ VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) {
|
|
1631
1643
|
type_class = Qnil;
|
1632
1644
|
}
|
1633
1645
|
|
1634
|
-
|
1635
|
-
|
1646
|
+
msgdef_add_field(_self, UPB_LABEL_REQUIRED, name, type, number, type_class,
|
1647
|
+
options, -1, false);
|
1648
|
+
|
1649
|
+
return Qnil;
|
1636
1650
|
}
|
1637
1651
|
|
1638
1652
|
/*
|
@@ -1645,7 +1659,6 @@ VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self) {
|
|
1645
1659
|
* string, if present (as accepted by FieldDescriptor#submsg_name=).
|
1646
1660
|
*/
|
1647
1661
|
VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) {
|
1648
|
-
DEFINE_SELF(MessageBuilderContext, self, _self);
|
1649
1662
|
VALUE name, type, number, type_class;
|
1650
1663
|
|
1651
1664
|
if (argc < 3) {
|
@@ -1656,8 +1669,10 @@ VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) {
|
|
1656
1669
|
number = argv[2];
|
1657
1670
|
type_class = (argc > 3) ? argv[3] : Qnil;
|
1658
1671
|
|
1659
|
-
|
1660
|
-
|
1672
|
+
msgdef_add_field(_self, UPB_LABEL_REPEATED, name, type, number, type_class,
|
1673
|
+
Qnil, -1, false);
|
1674
|
+
|
1675
|
+
return Qnil;
|
1661
1676
|
}
|
1662
1677
|
|
1663
1678
|
/*
|
@@ -1675,7 +1690,9 @@ VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self) {
|
|
1675
1690
|
VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
|
1676
1691
|
DEFINE_SELF(MessageBuilderContext, self, _self);
|
1677
1692
|
VALUE name, key_type, value_type, number, type_class;
|
1678
|
-
VALUE
|
1693
|
+
VALUE mapentry_desc_name;
|
1694
|
+
FileBuilderContext* file_builder;
|
1695
|
+
upb_strview msg_name;
|
1679
1696
|
|
1680
1697
|
if (argc < 4) {
|
1681
1698
|
rb_raise(rb_eArgError, "Expected at least 4 arguments.");
|
@@ -1698,77 +1715,44 @@ VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
|
|
1698
1715
|
"type.");
|
1699
1716
|
}
|
1700
1717
|
|
1701
|
-
|
1702
|
-
|
1718
|
+
file_builder = ruby_to_FileBuilderContext(self->file_builder);
|
1719
|
+
|
1720
|
+
// TODO(haberman): remove this restriction, maps are supported in proto2.
|
1721
|
+
if (upb_strview_eql(
|
1722
|
+
google_protobuf_FileDescriptorProto_syntax(file_builder->file_proto),
|
1723
|
+
upb_strview_makez("proto2"))) {
|
1703
1724
|
rb_raise(rb_eArgError,
|
1704
|
-
|
1725
|
+
"Cannot add a native map field using proto2 syntax.");
|
1705
1726
|
}
|
1706
1727
|
|
1707
1728
|
// Create a new message descriptor for the map entry message, and create a
|
1708
1729
|
// repeated submessage field here with that type.
|
1709
|
-
|
1710
|
-
|
1711
|
-
mapentry_desc = rb_class_new_instance(1, &file_descriptor_rb, cDescriptor);
|
1712
|
-
mapentry_desc_name = rb_funcall(self->descriptor, rb_intern("name"), 0);
|
1730
|
+
msg_name = google_protobuf_DescriptorProto_name(self->msg_proto);
|
1731
|
+
mapentry_desc_name = rb_str_new(msg_name.data, msg_name.size);
|
1713
1732
|
mapentry_desc_name = rb_str_cat2(mapentry_desc_name, "_MapEntry_");
|
1714
|
-
mapentry_desc_name =
|
1715
|
-
|
1716
|
-
Descriptor_name_set(mapentry_desc, mapentry_desc_name);
|
1717
|
-
|
1718
|
-
{
|
1719
|
-
// The 'mapentry' attribute has no Ruby setter because we do not want the
|
1720
|
-
// user attempting to DIY the setup below; we want to ensure that the fields
|
1721
|
-
// are correct. So we reach into the msgdef here to set the bit manually.
|
1722
|
-
Descriptor* mapentry_desc_self = ruby_to_Descriptor(mapentry_desc);
|
1723
|
-
upb_msgdef_setmapentry((upb_msgdef*)mapentry_desc_self->msgdef, true);
|
1724
|
-
}
|
1733
|
+
mapentry_desc_name =
|
1734
|
+
rb_str_cat2(mapentry_desc_name, rb_id2name(SYM2ID(name)));
|
1725
1735
|
|
1726
1736
|
{
|
1727
|
-
//
|
1728
|
-
VALUE
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
1732
|
-
FieldDescriptor_type_set(key_field, key_type);
|
1733
|
-
Descriptor_add_field(mapentry_desc, key_field);
|
1734
|
-
}
|
1735
|
-
|
1736
|
-
{
|
1737
|
-
// optional <type> value = 2;
|
1738
|
-
VALUE value_field = rb_class_new_instance(0, NULL, cFieldDescriptor);
|
1739
|
-
FieldDescriptor_name_set(value_field, rb_str_new2("value"));
|
1740
|
-
FieldDescriptor_label_set(value_field, ID2SYM(rb_intern("optional")));
|
1741
|
-
FieldDescriptor_number_set(value_field, INT2NUM(2));
|
1742
|
-
FieldDescriptor_type_set(value_field, value_type);
|
1743
|
-
if (type_class != Qnil) {
|
1744
|
-
VALUE submsg_name = rb_str_new2("."); // prepend '.' to make absolute.
|
1745
|
-
submsg_name = rb_str_append(submsg_name, type_class);
|
1746
|
-
FieldDescriptor_submsg_name_set(value_field, submsg_name);
|
1747
|
-
}
|
1748
|
-
Descriptor_add_field(mapentry_desc, value_field);
|
1737
|
+
// message <msgname>_MapEntry_ { /* ... */ }
|
1738
|
+
VALUE args[1] = {mapentry_desc_name};
|
1739
|
+
VALUE types = rb_ary_new3(3, key_type, value_type, type_class);
|
1740
|
+
rb_block_call(self->file_builder, rb_intern("add_message"), 1, args,
|
1741
|
+
make_mapentry, types);
|
1749
1742
|
}
|
1750
1743
|
|
1751
|
-
|
1752
|
-
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
1744
|
+
// If this file is in a package, we need to qualify the map entry type.
|
1745
|
+
if (google_protobuf_FileDescriptorProto_has_package(file_builder->file_proto)) {
|
1746
|
+
upb_strview package_view =
|
1747
|
+
google_protobuf_FileDescriptorProto_package(file_builder->file_proto);
|
1748
|
+
VALUE package = rb_str_new(package_view.data, package_view.size);
|
1749
|
+
package = rb_str_cat2(package, ".");
|
1750
|
+
mapentry_desc_name = rb_str_concat(package, mapentry_desc_name);
|
1756
1751
|
}
|
1757
1752
|
|
1758
|
-
|
1759
|
-
|
1760
|
-
|
1761
|
-
VALUE submsg_name;
|
1762
|
-
|
1763
|
-
FieldDescriptor_name_set(map_field, name_str);
|
1764
|
-
FieldDescriptor_number_set(map_field, number);
|
1765
|
-
FieldDescriptor_label_set(map_field, ID2SYM(rb_intern("repeated")));
|
1766
|
-
FieldDescriptor_type_set(map_field, ID2SYM(rb_intern("message")));
|
1767
|
-
submsg_name = rb_str_new2("."); // prepend '.' to make name absolute.
|
1768
|
-
submsg_name = rb_str_append(submsg_name, mapentry_desc_name);
|
1769
|
-
FieldDescriptor_submsg_name_set(map_field, submsg_name);
|
1770
|
-
Descriptor_add_field(self->descriptor, map_field);
|
1771
|
-
}
|
1753
|
+
// repeated MapEntry <name> = <number>;
|
1754
|
+
rb_funcall(_self, rb_intern("repeated"), 4, name,
|
1755
|
+
ID2SYM(rb_intern("message")), number, mapentry_desc_name);
|
1772
1756
|
|
1773
1757
|
return Qnil;
|
1774
1758
|
}
|
@@ -1786,18 +1770,81 @@ VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self) {
|
|
1786
1770
|
*/
|
1787
1771
|
VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name) {
|
1788
1772
|
DEFINE_SELF(MessageBuilderContext, self, _self);
|
1789
|
-
|
1790
|
-
|
1791
|
-
|
1792
|
-
|
1793
|
-
|
1794
|
-
|
1795
|
-
|
1796
|
-
|
1773
|
+
size_t oneof_count;
|
1774
|
+
FileBuilderContext* file_context =
|
1775
|
+
ruby_to_FileBuilderContext(self->file_builder);
|
1776
|
+
google_protobuf_OneofDescriptorProto* oneof_proto;
|
1777
|
+
|
1778
|
+
// Existing oneof_count becomes oneof_index.
|
1779
|
+
google_protobuf_DescriptorProto_oneof_decl(self->msg_proto, &oneof_count);
|
1780
|
+
|
1781
|
+
// Create oneof_proto and set its name.
|
1782
|
+
oneof_proto = google_protobuf_DescriptorProto_add_oneof_decl(
|
1783
|
+
self->msg_proto, file_context->arena);
|
1784
|
+
google_protobuf_OneofDescriptorProto_set_name(
|
1785
|
+
oneof_proto, FileBuilderContext_strdup_sym(self->file_builder, name));
|
1786
|
+
|
1787
|
+
// Evaluate the block with the builder as argument.
|
1788
|
+
{
|
1789
|
+
VALUE args[2] = { INT2NUM(oneof_count), _self };
|
1790
|
+
VALUE ctx = rb_class_new_instance(2, args, cOneofBuilderContext);
|
1791
|
+
VALUE block = rb_block_proc();
|
1792
|
+
rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
|
1793
|
+
}
|
1797
1794
|
|
1798
1795
|
return Qnil;
|
1799
1796
|
}
|
1800
1797
|
|
1798
|
+
void MessageBuilderContext_add_synthetic_oneofs(VALUE _self) {
|
1799
|
+
DEFINE_SELF(MessageBuilderContext, self, _self);
|
1800
|
+
FileBuilderContext* file_context =
|
1801
|
+
ruby_to_FileBuilderContext(self->file_builder);
|
1802
|
+
size_t field_count, oneof_count;
|
1803
|
+
google_protobuf_FieldDescriptorProto** fields =
|
1804
|
+
google_protobuf_DescriptorProto_mutable_field(self->msg_proto, &field_count);
|
1805
|
+
const google_protobuf_OneofDescriptorProto*const* oneofs =
|
1806
|
+
google_protobuf_DescriptorProto_oneof_decl(self->msg_proto, &oneof_count);
|
1807
|
+
VALUE names = rb_hash_new();
|
1808
|
+
VALUE underscore = rb_str_new2("_");
|
1809
|
+
size_t i;
|
1810
|
+
|
1811
|
+
// We have to build a set of all names, to ensure that synthetic oneofs are
|
1812
|
+
// not creating conflicts.
|
1813
|
+
for (i = 0; i < field_count; i++) {
|
1814
|
+
upb_strview name = google_protobuf_FieldDescriptorProto_name(fields[i]);
|
1815
|
+
rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue);
|
1816
|
+
}
|
1817
|
+
for (i = 0; i < oneof_count; i++) {
|
1818
|
+
upb_strview name = google_protobuf_OneofDescriptorProto_name(oneofs[i]);
|
1819
|
+
rb_hash_aset(names, rb_str_new(name.data, name.size), Qtrue);
|
1820
|
+
}
|
1821
|
+
|
1822
|
+
for (i = 0; i < field_count; i++) {
|
1823
|
+
google_protobuf_OneofDescriptorProto* oneof_proto;
|
1824
|
+
VALUE oneof_name;
|
1825
|
+
upb_strview field_name;
|
1826
|
+
|
1827
|
+
if (!google_protobuf_FieldDescriptorProto_proto3_optional(fields[i])) {
|
1828
|
+
continue;
|
1829
|
+
}
|
1830
|
+
|
1831
|
+
// Prepend '_' until we are no longer conflicting.
|
1832
|
+
field_name = google_protobuf_FieldDescriptorProto_name(fields[i]);
|
1833
|
+
oneof_name = rb_str_new(field_name.data, field_name.size);
|
1834
|
+
while (rb_hash_lookup(names, oneof_name) != Qnil) {
|
1835
|
+
oneof_name = rb_str_plus(underscore, oneof_name);
|
1836
|
+
}
|
1837
|
+
|
1838
|
+
rb_hash_aset(names, oneof_name, Qtrue);
|
1839
|
+
google_protobuf_FieldDescriptorProto_set_oneof_index(fields[i],
|
1840
|
+
oneof_count++);
|
1841
|
+
oneof_proto = google_protobuf_DescriptorProto_add_oneof_decl(
|
1842
|
+
self->msg_proto, file_context->arena);
|
1843
|
+
google_protobuf_OneofDescriptorProto_set_name(
|
1844
|
+
oneof_proto, FileBuilderContext_strdup(self->file_builder, oneof_name));
|
1845
|
+
}
|
1846
|
+
}
|
1847
|
+
|
1801
1848
|
// -----------------------------------------------------------------------------
|
1802
1849
|
// OneofBuilderContext.
|
1803
1850
|
// -----------------------------------------------------------------------------
|
@@ -1807,21 +1854,19 @@ DEFINE_CLASS(OneofBuilderContext,
|
|
1807
1854
|
|
1808
1855
|
void OneofBuilderContext_mark(void* _self) {
|
1809
1856
|
OneofBuilderContext* self = _self;
|
1810
|
-
rb_gc_mark(self->
|
1811
|
-
rb_gc_mark(self->builder);
|
1857
|
+
rb_gc_mark(self->message_builder);
|
1812
1858
|
}
|
1813
1859
|
|
1814
1860
|
void OneofBuilderContext_free(void* _self) {
|
1815
|
-
|
1816
|
-
xfree(self);
|
1861
|
+
xfree(_self);
|
1817
1862
|
}
|
1818
1863
|
|
1819
1864
|
VALUE OneofBuilderContext_alloc(VALUE klass) {
|
1820
1865
|
OneofBuilderContext* self = ALLOC(OneofBuilderContext);
|
1821
1866
|
VALUE ret = TypedData_Wrap_Struct(
|
1822
1867
|
klass, &_OneofBuilderContext_type, self);
|
1823
|
-
self->
|
1824
|
-
self->
|
1868
|
+
self->oneof_index = 0;
|
1869
|
+
self->message_builder = Qnil;
|
1825
1870
|
return ret;
|
1826
1871
|
}
|
1827
1872
|
|
@@ -1838,18 +1883,18 @@ void OneofBuilderContext_register(VALUE module) {
|
|
1838
1883
|
|
1839
1884
|
/*
|
1840
1885
|
* call-seq:
|
1841
|
-
* OneofBuilderContext.new(
|
1886
|
+
* OneofBuilderContext.new(oneof_index, message_builder) => context
|
1842
1887
|
*
|
1843
1888
|
* Create a new oneof builder context around the given oneof descriptor and
|
1844
1889
|
* builder context. This class is intended to serve as a DSL context to be used
|
1845
1890
|
* with #instance_eval.
|
1846
1891
|
*/
|
1847
1892
|
VALUE OneofBuilderContext_initialize(VALUE _self,
|
1848
|
-
VALUE
|
1849
|
-
VALUE
|
1893
|
+
VALUE oneof_index,
|
1894
|
+
VALUE message_builder) {
|
1850
1895
|
DEFINE_SELF(OneofBuilderContext, self, _self);
|
1851
|
-
self->
|
1852
|
-
self->
|
1896
|
+
self->oneof_index = NUM2INT(oneof_index);
|
1897
|
+
self->message_builder = message_builder;
|
1853
1898
|
return Qnil;
|
1854
1899
|
}
|
1855
1900
|
|
@@ -1870,8 +1915,10 @@ VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self) {
|
|
1870
1915
|
|
1871
1916
|
rb_scan_args(argc, argv, "32", &name, &type, &number, &type_class, &options);
|
1872
1917
|
|
1873
|
-
|
1874
|
-
|
1918
|
+
msgdef_add_field(self->message_builder, UPB_LABEL_OPTIONAL, name, type,
|
1919
|
+
number, type_class, options, self->oneof_index, false);
|
1920
|
+
|
1921
|
+
return Qnil;
|
1875
1922
|
}
|
1876
1923
|
|
1877
1924
|
// -----------------------------------------------------------------------------
|
@@ -1883,19 +1930,19 @@ DEFINE_CLASS(EnumBuilderContext,
|
|
1883
1930
|
|
1884
1931
|
void EnumBuilderContext_mark(void* _self) {
|
1885
1932
|
EnumBuilderContext* self = _self;
|
1886
|
-
rb_gc_mark(self->
|
1933
|
+
rb_gc_mark(self->file_builder);
|
1887
1934
|
}
|
1888
1935
|
|
1889
1936
|
void EnumBuilderContext_free(void* _self) {
|
1890
|
-
|
1891
|
-
xfree(self);
|
1937
|
+
xfree(_self);
|
1892
1938
|
}
|
1893
1939
|
|
1894
1940
|
VALUE EnumBuilderContext_alloc(VALUE klass) {
|
1895
1941
|
EnumBuilderContext* self = ALLOC(EnumBuilderContext);
|
1896
1942
|
VALUE ret = TypedData_Wrap_Struct(
|
1897
1943
|
klass, &_EnumBuilderContext_type, self);
|
1898
|
-
self->
|
1944
|
+
self->enum_proto = NULL;
|
1945
|
+
self->file_builder = Qnil;
|
1899
1946
|
return ret;
|
1900
1947
|
}
|
1901
1948
|
|
@@ -1903,8 +1950,7 @@ void EnumBuilderContext_register(VALUE module) {
|
|
1903
1950
|
VALUE klass = rb_define_class_under(
|
1904
1951
|
module, "EnumBuilderContext", rb_cObject);
|
1905
1952
|
rb_define_alloc_func(klass, EnumBuilderContext_alloc);
|
1906
|
-
rb_define_method(klass, "initialize",
|
1907
|
-
EnumBuilderContext_initialize, 1);
|
1953
|
+
rb_define_method(klass, "initialize", EnumBuilderContext_initialize, 2);
|
1908
1954
|
rb_define_method(klass, "value", EnumBuilderContext_value, 2);
|
1909
1955
|
rb_gc_register_address(&cEnumBuilderContext);
|
1910
1956
|
cEnumBuilderContext = klass;
|
@@ -1912,20 +1958,24 @@ void EnumBuilderContext_register(VALUE module) {
|
|
1912
1958
|
|
1913
1959
|
/*
|
1914
1960
|
* call-seq:
|
1915
|
-
* EnumBuilderContext.new(
|
1961
|
+
* EnumBuilderContext.new(file_builder) => context
|
1916
1962
|
*
|
1917
1963
|
* Create a new builder context around the given enum descriptor. This class is
|
1918
1964
|
* intended to serve as a DSL context to be used with #instance_eval.
|
1919
1965
|
*/
|
1920
|
-
VALUE EnumBuilderContext_initialize(VALUE _self, VALUE
|
1966
|
+
VALUE EnumBuilderContext_initialize(VALUE _self, VALUE _file_builder,
|
1967
|
+
VALUE name) {
|
1921
1968
|
DEFINE_SELF(EnumBuilderContext, self, _self);
|
1922
|
-
|
1923
|
-
|
1924
|
-
|
1969
|
+
FileBuilderContext* file_builder = ruby_to_FileBuilderContext(_file_builder);
|
1970
|
+
google_protobuf_FileDescriptorProto* file_proto = file_builder->file_proto;
|
1971
|
+
|
1972
|
+
self->file_builder = _file_builder;
|
1973
|
+
self->enum_proto = google_protobuf_FileDescriptorProto_add_enum_type(
|
1974
|
+
file_proto, file_builder->arena);
|
1975
|
+
|
1976
|
+
google_protobuf_EnumDescriptorProto_set_name(
|
1977
|
+
self->enum_proto, FileBuilderContext_strdup(_file_builder, name));
|
1925
1978
|
|
1926
|
-
static VALUE enumdef_add_value(VALUE enumdef,
|
1927
|
-
VALUE name, VALUE number) {
|
1928
|
-
rb_funcall(enumdef, rb_intern("add_value"), 2, name, number);
|
1929
1979
|
return Qnil;
|
1930
1980
|
}
|
1931
1981
|
|
@@ -1938,7 +1988,19 @@ static VALUE enumdef_add_value(VALUE enumdef,
|
|
1938
1988
|
*/
|
1939
1989
|
VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) {
|
1940
1990
|
DEFINE_SELF(EnumBuilderContext, self, _self);
|
1941
|
-
|
1991
|
+
FileBuilderContext* file_builder =
|
1992
|
+
ruby_to_FileBuilderContext(self->file_builder);
|
1993
|
+
google_protobuf_EnumValueDescriptorProto* enum_value;
|
1994
|
+
|
1995
|
+
enum_value = google_protobuf_EnumDescriptorProto_add_value(
|
1996
|
+
self->enum_proto, file_builder->arena);
|
1997
|
+
|
1998
|
+
google_protobuf_EnumValueDescriptorProto_set_name(
|
1999
|
+
enum_value, FileBuilderContext_strdup_sym(self->file_builder, name));
|
2000
|
+
google_protobuf_EnumValueDescriptorProto_set_number(enum_value,
|
2001
|
+
NUM2INT(number));
|
2002
|
+
|
2003
|
+
return Qnil;
|
1942
2004
|
}
|
1943
2005
|
|
1944
2006
|
|
@@ -1947,33 +2009,55 @@ VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number) {
|
|
1947
2009
|
// -----------------------------------------------------------------------------
|
1948
2010
|
|
1949
2011
|
DEFINE_CLASS(FileBuilderContext,
|
1950
|
-
|
2012
|
+
"Google::Protobuf::Internal::FileBuilderContext");
|
1951
2013
|
|
1952
2014
|
void FileBuilderContext_mark(void* _self) {
|
1953
2015
|
FileBuilderContext* self = _self;
|
1954
|
-
rb_gc_mark(self->
|
1955
|
-
rb_gc_mark(self->file_descriptor);
|
1956
|
-
rb_gc_mark(self->builder);
|
2016
|
+
rb_gc_mark(self->descriptor_pool);
|
1957
2017
|
}
|
1958
2018
|
|
1959
2019
|
void FileBuilderContext_free(void* _self) {
|
1960
2020
|
FileBuilderContext* self = _self;
|
2021
|
+
upb_arena_free(self->arena);
|
1961
2022
|
xfree(self);
|
1962
2023
|
}
|
1963
2024
|
|
2025
|
+
upb_strview FileBuilderContext_strdup2(VALUE _self, const char *str) {
|
2026
|
+
DEFINE_SELF(FileBuilderContext, self, _self);
|
2027
|
+
upb_strview ret;
|
2028
|
+
char *data;
|
2029
|
+
|
2030
|
+
ret.size = strlen(str);
|
2031
|
+
data = upb_malloc(upb_arena_alloc(self->arena), ret.size + 1);
|
2032
|
+
ret.data = data;
|
2033
|
+
memcpy(data, str, ret.size);
|
2034
|
+
/* Null-terminate required by rewrite_enum_defaults() above. */
|
2035
|
+
data[ret.size] = '\0';
|
2036
|
+
return ret;
|
2037
|
+
}
|
2038
|
+
|
2039
|
+
upb_strview FileBuilderContext_strdup(VALUE _self, VALUE rb_str) {
|
2040
|
+
return FileBuilderContext_strdup2(_self, get_str(rb_str));
|
2041
|
+
}
|
2042
|
+
|
2043
|
+
upb_strview FileBuilderContext_strdup_sym(VALUE _self, VALUE rb_sym) {
|
2044
|
+
Check_Type(rb_sym, T_SYMBOL);
|
2045
|
+
return FileBuilderContext_strdup(_self, rb_id2str(SYM2ID(rb_sym)));
|
2046
|
+
}
|
2047
|
+
|
1964
2048
|
VALUE FileBuilderContext_alloc(VALUE klass) {
|
1965
2049
|
FileBuilderContext* self = ALLOC(FileBuilderContext);
|
1966
2050
|
VALUE ret = TypedData_Wrap_Struct(klass, &_FileBuilderContext_type, self);
|
1967
|
-
self->
|
1968
|
-
self->
|
1969
|
-
self->
|
2051
|
+
self->arena = upb_arena_new();
|
2052
|
+
self->file_proto = google_protobuf_FileDescriptorProto_new(self->arena);
|
2053
|
+
self->descriptor_pool = Qnil;
|
1970
2054
|
return ret;
|
1971
2055
|
}
|
1972
2056
|
|
1973
2057
|
void FileBuilderContext_register(VALUE module) {
|
1974
2058
|
VALUE klass = rb_define_class_under(module, "FileBuilderContext", rb_cObject);
|
1975
2059
|
rb_define_alloc_func(klass, FileBuilderContext_alloc);
|
1976
|
-
rb_define_method(klass, "initialize", FileBuilderContext_initialize,
|
2060
|
+
rb_define_method(klass, "initialize", FileBuilderContext_initialize, 3);
|
1977
2061
|
rb_define_method(klass, "add_message", FileBuilderContext_add_message, 1);
|
1978
2062
|
rb_define_method(klass, "add_enum", FileBuilderContext_add_enum, 1);
|
1979
2063
|
rb_gc_register_address(&cFileBuilderContext);
|
@@ -1982,18 +2066,41 @@ void FileBuilderContext_register(VALUE module) {
|
|
1982
2066
|
|
1983
2067
|
/*
|
1984
2068
|
* call-seq:
|
1985
|
-
* FileBuilderContext.new(
|
2069
|
+
* FileBuilderContext.new(descriptor_pool) => context
|
1986
2070
|
*
|
1987
2071
|
* Create a new file builder context for the given file descriptor and
|
1988
2072
|
* builder context. This class is intended to serve as a DSL context to be used
|
1989
2073
|
* with #instance_eval.
|
1990
2074
|
*/
|
1991
|
-
VALUE FileBuilderContext_initialize(VALUE _self, VALUE
|
1992
|
-
|
2075
|
+
VALUE FileBuilderContext_initialize(VALUE _self, VALUE descriptor_pool,
|
2076
|
+
VALUE name, VALUE options) {
|
1993
2077
|
DEFINE_SELF(FileBuilderContext, self, _self);
|
1994
|
-
self->
|
1995
|
-
|
1996
|
-
|
2078
|
+
self->descriptor_pool = descriptor_pool;
|
2079
|
+
|
2080
|
+
google_protobuf_FileDescriptorProto_set_name(
|
2081
|
+
self->file_proto, FileBuilderContext_strdup(_self, name));
|
2082
|
+
|
2083
|
+
// Default syntax for Ruby is proto3.
|
2084
|
+
google_protobuf_FileDescriptorProto_set_syntax(
|
2085
|
+
self->file_proto,
|
2086
|
+
FileBuilderContext_strdup(_self, rb_str_new2("proto3")));
|
2087
|
+
|
2088
|
+
if (options != Qnil) {
|
2089
|
+
VALUE syntax;
|
2090
|
+
|
2091
|
+
Check_Type(options, T_HASH);
|
2092
|
+
syntax = rb_hash_lookup2(options, ID2SYM(rb_intern("syntax")), Qnil);
|
2093
|
+
|
2094
|
+
if (syntax != Qnil) {
|
2095
|
+
VALUE syntax_str;
|
2096
|
+
|
2097
|
+
Check_Type(syntax, T_SYMBOL);
|
2098
|
+
syntax_str = rb_id2str(SYM2ID(syntax));
|
2099
|
+
google_protobuf_FileDescriptorProto_set_syntax(
|
2100
|
+
self->file_proto, FileBuilderContext_strdup(_self, syntax_str));
|
2101
|
+
}
|
2102
|
+
}
|
2103
|
+
|
1997
2104
|
return Qnil;
|
1998
2105
|
}
|
1999
2106
|
|
@@ -2009,14 +2116,11 @@ VALUE FileBuilderContext_initialize(VALUE _self, VALUE file_descriptor,
|
|
2009
2116
|
* This is the recommended, idiomatic way to build message definitions.
|
2010
2117
|
*/
|
2011
2118
|
VALUE FileBuilderContext_add_message(VALUE _self, VALUE name) {
|
2012
|
-
|
2013
|
-
VALUE msgdef = rb_class_new_instance(1, &self->file_descriptor, cDescriptor);
|
2014
|
-
VALUE args[2] = { msgdef, self->builder };
|
2119
|
+
VALUE args[2] = { _self, name };
|
2015
2120
|
VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext);
|
2016
2121
|
VALUE block = rb_block_proc();
|
2017
|
-
rb_funcall(msgdef, rb_intern("name="), 1, name);
|
2018
2122
|
rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
|
2019
|
-
|
2123
|
+
MessageBuilderContext_add_synthetic_oneofs(ctx);
|
2020
2124
|
return Qnil;
|
2021
2125
|
}
|
2022
2126
|
|
@@ -2031,20 +2135,26 @@ VALUE FileBuilderContext_add_message(VALUE _self, VALUE name) {
|
|
2031
2135
|
* This is the recommended, idiomatic way to build enum definitions.
|
2032
2136
|
*/
|
2033
2137
|
VALUE FileBuilderContext_add_enum(VALUE _self, VALUE name) {
|
2034
|
-
|
2035
|
-
VALUE
|
2036
|
-
rb_class_new_instance(1, &self->file_descriptor, cEnumDescriptor);
|
2037
|
-
VALUE ctx = rb_class_new_instance(1, &enumdef, cEnumBuilderContext);
|
2138
|
+
VALUE args[2] = { _self, name };
|
2139
|
+
VALUE ctx = rb_class_new_instance(2, args, cEnumBuilderContext);
|
2038
2140
|
VALUE block = rb_block_proc();
|
2039
|
-
rb_funcall(enumdef, rb_intern("name="), 1, name);
|
2040
2141
|
rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
|
2041
|
-
rb_ary_push(self->pending_list, enumdef);
|
2042
2142
|
return Qnil;
|
2043
2143
|
}
|
2044
2144
|
|
2045
|
-
|
2145
|
+
void FileBuilderContext_build(VALUE _self) {
|
2046
2146
|
DEFINE_SELF(FileBuilderContext, self, _self);
|
2047
|
-
|
2147
|
+
DescriptorPool* pool = ruby_to_DescriptorPool(self->descriptor_pool);
|
2148
|
+
upb_status status;
|
2149
|
+
|
2150
|
+
rewrite_enum_defaults(pool->symtab, self->file_proto);
|
2151
|
+
rewrite_names(_self, self->file_proto);
|
2152
|
+
|
2153
|
+
upb_status_clear(&status);
|
2154
|
+
if (!upb_symtab_addfile(pool->symtab, self->file_proto, &status)) {
|
2155
|
+
rb_raise(cTypeError, "Unable to add defs to DescriptorPool: %s",
|
2156
|
+
upb_status_errmsg(&status));
|
2157
|
+
}
|
2048
2158
|
}
|
2049
2159
|
|
2050
2160
|
// -----------------------------------------------------------------------------
|
@@ -2055,58 +2165,46 @@ DEFINE_CLASS(Builder, "Google::Protobuf::Internal::Builder");
|
|
2055
2165
|
|
2056
2166
|
void Builder_mark(void* _self) {
|
2057
2167
|
Builder* self = _self;
|
2058
|
-
rb_gc_mark(self->
|
2059
|
-
rb_gc_mark(self->
|
2168
|
+
rb_gc_mark(self->descriptor_pool);
|
2169
|
+
rb_gc_mark(self->default_file_builder);
|
2060
2170
|
}
|
2061
2171
|
|
2062
2172
|
void Builder_free(void* _self) {
|
2063
|
-
|
2064
|
-
xfree(self->defs);
|
2065
|
-
xfree(self);
|
2173
|
+
xfree(_self);
|
2066
2174
|
}
|
2067
2175
|
|
2068
|
-
/*
|
2069
|
-
* call-seq:
|
2070
|
-
* Builder.new => builder
|
2071
|
-
*
|
2072
|
-
* Creates a new Builder. A Builder can accumulate a set of new message and enum
|
2073
|
-
* descriptors and atomically register them into a pool in a way that allows for
|
2074
|
-
* (co)recursive type references.
|
2075
|
-
*/
|
2076
2176
|
VALUE Builder_alloc(VALUE klass) {
|
2077
2177
|
Builder* self = ALLOC(Builder);
|
2078
2178
|
VALUE ret = TypedData_Wrap_Struct(
|
2079
2179
|
klass, &_Builder_type, self);
|
2080
|
-
self->
|
2081
|
-
self->
|
2082
|
-
self->default_file_descriptor = Qnil;
|
2180
|
+
self->descriptor_pool = Qnil;
|
2181
|
+
self->default_file_builder = Qnil;
|
2083
2182
|
return ret;
|
2084
2183
|
}
|
2085
2184
|
|
2086
2185
|
void Builder_register(VALUE module) {
|
2087
2186
|
VALUE klass = rb_define_class_under(module, "Builder", rb_cObject);
|
2088
|
-
rb_define_alloc_func(klass, Builder_alloc);
|
2089
|
-
rb_define_method(klass, "initialize", Builder_initialize,
|
2187
|
+
rb_define_alloc_func(klass, Builder_alloc);
|
2188
|
+
rb_define_method(klass, "initialize", Builder_initialize, 1);
|
2090
2189
|
rb_define_method(klass, "add_file", Builder_add_file, -1);
|
2091
2190
|
rb_define_method(klass, "add_message", Builder_add_message, 1);
|
2092
2191
|
rb_define_method(klass, "add_enum", Builder_add_enum, 1);
|
2093
|
-
rb_define_method(klass, "finalize_to_pool", Builder_finalize_to_pool, 1);
|
2094
2192
|
rb_gc_register_address(&cBuilder);
|
2095
2193
|
cBuilder = klass;
|
2096
2194
|
}
|
2097
2195
|
|
2098
2196
|
/*
|
2099
2197
|
* call-seq:
|
2100
|
-
*
|
2198
|
+
* Builder.new(descriptor_pool) => builder
|
2101
2199
|
*
|
2102
|
-
*
|
2200
|
+
* Creates a new Builder. A Builder can accumulate a set of new message and enum
|
2201
|
+
* descriptors and atomically register them into a pool in a way that allows for
|
2202
|
+
* (co)recursive type references.
|
2103
2203
|
*/
|
2104
|
-
VALUE Builder_initialize(VALUE _self) {
|
2204
|
+
VALUE Builder_initialize(VALUE _self, VALUE pool) {
|
2105
2205
|
DEFINE_SELF(Builder, self, _self);
|
2106
|
-
self->
|
2107
|
-
|
2108
|
-
self->default_file_descriptor =
|
2109
|
-
rb_class_new_instance(1, &file_name, cFileDescriptor);
|
2206
|
+
self->descriptor_pool = pool;
|
2207
|
+
self->default_file_builder = Qnil; // Created lazily if needed.
|
2110
2208
|
return Qnil;
|
2111
2209
|
}
|
2112
2210
|
|
@@ -2123,17 +2221,38 @@ VALUE Builder_initialize(VALUE _self) {
|
|
2123
2221
|
*/
|
2124
2222
|
VALUE Builder_add_file(int argc, VALUE* argv, VALUE _self) {
|
2125
2223
|
DEFINE_SELF(Builder, self, _self);
|
2126
|
-
VALUE
|
2127
|
-
VALUE
|
2128
|
-
VALUE
|
2129
|
-
|
2224
|
+
VALUE name, options;
|
2225
|
+
VALUE ctx;
|
2226
|
+
VALUE block;
|
2227
|
+
|
2228
|
+
rb_scan_args(argc, argv, "11", &name, &options);
|
2229
|
+
|
2230
|
+
{
|
2231
|
+
VALUE args[3] = { self->descriptor_pool, name, options };
|
2232
|
+
ctx = rb_class_new_instance(3, args, cFileBuilderContext);
|
2233
|
+
}
|
2234
|
+
|
2235
|
+
block = rb_block_proc();
|
2130
2236
|
rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
|
2237
|
+
FileBuilderContext_build(ctx);
|
2131
2238
|
|
2132
|
-
rb_ary_concat(self->pending_list,
|
2133
|
-
FileBuilderContext_pending_descriptors(ctx));
|
2134
2239
|
return Qnil;
|
2135
2240
|
}
|
2136
2241
|
|
2242
|
+
static VALUE Builder_get_default_file(VALUE _self) {
|
2243
|
+
DEFINE_SELF(Builder, self, _self);
|
2244
|
+
|
2245
|
+
/* Lazily create only if legacy builder-level methods are called. */
|
2246
|
+
if (self->default_file_builder == Qnil) {
|
2247
|
+
VALUE name = rb_str_new2("ruby_default_file.proto");
|
2248
|
+
VALUE args [3] = { self->descriptor_pool, name, rb_hash_new() };
|
2249
|
+
self->default_file_builder =
|
2250
|
+
rb_class_new_instance(3, args, cFileBuilderContext);
|
2251
|
+
}
|
2252
|
+
|
2253
|
+
return self->default_file_builder;
|
2254
|
+
}
|
2255
|
+
|
2137
2256
|
/*
|
2138
2257
|
* call-seq:
|
2139
2258
|
* Builder.add_message(name, &block)
|
@@ -2146,15 +2265,9 @@ VALUE Builder_add_file(int argc, VALUE* argv, VALUE _self) {
|
|
2146
2265
|
* Descriptors created this way get assigned to a default empty FileDescriptor.
|
2147
2266
|
*/
|
2148
2267
|
VALUE Builder_add_message(VALUE _self, VALUE name) {
|
2149
|
-
|
2150
|
-
|
2151
|
-
|
2152
|
-
VALUE args[2] = { msgdef, _self };
|
2153
|
-
VALUE ctx = rb_class_new_instance(2, args, cMessageBuilderContext);
|
2154
|
-
VALUE block = rb_block_proc();
|
2155
|
-
rb_funcall(msgdef, rb_intern("name="), 1, name);
|
2156
|
-
rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
|
2157
|
-
rb_ary_push(self->pending_list, msgdef);
|
2268
|
+
VALUE file_builder = Builder_get_default_file(_self);
|
2269
|
+
rb_funcall_with_block(file_builder, rb_intern("add_message"), 1, &name,
|
2270
|
+
rb_block_proc());
|
2158
2271
|
return Qnil;
|
2159
2272
|
}
|
2160
2273
|
|
@@ -2171,87 +2284,83 @@ VALUE Builder_add_message(VALUE _self, VALUE name) {
|
|
2171
2284
|
* FileDescriptor.
|
2172
2285
|
*/
|
2173
2286
|
VALUE Builder_add_enum(VALUE _self, VALUE name) {
|
2174
|
-
|
2175
|
-
|
2176
|
-
|
2177
|
-
VALUE ctx = rb_class_new_instance(1, &enumdef, cEnumBuilderContext);
|
2178
|
-
VALUE block = rb_block_proc();
|
2179
|
-
rb_funcall(enumdef, rb_intern("name="), 1, name);
|
2180
|
-
rb_funcall_with_block(ctx, rb_intern("instance_eval"), 0, NULL, block);
|
2181
|
-
rb_ary_push(self->pending_list, enumdef);
|
2287
|
+
VALUE file_builder = Builder_get_default_file(_self);
|
2288
|
+
rb_funcall_with_block(file_builder, rb_intern("add_enum"), 1, &name,
|
2289
|
+
rb_block_proc());
|
2182
2290
|
return Qnil;
|
2183
2291
|
}
|
2184
2292
|
|
2185
|
-
|
2186
|
-
|
2187
|
-
|
2188
|
-
|
2189
|
-
!upb_msg_field_done(&it);
|
2190
|
-
upb_msg_field_next(&it)) {
|
2191
|
-
const upb_fielddef* field = upb_msg_iter_field(&it);
|
2192
|
-
if (upb_fielddef_label(field) == UPB_LABEL_REQUIRED) {
|
2193
|
-
rb_raise(cTypeError, "Required fields are unsupported in proto3.");
|
2194
|
-
}
|
2195
|
-
}
|
2196
|
-
}
|
2293
|
+
/* This method is hidden from Ruby, and only called directly from
|
2294
|
+
* DescriptorPool_build(). */
|
2295
|
+
VALUE Builder_build(VALUE _self) {
|
2296
|
+
DEFINE_SELF(Builder, self, _self);
|
2197
2297
|
|
2198
|
-
|
2199
|
-
|
2200
|
-
|
2201
|
-
const char* lookup = upb_enumdef_iton(enumdef, 0);
|
2202
|
-
if (lookup == NULL) {
|
2203
|
-
rb_raise(cTypeError,
|
2204
|
-
"Enum definition does not contain a value for '0'.");
|
2298
|
+
if (self->default_file_builder != Qnil) {
|
2299
|
+
FileBuilderContext_build(self->default_file_builder);
|
2300
|
+
self->default_file_builder = Qnil;
|
2205
2301
|
}
|
2206
|
-
}
|
2207
|
-
|
2208
|
-
/*
|
2209
|
-
* call-seq:
|
2210
|
-
* Builder.finalize_to_pool(pool)
|
2211
|
-
*
|
2212
|
-
* Adds all accumulated message and enum descriptors created in this builder
|
2213
|
-
* context to the given pool. The operation occurs atomically, and all
|
2214
|
-
* descriptors can refer to each other (including in cycles). This is the only
|
2215
|
-
* way to build (co)recursive message definitions.
|
2216
|
-
*
|
2217
|
-
* This method is usually called automatically by DescriptorPool#build after it
|
2218
|
-
* invokes the given user block in the context of the builder. The user should
|
2219
|
-
* not normally need to call this manually because a Builder is not normally
|
2220
|
-
* created manually.
|
2221
|
-
*/
|
2222
|
-
VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb) {
|
2223
|
-
DEFINE_SELF(Builder, self, _self);
|
2224
2302
|
|
2225
|
-
|
2303
|
+
return Qnil;
|
2304
|
+
}
|
2226
2305
|
|
2227
|
-
|
2306
|
+
static VALUE get_def_obj(VALUE _descriptor_pool, const void* ptr, VALUE klass) {
|
2307
|
+
DEFINE_SELF(DescriptorPool, descriptor_pool, _descriptor_pool);
|
2308
|
+
VALUE key = ULL2NUM((intptr_t)ptr);
|
2309
|
+
VALUE def;
|
2228
2310
|
|
2229
|
-
|
2230
|
-
VALUE def_rb = rb_ary_entry(self->pending_list, i);
|
2231
|
-
if (CLASS_OF(def_rb) == cDescriptor) {
|
2232
|
-
self->defs[i] = (upb_def*)ruby_to_Descriptor(def_rb)->msgdef;
|
2311
|
+
def = rb_hash_aref(descriptor_pool->def_to_descriptor, key);
|
2233
2312
|
|
2234
|
-
|
2235
|
-
|
2236
|
-
|
2237
|
-
} else if (CLASS_OF(def_rb) == cEnumDescriptor) {
|
2238
|
-
self->defs[i] = (upb_def*)ruby_to_EnumDescriptor(def_rb)->enumdef;
|
2313
|
+
if (ptr == NULL) {
|
2314
|
+
return Qnil;
|
2315
|
+
}
|
2239
2316
|
|
2240
|
-
|
2241
|
-
|
2317
|
+
if (def == Qnil) {
|
2318
|
+
// Lazily create wrapper object.
|
2319
|
+
VALUE args[3] = { c_only_cookie, _descriptor_pool, key };
|
2320
|
+
def = rb_class_new_instance(3, args, klass);
|
2321
|
+
rb_hash_aset(descriptor_pool->def_to_descriptor, key, def);
|
2322
|
+
|
2323
|
+
// For message defs, we now eagerly get/create descriptors for all
|
2324
|
+
// submessages. We will need these anyway to parse or serialize this
|
2325
|
+
// message type. But more importantly, we must do this now so that
|
2326
|
+
// add_handlers_for_message() (which calls get_msgdef_obj()) does *not*
|
2327
|
+
// need to create a Ruby object or insert into a Ruby Hash. We need to
|
2328
|
+
// avoid triggering GC, which can switch Ruby threads and re-enter our
|
2329
|
+
// C extension from a different thread. This wreaks havoc on our state
|
2330
|
+
// if we were in the middle of building handlers.
|
2331
|
+
if (klass == cDescriptor) {
|
2332
|
+
const upb_msgdef *m = ptr;
|
2333
|
+
upb_msg_field_iter it;
|
2334
|
+
for (upb_msg_field_begin(&it, m);
|
2335
|
+
!upb_msg_field_done(&it);
|
2336
|
+
upb_msg_field_next(&it)) {
|
2337
|
+
const upb_fielddef* f = upb_msg_iter_field(&it);
|
2338
|
+
if (upb_fielddef_issubmsg(f)) {
|
2339
|
+
get_msgdef_obj(_descriptor_pool, upb_fielddef_msgsubdef(f));
|
2340
|
+
}
|
2242
2341
|
}
|
2243
2342
|
}
|
2244
2343
|
}
|
2245
2344
|
|
2246
|
-
|
2247
|
-
|
2248
|
-
"Unable to add defs to DescriptorPool");
|
2345
|
+
return def;
|
2346
|
+
}
|
2249
2347
|
|
2250
|
-
|
2251
|
-
|
2252
|
-
|
2253
|
-
}
|
2348
|
+
VALUE get_msgdef_obj(VALUE descriptor_pool, const upb_msgdef* def) {
|
2349
|
+
return get_def_obj(descriptor_pool, def, cDescriptor);
|
2350
|
+
}
|
2254
2351
|
|
2255
|
-
|
2256
|
-
return
|
2352
|
+
VALUE get_enumdef_obj(VALUE descriptor_pool, const upb_enumdef* def) {
|
2353
|
+
return get_def_obj(descriptor_pool, def, cEnumDescriptor);
|
2354
|
+
}
|
2355
|
+
|
2356
|
+
VALUE get_fielddef_obj(VALUE descriptor_pool, const upb_fielddef* def) {
|
2357
|
+
return get_def_obj(descriptor_pool, def, cFieldDescriptor);
|
2358
|
+
}
|
2359
|
+
|
2360
|
+
VALUE get_filedef_obj(VALUE descriptor_pool, const upb_filedef* def) {
|
2361
|
+
return get_def_obj(descriptor_pool, def, cFileDescriptor);
|
2362
|
+
}
|
2363
|
+
|
2364
|
+
VALUE get_oneofdef_obj(VALUE descriptor_pool, const upb_oneofdef* def) {
|
2365
|
+
return get_def_obj(descriptor_pool, def, cOneofDescriptor);
|
2257
2366
|
}
|