google-protobuf 3.0.0.alpha.1.1 → 3.0.0.alpha.2.0
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 +5 -13
- data/ext/google/protobuf_c/defs.c +298 -9
- data/ext/google/protobuf_c/encode_decode.c +204 -29
- data/ext/google/protobuf_c/map.c +1 -1
- data/ext/google/protobuf_c/message.c +44 -0
- data/ext/google/protobuf_c/protobuf.c +2 -0
- data/ext/google/protobuf_c/protobuf.h +61 -2
- data/ext/google/protobuf_c/repeated_field.c +28 -31
- data/ext/google/protobuf_c/storage.c +230 -66
- data/ext/google/protobuf_c/upb.c +938 -153
- data/ext/google/protobuf_c/upb.h +607 -55
- data/tests/basic.rb +114 -2
- data/tests/generated_code_test.rb +17 -0
- metadata +7 -5
data/ext/google/protobuf_c/map.c
CHANGED
@@ -683,7 +683,7 @@ VALUE Map_inspect(VALUE _self) {
|
|
683
683
|
first = false;
|
684
684
|
}
|
685
685
|
str = rb_str_append(str, rb_funcall(key, inspect_sym, 0));
|
686
|
-
str = rb_str_cat2(str, "
|
686
|
+
str = rb_str_cat2(str, "=>");
|
687
687
|
str = rb_str_append(str, rb_funcall(value, inspect_sym, 0));
|
688
688
|
}
|
689
689
|
|
@@ -70,6 +70,35 @@ VALUE Message_alloc(VALUE klass) {
|
|
70
70
|
return ret;
|
71
71
|
}
|
72
72
|
|
73
|
+
static VALUE which_oneof_field(MessageHeader* self, const upb_oneofdef* o) {
|
74
|
+
// If no fields in the oneof, always nil.
|
75
|
+
if (upb_oneofdef_numfields(o) == 0) {
|
76
|
+
return Qnil;
|
77
|
+
}
|
78
|
+
// Grab the first field in the oneof so we can get its layout info to find the
|
79
|
+
// oneof_case field.
|
80
|
+
upb_oneof_iter it;
|
81
|
+
upb_oneof_begin(&it, o);
|
82
|
+
assert(!upb_oneof_done(&it));
|
83
|
+
const upb_fielddef* first_field = upb_oneof_iter_field(&it);
|
84
|
+
assert(upb_fielddef_containingoneof(first_field) != NULL);
|
85
|
+
|
86
|
+
size_t case_ofs =
|
87
|
+
self->descriptor->layout->
|
88
|
+
fields[upb_fielddef_index(first_field)].case_offset;
|
89
|
+
uint32_t oneof_case = *((uint32_t*)(Message_data(self) + case_ofs));
|
90
|
+
|
91
|
+
if (oneof_case == ONEOF_CASE_NONE) {
|
92
|
+
return Qnil;
|
93
|
+
}
|
94
|
+
|
95
|
+
// oneof_case is a field index, so find that field.
|
96
|
+
const upb_fielddef* f = upb_oneofdef_itof(o, oneof_case);
|
97
|
+
assert(f != NULL);
|
98
|
+
|
99
|
+
return ID2SYM(rb_intern(upb_fielddef_name(f)));
|
100
|
+
}
|
101
|
+
|
73
102
|
/*
|
74
103
|
* call-seq:
|
75
104
|
* Message.method_missing(*args)
|
@@ -82,6 +111,10 @@ VALUE Message_alloc(VALUE klass) {
|
|
82
111
|
*
|
83
112
|
* msg.foo = 42
|
84
113
|
* puts msg.foo
|
114
|
+
*
|
115
|
+
* This method also provides read-only accessors for oneofs. If a oneof exists
|
116
|
+
* with name 'my_oneof', then msg.my_oneof will return a Ruby symbol equal to
|
117
|
+
* the name of the field in that oneof that is currently set, or nil if none.
|
85
118
|
*/
|
86
119
|
VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
87
120
|
MessageHeader* self;
|
@@ -104,6 +137,17 @@ VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
|
104
137
|
name_len--;
|
105
138
|
}
|
106
139
|
|
140
|
+
// Check for a oneof name first.
|
141
|
+
const upb_oneofdef* o = upb_msgdef_ntoo(self->descriptor->msgdef,
|
142
|
+
name, name_len);
|
143
|
+
if (o != NULL) {
|
144
|
+
if (setter) {
|
145
|
+
rb_raise(rb_eRuntimeError, "Oneof accessors are read-only.");
|
146
|
+
}
|
147
|
+
return which_oneof_field(self, o);
|
148
|
+
}
|
149
|
+
|
150
|
+
// Otherwise, check for a field with that name.
|
107
151
|
const upb_fielddef* f = upb_msgdef_ntof(self->descriptor->msgdef,
|
108
152
|
name, name_len);
|
109
153
|
|
@@ -77,8 +77,10 @@ void Init_protobuf_c() {
|
|
77
77
|
DescriptorPool_register(protobuf);
|
78
78
|
Descriptor_register(protobuf);
|
79
79
|
FieldDescriptor_register(protobuf);
|
80
|
+
OneofDescriptor_register(protobuf);
|
80
81
|
EnumDescriptor_register(protobuf);
|
81
82
|
MessageBuilderContext_register(internal);
|
83
|
+
OneofBuilderContext_register(internal);
|
82
84
|
EnumBuilderContext_register(internal);
|
83
85
|
Builder_register(internal);
|
84
86
|
RepeatedField_register(protobuf);
|
@@ -43,6 +43,7 @@ struct Descriptor;
|
|
43
43
|
struct FieldDescriptor;
|
44
44
|
struct EnumDescriptor;
|
45
45
|
struct MessageLayout;
|
46
|
+
struct MessageField;
|
46
47
|
struct MessageHeader;
|
47
48
|
struct MessageBuilderContext;
|
48
49
|
struct EnumBuilderContext;
|
@@ -51,10 +52,13 @@ struct Builder;
|
|
51
52
|
typedef struct DescriptorPool DescriptorPool;
|
52
53
|
typedef struct Descriptor Descriptor;
|
53
54
|
typedef struct FieldDescriptor FieldDescriptor;
|
55
|
+
typedef struct OneofDescriptor OneofDescriptor;
|
54
56
|
typedef struct EnumDescriptor EnumDescriptor;
|
55
57
|
typedef struct MessageLayout MessageLayout;
|
58
|
+
typedef struct MessageField MessageField;
|
56
59
|
typedef struct MessageHeader MessageHeader;
|
57
60
|
typedef struct MessageBuilderContext MessageBuilderContext;
|
61
|
+
typedef struct OneofBuilderContext OneofBuilderContext;
|
58
62
|
typedef struct EnumBuilderContext EnumBuilderContext;
|
59
63
|
typedef struct Builder Builder;
|
60
64
|
|
@@ -120,6 +124,10 @@ struct FieldDescriptor {
|
|
120
124
|
const upb_fielddef* fielddef;
|
121
125
|
};
|
122
126
|
|
127
|
+
struct OneofDescriptor {
|
128
|
+
const upb_oneofdef* oneofdef;
|
129
|
+
};
|
130
|
+
|
123
131
|
struct EnumDescriptor {
|
124
132
|
const upb_enumdef* enumdef;
|
125
133
|
VALUE module; // begins as nil
|
@@ -130,6 +138,11 @@ struct MessageBuilderContext {
|
|
130
138
|
VALUE builder;
|
131
139
|
};
|
132
140
|
|
141
|
+
struct OneofBuilderContext {
|
142
|
+
VALUE descriptor;
|
143
|
+
VALUE builder;
|
144
|
+
};
|
145
|
+
|
133
146
|
struct EnumBuilderContext {
|
134
147
|
VALUE enumdesc;
|
135
148
|
};
|
@@ -144,6 +157,7 @@ extern VALUE cDescriptor;
|
|
144
157
|
extern VALUE cFieldDescriptor;
|
145
158
|
extern VALUE cEnumDescriptor;
|
146
159
|
extern VALUE cMessageBuilderContext;
|
160
|
+
extern VALUE cOneofBuilderContext;
|
147
161
|
extern VALUE cEnumBuilderContext;
|
148
162
|
extern VALUE cBuilder;
|
149
163
|
|
@@ -175,6 +189,9 @@ VALUE Descriptor_name_set(VALUE _self, VALUE str);
|
|
175
189
|
VALUE Descriptor_each(VALUE _self);
|
176
190
|
VALUE Descriptor_lookup(VALUE _self, VALUE name);
|
177
191
|
VALUE Descriptor_add_field(VALUE _self, VALUE obj);
|
192
|
+
VALUE Descriptor_add_oneof(VALUE _self, VALUE obj);
|
193
|
+
VALUE Descriptor_each_oneof(VALUE _self);
|
194
|
+
VALUE Descriptor_lookup_oneof(VALUE _self, VALUE name);
|
178
195
|
VALUE Descriptor_msgclass(VALUE _self);
|
179
196
|
extern const rb_data_type_t _Descriptor_type;
|
180
197
|
|
@@ -199,6 +216,16 @@ VALUE FieldDescriptor_set(VALUE _self, VALUE msg_rb, VALUE value);
|
|
199
216
|
upb_fieldtype_t ruby_to_fieldtype(VALUE type);
|
200
217
|
VALUE fieldtype_to_ruby(upb_fieldtype_t type);
|
201
218
|
|
219
|
+
void OneofDescriptor_mark(void* _self);
|
220
|
+
void OneofDescriptor_free(void* _self);
|
221
|
+
VALUE OneofDescriptor_alloc(VALUE klass);
|
222
|
+
void OneofDescriptor_register(VALUE module);
|
223
|
+
OneofDescriptor* ruby_to_OneofDescriptor(VALUE value);
|
224
|
+
VALUE OneofDescriptor_name(VALUE _self);
|
225
|
+
VALUE OneofDescriptor_name_set(VALUE _self, VALUE value);
|
226
|
+
VALUE OneofDescriptor_add_field(VALUE _self, VALUE field);
|
227
|
+
VALUE OneofDescriptor_each(VALUE _self, VALUE field);
|
228
|
+
|
202
229
|
void EnumDescriptor_mark(void* _self);
|
203
230
|
void EnumDescriptor_free(void* _self);
|
204
231
|
VALUE EnumDescriptor_alloc(VALUE klass);
|
@@ -225,6 +252,17 @@ VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self);
|
|
225
252
|
VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self);
|
226
253
|
VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self);
|
227
254
|
VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self);
|
255
|
+
VALUE MessageBuilderContext_oneof(VALUE _self, VALUE name);
|
256
|
+
|
257
|
+
void OneofBuilderContext_mark(void* _self);
|
258
|
+
void OneofBuilderContext_free(void* _self);
|
259
|
+
VALUE OneofBuilderContext_alloc(VALUE klass);
|
260
|
+
void OneofBuilderContext_register(VALUE module);
|
261
|
+
OneofBuilderContext* ruby_to_OneofBuilderContext(VALUE value);
|
262
|
+
VALUE OneofBuilderContext_initialize(VALUE _self,
|
263
|
+
VALUE descriptor,
|
264
|
+
VALUE builder);
|
265
|
+
VALUE OneofBuilderContext_optional(int argc, VALUE* argv, VALUE _self);
|
228
266
|
|
229
267
|
void EnumBuilderContext_mark(void* _self);
|
230
268
|
void EnumBuilderContext_free(void* _self);
|
@@ -247,13 +285,22 @@ VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb);
|
|
247
285
|
// Native slot storage abstraction.
|
248
286
|
// -----------------------------------------------------------------------------
|
249
287
|
|
250
|
-
#define NATIVE_SLOT_MAX_SIZE sizeof(
|
288
|
+
#define NATIVE_SLOT_MAX_SIZE sizeof(uint64_t)
|
251
289
|
|
252
290
|
size_t native_slot_size(upb_fieldtype_t type);
|
253
291
|
void native_slot_set(upb_fieldtype_t type,
|
254
292
|
VALUE type_class,
|
255
293
|
void* memory,
|
256
294
|
VALUE value);
|
295
|
+
// Atomically (with respect to Ruby VM calls) either update the value and set a
|
296
|
+
// oneof case, or do neither. If |case_memory| is null, then no case value is
|
297
|
+
// set.
|
298
|
+
void native_slot_set_value_and_case(upb_fieldtype_t type,
|
299
|
+
VALUE type_class,
|
300
|
+
void* memory,
|
301
|
+
VALUE value,
|
302
|
+
uint32_t* case_memory,
|
303
|
+
uint32_t case_number);
|
257
304
|
VALUE native_slot_get(upb_fieldtype_t type,
|
258
305
|
VALUE type_class,
|
259
306
|
const void* memory);
|
@@ -275,6 +322,11 @@ VALUE field_type_class(const upb_fielddef* field);
|
|
275
322
|
#define MAP_KEY_FIELD 1
|
276
323
|
#define MAP_VALUE_FIELD 2
|
277
324
|
|
325
|
+
// Oneof case slot value to indicate that no oneof case is set. The value `0` is
|
326
|
+
// safe because field numbers are used as case identifiers, and no field can
|
327
|
+
// have a number of 0.
|
328
|
+
#define ONEOF_CASE_NONE 0
|
329
|
+
|
278
330
|
// These operate on a map field (i.e., a repeated field of submessages whose
|
279
331
|
// submessage type is a map-entry msgdef).
|
280
332
|
bool is_map_field(const upb_fielddef* field);
|
@@ -384,9 +436,16 @@ VALUE Map_iter_value(Map_iter* iter);
|
|
384
436
|
// Message layout / storage.
|
385
437
|
// -----------------------------------------------------------------------------
|
386
438
|
|
439
|
+
#define MESSAGE_FIELD_NO_CASE ((size_t)-1)
|
440
|
+
|
441
|
+
struct MessageField {
|
442
|
+
size_t offset;
|
443
|
+
size_t case_offset; // for oneofs, a uint32. Else, MESSAGE_FIELD_NO_CASE.
|
444
|
+
};
|
445
|
+
|
387
446
|
struct MessageLayout {
|
388
447
|
const upb_msgdef* msgdef;
|
389
|
-
|
448
|
+
MessageField* fields;
|
390
449
|
size_t size;
|
391
450
|
};
|
392
451
|
|
@@ -316,6 +316,29 @@ VALUE RepeatedField_deep_copy(VALUE _self) {
|
|
316
316
|
return new_rptfield;
|
317
317
|
}
|
318
318
|
|
319
|
+
/*
|
320
|
+
* call-seq:
|
321
|
+
* RepeatedField.to_ary => array
|
322
|
+
*
|
323
|
+
* Used when converted implicitly into array, e.g. compared to an Array.
|
324
|
+
* Also called as a fallback of Object#to_a
|
325
|
+
*/
|
326
|
+
VALUE RepeatedField_to_ary(VALUE _self) {
|
327
|
+
RepeatedField* self = ruby_to_RepeatedField(_self);
|
328
|
+
upb_fieldtype_t field_type = self->field_type;
|
329
|
+
|
330
|
+
size_t elem_size = native_slot_size(field_type);
|
331
|
+
size_t off = 0;
|
332
|
+
VALUE ary = rb_ary_new2(self->size);
|
333
|
+
for (int i = 0; i < self->size; i++, off += elem_size) {
|
334
|
+
void* mem = ((uint8_t *)self->elements) + off;
|
335
|
+
VALUE elem = native_slot_get(field_type, self->field_type_class, mem);
|
336
|
+
|
337
|
+
rb_ary_push(ary, elem);
|
338
|
+
}
|
339
|
+
return ary;
|
340
|
+
}
|
341
|
+
|
319
342
|
/*
|
320
343
|
* call-seq:
|
321
344
|
* RepeatedField.==(other) => boolean
|
@@ -335,15 +358,9 @@ VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
|
|
335
358
|
}
|
336
359
|
RepeatedField* self = ruby_to_RepeatedField(_self);
|
337
360
|
|
338
|
-
// Inefficient but workable: to support comparison to a generic array, we
|
339
|
-
// build a temporary RepeatedField of our type.
|
340
361
|
if (TYPE(_other) == T_ARRAY) {
|
341
|
-
VALUE
|
342
|
-
|
343
|
-
VALUE elem = rb_ary_entry(_other, i);
|
344
|
-
RepeatedField_push(new_rptfield, elem);
|
345
|
-
}
|
346
|
-
_other = new_rptfield;
|
362
|
+
VALUE self_ary = RepeatedField_to_ary(_self);
|
363
|
+
return rb_equal(self_ary, _other);
|
347
364
|
}
|
348
365
|
|
349
366
|
RepeatedField* other = ruby_to_RepeatedField(_other);
|
@@ -401,29 +418,8 @@ VALUE RepeatedField_hash(VALUE _self) {
|
|
401
418
|
* representation computed by its own #inspect method.
|
402
419
|
*/
|
403
420
|
VALUE RepeatedField_inspect(VALUE _self) {
|
404
|
-
|
405
|
-
|
406
|
-
VALUE str = rb_str_new2("[");
|
407
|
-
|
408
|
-
bool first = true;
|
409
|
-
|
410
|
-
upb_fieldtype_t field_type = self->field_type;
|
411
|
-
VALUE field_type_class = self->field_type_class;
|
412
|
-
size_t elem_size = native_slot_size(field_type);
|
413
|
-
size_t off = 0;
|
414
|
-
for (int i = 0; i < self->size; i++, off += elem_size) {
|
415
|
-
void* mem = ((uint8_t *)self->elements) + off;
|
416
|
-
VALUE elem = native_slot_get(field_type, field_type_class, mem);
|
417
|
-
if (!first) {
|
418
|
-
str = rb_str_cat2(str, ", ");
|
419
|
-
} else {
|
420
|
-
first = false;
|
421
|
-
}
|
422
|
-
str = rb_str_append(str, rb_funcall(elem, rb_intern("inspect"), 0));
|
423
|
-
}
|
424
|
-
|
425
|
-
str = rb_str_cat2(str, "]");
|
426
|
-
return str;
|
421
|
+
VALUE self_ary = RepeatedField_to_ary(_self);
|
422
|
+
return rb_funcall(self_ary, rb_intern("inspect"), 0);
|
427
423
|
}
|
428
424
|
|
429
425
|
/*
|
@@ -594,6 +590,7 @@ void RepeatedField_register(VALUE module) {
|
|
594
590
|
// Also define #clone so that we don't inherit Object#clone.
|
595
591
|
rb_define_method(klass, "clone", RepeatedField_dup, 0);
|
596
592
|
rb_define_method(klass, "==", RepeatedField_eq, 1);
|
593
|
+
rb_define_method(klass, "to_ary", RepeatedField_to_ary, 0);
|
597
594
|
rb_define_method(klass, "hash", RepeatedField_hash, 0);
|
598
595
|
rb_define_method(klass, "inspect", RepeatedField_inspect, 0);
|
599
596
|
rb_define_method(klass, "+", RepeatedField_plus, 1);
|
@@ -109,6 +109,17 @@ void native_slot_validate_string_encoding(upb_fieldtype_t type, VALUE value) {
|
|
109
109
|
|
110
110
|
void native_slot_set(upb_fieldtype_t type, VALUE type_class,
|
111
111
|
void* memory, VALUE value) {
|
112
|
+
native_slot_set_value_and_case(type, type_class, memory, value, NULL, 0);
|
113
|
+
}
|
114
|
+
|
115
|
+
void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
|
116
|
+
void* memory, VALUE value,
|
117
|
+
uint32_t* case_memory,
|
118
|
+
uint32_t case_number) {
|
119
|
+
// Note that in order to atomically change the value in memory and the case
|
120
|
+
// value (w.r.t. Ruby VM calls), we must set the value at |memory| only after
|
121
|
+
// all Ruby VM calls are complete. The case is then set at the bottom of this
|
122
|
+
// function.
|
112
123
|
switch (type) {
|
113
124
|
case UPB_TYPE_FLOAT:
|
114
125
|
if (!is_ruby_num(value)) {
|
@@ -198,6 +209,10 @@ void native_slot_set(upb_fieldtype_t type, VALUE type_class,
|
|
198
209
|
default:
|
199
210
|
break;
|
200
211
|
}
|
212
|
+
|
213
|
+
if (case_memory != NULL) {
|
214
|
+
*case_memory = case_number;
|
215
|
+
}
|
201
216
|
}
|
202
217
|
|
203
218
|
VALUE native_slot_get(upb_fieldtype_t type,
|
@@ -366,24 +381,94 @@ const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
|
|
366
381
|
// Memory layout management.
|
367
382
|
// -----------------------------------------------------------------------------
|
368
383
|
|
384
|
+
static size_t align_up_to(size_t offset, size_t granularity) {
|
385
|
+
// Granularity must be a power of two.
|
386
|
+
return (offset + granularity - 1) & ~(granularity - 1);
|
387
|
+
}
|
388
|
+
|
369
389
|
MessageLayout* create_layout(const upb_msgdef* msgdef) {
|
370
390
|
MessageLayout* layout = ALLOC(MessageLayout);
|
371
391
|
int nfields = upb_msgdef_numfields(msgdef);
|
372
|
-
layout->
|
392
|
+
layout->fields = ALLOC_N(MessageField, nfields);
|
373
393
|
|
374
|
-
|
394
|
+
upb_msg_field_iter it;
|
375
395
|
size_t off = 0;
|
376
|
-
for (
|
396
|
+
for (upb_msg_field_begin(&it, msgdef);
|
397
|
+
!upb_msg_field_done(&it);
|
398
|
+
upb_msg_field_next(&it)) {
|
377
399
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
400
|
+
|
401
|
+
if (upb_fielddef_containingoneof(field)) {
|
402
|
+
// Oneofs are handled separately below.
|
403
|
+
continue;
|
404
|
+
}
|
405
|
+
|
406
|
+
// Allocate |field_size| bytes for this field in the layout.
|
378
407
|
size_t field_size = 0;
|
379
408
|
if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
380
409
|
field_size = sizeof(VALUE);
|
381
410
|
} else {
|
382
411
|
field_size = native_slot_size(upb_fielddef_type(field));
|
383
412
|
}
|
384
|
-
//
|
413
|
+
// Align current offset up to |size| granularity.
|
414
|
+
off = align_up_to(off, field_size);
|
415
|
+
layout->fields[upb_fielddef_index(field)].offset = off;
|
416
|
+
layout->fields[upb_fielddef_index(field)].case_offset = MESSAGE_FIELD_NO_CASE;
|
417
|
+
off += field_size;
|
418
|
+
}
|
419
|
+
|
420
|
+
// Handle oneofs now -- we iterate over oneofs specifically and allocate only
|
421
|
+
// one slot per oneof.
|
422
|
+
//
|
423
|
+
// We assign all value slots first, then pack the 'case' fields at the end,
|
424
|
+
// since in the common case (modern 64-bit platform) these are 8 bytes and 4
|
425
|
+
// bytes respectively and we want to avoid alignment overhead.
|
426
|
+
//
|
427
|
+
// Note that we reserve 4 bytes (a uint32) per 'case' slot because the value
|
428
|
+
// space for oneof cases is conceptually as wide as field tag numbers. In
|
429
|
+
// practice, it's unlikely that a oneof would have more than e.g. 256 or 64K
|
430
|
+
// members (8 or 16 bits respectively), so conceivably we could assign
|
431
|
+
// consecutive case numbers and then pick a smaller oneof case slot size, but
|
432
|
+
// the complexity to implement this indirection is probably not worthwhile.
|
433
|
+
upb_msg_oneof_iter oit;
|
434
|
+
for (upb_msg_oneof_begin(&oit, msgdef);
|
435
|
+
!upb_msg_oneof_done(&oit);
|
436
|
+
upb_msg_oneof_next(&oit)) {
|
437
|
+
const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
|
438
|
+
|
439
|
+
// Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
|
440
|
+
// all fields.
|
441
|
+
size_t field_size = NATIVE_SLOT_MAX_SIZE;
|
442
|
+
// Align the offset.
|
443
|
+
off = align_up_to(off, field_size);
|
444
|
+
// Assign all fields in the oneof this same offset.
|
445
|
+
upb_oneof_iter fit;
|
446
|
+
for (upb_oneof_begin(&fit, oneof);
|
447
|
+
!upb_oneof_done(&fit);
|
448
|
+
upb_oneof_next(&fit)) {
|
449
|
+
const upb_fielddef* field = upb_oneof_iter_field(&fit);
|
450
|
+
layout->fields[upb_fielddef_index(field)].offset = off;
|
451
|
+
}
|
452
|
+
off += field_size;
|
453
|
+
}
|
454
|
+
|
455
|
+
// Now the case fields.
|
456
|
+
for (upb_msg_oneof_begin(&oit, msgdef);
|
457
|
+
!upb_msg_oneof_done(&oit);
|
458
|
+
upb_msg_oneof_next(&oit)) {
|
459
|
+
const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
|
460
|
+
|
461
|
+
size_t field_size = sizeof(uint32_t);
|
462
|
+
// Align the offset.
|
385
463
|
off = (off + field_size - 1) & ~(field_size - 1);
|
386
|
-
|
464
|
+
// Assign all fields in the oneof this same offset.
|
465
|
+
upb_oneof_iter fit;
|
466
|
+
for (upb_oneof_begin(&fit, oneof);
|
467
|
+
!upb_oneof_done(&fit);
|
468
|
+
upb_oneof_next(&fit)) {
|
469
|
+
const upb_fielddef* field = upb_oneof_iter_field(&fit);
|
470
|
+
layout->fields[upb_fielddef_index(field)].case_offset = off;
|
471
|
+
}
|
387
472
|
off += field_size;
|
388
473
|
}
|
389
474
|
|
@@ -396,7 +481,7 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
|
|
396
481
|
}
|
397
482
|
|
398
483
|
void free_layout(MessageLayout* layout) {
|
399
|
-
xfree(layout->
|
484
|
+
xfree(layout->fields);
|
400
485
|
upb_msgdef_unref(layout->msgdef, &layout->msgdef);
|
401
486
|
xfree(layout);
|
402
487
|
}
|
@@ -415,12 +500,35 @@ VALUE field_type_class(const upb_fielddef* field) {
|
|
415
500
|
return type_class;
|
416
501
|
}
|
417
502
|
|
503
|
+
static void* slot_memory(MessageLayout* layout,
|
504
|
+
const void* storage,
|
505
|
+
const upb_fielddef* field) {
|
506
|
+
return ((uint8_t *)storage) +
|
507
|
+
layout->fields[upb_fielddef_index(field)].offset;
|
508
|
+
}
|
509
|
+
|
510
|
+
static uint32_t* slot_oneof_case(MessageLayout* layout,
|
511
|
+
const void* storage,
|
512
|
+
const upb_fielddef* field) {
|
513
|
+
return (uint32_t *)(((uint8_t *)storage) +
|
514
|
+
layout->fields[upb_fielddef_index(field)].case_offset);
|
515
|
+
}
|
516
|
+
|
517
|
+
|
418
518
|
VALUE layout_get(MessageLayout* layout,
|
419
519
|
const void* storage,
|
420
520
|
const upb_fielddef* field) {
|
421
|
-
void* memory = (
|
422
|
-
|
423
|
-
|
521
|
+
void* memory = slot_memory(layout, storage, field);
|
522
|
+
uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
|
523
|
+
|
524
|
+
if (upb_fielddef_containingoneof(field)) {
|
525
|
+
if (*oneof_case != upb_fielddef_number(field)) {
|
526
|
+
return Qnil;
|
527
|
+
}
|
528
|
+
return native_slot_get(upb_fielddef_type(field),
|
529
|
+
field_type_class(field),
|
530
|
+
memory);
|
531
|
+
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
424
532
|
return *((VALUE *)memory);
|
425
533
|
} else {
|
426
534
|
return native_slot_get(upb_fielddef_type(field),
|
@@ -484,9 +592,33 @@ void layout_set(MessageLayout* layout,
|
|
484
592
|
void* storage,
|
485
593
|
const upb_fielddef* field,
|
486
594
|
VALUE val) {
|
487
|
-
void* memory = (
|
488
|
-
|
489
|
-
|
595
|
+
void* memory = slot_memory(layout, storage, field);
|
596
|
+
uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
|
597
|
+
|
598
|
+
if (upb_fielddef_containingoneof(field)) {
|
599
|
+
if (val == Qnil) {
|
600
|
+
// Assigning nil to a oneof field clears the oneof completely.
|
601
|
+
*oneof_case = ONEOF_CASE_NONE;
|
602
|
+
memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
|
603
|
+
} else {
|
604
|
+
// The transition between field types for a single oneof (union) slot is
|
605
|
+
// somewhat complex because we need to ensure that a GC triggered at any
|
606
|
+
// point by a call into the Ruby VM sees a valid state for this field and
|
607
|
+
// does not either go off into the weeds (following what it thinks is a
|
608
|
+
// VALUE but is actually a different field type) or miss an object (seeing
|
609
|
+
// what it thinks is a primitive field but is actually a VALUE for the new
|
610
|
+
// field type).
|
611
|
+
//
|
612
|
+
// In order for the transition to be safe, the oneof case slot must be in
|
613
|
+
// sync with the value slot whenever the Ruby VM has been called. Thus, we
|
614
|
+
// use native_slot_set_value_and_case(), which ensures that both the value
|
615
|
+
// and case number are altered atomically (w.r.t. the Ruby VM).
|
616
|
+
native_slot_set_value_and_case(
|
617
|
+
upb_fielddef_type(field), field_type_class(field),
|
618
|
+
memory, val,
|
619
|
+
oneof_case, upb_fielddef_number(field));
|
620
|
+
}
|
621
|
+
} else if (is_map_field(field)) {
|
490
622
|
check_map_field_type(val, field);
|
491
623
|
DEREF(memory, VALUE) = val;
|
492
624
|
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
@@ -500,15 +632,18 @@ void layout_set(MessageLayout* layout,
|
|
500
632
|
|
501
633
|
void layout_init(MessageLayout* layout,
|
502
634
|
void* storage) {
|
503
|
-
|
504
|
-
for (
|
505
|
-
!
|
506
|
-
|
635
|
+
upb_msg_field_iter it;
|
636
|
+
for (upb_msg_field_begin(&it, layout->msgdef);
|
637
|
+
!upb_msg_field_done(&it);
|
638
|
+
upb_msg_field_next(&it)) {
|
507
639
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
508
|
-
void* memory = (
|
509
|
-
|
640
|
+
void* memory = slot_memory(layout, storage, field);
|
641
|
+
uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
|
510
642
|
|
511
|
-
if (
|
643
|
+
if (upb_fielddef_containingoneof(field)) {
|
644
|
+
memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
|
645
|
+
*oneof_case = ONEOF_CASE_NONE;
|
646
|
+
} else if (is_map_field(field)) {
|
512
647
|
VALUE map = Qnil;
|
513
648
|
|
514
649
|
const upb_fielddef* key_field = map_field_key(field);
|
@@ -555,15 +690,19 @@ void layout_init(MessageLayout* layout,
|
|
555
690
|
}
|
556
691
|
|
557
692
|
void layout_mark(MessageLayout* layout, void* storage) {
|
558
|
-
|
559
|
-
for (
|
560
|
-
!
|
561
|
-
|
693
|
+
upb_msg_field_iter it;
|
694
|
+
for (upb_msg_field_begin(&it, layout->msgdef);
|
695
|
+
!upb_msg_field_done(&it);
|
696
|
+
upb_msg_field_next(&it)) {
|
562
697
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
563
|
-
void* memory = (
|
564
|
-
|
698
|
+
void* memory = slot_memory(layout, storage, field);
|
699
|
+
uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
|
565
700
|
|
566
|
-
if (
|
701
|
+
if (upb_fielddef_containingoneof(field)) {
|
702
|
+
if (*oneof_case == upb_fielddef_number(field)) {
|
703
|
+
native_slot_mark(upb_fielddef_type(field), memory);
|
704
|
+
}
|
705
|
+
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
567
706
|
rb_gc_mark(DEREF(memory, VALUE));
|
568
707
|
} else {
|
569
708
|
native_slot_mark(upb_fielddef_type(field), memory);
|
@@ -572,17 +711,23 @@ void layout_mark(MessageLayout* layout, void* storage) {
|
|
572
711
|
}
|
573
712
|
|
574
713
|
void layout_dup(MessageLayout* layout, void* to, void* from) {
|
575
|
-
|
576
|
-
for (
|
577
|
-
!
|
578
|
-
|
714
|
+
upb_msg_field_iter it;
|
715
|
+
for (upb_msg_field_begin(&it, layout->msgdef);
|
716
|
+
!upb_msg_field_done(&it);
|
717
|
+
upb_msg_field_next(&it)) {
|
579
718
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
580
|
-
void* to_memory = ((uint8_t *)to) +
|
581
|
-
layout->offsets[upb_fielddef_index(field)];
|
582
|
-
void* from_memory = ((uint8_t *)from) +
|
583
|
-
layout->offsets[upb_fielddef_index(field)];
|
584
719
|
|
585
|
-
|
720
|
+
void* to_memory = slot_memory(layout, to, field);
|
721
|
+
uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
|
722
|
+
void* from_memory = slot_memory(layout, from, field);
|
723
|
+
uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
|
724
|
+
|
725
|
+
if (upb_fielddef_containingoneof(field)) {
|
726
|
+
if (*from_oneof_case == upb_fielddef_number(field)) {
|
727
|
+
*to_oneof_case = *from_oneof_case;
|
728
|
+
native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
|
729
|
+
}
|
730
|
+
} else if (is_map_field(field)) {
|
586
731
|
DEREF(to_memory, VALUE) = Map_dup(DEREF(from_memory, VALUE));
|
587
732
|
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
588
733
|
DEREF(to_memory, VALUE) = RepeatedField_dup(DEREF(from_memory, VALUE));
|
@@ -593,17 +738,23 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
|
|
593
738
|
}
|
594
739
|
|
595
740
|
void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
|
596
|
-
|
597
|
-
for (
|
598
|
-
!
|
599
|
-
|
741
|
+
upb_msg_field_iter it;
|
742
|
+
for (upb_msg_field_begin(&it, layout->msgdef);
|
743
|
+
!upb_msg_field_done(&it);
|
744
|
+
upb_msg_field_next(&it)) {
|
600
745
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
601
|
-
void* to_memory = ((uint8_t *)to) +
|
602
|
-
layout->offsets[upb_fielddef_index(field)];
|
603
|
-
void* from_memory = ((uint8_t *)from) +
|
604
|
-
layout->offsets[upb_fielddef_index(field)];
|
605
746
|
|
606
|
-
|
747
|
+
void* to_memory = slot_memory(layout, to, field);
|
748
|
+
uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
|
749
|
+
void* from_memory = slot_memory(layout, from, field);
|
750
|
+
uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
|
751
|
+
|
752
|
+
if (upb_fielddef_containingoneof(field)) {
|
753
|
+
if (*from_oneof_case == upb_fielddef_number(field)) {
|
754
|
+
*to_oneof_case = *from_oneof_case;
|
755
|
+
native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
|
756
|
+
}
|
757
|
+
} else if (is_map_field(field)) {
|
607
758
|
DEREF(to_memory, VALUE) =
|
608
759
|
Map_deep_copy(DEREF(from_memory, VALUE));
|
609
760
|
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
@@ -616,22 +767,35 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
|
|
616
767
|
}
|
617
768
|
|
618
769
|
VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
|
619
|
-
|
620
|
-
for (
|
621
|
-
!
|
622
|
-
|
770
|
+
upb_msg_field_iter it;
|
771
|
+
for (upb_msg_field_begin(&it, layout->msgdef);
|
772
|
+
!upb_msg_field_done(&it);
|
773
|
+
upb_msg_field_next(&it)) {
|
623
774
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
775
|
+
|
776
|
+
void* msg1_memory = slot_memory(layout, msg1, field);
|
777
|
+
uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field);
|
778
|
+
void* msg2_memory = slot_memory(layout, msg2, field);
|
779
|
+
uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field);
|
780
|
+
|
781
|
+
if (upb_fielddef_containingoneof(field)) {
|
782
|
+
if (*msg1_oneof_case != *msg2_oneof_case ||
|
783
|
+
(*msg1_oneof_case == upb_fielddef_number(field) &&
|
784
|
+
!native_slot_eq(upb_fielddef_type(field),
|
785
|
+
msg1_memory,
|
786
|
+
msg2_memory))) {
|
787
|
+
return Qfalse;
|
788
|
+
}
|
789
|
+
} else if (is_map_field(field)) {
|
790
|
+
if (!Map_eq(DEREF(msg1_memory, VALUE),
|
791
|
+
DEREF(msg2_memory, VALUE))) {
|
792
|
+
return Qfalse;
|
793
|
+
}
|
632
794
|
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
633
|
-
|
634
|
-
|
795
|
+
if (!RepeatedField_eq(DEREF(msg1_memory, VALUE),
|
796
|
+
DEREF(msg2_memory, VALUE))) {
|
797
|
+
return Qfalse;
|
798
|
+
}
|
635
799
|
} else {
|
636
800
|
if (!native_slot_eq(upb_fielddef_type(field),
|
637
801
|
msg1_memory, msg2_memory)) {
|
@@ -643,12 +807,12 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
|
|
643
807
|
}
|
644
808
|
|
645
809
|
VALUE layout_hash(MessageLayout* layout, void* storage) {
|
646
|
-
|
810
|
+
upb_msg_field_iter it;
|
647
811
|
st_index_t h = rb_hash_start(0);
|
648
812
|
VALUE hash_sym = rb_intern("hash");
|
649
|
-
for (
|
650
|
-
!
|
651
|
-
|
813
|
+
for (upb_msg_field_begin(&it, layout->msgdef);
|
814
|
+
!upb_msg_field_done(&it);
|
815
|
+
upb_msg_field_next(&it)) {
|
652
816
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
653
817
|
VALUE field_val = layout_get(layout, storage, field);
|
654
818
|
h = rb_hash_uint(h, NUM2LONG(rb_funcall(field_val, hash_sym, 0)));
|
@@ -661,11 +825,11 @@ VALUE layout_hash(MessageLayout* layout, void* storage) {
|
|
661
825
|
VALUE layout_inspect(MessageLayout* layout, void* storage) {
|
662
826
|
VALUE str = rb_str_new2("");
|
663
827
|
|
664
|
-
|
828
|
+
upb_msg_field_iter it;
|
665
829
|
bool first = true;
|
666
|
-
for (
|
667
|
-
!
|
668
|
-
|
830
|
+
for (upb_msg_field_begin(&it, layout->msgdef);
|
831
|
+
!upb_msg_field_done(&it);
|
832
|
+
upb_msg_field_next(&it)) {
|
669
833
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
670
834
|
VALUE field_val = layout_get(layout, storage, field);
|
671
835
|
|