google-protobuf 3.2.0 → 3.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of google-protobuf might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/ext/google/protobuf_c/defs.c +575 -81
- data/ext/google/protobuf_c/encode_decode.c +456 -149
- data/ext/google/protobuf_c/extconf.rb +15 -2
- data/ext/google/protobuf_c/map.c +47 -3
- data/ext/google/protobuf_c/message.c +308 -82
- data/ext/google/protobuf_c/protobuf.c +7 -3
- data/ext/google/protobuf_c/protobuf.h +86 -12
- data/ext/google/protobuf_c/repeated_field.c +10 -4
- data/ext/google/protobuf_c/storage.c +286 -117
- data/ext/google/protobuf_c/upb.c +14482 -10935
- data/ext/google/protobuf_c/upb.h +2401 -613
- data/ext/google/protobuf_c/wrap_memcpy.c +51 -0
- data/lib/google/protobuf.rb +5 -4
- data/lib/google/protobuf/any_pb.rb +5 -3
- data/lib/google/protobuf/api_pb.rb +23 -21
- data/lib/google/protobuf/duration_pb.rb +5 -3
- data/lib/google/protobuf/empty_pb.rb +3 -1
- data/lib/google/protobuf/field_mask_pb.rb +4 -2
- data/lib/google/protobuf/message_exts.rb +2 -2
- data/lib/google/protobuf/repeated_field.rb +3 -3
- data/lib/google/protobuf/source_context_pb.rb +4 -2
- data/lib/google/protobuf/struct_pb.rb +19 -17
- data/lib/google/protobuf/timestamp_pb.rb +5 -3
- data/lib/google/protobuf/type_pb.rb +68 -66
- data/lib/google/protobuf/well_known_types.rb +13 -1
- data/lib/google/protobuf/wrappers_pb.rb +28 -26
- data/tests/basic.rb +206 -1023
- data/tests/generated_code_test.rb +6 -2
- metadata +5 -5
@@ -41,6 +41,7 @@ VALUE upb_def_to_ruby_obj_map;
|
|
41
41
|
|
42
42
|
VALUE cError;
|
43
43
|
VALUE cParseError;
|
44
|
+
VALUE cTypeError;
|
44
45
|
|
45
46
|
void add_def_obj(const void* def, VALUE value) {
|
46
47
|
rb_hash_aset(upb_def_to_ruby_obj_map, ULL2NUM((intptr_t)def), value);
|
@@ -90,19 +91,24 @@ void Init_protobuf_c() {
|
|
90
91
|
descriptor_instancevar_interned = rb_intern(kDescriptorInstanceVar);
|
91
92
|
DescriptorPool_register(protobuf);
|
92
93
|
Descriptor_register(protobuf);
|
94
|
+
FileDescriptor_register(protobuf);
|
93
95
|
FieldDescriptor_register(protobuf);
|
94
96
|
OneofDescriptor_register(protobuf);
|
95
97
|
EnumDescriptor_register(protobuf);
|
96
98
|
MessageBuilderContext_register(internal);
|
97
99
|
OneofBuilderContext_register(internal);
|
98
100
|
EnumBuilderContext_register(internal);
|
101
|
+
FileBuilderContext_register(internal);
|
99
102
|
Builder_register(internal);
|
100
103
|
RepeatedField_register(protobuf);
|
101
104
|
Map_register(protobuf);
|
102
105
|
|
103
106
|
cError = rb_const_get(protobuf, rb_intern("Error"));
|
104
107
|
cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
|
108
|
+
cTypeError = rb_const_get(protobuf, rb_intern("TypeError"));
|
105
109
|
|
110
|
+
rb_define_singleton_method(protobuf, "discard_unknown",
|
111
|
+
Google_Protobuf_discard_unknown, 1);
|
106
112
|
rb_define_singleton_method(protobuf, "deep_copy",
|
107
113
|
Google_Protobuf_deep_copy, 1);
|
108
114
|
|
@@ -110,8 +116,6 @@ void Init_protobuf_c() {
|
|
110
116
|
kRubyStringASCIIEncoding = rb_usascii_encoding();
|
111
117
|
kRubyString8bitEncoding = rb_ascii8bit_encoding();
|
112
118
|
|
113
|
-
upb_def_to_ruby_obj_map = rb_hash_new();
|
114
119
|
rb_gc_register_address(&upb_def_to_ruby_obj_map);
|
115
|
-
|
116
|
-
rb_gc_register_address(&map_parse_frames);
|
120
|
+
upb_def_to_ruby_obj_map = rb_hash_new();
|
117
121
|
}
|
@@ -40,6 +40,7 @@
|
|
40
40
|
// Forward decls.
|
41
41
|
struct DescriptorPool;
|
42
42
|
struct Descriptor;
|
43
|
+
struct FileDescriptor;
|
43
44
|
struct FieldDescriptor;
|
44
45
|
struct EnumDescriptor;
|
45
46
|
struct MessageLayout;
|
@@ -47,10 +48,12 @@ struct MessageField;
|
|
47
48
|
struct MessageHeader;
|
48
49
|
struct MessageBuilderContext;
|
49
50
|
struct EnumBuilderContext;
|
51
|
+
struct FileBuilderContext;
|
50
52
|
struct Builder;
|
51
53
|
|
52
54
|
typedef struct DescriptorPool DescriptorPool;
|
53
55
|
typedef struct Descriptor Descriptor;
|
56
|
+
typedef struct FileDescriptor FileDescriptor;
|
54
57
|
typedef struct FieldDescriptor FieldDescriptor;
|
55
58
|
typedef struct OneofDescriptor OneofDescriptor;
|
56
59
|
typedef struct EnumDescriptor EnumDescriptor;
|
@@ -60,6 +63,7 @@ typedef struct MessageHeader MessageHeader;
|
|
60
63
|
typedef struct MessageBuilderContext MessageBuilderContext;
|
61
64
|
typedef struct OneofBuilderContext OneofBuilderContext;
|
62
65
|
typedef struct EnumBuilderContext EnumBuilderContext;
|
66
|
+
typedef struct FileBuilderContext FileBuilderContext;
|
63
67
|
typedef struct Builder Builder;
|
64
68
|
|
65
69
|
/*
|
@@ -116,10 +120,10 @@ struct Descriptor {
|
|
116
120
|
const upb_handlers* pb_serialize_handlers;
|
117
121
|
const upb_handlers* json_serialize_handlers;
|
118
122
|
const upb_handlers* json_serialize_handlers_preserve;
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
+
};
|
124
|
+
|
125
|
+
struct FileDescriptor {
|
126
|
+
const upb_filedef* filedef;
|
123
127
|
};
|
124
128
|
|
125
129
|
struct FieldDescriptor {
|
@@ -149,24 +153,32 @@ struct EnumBuilderContext {
|
|
149
153
|
VALUE enumdesc;
|
150
154
|
};
|
151
155
|
|
156
|
+
struct FileBuilderContext {
|
157
|
+
VALUE pending_list;
|
158
|
+
VALUE file_descriptor;
|
159
|
+
VALUE builder;
|
160
|
+
};
|
161
|
+
|
152
162
|
struct Builder {
|
153
163
|
VALUE pending_list;
|
164
|
+
VALUE default_file_descriptor;
|
154
165
|
upb_def** defs; // used only while finalizing
|
155
166
|
};
|
156
167
|
|
157
168
|
extern VALUE cDescriptorPool;
|
158
169
|
extern VALUE cDescriptor;
|
170
|
+
extern VALUE cFileDescriptor;
|
159
171
|
extern VALUE cFieldDescriptor;
|
160
172
|
extern VALUE cEnumDescriptor;
|
161
173
|
extern VALUE cMessageBuilderContext;
|
162
174
|
extern VALUE cOneofBuilderContext;
|
163
175
|
extern VALUE cEnumBuilderContext;
|
176
|
+
extern VALUE cFileBuilderContext;
|
164
177
|
extern VALUE cBuilder;
|
165
178
|
|
166
179
|
extern VALUE cError;
|
167
180
|
extern VALUE cParseError;
|
168
|
-
|
169
|
-
extern VALUE map_parse_frames;
|
181
|
+
extern VALUE cTypeError;
|
170
182
|
|
171
183
|
// We forward-declare all of the Ruby method implementations here because we
|
172
184
|
// sometimes call the methods directly across .c files, rather than going
|
@@ -180,15 +192,18 @@ VALUE DescriptorPool_alloc(VALUE klass);
|
|
180
192
|
void DescriptorPool_register(VALUE module);
|
181
193
|
DescriptorPool* ruby_to_DescriptorPool(VALUE value);
|
182
194
|
VALUE DescriptorPool_add(VALUE _self, VALUE def);
|
183
|
-
VALUE DescriptorPool_build(VALUE _self);
|
195
|
+
VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self);
|
184
196
|
VALUE DescriptorPool_lookup(VALUE _self, VALUE name);
|
185
197
|
VALUE DescriptorPool_generated_pool(VALUE _self);
|
186
198
|
|
199
|
+
extern VALUE generated_pool;
|
200
|
+
|
187
201
|
void Descriptor_mark(void* _self);
|
188
202
|
void Descriptor_free(void* _self);
|
189
203
|
VALUE Descriptor_alloc(VALUE klass);
|
190
204
|
void Descriptor_register(VALUE module);
|
191
205
|
Descriptor* ruby_to_Descriptor(VALUE value);
|
206
|
+
VALUE Descriptor_initialize(VALUE _self, VALUE file_descriptor_rb);
|
192
207
|
VALUE Descriptor_name(VALUE _self);
|
193
208
|
VALUE Descriptor_name_set(VALUE _self, VALUE str);
|
194
209
|
VALUE Descriptor_each(VALUE _self);
|
@@ -198,8 +213,19 @@ VALUE Descriptor_add_oneof(VALUE _self, VALUE obj);
|
|
198
213
|
VALUE Descriptor_each_oneof(VALUE _self);
|
199
214
|
VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name);
|
200
215
|
VALUE Descriptor_msgclass(VALUE _self);
|
216
|
+
VALUE Descriptor_file_descriptor(VALUE _self);
|
201
217
|
extern const rb_data_type_t _Descriptor_type;
|
202
218
|
|
219
|
+
void FileDescriptor_mark(void* _self);
|
220
|
+
void FileDescriptor_free(void* _self);
|
221
|
+
VALUE FileDescriptor_alloc(VALUE klass);
|
222
|
+
void FileDescriptor_register(VALUE module);
|
223
|
+
FileDescriptor* ruby_to_FileDescriptor(VALUE value);
|
224
|
+
VALUE FileDescriptor_initialize(int argc, VALUE* argv, VALUE _self);
|
225
|
+
VALUE FileDescriptor_name(VALUE _self);
|
226
|
+
VALUE FileDescriptor_syntax(VALUE _self);
|
227
|
+
VALUE FileDescriptor_syntax_set(VALUE _self, VALUE syntax);
|
228
|
+
|
203
229
|
void FieldDescriptor_mark(void* _self);
|
204
230
|
void FieldDescriptor_free(void* _self);
|
205
231
|
VALUE FieldDescriptor_alloc(VALUE klass);
|
@@ -209,6 +235,8 @@ VALUE FieldDescriptor_name(VALUE _self);
|
|
209
235
|
VALUE FieldDescriptor_name_set(VALUE _self, VALUE str);
|
210
236
|
VALUE FieldDescriptor_type(VALUE _self);
|
211
237
|
VALUE FieldDescriptor_type_set(VALUE _self, VALUE type);
|
238
|
+
VALUE FieldDescriptor_default(VALUE _self);
|
239
|
+
VALUE FieldDescriptor_default_set(VALUE _self, VALUE default_value);
|
212
240
|
VALUE FieldDescriptor_label(VALUE _self);
|
213
241
|
VALUE FieldDescriptor_label_set(VALUE _self, VALUE label);
|
214
242
|
VALUE FieldDescriptor_number(VALUE _self);
|
@@ -216,6 +244,8 @@ VALUE FieldDescriptor_number_set(VALUE _self, VALUE number);
|
|
216
244
|
VALUE FieldDescriptor_submsg_name(VALUE _self);
|
217
245
|
VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value);
|
218
246
|
VALUE FieldDescriptor_subtype(VALUE _self);
|
247
|
+
VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb);
|
248
|
+
VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb);
|
219
249
|
VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb);
|
220
250
|
VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value);
|
221
251
|
upb_fieldtype_t ruby_to_fieldtype(VALUE type);
|
@@ -236,6 +266,8 @@ void EnumDescriptor_free(void* _self);
|
|
236
266
|
VALUE EnumDescriptor_alloc(VALUE klass);
|
237
267
|
void EnumDescriptor_register(VALUE module);
|
238
268
|
EnumDescriptor* ruby_to_EnumDescriptor(VALUE value);
|
269
|
+
VALUE EnumDescriptor_initialize(VALUE _self, VALUE file_descriptor_rb);
|
270
|
+
VALUE EnumDescriptor_file_descriptor(VALUE _self);
|
239
271
|
VALUE EnumDescriptor_name(VALUE _self);
|
240
272
|
VALUE EnumDescriptor_name_set(VALUE _self, VALUE str);
|
241
273
|
VALUE EnumDescriptor_add_value(VALUE _self, VALUE name, VALUE number);
|
@@ -277,11 +309,23 @@ EnumBuilderContext* ruby_to_EnumBuilderContext(VALUE value);
|
|
277
309
|
VALUE EnumBuilderContext_initialize(VALUE _self, VALUE enumdesc);
|
278
310
|
VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number);
|
279
311
|
|
312
|
+
void FileBuilderContext_mark(void* _self);
|
313
|
+
void FileBuilderContext_free(void* _self);
|
314
|
+
VALUE FileBuilderContext_alloc(VALUE klass);
|
315
|
+
void FileBuilderContext_register(VALUE module);
|
316
|
+
VALUE FileBuilderContext_initialize(VALUE _self, VALUE file_descriptor,
|
317
|
+
VALUE builder);
|
318
|
+
VALUE FileBuilderContext_add_message(VALUE _self, VALUE name);
|
319
|
+
VALUE FileBuilderContext_add_enum(VALUE _self, VALUE name);
|
320
|
+
VALUE FileBuilderContext_pending_descriptors(VALUE _self);
|
321
|
+
|
280
322
|
void Builder_mark(void* _self);
|
281
323
|
void Builder_free(void* _self);
|
282
324
|
VALUE Builder_alloc(VALUE klass);
|
283
325
|
void Builder_register(VALUE module);
|
284
326
|
Builder* ruby_to_Builder(VALUE value);
|
327
|
+
VALUE Builder_initialize(VALUE _self);
|
328
|
+
VALUE Builder_add_file(int argc, VALUE *argv, VALUE _self);
|
285
329
|
VALUE Builder_add_message(VALUE _self, VALUE name);
|
286
330
|
VALUE Builder_add_enum(VALUE _self, VALUE name);
|
287
331
|
VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb);
|
@@ -293,14 +337,16 @@ VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb);
|
|
293
337
|
#define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t)
|
294
338
|
|
295
339
|
size_t native_slot_size(upb_fieldtype_t type);
|
296
|
-
void native_slot_set(
|
340
|
+
void native_slot_set(const char* name,
|
341
|
+
upb_fieldtype_t type,
|
297
342
|
VALUE type_class,
|
298
343
|
void* memory,
|
299
344
|
VALUE value);
|
300
345
|
// Atomically (with respect to Ruby VM calls) either update the value and set a
|
301
346
|
// oneof case, or do neither. If |case_memory| is null, then no case value is
|
302
347
|
// set.
|
303
|
-
void native_slot_set_value_and_case(
|
348
|
+
void native_slot_set_value_and_case(const char* name,
|
349
|
+
upb_fieldtype_t type,
|
304
350
|
VALUE type_class,
|
305
351
|
void* memory,
|
306
352
|
VALUE value,
|
@@ -316,7 +362,7 @@ void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from);
|
|
316
362
|
bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2);
|
317
363
|
|
318
364
|
VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value);
|
319
|
-
void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE value);
|
365
|
+
void native_slot_check_int_range_precision(const char* name, upb_fieldtype_t type, VALUE value);
|
320
366
|
|
321
367
|
extern rb_encoding* kRubyStringUtf8Encoding;
|
322
368
|
extern rb_encoding* kRubyStringASCIIEncoding;
|
@@ -397,6 +443,7 @@ typedef struct {
|
|
397
443
|
upb_fieldtype_t key_type;
|
398
444
|
upb_fieldtype_t value_type;
|
399
445
|
VALUE value_type_class;
|
446
|
+
VALUE parse_frame;
|
400
447
|
upb_strtable table;
|
401
448
|
} Map;
|
402
449
|
|
@@ -405,6 +452,7 @@ void Map_free(void* self);
|
|
405
452
|
VALUE Map_alloc(VALUE klass);
|
406
453
|
VALUE Map_init(int argc, VALUE* argv, VALUE self);
|
407
454
|
void Map_register(VALUE module);
|
455
|
+
VALUE Map_set_frame(VALUE self, VALUE val);
|
408
456
|
|
409
457
|
extern const rb_data_type_t Map_type;
|
410
458
|
extern VALUE cMap;
|
@@ -424,6 +472,7 @@ VALUE Map_dup(VALUE _self);
|
|
424
472
|
VALUE Map_deep_copy(VALUE _self);
|
425
473
|
VALUE Map_eq(VALUE _self, VALUE _other);
|
426
474
|
VALUE Map_hash(VALUE _self);
|
475
|
+
VALUE Map_to_h(VALUE _self);
|
427
476
|
VALUE Map_inspect(VALUE _self);
|
428
477
|
VALUE Map_merge(VALUE _self, VALUE hashmap);
|
429
478
|
VALUE Map_merge_into_self(VALUE _self, VALUE hashmap);
|
@@ -444,10 +493,12 @@ VALUE Map_iter_value(Map_iter* iter);
|
|
444
493
|
// -----------------------------------------------------------------------------
|
445
494
|
|
446
495
|
#define MESSAGE_FIELD_NO_CASE ((size_t)-1)
|
496
|
+
#define MESSAGE_FIELD_NO_HASBIT ((size_t)-1)
|
447
497
|
|
448
498
|
struct MessageField {
|
449
499
|
size_t offset;
|
450
500
|
size_t case_offset; // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE.
|
501
|
+
size_t hasbit;
|
451
502
|
};
|
452
503
|
|
453
504
|
struct MessageLayout {
|
@@ -458,6 +509,9 @@ struct MessageLayout {
|
|
458
509
|
|
459
510
|
MessageLayout* create_layout(const upb_msgdef* msgdef);
|
460
511
|
void free_layout(MessageLayout* layout);
|
512
|
+
bool field_contains_hasbit(MessageLayout* layout,
|
513
|
+
const upb_fielddef* field);
|
514
|
+
VALUE layout_get_default(const upb_fielddef* field);
|
461
515
|
VALUE layout_get(MessageLayout* layout,
|
462
516
|
const void* storage,
|
463
517
|
const upb_fielddef* field);
|
@@ -465,6 +519,12 @@ void layout_set(MessageLayout* layout,
|
|
465
519
|
void* storage,
|
466
520
|
const upb_fielddef* field,
|
467
521
|
VALUE val);
|
522
|
+
VALUE layout_has(MessageLayout* layout,
|
523
|
+
const void* storage,
|
524
|
+
const upb_fielddef* field);
|
525
|
+
void layout_clear(MessageLayout* layout,
|
526
|
+
const void* storage,
|
527
|
+
const upb_fielddef* field);
|
468
528
|
void layout_init(MessageLayout* layout, void* storage);
|
469
529
|
void layout_mark(MessageLayout* layout, void* storage);
|
470
530
|
void layout_dup(MessageLayout* layout, void* to, void* from);
|
@@ -477,8 +537,20 @@ VALUE layout_inspect(MessageLayout* layout, void* storage);
|
|
477
537
|
// Message class creation.
|
478
538
|
// -----------------------------------------------------------------------------
|
479
539
|
|
540
|
+
// This should probably be factored into a common upb component.
|
541
|
+
|
542
|
+
typedef struct {
|
543
|
+
upb_byteshandler handler;
|
544
|
+
upb_bytessink sink;
|
545
|
+
char *ptr;
|
546
|
+
size_t len, size;
|
547
|
+
} stringsink;
|
548
|
+
|
549
|
+
void stringsink_uninit(stringsink *sink);
|
550
|
+
|
480
551
|
struct MessageHeader {
|
481
|
-
Descriptor* descriptor;
|
552
|
+
Descriptor* descriptor; // kept alive by self.class.descriptor reference.
|
553
|
+
stringsink* unknown_fields; // store unknown fields in decoding.
|
482
554
|
// Data comes after this.
|
483
555
|
};
|
484
556
|
|
@@ -496,14 +568,16 @@ VALUE Message_deep_copy(VALUE _self);
|
|
496
568
|
VALUE Message_eq(VALUE _self, VALUE _other);
|
497
569
|
VALUE Message_hash(VALUE _self);
|
498
570
|
VALUE Message_inspect(VALUE _self);
|
571
|
+
VALUE Message_to_h(VALUE _self);
|
499
572
|
VALUE Message_index(VALUE _self, VALUE field_name);
|
500
573
|
VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value);
|
501
574
|
VALUE Message_descriptor(VALUE klass);
|
502
575
|
VALUE Message_decode(VALUE klass, VALUE data);
|
503
576
|
VALUE Message_encode(VALUE klass, VALUE msg_rb);
|
504
|
-
VALUE Message_decode_json(VALUE
|
577
|
+
VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass);
|
505
578
|
VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass);
|
506
579
|
|
580
|
+
VALUE Google_Protobuf_discard_unknown(VALUE self, VALUE msg_rb);
|
507
581
|
VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj);
|
508
582
|
|
509
583
|
VALUE build_module_from_enumdesc(EnumDescriptor* enumdef);
|
@@ -178,7 +178,7 @@ VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
|
|
178
178
|
}
|
179
179
|
|
180
180
|
memory = RepeatedField_memoryat(self, index, element_size);
|
181
|
-
native_slot_set(field_type, field_type_class, memory, val);
|
181
|
+
native_slot_set("", field_type, field_type_class, memory, val);
|
182
182
|
return Qnil;
|
183
183
|
}
|
184
184
|
|
@@ -217,12 +217,18 @@ VALUE RepeatedField_push(VALUE _self, VALUE val) {
|
|
217
217
|
|
218
218
|
RepeatedField_reserve(self, self->size + 1);
|
219
219
|
memory = (void *) (((uint8_t *)self->elements) + self->size * element_size);
|
220
|
-
native_slot_set(field_type, self->field_type_class, memory, val);
|
220
|
+
native_slot_set("", field_type, self->field_type_class, memory, val);
|
221
221
|
// native_slot_set may raise an error; bump size only after set.
|
222
222
|
self->size++;
|
223
223
|
return _self;
|
224
224
|
}
|
225
225
|
|
226
|
+
VALUE RepeatedField_push_vararg(VALUE _self, VALUE args) {
|
227
|
+
for (int i = 0; i < RARRAY_LEN(args); i++) {
|
228
|
+
RepeatedField_push(_self, rb_ary_entry(args, i));
|
229
|
+
}
|
230
|
+
return _self;
|
231
|
+
}
|
226
232
|
|
227
233
|
// Used by parsing handlers.
|
228
234
|
void RepeatedField_push_native(VALUE _self, void* data) {
|
@@ -626,8 +632,8 @@ void RepeatedField_register(VALUE module) {
|
|
626
632
|
VALUE klass = rb_define_class_under(
|
627
633
|
module, "RepeatedField", rb_cObject);
|
628
634
|
rb_define_alloc_func(klass, RepeatedField_alloc);
|
629
|
-
cRepeatedField = klass;
|
630
635
|
rb_gc_register_address(&cRepeatedField);
|
636
|
+
cRepeatedField = klass;
|
631
637
|
|
632
638
|
rb_define_method(klass, "initialize",
|
633
639
|
RepeatedField_init, -1);
|
@@ -635,7 +641,7 @@ void RepeatedField_register(VALUE module) {
|
|
635
641
|
rb_define_method(klass, "[]", RepeatedField_index, -1);
|
636
642
|
rb_define_method(klass, "at", RepeatedField_index, -1);
|
637
643
|
rb_define_method(klass, "[]=", RepeatedField_index_set, 2);
|
638
|
-
rb_define_method(klass, "push",
|
644
|
+
rb_define_method(klass, "push", RepeatedField_push_vararg, -2);
|
639
645
|
rb_define_method(klass, "<<", RepeatedField_push, 1);
|
640
646
|
rb_define_private_method(klass, "pop_one", RepeatedField_pop_one, 0);
|
641
647
|
rb_define_method(klass, "replace", RepeatedField_replace, 1);
|
@@ -38,6 +38,8 @@
|
|
38
38
|
// Ruby <-> native slot management.
|
39
39
|
// -----------------------------------------------------------------------------
|
40
40
|
|
41
|
+
#define CHARPTR_AT(msg, ofs) ((char*)msg + ofs)
|
42
|
+
#define DEREF_OFFSET(msg, ofs, type) *(type*)CHARPTR_AT(msg, ofs)
|
41
43
|
#define DEREF(memory, type) *(type*)(memory)
|
42
44
|
|
43
45
|
size_t native_slot_size(upb_fieldtype_t type) {
|
@@ -57,46 +59,16 @@ size_t native_slot_size(upb_fieldtype_t type) {
|
|
57
59
|
}
|
58
60
|
}
|
59
61
|
|
60
|
-
static VALUE value_from_default(const upb_fielddef *field) {
|
61
|
-
switch (upb_fielddef_type(field)) {
|
62
|
-
case UPB_TYPE_FLOAT: return DBL2NUM(upb_fielddef_defaultfloat(field));
|
63
|
-
case UPB_TYPE_DOUBLE: return DBL2NUM(upb_fielddef_defaultdouble(field));
|
64
|
-
case UPB_TYPE_BOOL:
|
65
|
-
return upb_fielddef_defaultbool(field) ? Qtrue : Qfalse;
|
66
|
-
case UPB_TYPE_MESSAGE: return Qnil;
|
67
|
-
case UPB_TYPE_ENUM: {
|
68
|
-
const upb_enumdef *enumdef = upb_fielddef_enumsubdef(field);
|
69
|
-
int32_t num = upb_fielddef_defaultint32(field);
|
70
|
-
const char *label = upb_enumdef_iton(enumdef, num);
|
71
|
-
if (label) {
|
72
|
-
return ID2SYM(rb_intern(label));
|
73
|
-
} else {
|
74
|
-
return INT2NUM(num);
|
75
|
-
}
|
76
|
-
}
|
77
|
-
case UPB_TYPE_INT32: return INT2NUM(upb_fielddef_defaultint32(field));
|
78
|
-
case UPB_TYPE_INT64: return LL2NUM(upb_fielddef_defaultint64(field));;
|
79
|
-
case UPB_TYPE_UINT32: return UINT2NUM(upb_fielddef_defaultuint32(field));
|
80
|
-
case UPB_TYPE_UINT64: return ULL2NUM(upb_fielddef_defaultuint64(field));
|
81
|
-
case UPB_TYPE_STRING:
|
82
|
-
case UPB_TYPE_BYTES: {
|
83
|
-
size_t size;
|
84
|
-
const char *str = upb_fielddef_defaultstr(field, &size);
|
85
|
-
return rb_str_new(str, size);
|
86
|
-
}
|
87
|
-
default: return Qnil;
|
88
|
-
}
|
89
|
-
}
|
90
|
-
|
91
62
|
static bool is_ruby_num(VALUE value) {
|
92
63
|
return (TYPE(value) == T_FLOAT ||
|
93
64
|
TYPE(value) == T_FIXNUM ||
|
94
65
|
TYPE(value) == T_BIGNUM);
|
95
66
|
}
|
96
67
|
|
97
|
-
void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) {
|
68
|
+
void native_slot_check_int_range_precision(const char* name, upb_fieldtype_t type, VALUE val) {
|
98
69
|
if (!is_ruby_num(val)) {
|
99
|
-
rb_raise(
|
70
|
+
rb_raise(cTypeError, "Expected number type for integral field '%s' (given %s).",
|
71
|
+
name, rb_class2name(CLASS_OF(val)));
|
100
72
|
}
|
101
73
|
|
102
74
|
// NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper
|
@@ -106,13 +78,15 @@ void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) {
|
|
106
78
|
double dbl_val = NUM2DBL(val);
|
107
79
|
if (floor(dbl_val) != dbl_val) {
|
108
80
|
rb_raise(rb_eRangeError,
|
109
|
-
"Non-integral floating point value assigned to integer field."
|
81
|
+
"Non-integral floating point value assigned to integer field '%s' (given %s).",
|
82
|
+
name, rb_class2name(CLASS_OF(val)));
|
110
83
|
}
|
111
84
|
}
|
112
85
|
if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) {
|
113
86
|
if (NUM2DBL(val) < 0) {
|
114
87
|
rb_raise(rb_eRangeError,
|
115
|
-
"Assigning negative value to unsigned integer field."
|
88
|
+
"Assigning negative value to unsigned integer field '%s' (given %s).",
|
89
|
+
name, rb_class2name(CLASS_OF(val)));
|
116
90
|
}
|
117
91
|
}
|
118
92
|
}
|
@@ -137,12 +111,14 @@ VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value) {
|
|
137
111
|
return value;
|
138
112
|
}
|
139
113
|
|
140
|
-
void native_slot_set(
|
114
|
+
void native_slot_set(const char* name,
|
115
|
+
upb_fieldtype_t type, VALUE type_class,
|
141
116
|
void* memory, VALUE value) {
|
142
|
-
native_slot_set_value_and_case(type, type_class, memory, value, NULL, 0);
|
117
|
+
native_slot_set_value_and_case(name, type, type_class, memory, value, NULL, 0);
|
143
118
|
}
|
144
119
|
|
145
|
-
void native_slot_set_value_and_case(
|
120
|
+
void native_slot_set_value_and_case(const char* name,
|
121
|
+
upb_fieldtype_t type, VALUE type_class,
|
146
122
|
void* memory, VALUE value,
|
147
123
|
uint32_t* case_memory,
|
148
124
|
uint32_t case_number) {
|
@@ -153,13 +129,15 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
|
|
153
129
|
switch (type) {
|
154
130
|
case UPB_TYPE_FLOAT:
|
155
131
|
if (!is_ruby_num(value)) {
|
156
|
-
rb_raise(
|
132
|
+
rb_raise(cTypeError, "Expected number type for float field '%s' (given %s).",
|
133
|
+
name, rb_class2name(CLASS_OF(value)));
|
157
134
|
}
|
158
135
|
DEREF(memory, float) = NUM2DBL(value);
|
159
136
|
break;
|
160
137
|
case UPB_TYPE_DOUBLE:
|
161
138
|
if (!is_ruby_num(value)) {
|
162
|
-
rb_raise(
|
139
|
+
rb_raise(cTypeError, "Expected number type for double field '%s' (given %s).",
|
140
|
+
name, rb_class2name(CLASS_OF(value)));
|
163
141
|
}
|
164
142
|
DEREF(memory, double) = NUM2DBL(value);
|
165
143
|
break;
|
@@ -170,15 +148,27 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
|
|
170
148
|
} else if (value == Qfalse) {
|
171
149
|
val = 0;
|
172
150
|
} else {
|
173
|
-
rb_raise(
|
151
|
+
rb_raise(cTypeError, "Invalid argument for boolean field '%s' (given %s).",
|
152
|
+
name, rb_class2name(CLASS_OF(value)));
|
174
153
|
}
|
175
154
|
DEREF(memory, int8_t) = val;
|
176
155
|
break;
|
177
156
|
}
|
178
157
|
case UPB_TYPE_STRING:
|
158
|
+
if (CLASS_OF(value) == rb_cSymbol) {
|
159
|
+
value = rb_funcall(value, rb_intern("to_s"), 0);
|
160
|
+
} else if (CLASS_OF(value) != rb_cString) {
|
161
|
+
rb_raise(cTypeError, "Invalid argument for string field '%s' (given %s).",
|
162
|
+
name, rb_class2name(CLASS_OF(value)));
|
163
|
+
}
|
164
|
+
|
165
|
+
DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
|
166
|
+
break;
|
167
|
+
|
179
168
|
case UPB_TYPE_BYTES: {
|
180
169
|
if (CLASS_OF(value) != rb_cString) {
|
181
|
-
rb_raise(
|
170
|
+
rb_raise(cTypeError, "Invalid argument for bytes field '%s' (given %s).",
|
171
|
+
name, rb_class2name(CLASS_OF(value)));
|
182
172
|
}
|
183
173
|
|
184
174
|
DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
|
@@ -188,29 +178,61 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
|
|
188
178
|
if (CLASS_OF(value) == CLASS_OF(Qnil)) {
|
189
179
|
value = Qnil;
|
190
180
|
} else if (CLASS_OF(value) != type_class) {
|
191
|
-
|
192
|
-
|
193
|
-
|
181
|
+
// check for possible implicit conversions
|
182
|
+
VALUE converted_value = NULL;
|
183
|
+
char* field_type_name = rb_class2name(type_class);
|
184
|
+
|
185
|
+
if (strcmp(field_type_name, "Google::Protobuf::Timestamp") == 0 &&
|
186
|
+
rb_obj_is_kind_of(value, rb_cTime)) {
|
187
|
+
// Time -> Google::Protobuf::Timestamp
|
188
|
+
VALUE hash = rb_hash_new();
|
189
|
+
rb_hash_aset(hash, rb_str_new2("seconds"), rb_funcall(value, rb_intern("to_i"), 0));
|
190
|
+
rb_hash_aset(hash, rb_str_new2("nanos"), rb_funcall(value, rb_intern("nsec"), 0));
|
191
|
+
VALUE args[1] = { hash };
|
192
|
+
converted_value = rb_class_new_instance(1, args, type_class);
|
193
|
+
} else if (strcmp(field_type_name, "Google::Protobuf::Duration") == 0 &&
|
194
|
+
rb_obj_is_kind_of(value, rb_cNumeric)) {
|
195
|
+
// Numeric -> Google::Protobuf::Duration
|
196
|
+
VALUE hash = rb_hash_new();
|
197
|
+
rb_hash_aset(hash, rb_str_new2("seconds"), rb_funcall(value, rb_intern("to_i"), 0));
|
198
|
+
VALUE n_value = rb_funcall(value, rb_intern("remainder"), 1, INT2NUM(1));
|
199
|
+
n_value = rb_funcall(n_value, rb_intern("*"), 1, INT2NUM(1000000000));
|
200
|
+
n_value = rb_funcall(n_value, rb_intern("round"), 0);
|
201
|
+
rb_hash_aset(hash, rb_str_new2("nanos"), n_value);
|
202
|
+
VALUE args[1] = { hash };
|
203
|
+
converted_value = rb_class_new_instance(1, args, type_class);
|
204
|
+
}
|
205
|
+
|
206
|
+
// raise if no suitable conversaion could be found
|
207
|
+
if (converted_value == NULL) {
|
208
|
+
rb_raise(cTypeError,
|
209
|
+
"Invalid type %s to assign to submessage field '%s'.",
|
210
|
+
rb_class2name(CLASS_OF(value)), name);
|
211
|
+
} else {
|
212
|
+
value = converted_value;
|
213
|
+
}
|
194
214
|
}
|
195
215
|
DEREF(memory, VALUE) = value;
|
196
216
|
break;
|
197
217
|
}
|
198
218
|
case UPB_TYPE_ENUM: {
|
199
219
|
int32_t int_val = 0;
|
200
|
-
if (
|
201
|
-
|
202
|
-
|
220
|
+
if (TYPE(value) == T_STRING) {
|
221
|
+
value = rb_funcall(value, rb_intern("to_sym"), 0);
|
222
|
+
} else if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) {
|
223
|
+
rb_raise(cTypeError,
|
224
|
+
"Expected number or symbol type for enum field '%s'.", name);
|
203
225
|
}
|
204
226
|
if (TYPE(value) == T_SYMBOL) {
|
205
227
|
// Ensure that the given symbol exists in the enum module.
|
206
228
|
VALUE lookup = rb_funcall(type_class, rb_intern("resolve"), 1, value);
|
207
229
|
if (lookup == Qnil) {
|
208
|
-
rb_raise(rb_eRangeError, "Unknown symbol value for enum field.");
|
230
|
+
rb_raise(rb_eRangeError, "Unknown symbol value for enum field '%s'.", name);
|
209
231
|
} else {
|
210
232
|
int_val = NUM2INT(lookup);
|
211
233
|
}
|
212
234
|
} else {
|
213
|
-
native_slot_check_int_range_precision(UPB_TYPE_INT32, value);
|
235
|
+
native_slot_check_int_range_precision(name, UPB_TYPE_INT32, value);
|
214
236
|
int_val = NUM2INT(value);
|
215
237
|
}
|
216
238
|
DEREF(memory, int32_t) = int_val;
|
@@ -220,7 +242,7 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
|
|
220
242
|
case UPB_TYPE_INT64:
|
221
243
|
case UPB_TYPE_UINT32:
|
222
244
|
case UPB_TYPE_UINT64:
|
223
|
-
native_slot_check_int_range_precision(type, value);
|
245
|
+
native_slot_check_int_range_precision(name, type, value);
|
224
246
|
switch (type) {
|
225
247
|
case UPB_TYPE_INT32:
|
226
248
|
DEREF(memory, int32_t) = NUM2INT(value);
|
@@ -393,7 +415,12 @@ const upb_msgdef *map_entry_msgdef(const upb_fielddef* field) {
|
|
393
415
|
}
|
394
416
|
|
395
417
|
bool is_map_field(const upb_fielddef *field) {
|
396
|
-
|
418
|
+
const upb_msgdef* subdef = tryget_map_entry_msgdef(field);
|
419
|
+
if (subdef == NULL) return false;
|
420
|
+
|
421
|
+
// Map fields are a proto3 feature.
|
422
|
+
// If we're using proto2 syntax we need to fallback to the repeated field.
|
423
|
+
return upb_msgdef_syntax(subdef) == UPB_SYNTAX_PROTO3;
|
397
424
|
}
|
398
425
|
|
399
426
|
const upb_fielddef* map_field_key(const upb_fielddef* field) {
|
@@ -422,6 +449,12 @@ const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
|
|
422
449
|
// Memory layout management.
|
423
450
|
// -----------------------------------------------------------------------------
|
424
451
|
|
452
|
+
bool field_contains_hasbit(MessageLayout* layout,
|
453
|
+
const upb_fielddef* field) {
|
454
|
+
return layout->fields[upb_fielddef_index(field)].hasbit !=
|
455
|
+
MESSAGE_FIELD_NO_HASBIT;
|
456
|
+
}
|
457
|
+
|
425
458
|
static size_t align_up_to(size_t offset, size_t granularity) {
|
426
459
|
// Granularity must be a power of two.
|
427
460
|
return (offset + granularity - 1) & ~(granularity - 1);
|
@@ -436,6 +469,23 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
|
|
436
469
|
|
437
470
|
layout->fields = ALLOC_N(MessageField, nfields);
|
438
471
|
|
472
|
+
size_t hasbit = 0;
|
473
|
+
for (upb_msg_field_begin(&it, msgdef);
|
474
|
+
!upb_msg_field_done(&it);
|
475
|
+
upb_msg_field_next(&it)) {
|
476
|
+
const upb_fielddef* field = upb_msg_iter_field(&it);
|
477
|
+
if (upb_fielddef_haspresence(field)) {
|
478
|
+
layout->fields[upb_fielddef_index(field)].hasbit = hasbit++;
|
479
|
+
} else {
|
480
|
+
layout->fields[upb_fielddef_index(field)].hasbit =
|
481
|
+
MESSAGE_FIELD_NO_HASBIT;
|
482
|
+
}
|
483
|
+
}
|
484
|
+
|
485
|
+
if (hasbit != 0) {
|
486
|
+
off += (hasbit + 8 - 1) / 8;
|
487
|
+
}
|
488
|
+
|
439
489
|
for (upb_msg_field_begin(&it, msgdef);
|
440
490
|
!upb_msg_field_done(&it);
|
441
491
|
upb_msg_field_next(&it)) {
|
@@ -558,6 +608,137 @@ static uint32_t* slot_oneof_case(MessageLayout* layout,
|
|
558
608
|
layout->fields[upb_fielddef_index(field)].case_offset);
|
559
609
|
}
|
560
610
|
|
611
|
+
static void slot_set_hasbit(MessageLayout* layout,
|
612
|
+
const void* storage,
|
613
|
+
const upb_fielddef* field) {
|
614
|
+
size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
|
615
|
+
assert(hasbit != MESSAGE_FIELD_NO_HASBIT);
|
616
|
+
|
617
|
+
((uint8_t*)storage)[hasbit / 8] |= 1 << (hasbit % 8);
|
618
|
+
}
|
619
|
+
|
620
|
+
static void slot_clear_hasbit(MessageLayout* layout,
|
621
|
+
const void* storage,
|
622
|
+
const upb_fielddef* field) {
|
623
|
+
size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
|
624
|
+
assert(hasbit != MESSAGE_FIELD_NO_HASBIT);
|
625
|
+
((uint8_t*)storage)[hasbit / 8] &= ~(1 << (hasbit % 8));
|
626
|
+
}
|
627
|
+
|
628
|
+
static bool slot_is_hasbit_set(MessageLayout* layout,
|
629
|
+
const void* storage,
|
630
|
+
const upb_fielddef* field) {
|
631
|
+
size_t hasbit = layout->fields[upb_fielddef_index(field)].hasbit;
|
632
|
+
if (hasbit == MESSAGE_FIELD_NO_HASBIT) {
|
633
|
+
return false;
|
634
|
+
}
|
635
|
+
|
636
|
+
return DEREF_OFFSET(
|
637
|
+
(uint8_t*)storage, hasbit / 8, char) & (1 << (hasbit % 8));
|
638
|
+
}
|
639
|
+
|
640
|
+
VALUE layout_has(MessageLayout* layout,
|
641
|
+
const void* storage,
|
642
|
+
const upb_fielddef* field) {
|
643
|
+
assert(field_contains_hasbit(layout, field));
|
644
|
+
return slot_is_hasbit_set(layout, storage, field) ? Qtrue : Qfalse;
|
645
|
+
}
|
646
|
+
|
647
|
+
void layout_clear(MessageLayout* layout,
|
648
|
+
const void* storage,
|
649
|
+
const upb_fielddef* field) {
|
650
|
+
void* memory = slot_memory(layout, storage, field);
|
651
|
+
uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
|
652
|
+
|
653
|
+
if (field_contains_hasbit(layout, field)) {
|
654
|
+
slot_clear_hasbit(layout, storage, field);
|
655
|
+
}
|
656
|
+
|
657
|
+
if (upb_fielddef_containingoneof(field)) {
|
658
|
+
memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
|
659
|
+
*oneof_case = ONEOF_CASE_NONE;
|
660
|
+
} else if (is_map_field(field)) {
|
661
|
+
VALUE map = Qnil;
|
662
|
+
|
663
|
+
const upb_fielddef* key_field = map_field_key(field);
|
664
|
+
const upb_fielddef* value_field = map_field_value(field);
|
665
|
+
VALUE type_class = field_type_class(value_field);
|
666
|
+
|
667
|
+
if (type_class != Qnil) {
|
668
|
+
VALUE args[3] = {
|
669
|
+
fieldtype_to_ruby(upb_fielddef_type(key_field)),
|
670
|
+
fieldtype_to_ruby(upb_fielddef_type(value_field)),
|
671
|
+
type_class,
|
672
|
+
};
|
673
|
+
map = rb_class_new_instance(3, args, cMap);
|
674
|
+
} else {
|
675
|
+
VALUE args[2] = {
|
676
|
+
fieldtype_to_ruby(upb_fielddef_type(key_field)),
|
677
|
+
fieldtype_to_ruby(upb_fielddef_type(value_field)),
|
678
|
+
};
|
679
|
+
map = rb_class_new_instance(2, args, cMap);
|
680
|
+
}
|
681
|
+
|
682
|
+
DEREF(memory, VALUE) = map;
|
683
|
+
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
684
|
+
VALUE ary = Qnil;
|
685
|
+
|
686
|
+
VALUE type_class = field_type_class(field);
|
687
|
+
|
688
|
+
if (type_class != Qnil) {
|
689
|
+
VALUE args[2] = {
|
690
|
+
fieldtype_to_ruby(upb_fielddef_type(field)),
|
691
|
+
type_class,
|
692
|
+
};
|
693
|
+
ary = rb_class_new_instance(2, args, cRepeatedField);
|
694
|
+
} else {
|
695
|
+
VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
|
696
|
+
ary = rb_class_new_instance(1, args, cRepeatedField);
|
697
|
+
}
|
698
|
+
|
699
|
+
DEREF(memory, VALUE) = ary;
|
700
|
+
} else {
|
701
|
+
native_slot_set(upb_fielddef_name(field),
|
702
|
+
upb_fielddef_type(field), field_type_class(field),
|
703
|
+
memory, layout_get_default(field));
|
704
|
+
}
|
705
|
+
}
|
706
|
+
|
707
|
+
VALUE layout_get_default(const upb_fielddef *field) {
|
708
|
+
switch (upb_fielddef_type(field)) {
|
709
|
+
case UPB_TYPE_FLOAT: return DBL2NUM(upb_fielddef_defaultfloat(field));
|
710
|
+
case UPB_TYPE_DOUBLE: return DBL2NUM(upb_fielddef_defaultdouble(field));
|
711
|
+
case UPB_TYPE_BOOL:
|
712
|
+
return upb_fielddef_defaultbool(field) ? Qtrue : Qfalse;
|
713
|
+
case UPB_TYPE_MESSAGE: return Qnil;
|
714
|
+
case UPB_TYPE_ENUM: {
|
715
|
+
const upb_enumdef *enumdef = upb_fielddef_enumsubdef(field);
|
716
|
+
int32_t num = upb_fielddef_defaultint32(field);
|
717
|
+
const char *label = upb_enumdef_iton(enumdef, num);
|
718
|
+
if (label) {
|
719
|
+
return ID2SYM(rb_intern(label));
|
720
|
+
} else {
|
721
|
+
return INT2NUM(num);
|
722
|
+
}
|
723
|
+
}
|
724
|
+
case UPB_TYPE_INT32: return INT2NUM(upb_fielddef_defaultint32(field));
|
725
|
+
case UPB_TYPE_INT64: return LL2NUM(upb_fielddef_defaultint64(field));;
|
726
|
+
case UPB_TYPE_UINT32: return UINT2NUM(upb_fielddef_defaultuint32(field));
|
727
|
+
case UPB_TYPE_UINT64: return ULL2NUM(upb_fielddef_defaultuint64(field));
|
728
|
+
case UPB_TYPE_STRING:
|
729
|
+
case UPB_TYPE_BYTES: {
|
730
|
+
size_t size;
|
731
|
+
const char *str = upb_fielddef_defaultstr(field, &size);
|
732
|
+
VALUE str_rb = rb_str_new(str, size);
|
733
|
+
|
734
|
+
rb_enc_associate(str_rb, (upb_fielddef_type(field) == UPB_TYPE_BYTES) ?
|
735
|
+
kRubyString8bitEncoding : kRubyStringUtf8Encoding);
|
736
|
+
rb_obj_freeze(str_rb);
|
737
|
+
return str_rb;
|
738
|
+
}
|
739
|
+
default: return Qnil;
|
740
|
+
}
|
741
|
+
}
|
561
742
|
|
562
743
|
VALUE layout_get(MessageLayout* layout,
|
563
744
|
const void* storage,
|
@@ -565,15 +746,24 @@ VALUE layout_get(MessageLayout* layout,
|
|
565
746
|
void* memory = slot_memory(layout, storage, field);
|
566
747
|
uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
|
567
748
|
|
749
|
+
bool field_set;
|
750
|
+
if (field_contains_hasbit(layout, field)) {
|
751
|
+
field_set = slot_is_hasbit_set(layout, storage, field);
|
752
|
+
} else {
|
753
|
+
field_set = true;
|
754
|
+
}
|
755
|
+
|
568
756
|
if (upb_fielddef_containingoneof(field)) {
|
569
757
|
if (*oneof_case != upb_fielddef_number(field)) {
|
570
|
-
return
|
758
|
+
return layout_get_default(field);
|
571
759
|
}
|
572
760
|
return native_slot_get(upb_fielddef_type(field),
|
573
761
|
field_type_class(field),
|
574
762
|
memory);
|
575
763
|
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
576
764
|
return *((VALUE *)memory);
|
765
|
+
} else if (!field_set) {
|
766
|
+
return layout_get_default(field);
|
577
767
|
} else {
|
578
768
|
return native_slot_get(upb_fielddef_type(field),
|
579
769
|
field_type_class(field),
|
@@ -587,20 +777,28 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
|
|
587
777
|
|
588
778
|
if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
|
589
779
|
RTYPEDDATA_TYPE(val) != &RepeatedField_type) {
|
590
|
-
rb_raise(
|
780
|
+
rb_raise(cTypeError, "Expected repeated field array");
|
591
781
|
}
|
592
782
|
|
593
783
|
self = ruby_to_RepeatedField(val);
|
594
784
|
if (self->field_type != upb_fielddef_type(field)) {
|
595
|
-
rb_raise(
|
785
|
+
rb_raise(cTypeError, "Repeated field array has wrong element type");
|
596
786
|
}
|
597
787
|
|
598
|
-
if (self->field_type == UPB_TYPE_MESSAGE
|
599
|
-
self->field_type == UPB_TYPE_ENUM) {
|
788
|
+
if (self->field_type == UPB_TYPE_MESSAGE) {
|
600
789
|
if (self->field_type_class !=
|
601
|
-
get_def_obj(upb_fielddef_subdef(field))) {
|
602
|
-
rb_raise(
|
603
|
-
"Repeated field array has wrong message
|
790
|
+
Descriptor_msgclass(get_def_obj(upb_fielddef_subdef(field)))) {
|
791
|
+
rb_raise(cTypeError,
|
792
|
+
"Repeated field array has wrong message class");
|
793
|
+
}
|
794
|
+
}
|
795
|
+
|
796
|
+
|
797
|
+
if (self->field_type == UPB_TYPE_ENUM) {
|
798
|
+
if (self->field_type_class !=
|
799
|
+
EnumDescriptor_enummodule(get_def_obj(upb_fielddef_subdef(field)))) {
|
800
|
+
rb_raise(cTypeError,
|
801
|
+
"Repeated field array has wrong enum class");
|
604
802
|
}
|
605
803
|
}
|
606
804
|
}
|
@@ -612,21 +810,21 @@ static void check_map_field_type(VALUE val, const upb_fielddef* field) {
|
|
612
810
|
|
613
811
|
if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
|
614
812
|
RTYPEDDATA_TYPE(val) != &Map_type) {
|
615
|
-
rb_raise(
|
813
|
+
rb_raise(cTypeError, "Expected Map instance");
|
616
814
|
}
|
617
815
|
|
618
816
|
self = ruby_to_Map(val);
|
619
817
|
if (self->key_type != upb_fielddef_type(key_field)) {
|
620
|
-
rb_raise(
|
818
|
+
rb_raise(cTypeError, "Map key type does not match field's key type");
|
621
819
|
}
|
622
820
|
if (self->value_type != upb_fielddef_type(value_field)) {
|
623
|
-
rb_raise(
|
821
|
+
rb_raise(cTypeError, "Map value type does not match field's value type");
|
624
822
|
}
|
625
823
|
if (upb_fielddef_type(value_field) == UPB_TYPE_MESSAGE ||
|
626
824
|
upb_fielddef_type(value_field) == UPB_TYPE_ENUM) {
|
627
825
|
if (self->value_type_class !=
|
628
826
|
get_def_obj(upb_fielddef_subdef(value_field))) {
|
629
|
-
rb_raise(
|
827
|
+
rb_raise(cTypeError,
|
630
828
|
"Map value type has wrong message/enum class");
|
631
829
|
}
|
632
830
|
}
|
@@ -659,6 +857,7 @@ void layout_set(MessageLayout* layout,
|
|
659
857
|
// use native_slot_set_value_and_case(), which ensures that both the value
|
660
858
|
// and case number are altered atomically (w.r.t. the Ruby VM).
|
661
859
|
native_slot_set_value_and_case(
|
860
|
+
upb_fielddef_name(field),
|
662
861
|
upb_fielddef_type(field), field_type_class(field),
|
663
862
|
memory, val,
|
664
863
|
oneof_case, upb_fielddef_number(field));
|
@@ -670,67 +869,25 @@ void layout_set(MessageLayout* layout,
|
|
670
869
|
check_repeated_field_type(val, field);
|
671
870
|
DEREF(memory, VALUE) = val;
|
672
871
|
} else {
|
673
|
-
native_slot_set(
|
872
|
+
native_slot_set(upb_fielddef_name(field),
|
873
|
+
upb_fielddef_type(field), field_type_class(field),
|
674
874
|
memory, val);
|
675
875
|
}
|
876
|
+
|
877
|
+
if (layout->fields[upb_fielddef_index(field)].hasbit !=
|
878
|
+
MESSAGE_FIELD_NO_HASBIT) {
|
879
|
+
slot_set_hasbit(layout, storage, field);
|
880
|
+
}
|
676
881
|
}
|
677
882
|
|
678
883
|
void layout_init(MessageLayout* layout,
|
679
884
|
void* storage) {
|
885
|
+
|
680
886
|
upb_msg_field_iter it;
|
681
887
|
for (upb_msg_field_begin(&it, layout->msgdef);
|
682
888
|
!upb_msg_field_done(&it);
|
683
889
|
upb_msg_field_next(&it)) {
|
684
|
-
|
685
|
-
void* memory = slot_memory(layout, storage, field);
|
686
|
-
uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
|
687
|
-
|
688
|
-
if (upb_fielddef_containingoneof(field)) {
|
689
|
-
memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
|
690
|
-
*oneof_case = ONEOF_CASE_NONE;
|
691
|
-
} else if (is_map_field(field)) {
|
692
|
-
VALUE map = Qnil;
|
693
|
-
|
694
|
-
const upb_fielddef* key_field = map_field_key(field);
|
695
|
-
const upb_fielddef* value_field = map_field_value(field);
|
696
|
-
VALUE type_class = field_type_class(value_field);
|
697
|
-
|
698
|
-
if (type_class != Qnil) {
|
699
|
-
VALUE args[3] = {
|
700
|
-
fieldtype_to_ruby(upb_fielddef_type(key_field)),
|
701
|
-
fieldtype_to_ruby(upb_fielddef_type(value_field)),
|
702
|
-
type_class,
|
703
|
-
};
|
704
|
-
map = rb_class_new_instance(3, args, cMap);
|
705
|
-
} else {
|
706
|
-
VALUE args[2] = {
|
707
|
-
fieldtype_to_ruby(upb_fielddef_type(key_field)),
|
708
|
-
fieldtype_to_ruby(upb_fielddef_type(value_field)),
|
709
|
-
};
|
710
|
-
map = rb_class_new_instance(2, args, cMap);
|
711
|
-
}
|
712
|
-
|
713
|
-
DEREF(memory, VALUE) = map;
|
714
|
-
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
715
|
-
VALUE ary = Qnil;
|
716
|
-
|
717
|
-
VALUE type_class = field_type_class(field);
|
718
|
-
|
719
|
-
if (type_class != Qnil) {
|
720
|
-
VALUE args[2] = {
|
721
|
-
fieldtype_to_ruby(upb_fielddef_type(field)),
|
722
|
-
type_class,
|
723
|
-
};
|
724
|
-
ary = rb_class_new_instance(2, args, cRepeatedField);
|
725
|
-
} else {
|
726
|
-
VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
|
727
|
-
ary = rb_class_new_instance(1, args, cRepeatedField);
|
728
|
-
}
|
729
|
-
|
730
|
-
DEREF(memory, VALUE) = ary;
|
731
|
-
} else {
|
732
|
-
native_slot_init(upb_fielddef_type(field), memory);
|
733
|
-
}
|
890
|
+
layout_clear(layout, storage, upb_msg_iter_field(&it));
|
734
891
|
}
|
735
892
|
}
|
736
893
|
|
@@ -777,6 +934,11 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
|
|
777
934
|
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
778
935
|
DEREF(to_memory, VALUE) = RepeatedField_dup(DEREF(from_memory, VALUE));
|
779
936
|
} else {
|
937
|
+
if (field_contains_hasbit(layout, field)) {
|
938
|
+
if (!slot_is_hasbit_set(layout, from, field)) continue;
|
939
|
+
slot_set_hasbit(layout, to, field);
|
940
|
+
}
|
941
|
+
|
780
942
|
native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
|
781
943
|
}
|
782
944
|
}
|
@@ -806,6 +968,11 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
|
|
806
968
|
DEREF(to_memory, VALUE) =
|
807
969
|
RepeatedField_deep_copy(DEREF(from_memory, VALUE));
|
808
970
|
} else {
|
971
|
+
if (field_contains_hasbit(layout, field)) {
|
972
|
+
if (!slot_is_hasbit_set(layout, from, field)) continue;
|
973
|
+
slot_set_hasbit(layout, to, field);
|
974
|
+
}
|
975
|
+
|
809
976
|
native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
|
810
977
|
}
|
811
978
|
}
|
@@ -842,8 +1009,10 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
|
|
842
1009
|
return Qfalse;
|
843
1010
|
}
|
844
1011
|
} else {
|
845
|
-
if (
|
846
|
-
|
1012
|
+
if (slot_is_hasbit_set(layout, msg1, field) !=
|
1013
|
+
slot_is_hasbit_set(layout, msg2, field) ||
|
1014
|
+
!native_slot_eq(upb_fielddef_type(field),
|
1015
|
+
msg1_memory, msg2_memory)) {
|
847
1016
|
return Qfalse;
|
848
1017
|
}
|
849
1018
|
}
|