google-protobuf 3.0.0.alpha.1.1 → 3.0.0.alpha.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of google-protobuf might be problematic. Click here for more details.
- checksums.yaml +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
|
|