google-protobuf 3.6.1 → 3.9.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of google-protobuf might be problematic. Click here for more details.
- 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
|
}
|