google-protobuf 3.6.1 → 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 +4 -4
- data/ext/google/protobuf_c/defs.c +553 -70
- data/ext/google/protobuf_c/encode_decode.c +281 -66
- data/ext/google/protobuf_c/extconf.rb +5 -1
- data/ext/google/protobuf_c/map.c +8 -3
- data/ext/google/protobuf_c/message.c +253 -72
- data/ext/google/protobuf_c/protobuf.c +4 -0
- data/ext/google/protobuf_c/protobuf.h +67 -5
- data/ext/google/protobuf_c/repeated_field.c +9 -3
- data/ext/google/protobuf_c/storage.c +265 -115
- data/ext/google/protobuf_c/upb.c +4329 -1745
- data/ext/google/protobuf_c/upb.h +2190 -518
- data/ext/google/protobuf_c/wrap_memcpy.c +1 -1
- data/lib/google/protobuf.rb +3 -2
- 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/repeated_field.rb +1 -1
- 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 +12 -0
- data/lib/google/protobuf/wrappers_pb.rb +28 -26
- data/tests/basic.rb +174 -1192
- data/tests/generated_code_test.rb +5 -3
- metadata +4 -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,18 +91,21 @@ 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
|
|
106
110
|
rb_define_singleton_method(protobuf, "discard_unknown",
|
107
111
|
Google_Protobuf_discard_unknown, 1);
|
@@ -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
|
/*
|
@@ -118,6 +122,10 @@ struct Descriptor {
|
|
118
122
|
const upb_handlers* json_serialize_handlers_preserve;
|
119
123
|
};
|
120
124
|
|
125
|
+
struct FileDescriptor {
|
126
|
+
const upb_filedef* filedef;
|
127
|
+
};
|
128
|
+
|
121
129
|
struct FieldDescriptor {
|
122
130
|
const upb_fielddef* fielddef;
|
123
131
|
};
|
@@ -145,22 +153,32 @@ struct EnumBuilderContext {
|
|
145
153
|
VALUE enumdesc;
|
146
154
|
};
|
147
155
|
|
156
|
+
struct FileBuilderContext {
|
157
|
+
VALUE pending_list;
|
158
|
+
VALUE file_descriptor;
|
159
|
+
VALUE builder;
|
160
|
+
};
|
161
|
+
|
148
162
|
struct Builder {
|
149
163
|
VALUE pending_list;
|
164
|
+
VALUE default_file_descriptor;
|
150
165
|
upb_def** defs; // used only while finalizing
|
151
166
|
};
|
152
167
|
|
153
168
|
extern VALUE cDescriptorPool;
|
154
169
|
extern VALUE cDescriptor;
|
170
|
+
extern VALUE cFileDescriptor;
|
155
171
|
extern VALUE cFieldDescriptor;
|
156
172
|
extern VALUE cEnumDescriptor;
|
157
173
|
extern VALUE cMessageBuilderContext;
|
158
174
|
extern VALUE cOneofBuilderContext;
|
159
175
|
extern VALUE cEnumBuilderContext;
|
176
|
+
extern VALUE cFileBuilderContext;
|
160
177
|
extern VALUE cBuilder;
|
161
178
|
|
162
179
|
extern VALUE cError;
|
163
180
|
extern VALUE cParseError;
|
181
|
+
extern VALUE cTypeError;
|
164
182
|
|
165
183
|
// We forward-declare all of the Ruby method implementations here because we
|
166
184
|
// sometimes call the methods directly across .c files, rather than going
|
@@ -174,15 +192,18 @@ VALUE DescriptorPool_alloc(VALUE klass);
|
|
174
192
|
void DescriptorPool_register(VALUE module);
|
175
193
|
DescriptorPool* ruby_to_DescriptorPool(VALUE value);
|
176
194
|
VALUE DescriptorPool_add(VALUE _self, VALUE def);
|
177
|
-
VALUE DescriptorPool_build(VALUE _self);
|
195
|
+
VALUE DescriptorPool_build(int argc, VALUE* argv, VALUE _self);
|
178
196
|
VALUE DescriptorPool_lookup(VALUE _self, VALUE name);
|
179
197
|
VALUE DescriptorPool_generated_pool(VALUE _self);
|
180
198
|
|
199
|
+
extern VALUE generated_pool;
|
200
|
+
|
181
201
|
void Descriptor_mark(void* _self);
|
182
202
|
void Descriptor_free(void* _self);
|
183
203
|
VALUE Descriptor_alloc(VALUE klass);
|
184
204
|
void Descriptor_register(VALUE module);
|
185
205
|
Descriptor* ruby_to_Descriptor(VALUE value);
|
206
|
+
VALUE Descriptor_initialize(VALUE _self, VALUE file_descriptor_rb);
|
186
207
|
VALUE Descriptor_name(VALUE _self);
|
187
208
|
VALUE Descriptor_name_set(VALUE _self, VALUE str);
|
188
209
|
VALUE Descriptor_each(VALUE _self);
|
@@ -192,8 +213,19 @@ VALUE Descriptor_add_oneof(VALUE _self, VALUE obj);
|
|
192
213
|
VALUE Descriptor_each_oneof(VALUE _self);
|
193
214
|
VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name);
|
194
215
|
VALUE Descriptor_msgclass(VALUE _self);
|
216
|
+
VALUE Descriptor_file_descriptor(VALUE _self);
|
195
217
|
extern const rb_data_type_t _Descriptor_type;
|
196
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
|
+
|
197
229
|
void FieldDescriptor_mark(void* _self);
|
198
230
|
void FieldDescriptor_free(void* _self);
|
199
231
|
VALUE FieldDescriptor_alloc(VALUE klass);
|
@@ -203,6 +235,8 @@ VALUE FieldDescriptor_name(VALUE _self);
|
|
203
235
|
VALUE FieldDescriptor_name_set(VALUE _self, VALUE str);
|
204
236
|
VALUE FieldDescriptor_type(VALUE _self);
|
205
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);
|
206
240
|
VALUE FieldDescriptor_label(VALUE _self);
|
207
241
|
VALUE FieldDescriptor_label_set(VALUE _self, VALUE label);
|
208
242
|
VALUE FieldDescriptor_number(VALUE _self);
|
@@ -210,6 +244,8 @@ VALUE FieldDescriptor_number_set(VALUE _self, VALUE number);
|
|
210
244
|
VALUE FieldDescriptor_submsg_name(VALUE _self);
|
211
245
|
VALUE FieldDescriptor_submsg_name_set(VALUE _self, VALUE value);
|
212
246
|
VALUE FieldDescriptor_subtype(VALUE _self);
|
247
|
+
VALUE FieldDescriptor_has(VALUE _self, VALUE msg_rb);
|
248
|
+
VALUE FieldDescriptor_clear(VALUE _self, VALUE msg_rb);
|
213
249
|
VALUE FieldDescriptor_get(VALUE _self, VALUE msg_rb);
|
214
250
|
VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value);
|
215
251
|
upb_fieldtype_t ruby_to_fieldtype(VALUE type);
|
@@ -230,6 +266,8 @@ void EnumDescriptor_free(void* _self);
|
|
230
266
|
VALUE EnumDescriptor_alloc(VALUE klass);
|
231
267
|
void EnumDescriptor_register(VALUE module);
|
232
268
|
EnumDescriptor* ruby_to_EnumDescriptor(VALUE value);
|
269
|
+
VALUE EnumDescriptor_initialize(VALUE _self, VALUE file_descriptor_rb);
|
270
|
+
VALUE EnumDescriptor_file_descriptor(VALUE _self);
|
233
271
|
VALUE EnumDescriptor_name(VALUE _self);
|
234
272
|
VALUE EnumDescriptor_name_set(VALUE _self, VALUE str);
|
235
273
|
VALUE EnumDescriptor_add_value(VALUE _self, VALUE name, VALUE number);
|
@@ -271,12 +309,23 @@ EnumBuilderContext* ruby_to_EnumBuilderContext(VALUE value);
|
|
271
309
|
VALUE EnumBuilderContext_initialize(VALUE _self, VALUE enumdesc);
|
272
310
|
VALUE EnumBuilderContext_value(VALUE _self, VALUE name, VALUE number);
|
273
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
|
+
|
274
322
|
void Builder_mark(void* _self);
|
275
323
|
void Builder_free(void* _self);
|
276
324
|
VALUE Builder_alloc(VALUE klass);
|
277
325
|
void Builder_register(VALUE module);
|
278
326
|
Builder* ruby_to_Builder(VALUE value);
|
279
327
|
VALUE Builder_initialize(VALUE _self);
|
328
|
+
VALUE Builder_add_file(int argc, VALUE *argv, VALUE _self);
|
280
329
|
VALUE Builder_add_message(VALUE _self, VALUE name);
|
281
330
|
VALUE Builder_add_enum(VALUE _self, VALUE name);
|
282
331
|
VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb);
|
@@ -288,14 +337,16 @@ VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb);
|
|
288
337
|
#define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t)
|
289
338
|
|
290
339
|
size_t native_slot_size(upb_fieldtype_t type);
|
291
|
-
void native_slot_set(
|
340
|
+
void native_slot_set(const char* name,
|
341
|
+
upb_fieldtype_t type,
|
292
342
|
VALUE type_class,
|
293
343
|
void* memory,
|
294
344
|
VALUE value);
|
295
345
|
// Atomically (with respect to Ruby VM calls) either update the value and set a
|
296
346
|
// oneof case, or do neither. If |case_memory| is null, then no case value is
|
297
347
|
// set.
|
298
|
-
void native_slot_set_value_and_case(
|
348
|
+
void native_slot_set_value_and_case(const char* name,
|
349
|
+
upb_fieldtype_t type,
|
299
350
|
VALUE type_class,
|
300
351
|
void* memory,
|
301
352
|
VALUE value,
|
@@ -311,7 +362,7 @@ void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from);
|
|
311
362
|
bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2);
|
312
363
|
|
313
364
|
VALUE native_slot_encode_and_freeze_string(upb_fieldtype_t type, VALUE value);
|
314
|
-
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);
|
315
366
|
|
316
367
|
extern rb_encoding* kRubyStringUtf8Encoding;
|
317
368
|
extern rb_encoding* kRubyStringASCIIEncoding;
|
@@ -442,10 +493,12 @@ VALUE Map_iter_value(Map_iter* iter);
|
|
442
493
|
// -----------------------------------------------------------------------------
|
443
494
|
|
444
495
|
#define MESSAGE_FIELD_NO_CASE ((size_t)-1)
|
496
|
+
#define MESSAGE_FIELD_NO_HASBIT ((size_t)-1)
|
445
497
|
|
446
498
|
struct MessageField {
|
447
499
|
size_t offset;
|
448
500
|
size_t case_offset; // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE.
|
501
|
+
size_t hasbit;
|
449
502
|
};
|
450
503
|
|
451
504
|
struct MessageLayout {
|
@@ -456,6 +509,9 @@ struct MessageLayout {
|
|
456
509
|
|
457
510
|
MessageLayout* create_layout(const upb_msgdef* msgdef);
|
458
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);
|
459
515
|
VALUE layout_get(MessageLayout* layout,
|
460
516
|
const void* storage,
|
461
517
|
const upb_fielddef* field);
|
@@ -463,6 +519,12 @@ void layout_set(MessageLayout* layout,
|
|
463
519
|
void* storage,
|
464
520
|
const upb_fielddef* field,
|
465
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);
|
466
528
|
void layout_init(MessageLayout* layout, void* storage);
|
467
529
|
void layout_mark(MessageLayout* layout, void* storage);
|
468
530
|
void layout_dup(MessageLayout* layout, void* to, void* from);
|
@@ -512,7 +574,7 @@ VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value);
|
|
512
574
|
VALUE Message_descriptor(VALUE klass);
|
513
575
|
VALUE Message_decode(VALUE klass, VALUE data);
|
514
576
|
VALUE Message_encode(VALUE klass, VALUE msg_rb);
|
515
|
-
VALUE Message_decode_json(VALUE
|
577
|
+
VALUE Message_decode_json(int argc, VALUE* argv, VALUE klass);
|
516
578
|
VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass);
|
517
579
|
|
518
580
|
VALUE Google_Protobuf_discard_unknown(VALUE self, VALUE msg_rb);
|
@@ -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) {
|
@@ -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,7 +148,8 @@ 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;
|
@@ -179,7 +158,8 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
|
|
179
158
|
if (CLASS_OF(value) == rb_cSymbol) {
|
180
159
|
value = rb_funcall(value, rb_intern("to_s"), 0);
|
181
160
|
} else if (CLASS_OF(value) != rb_cString) {
|
182
|
-
rb_raise(
|
161
|
+
rb_raise(cTypeError, "Invalid argument for string field '%s' (given %s).",
|
162
|
+
name, rb_class2name(CLASS_OF(value)));
|
183
163
|
}
|
184
164
|
|
185
165
|
DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
|
@@ -187,7 +167,8 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
|
|
187
167
|
|
188
168
|
case UPB_TYPE_BYTES: {
|
189
169
|
if (CLASS_OF(value) != rb_cString) {
|
190
|
-
rb_raise(
|
170
|
+
rb_raise(cTypeError, "Invalid argument for bytes field '%s' (given %s).",
|
171
|
+
name, rb_class2name(CLASS_OF(value)));
|
191
172
|
}
|
192
173
|
|
193
174
|
DEREF(memory, VALUE) = native_slot_encode_and_freeze_string(type, value);
|
@@ -197,9 +178,39 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
|
|
197
178
|
if (CLASS_OF(value) == CLASS_OF(Qnil)) {
|
198
179
|
value = Qnil;
|
199
180
|
} else if (CLASS_OF(value) != type_class) {
|
200
|
-
|
201
|
-
|
202
|
-
|
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
|
+
}
|
203
214
|
}
|
204
215
|
DEREF(memory, VALUE) = value;
|
205
216
|
break;
|
@@ -209,19 +220,19 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
|
|
209
220
|
if (TYPE(value) == T_STRING) {
|
210
221
|
value = rb_funcall(value, rb_intern("to_sym"), 0);
|
211
222
|
} else if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) {
|
212
|
-
rb_raise(
|
213
|
-
"Expected number or symbol type for enum field.");
|
223
|
+
rb_raise(cTypeError,
|
224
|
+
"Expected number or symbol type for enum field '%s'.", name);
|
214
225
|
}
|
215
226
|
if (TYPE(value) == T_SYMBOL) {
|
216
227
|
// Ensure that the given symbol exists in the enum module.
|
217
228
|
VALUE lookup = rb_funcall(type_class, rb_intern("resolve"), 1, value);
|
218
229
|
if (lookup == Qnil) {
|
219
|
-
rb_raise(rb_eRangeError, "Unknown symbol value for enum field.");
|
230
|
+
rb_raise(rb_eRangeError, "Unknown symbol value for enum field '%s'.", name);
|
220
231
|
} else {
|
221
232
|
int_val = NUM2INT(lookup);
|
222
233
|
}
|
223
234
|
} else {
|
224
|
-
native_slot_check_int_range_precision(UPB_TYPE_INT32, value);
|
235
|
+
native_slot_check_int_range_precision(name, UPB_TYPE_INT32, value);
|
225
236
|
int_val = NUM2INT(value);
|
226
237
|
}
|
227
238
|
DEREF(memory, int32_t) = int_val;
|
@@ -231,7 +242,7 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
|
|
231
242
|
case UPB_TYPE_INT64:
|
232
243
|
case UPB_TYPE_UINT32:
|
233
244
|
case UPB_TYPE_UINT64:
|
234
|
-
native_slot_check_int_range_precision(type, value);
|
245
|
+
native_slot_check_int_range_precision(name, type, value);
|
235
246
|
switch (type) {
|
236
247
|
case UPB_TYPE_INT32:
|
237
248
|
DEREF(memory, int32_t) = NUM2INT(value);
|
@@ -404,7 +415,12 @@ const upb_msgdef *map_entry_msgdef(const upb_fielddef* field) {
|
|
404
415
|
}
|
405
416
|
|
406
417
|
bool is_map_field(const upb_fielddef *field) {
|
407
|
-
|
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;
|
408
424
|
}
|
409
425
|
|
410
426
|
const upb_fielddef* map_field_key(const upb_fielddef* field) {
|
@@ -433,6 +449,12 @@ const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
|
|
433
449
|
// Memory layout management.
|
434
450
|
// -----------------------------------------------------------------------------
|
435
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
|
+
|
436
458
|
static size_t align_up_to(size_t offset, size_t granularity) {
|
437
459
|
// Granularity must be a power of two.
|
438
460
|
return (offset + granularity - 1) & ~(granularity - 1);
|
@@ -447,6 +469,23 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
|
|
447
469
|
|
448
470
|
layout->fields = ALLOC_N(MessageField, nfields);
|
449
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
|
+
|
450
489
|
for (upb_msg_field_begin(&it, msgdef);
|
451
490
|
!upb_msg_field_done(&it);
|
452
491
|
upb_msg_field_next(&it)) {
|
@@ -569,6 +608,137 @@ static uint32_t* slot_oneof_case(MessageLayout* layout,
|
|
569
608
|
layout->fields[upb_fielddef_index(field)].case_offset);
|
570
609
|
}
|
571
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
|
+
}
|
572
742
|
|
573
743
|
VALUE layout_get(MessageLayout* layout,
|
574
744
|
const void* storage,
|
@@ -576,15 +746,24 @@ VALUE layout_get(MessageLayout* layout,
|
|
576
746
|
void* memory = slot_memory(layout, storage, field);
|
577
747
|
uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
|
578
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
|
+
|
579
756
|
if (upb_fielddef_containingoneof(field)) {
|
580
757
|
if (*oneof_case != upb_fielddef_number(field)) {
|
581
|
-
return
|
758
|
+
return layout_get_default(field);
|
582
759
|
}
|
583
760
|
return native_slot_get(upb_fielddef_type(field),
|
584
761
|
field_type_class(field),
|
585
762
|
memory);
|
586
763
|
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
587
764
|
return *((VALUE *)memory);
|
765
|
+
} else if (!field_set) {
|
766
|
+
return layout_get_default(field);
|
588
767
|
} else {
|
589
768
|
return native_slot_get(upb_fielddef_type(field),
|
590
769
|
field_type_class(field),
|
@@ -598,18 +777,18 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
|
|
598
777
|
|
599
778
|
if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
|
600
779
|
RTYPEDDATA_TYPE(val) != &RepeatedField_type) {
|
601
|
-
rb_raise(
|
780
|
+
rb_raise(cTypeError, "Expected repeated field array");
|
602
781
|
}
|
603
782
|
|
604
783
|
self = ruby_to_RepeatedField(val);
|
605
784
|
if (self->field_type != upb_fielddef_type(field)) {
|
606
|
-
rb_raise(
|
785
|
+
rb_raise(cTypeError, "Repeated field array has wrong element type");
|
607
786
|
}
|
608
787
|
|
609
|
-
if (self->field_type == UPB_TYPE_MESSAGE) {
|
788
|
+
if (self->field_type == UPB_TYPE_MESSAGE) {
|
610
789
|
if (self->field_type_class !=
|
611
790
|
Descriptor_msgclass(get_def_obj(upb_fielddef_subdef(field)))) {
|
612
|
-
rb_raise(
|
791
|
+
rb_raise(cTypeError,
|
613
792
|
"Repeated field array has wrong message class");
|
614
793
|
}
|
615
794
|
}
|
@@ -618,7 +797,7 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
|
|
618
797
|
if (self->field_type == UPB_TYPE_ENUM) {
|
619
798
|
if (self->field_type_class !=
|
620
799
|
EnumDescriptor_enummodule(get_def_obj(upb_fielddef_subdef(field)))) {
|
621
|
-
rb_raise(
|
800
|
+
rb_raise(cTypeError,
|
622
801
|
"Repeated field array has wrong enum class");
|
623
802
|
}
|
624
803
|
}
|
@@ -631,21 +810,21 @@ static void check_map_field_type(VALUE val, const upb_fielddef* field) {
|
|
631
810
|
|
632
811
|
if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
|
633
812
|
RTYPEDDATA_TYPE(val) != &Map_type) {
|
634
|
-
rb_raise(
|
813
|
+
rb_raise(cTypeError, "Expected Map instance");
|
635
814
|
}
|
636
815
|
|
637
816
|
self = ruby_to_Map(val);
|
638
817
|
if (self->key_type != upb_fielddef_type(key_field)) {
|
639
|
-
rb_raise(
|
818
|
+
rb_raise(cTypeError, "Map key type does not match field's key type");
|
640
819
|
}
|
641
820
|
if (self->value_type != upb_fielddef_type(value_field)) {
|
642
|
-
rb_raise(
|
821
|
+
rb_raise(cTypeError, "Map value type does not match field's value type");
|
643
822
|
}
|
644
823
|
if (upb_fielddef_type(value_field) == UPB_TYPE_MESSAGE ||
|
645
824
|
upb_fielddef_type(value_field) == UPB_TYPE_ENUM) {
|
646
825
|
if (self->value_type_class !=
|
647
826
|
get_def_obj(upb_fielddef_subdef(value_field))) {
|
648
|
-
rb_raise(
|
827
|
+
rb_raise(cTypeError,
|
649
828
|
"Map value type has wrong message/enum class");
|
650
829
|
}
|
651
830
|
}
|
@@ -678,6 +857,7 @@ void layout_set(MessageLayout* layout,
|
|
678
857
|
// use native_slot_set_value_and_case(), which ensures that both the value
|
679
858
|
// and case number are altered atomically (w.r.t. the Ruby VM).
|
680
859
|
native_slot_set_value_and_case(
|
860
|
+
upb_fielddef_name(field),
|
681
861
|
upb_fielddef_type(field), field_type_class(field),
|
682
862
|
memory, val,
|
683
863
|
oneof_case, upb_fielddef_number(field));
|
@@ -689,67 +869,25 @@ void layout_set(MessageLayout* layout,
|
|
689
869
|
check_repeated_field_type(val, field);
|
690
870
|
DEREF(memory, VALUE) = val;
|
691
871
|
} else {
|
692
|
-
native_slot_set(
|
872
|
+
native_slot_set(upb_fielddef_name(field),
|
873
|
+
upb_fielddef_type(field), field_type_class(field),
|
693
874
|
memory, val);
|
694
875
|
}
|
876
|
+
|
877
|
+
if (layout->fields[upb_fielddef_index(field)].hasbit !=
|
878
|
+
MESSAGE_FIELD_NO_HASBIT) {
|
879
|
+
slot_set_hasbit(layout, storage, field);
|
880
|
+
}
|
695
881
|
}
|
696
882
|
|
697
883
|
void layout_init(MessageLayout* layout,
|
698
884
|
void* storage) {
|
885
|
+
|
699
886
|
upb_msg_field_iter it;
|
700
887
|
for (upb_msg_field_begin(&it, layout->msgdef);
|
701
888
|
!upb_msg_field_done(&it);
|
702
889
|
upb_msg_field_next(&it)) {
|
703
|
-
|
704
|
-
void* memory = slot_memory(layout, storage, field);
|
705
|
-
uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
|
706
|
-
|
707
|
-
if (upb_fielddef_containingoneof(field)) {
|
708
|
-
memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
|
709
|
-
*oneof_case = ONEOF_CASE_NONE;
|
710
|
-
} else if (is_map_field(field)) {
|
711
|
-
VALUE map = Qnil;
|
712
|
-
|
713
|
-
const upb_fielddef* key_field = map_field_key(field);
|
714
|
-
const upb_fielddef* value_field = map_field_value(field);
|
715
|
-
VALUE type_class = field_type_class(value_field);
|
716
|
-
|
717
|
-
if (type_class != Qnil) {
|
718
|
-
VALUE args[3] = {
|
719
|
-
fieldtype_to_ruby(upb_fielddef_type(key_field)),
|
720
|
-
fieldtype_to_ruby(upb_fielddef_type(value_field)),
|
721
|
-
type_class,
|
722
|
-
};
|
723
|
-
map = rb_class_new_instance(3, args, cMap);
|
724
|
-
} else {
|
725
|
-
VALUE args[2] = {
|
726
|
-
fieldtype_to_ruby(upb_fielddef_type(key_field)),
|
727
|
-
fieldtype_to_ruby(upb_fielddef_type(value_field)),
|
728
|
-
};
|
729
|
-
map = rb_class_new_instance(2, args, cMap);
|
730
|
-
}
|
731
|
-
|
732
|
-
DEREF(memory, VALUE) = map;
|
733
|
-
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
734
|
-
VALUE ary = Qnil;
|
735
|
-
|
736
|
-
VALUE type_class = field_type_class(field);
|
737
|
-
|
738
|
-
if (type_class != Qnil) {
|
739
|
-
VALUE args[2] = {
|
740
|
-
fieldtype_to_ruby(upb_fielddef_type(field)),
|
741
|
-
type_class,
|
742
|
-
};
|
743
|
-
ary = rb_class_new_instance(2, args, cRepeatedField);
|
744
|
-
} else {
|
745
|
-
VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
|
746
|
-
ary = rb_class_new_instance(1, args, cRepeatedField);
|
747
|
-
}
|
748
|
-
|
749
|
-
DEREF(memory, VALUE) = ary;
|
750
|
-
} else {
|
751
|
-
native_slot_init(upb_fielddef_type(field), memory);
|
752
|
-
}
|
890
|
+
layout_clear(layout, storage, upb_msg_iter_field(&it));
|
753
891
|
}
|
754
892
|
}
|
755
893
|
|
@@ -796,6 +934,11 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
|
|
796
934
|
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
797
935
|
DEREF(to_memory, VALUE) = RepeatedField_dup(DEREF(from_memory, VALUE));
|
798
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
|
+
|
799
942
|
native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
|
800
943
|
}
|
801
944
|
}
|
@@ -825,6 +968,11 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
|
|
825
968
|
DEREF(to_memory, VALUE) =
|
826
969
|
RepeatedField_deep_copy(DEREF(from_memory, VALUE));
|
827
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
|
+
|
828
976
|
native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
|
829
977
|
}
|
830
978
|
}
|
@@ -861,8 +1009,10 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
|
|
861
1009
|
return Qfalse;
|
862
1010
|
}
|
863
1011
|
} else {
|
864
|
-
if (
|
865
|
-
|
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)) {
|
866
1016
|
return Qfalse;
|
867
1017
|
}
|
868
1018
|
}
|