google-protoc 3.0.0.alpha.6.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,894 @@
1
+ // Protocol Buffers - Google's data interchange format
2
+ // Copyright 2014 Google Inc. All rights reserved.
3
+ // https://developers.google.com/protocol-buffers/
4
+ //
5
+ // Redistribution and use in source and binary forms, with or without
6
+ // modification, are permitted provided that the following conditions are
7
+ // met:
8
+ //
9
+ // * Redistributions of source code must retain the above copyright
10
+ // notice, this list of conditions and the following disclaimer.
11
+ // * Redistributions in binary form must reproduce the above
12
+ // copyright notice, this list of conditions and the following disclaimer
13
+ // in the documentation and/or other materials provided with the
14
+ // distribution.
15
+ // * Neither the name of Google Inc. nor the names of its
16
+ // contributors may be used to endorse or promote products derived from
17
+ // this software without specific prior written permission.
18
+ //
19
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+
31
+ #include "protobuf.h"
32
+
33
+ #include <math.h>
34
+
35
+ #include <ruby/encoding.h>
36
+
37
+ // -----------------------------------------------------------------------------
38
+ // Ruby <-> native slot management.
39
+ // -----------------------------------------------------------------------------
40
+
41
+ #define DEREF(memory, type) *(type*)(memory)
42
+
43
+ size_t native_slot_size(upb_fieldtype_t type) {
44
+ switch (type) {
45
+ case UPB_TYPE_FLOAT: return 4;
46
+ case UPB_TYPE_DOUBLE: return 8;
47
+ case UPB_TYPE_BOOL: return 1;
48
+ case UPB_TYPE_STRING: return sizeof(VALUE);
49
+ case UPB_TYPE_BYTES: return sizeof(VALUE);
50
+ case UPB_TYPE_MESSAGE: return sizeof(VALUE);
51
+ case UPB_TYPE_ENUM: return 4;
52
+ case UPB_TYPE_INT32: return 4;
53
+ case UPB_TYPE_INT64: return 8;
54
+ case UPB_TYPE_UINT32: return 4;
55
+ case UPB_TYPE_UINT64: return 8;
56
+ default: return 0;
57
+ }
58
+ }
59
+
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
+ static bool is_ruby_num(VALUE value) {
92
+ return (TYPE(value) == T_FLOAT ||
93
+ TYPE(value) == T_FIXNUM ||
94
+ TYPE(value) == T_BIGNUM);
95
+ }
96
+
97
+ void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) {
98
+ if (!is_ruby_num(val)) {
99
+ rb_raise(rb_eTypeError, "Expected number type for integral field.");
100
+ }
101
+
102
+ // NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper
103
+ // bound; we just need to do precision checks (i.e., disallow rounding) and
104
+ // check for < 0 on unsigned types.
105
+ if (TYPE(val) == T_FLOAT) {
106
+ double dbl_val = NUM2DBL(val);
107
+ if (floor(dbl_val) != dbl_val) {
108
+ rb_raise(rb_eRangeError,
109
+ "Non-integral floating point value assigned to integer field.");
110
+ }
111
+ }
112
+ if (type == UPB_TYPE_UINT32 || type == UPB_TYPE_UINT64) {
113
+ if (NUM2DBL(val) < 0) {
114
+ rb_raise(rb_eRangeError,
115
+ "Assigning negative value to unsigned integer field.");
116
+ }
117
+ }
118
+ }
119
+
120
+ void native_slot_validate_string_encoding(upb_fieldtype_t type, VALUE value) {
121
+ bool bad_encoding = false;
122
+ rb_encoding* string_encoding = rb_enc_from_index(ENCODING_GET(value));
123
+ if (type == UPB_TYPE_STRING) {
124
+ bad_encoding =
125
+ string_encoding != kRubyStringUtf8Encoding &&
126
+ string_encoding != kRubyStringASCIIEncoding;
127
+ } else {
128
+ bad_encoding =
129
+ string_encoding != kRubyString8bitEncoding;
130
+ }
131
+ // Check that encoding is UTF-8 or ASCII (for string fields) or ASCII-8BIT
132
+ // (for bytes fields).
133
+ if (bad_encoding) {
134
+ rb_raise(rb_eTypeError, "Encoding for '%s' fields must be %s (was %s)",
135
+ (type == UPB_TYPE_STRING) ? "string" : "bytes",
136
+ (type == UPB_TYPE_STRING) ? "UTF-8 or ASCII" : "ASCII-8BIT",
137
+ rb_enc_name(string_encoding));
138
+ }
139
+ }
140
+
141
+ void native_slot_set(upb_fieldtype_t type, VALUE type_class,
142
+ void* memory, VALUE value) {
143
+ native_slot_set_value_and_case(type, type_class, memory, value, NULL, 0);
144
+ }
145
+
146
+ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
147
+ void* memory, VALUE value,
148
+ uint32_t* case_memory,
149
+ uint32_t case_number) {
150
+ // Note that in order to atomically change the value in memory and the case
151
+ // value (w.r.t. Ruby VM calls), we must set the value at |memory| only after
152
+ // all Ruby VM calls are complete. The case is then set at the bottom of this
153
+ // function.
154
+ switch (type) {
155
+ case UPB_TYPE_FLOAT:
156
+ if (!is_ruby_num(value)) {
157
+ rb_raise(rb_eTypeError, "Expected number type for float field.");
158
+ }
159
+ DEREF(memory, float) = NUM2DBL(value);
160
+ break;
161
+ case UPB_TYPE_DOUBLE:
162
+ if (!is_ruby_num(value)) {
163
+ rb_raise(rb_eTypeError, "Expected number type for double field.");
164
+ }
165
+ DEREF(memory, double) = NUM2DBL(value);
166
+ break;
167
+ case UPB_TYPE_BOOL: {
168
+ int8_t val = -1;
169
+ if (value == Qtrue) {
170
+ val = 1;
171
+ } else if (value == Qfalse) {
172
+ val = 0;
173
+ } else {
174
+ rb_raise(rb_eTypeError, "Invalid argument for boolean field.");
175
+ }
176
+ DEREF(memory, int8_t) = val;
177
+ break;
178
+ }
179
+ case UPB_TYPE_STRING:
180
+ case UPB_TYPE_BYTES: {
181
+ if (CLASS_OF(value) != rb_cString) {
182
+ rb_raise(rb_eTypeError, "Invalid argument for string field.");
183
+ }
184
+ native_slot_validate_string_encoding(type, value);
185
+ DEREF(memory, VALUE) = value;
186
+ break;
187
+ }
188
+ case UPB_TYPE_MESSAGE: {
189
+ if (CLASS_OF(value) == CLASS_OF(Qnil)) {
190
+ value = Qnil;
191
+ } else if (CLASS_OF(value) != type_class) {
192
+ rb_raise(rb_eTypeError,
193
+ "Invalid type %s to assign to submessage field.",
194
+ rb_class2name(CLASS_OF(value)));
195
+ }
196
+ DEREF(memory, VALUE) = value;
197
+ break;
198
+ }
199
+ case UPB_TYPE_ENUM: {
200
+ int32_t int_val = 0;
201
+ if (!is_ruby_num(value) && TYPE(value) != T_SYMBOL) {
202
+ rb_raise(rb_eTypeError,
203
+ "Expected number or symbol type for enum field.");
204
+ }
205
+ if (TYPE(value) == T_SYMBOL) {
206
+ // Ensure that the given symbol exists in the enum module.
207
+ VALUE lookup = rb_funcall(type_class, rb_intern("resolve"), 1, value);
208
+ if (lookup == Qnil) {
209
+ rb_raise(rb_eRangeError, "Unknown symbol value for enum field.");
210
+ } else {
211
+ int_val = NUM2INT(lookup);
212
+ }
213
+ } else {
214
+ native_slot_check_int_range_precision(UPB_TYPE_INT32, value);
215
+ int_val = NUM2INT(value);
216
+ }
217
+ DEREF(memory, int32_t) = int_val;
218
+ break;
219
+ }
220
+ case UPB_TYPE_INT32:
221
+ case UPB_TYPE_INT64:
222
+ case UPB_TYPE_UINT32:
223
+ case UPB_TYPE_UINT64:
224
+ native_slot_check_int_range_precision(type, value);
225
+ switch (type) {
226
+ case UPB_TYPE_INT32:
227
+ DEREF(memory, int32_t) = NUM2INT(value);
228
+ break;
229
+ case UPB_TYPE_INT64:
230
+ DEREF(memory, int64_t) = NUM2LL(value);
231
+ break;
232
+ case UPB_TYPE_UINT32:
233
+ DEREF(memory, uint32_t) = NUM2UINT(value);
234
+ break;
235
+ case UPB_TYPE_UINT64:
236
+ DEREF(memory, uint64_t) = NUM2ULL(value);
237
+ break;
238
+ default:
239
+ break;
240
+ }
241
+ break;
242
+ default:
243
+ break;
244
+ }
245
+
246
+ if (case_memory != NULL) {
247
+ *case_memory = case_number;
248
+ }
249
+ }
250
+
251
+ VALUE native_slot_get(upb_fieldtype_t type,
252
+ VALUE type_class,
253
+ const void* memory) {
254
+ switch (type) {
255
+ case UPB_TYPE_FLOAT:
256
+ return DBL2NUM(DEREF(memory, float));
257
+ case UPB_TYPE_DOUBLE:
258
+ return DBL2NUM(DEREF(memory, double));
259
+ case UPB_TYPE_BOOL:
260
+ return DEREF(memory, int8_t) ? Qtrue : Qfalse;
261
+ case UPB_TYPE_STRING:
262
+ case UPB_TYPE_BYTES:
263
+ case UPB_TYPE_MESSAGE:
264
+ return DEREF(memory, VALUE);
265
+ case UPB_TYPE_ENUM: {
266
+ int32_t val = DEREF(memory, int32_t);
267
+ VALUE symbol = enum_lookup(type_class, INT2NUM(val));
268
+ if (symbol == Qnil) {
269
+ return INT2NUM(val);
270
+ } else {
271
+ return symbol;
272
+ }
273
+ }
274
+ case UPB_TYPE_INT32:
275
+ return INT2NUM(DEREF(memory, int32_t));
276
+ case UPB_TYPE_INT64:
277
+ return LL2NUM(DEREF(memory, int64_t));
278
+ case UPB_TYPE_UINT32:
279
+ return UINT2NUM(DEREF(memory, uint32_t));
280
+ case UPB_TYPE_UINT64:
281
+ return ULL2NUM(DEREF(memory, uint64_t));
282
+ default:
283
+ return Qnil;
284
+ }
285
+ }
286
+
287
+ void native_slot_init(upb_fieldtype_t type, void* memory) {
288
+ switch (type) {
289
+ case UPB_TYPE_FLOAT:
290
+ DEREF(memory, float) = 0.0;
291
+ break;
292
+ case UPB_TYPE_DOUBLE:
293
+ DEREF(memory, double) = 0.0;
294
+ break;
295
+ case UPB_TYPE_BOOL:
296
+ DEREF(memory, int8_t) = 0;
297
+ break;
298
+ case UPB_TYPE_STRING:
299
+ case UPB_TYPE_BYTES:
300
+ DEREF(memory, VALUE) = rb_str_new2("");
301
+ rb_enc_associate(DEREF(memory, VALUE), (type == UPB_TYPE_BYTES) ?
302
+ kRubyString8bitEncoding : kRubyStringUtf8Encoding);
303
+ break;
304
+ case UPB_TYPE_MESSAGE:
305
+ DEREF(memory, VALUE) = Qnil;
306
+ break;
307
+ case UPB_TYPE_ENUM:
308
+ case UPB_TYPE_INT32:
309
+ DEREF(memory, int32_t) = 0;
310
+ break;
311
+ case UPB_TYPE_INT64:
312
+ DEREF(memory, int64_t) = 0;
313
+ break;
314
+ case UPB_TYPE_UINT32:
315
+ DEREF(memory, uint32_t) = 0;
316
+ break;
317
+ case UPB_TYPE_UINT64:
318
+ DEREF(memory, uint64_t) = 0;
319
+ break;
320
+ default:
321
+ break;
322
+ }
323
+ }
324
+
325
+ void native_slot_mark(upb_fieldtype_t type, void* memory) {
326
+ switch (type) {
327
+ case UPB_TYPE_STRING:
328
+ case UPB_TYPE_BYTES:
329
+ case UPB_TYPE_MESSAGE:
330
+ rb_gc_mark(DEREF(memory, VALUE));
331
+ break;
332
+ default:
333
+ break;
334
+ }
335
+ }
336
+
337
+ void native_slot_dup(upb_fieldtype_t type, void* to, void* from) {
338
+ memcpy(to, from, native_slot_size(type));
339
+ }
340
+
341
+ void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from) {
342
+ switch (type) {
343
+ case UPB_TYPE_STRING:
344
+ case UPB_TYPE_BYTES: {
345
+ VALUE from_val = DEREF(from, VALUE);
346
+ DEREF(to, VALUE) = (from_val != Qnil) ?
347
+ rb_funcall(from_val, rb_intern("dup"), 0) : Qnil;
348
+ break;
349
+ }
350
+ case UPB_TYPE_MESSAGE: {
351
+ VALUE from_val = DEREF(from, VALUE);
352
+ DEREF(to, VALUE) = (from_val != Qnil) ?
353
+ Message_deep_copy(from_val) : Qnil;
354
+ break;
355
+ }
356
+ default:
357
+ memcpy(to, from, native_slot_size(type));
358
+ }
359
+ }
360
+
361
+ bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2) {
362
+ switch (type) {
363
+ case UPB_TYPE_STRING:
364
+ case UPB_TYPE_BYTES:
365
+ case UPB_TYPE_MESSAGE: {
366
+ VALUE val1 = DEREF(mem1, VALUE);
367
+ VALUE val2 = DEREF(mem2, VALUE);
368
+ VALUE ret = rb_funcall(val1, rb_intern("=="), 1, val2);
369
+ return ret == Qtrue;
370
+ }
371
+ default:
372
+ return !memcmp(mem1, mem2, native_slot_size(type));
373
+ }
374
+ }
375
+
376
+ // -----------------------------------------------------------------------------
377
+ // Map field utilities.
378
+ // -----------------------------------------------------------------------------
379
+
380
+ const upb_msgdef* tryget_map_entry_msgdef(const upb_fielddef* field) {
381
+ const upb_msgdef* subdef;
382
+ if (upb_fielddef_label(field) != UPB_LABEL_REPEATED ||
383
+ upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
384
+ return NULL;
385
+ }
386
+ subdef = upb_fielddef_msgsubdef(field);
387
+ return upb_msgdef_mapentry(subdef) ? subdef : NULL;
388
+ }
389
+
390
+ const upb_msgdef *map_entry_msgdef(const upb_fielddef* field) {
391
+ const upb_msgdef* subdef = tryget_map_entry_msgdef(field);
392
+ assert(subdef);
393
+ return subdef;
394
+ }
395
+
396
+ bool is_map_field(const upb_fielddef *field) {
397
+ return tryget_map_entry_msgdef(field) != NULL;
398
+ }
399
+
400
+ const upb_fielddef* map_field_key(const upb_fielddef* field) {
401
+ const upb_msgdef* subdef = map_entry_msgdef(field);
402
+ return map_entry_key(subdef);
403
+ }
404
+
405
+ const upb_fielddef* map_field_value(const upb_fielddef* field) {
406
+ const upb_msgdef* subdef = map_entry_msgdef(field);
407
+ return map_entry_value(subdef);
408
+ }
409
+
410
+ const upb_fielddef* map_entry_key(const upb_msgdef* msgdef) {
411
+ const upb_fielddef* key_field = upb_msgdef_itof(msgdef, MAP_KEY_FIELD);
412
+ assert(key_field != NULL);
413
+ return key_field;
414
+ }
415
+
416
+ const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
417
+ const upb_fielddef* value_field = upb_msgdef_itof(msgdef, MAP_VALUE_FIELD);
418
+ assert(value_field != NULL);
419
+ return value_field;
420
+ }
421
+
422
+ // -----------------------------------------------------------------------------
423
+ // Memory layout management.
424
+ // -----------------------------------------------------------------------------
425
+
426
+ static size_t align_up_to(size_t offset, size_t granularity) {
427
+ // Granularity must be a power of two.
428
+ return (offset + granularity - 1) & ~(granularity - 1);
429
+ }
430
+
431
+ MessageLayout* create_layout(const upb_msgdef* msgdef) {
432
+ MessageLayout* layout = ALLOC(MessageLayout);
433
+ int nfields = upb_msgdef_numfields(msgdef);
434
+ upb_msg_field_iter it;
435
+ upb_msg_oneof_iter oit;
436
+ size_t off = 0;
437
+
438
+ layout->fields = ALLOC_N(MessageField, nfields);
439
+
440
+ for (upb_msg_field_begin(&it, msgdef);
441
+ !upb_msg_field_done(&it);
442
+ upb_msg_field_next(&it)) {
443
+ const upb_fielddef* field = upb_msg_iter_field(&it);
444
+ size_t field_size;
445
+
446
+ if (upb_fielddef_containingoneof(field)) {
447
+ // Oneofs are handled separately below.
448
+ continue;
449
+ }
450
+
451
+ // Allocate |field_size| bytes for this field in the layout.
452
+ field_size = 0;
453
+ if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
454
+ field_size = sizeof(VALUE);
455
+ } else {
456
+ field_size = native_slot_size(upb_fielddef_type(field));
457
+ }
458
+ // Align current offset up to |size| granularity.
459
+ off = align_up_to(off, field_size);
460
+ layout->fields[upb_fielddef_index(field)].offset = off;
461
+ layout->fields[upb_fielddef_index(field)].case_offset =
462
+ MESSAGE_FIELD_NO_CASE;
463
+ off += field_size;
464
+ }
465
+
466
+ // Handle oneofs now -- we iterate over oneofs specifically and allocate only
467
+ // one slot per oneof.
468
+ //
469
+ // We assign all value slots first, then pack the 'case' fields at the end,
470
+ // since in the common case (modern 64-bit platform) these are 8 bytes and 4
471
+ // bytes respectively and we want to avoid alignment overhead.
472
+ //
473
+ // Note that we reserve 4 bytes (a uint32) per 'case' slot because the value
474
+ // space for oneof cases is conceptually as wide as field tag numbers. In
475
+ // practice, it's unlikely that a oneof would have more than e.g. 256 or 64K
476
+ // members (8 or 16 bits respectively), so conceivably we could assign
477
+ // consecutive case numbers and then pick a smaller oneof case slot size, but
478
+ // the complexity to implement this indirection is probably not worthwhile.
479
+ for (upb_msg_oneof_begin(&oit, msgdef);
480
+ !upb_msg_oneof_done(&oit);
481
+ upb_msg_oneof_next(&oit)) {
482
+ const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
483
+ upb_oneof_iter fit;
484
+
485
+ // Always allocate NATIVE_SLOT_MAX_SIZE bytes, but share the slot between
486
+ // all fields.
487
+ size_t field_size = NATIVE_SLOT_MAX_SIZE;
488
+ // Align the offset.
489
+ off = align_up_to(off, field_size);
490
+ // Assign all fields in the oneof this same offset.
491
+ for (upb_oneof_begin(&fit, oneof);
492
+ !upb_oneof_done(&fit);
493
+ upb_oneof_next(&fit)) {
494
+ const upb_fielddef* field = upb_oneof_iter_field(&fit);
495
+ layout->fields[upb_fielddef_index(field)].offset = off;
496
+ }
497
+ off += field_size;
498
+ }
499
+
500
+ // Now the case fields.
501
+ for (upb_msg_oneof_begin(&oit, msgdef);
502
+ !upb_msg_oneof_done(&oit);
503
+ upb_msg_oneof_next(&oit)) {
504
+ const upb_oneofdef* oneof = upb_msg_iter_oneof(&oit);
505
+ upb_oneof_iter fit;
506
+
507
+ size_t field_size = sizeof(uint32_t);
508
+ // Align the offset.
509
+ off = (off + field_size - 1) & ~(field_size - 1);
510
+ // Assign all fields in the oneof this same offset.
511
+ for (upb_oneof_begin(&fit, oneof);
512
+ !upb_oneof_done(&fit);
513
+ upb_oneof_next(&fit)) {
514
+ const upb_fielddef* field = upb_oneof_iter_field(&fit);
515
+ layout->fields[upb_fielddef_index(field)].case_offset = off;
516
+ }
517
+ off += field_size;
518
+ }
519
+
520
+ layout->size = off;
521
+
522
+ layout->msgdef = msgdef;
523
+ upb_msgdef_ref(layout->msgdef, &layout->msgdef);
524
+
525
+ return layout;
526
+ }
527
+
528
+ void free_layout(MessageLayout* layout) {
529
+ xfree(layout->fields);
530
+ upb_msgdef_unref(layout->msgdef, &layout->msgdef);
531
+ xfree(layout);
532
+ }
533
+
534
+ VALUE field_type_class(const upb_fielddef* field) {
535
+ VALUE type_class = Qnil;
536
+ if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
537
+ VALUE submsgdesc =
538
+ get_def_obj(upb_fielddef_subdef(field));
539
+ type_class = Descriptor_msgclass(submsgdesc);
540
+ } else if (upb_fielddef_type(field) == UPB_TYPE_ENUM) {
541
+ VALUE subenumdesc =
542
+ get_def_obj(upb_fielddef_subdef(field));
543
+ type_class = EnumDescriptor_enummodule(subenumdesc);
544
+ }
545
+ return type_class;
546
+ }
547
+
548
+ static void* slot_memory(MessageLayout* layout,
549
+ const void* storage,
550
+ const upb_fielddef* field) {
551
+ return ((uint8_t *)storage) +
552
+ layout->fields[upb_fielddef_index(field)].offset;
553
+ }
554
+
555
+ static uint32_t* slot_oneof_case(MessageLayout* layout,
556
+ const void* storage,
557
+ const upb_fielddef* field) {
558
+ return (uint32_t *)(((uint8_t *)storage) +
559
+ layout->fields[upb_fielddef_index(field)].case_offset);
560
+ }
561
+
562
+
563
+ VALUE layout_get(MessageLayout* layout,
564
+ const void* storage,
565
+ const upb_fielddef* field) {
566
+ void* memory = slot_memory(layout, storage, field);
567
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
568
+
569
+ if (upb_fielddef_containingoneof(field)) {
570
+ if (*oneof_case != upb_fielddef_number(field)) {
571
+ return value_from_default(field);
572
+ }
573
+ return native_slot_get(upb_fielddef_type(field),
574
+ field_type_class(field),
575
+ memory);
576
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
577
+ return *((VALUE *)memory);
578
+ } else {
579
+ return native_slot_get(upb_fielddef_type(field),
580
+ field_type_class(field),
581
+ memory);
582
+ }
583
+ }
584
+
585
+ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
586
+ RepeatedField* self;
587
+ assert(upb_fielddef_label(field) == UPB_LABEL_REPEATED);
588
+
589
+ if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
590
+ RTYPEDDATA_TYPE(val) != &RepeatedField_type) {
591
+ rb_raise(rb_eTypeError, "Expected repeated field array");
592
+ }
593
+
594
+ self = ruby_to_RepeatedField(val);
595
+ if (self->field_type != upb_fielddef_type(field)) {
596
+ rb_raise(rb_eTypeError, "Repeated field array has wrong element type");
597
+ }
598
+
599
+ if (self->field_type == UPB_TYPE_MESSAGE ||
600
+ self->field_type == UPB_TYPE_ENUM) {
601
+ if (self->field_type_class !=
602
+ get_def_obj(upb_fielddef_subdef(field))) {
603
+ rb_raise(rb_eTypeError,
604
+ "Repeated field array has wrong message/enum class");
605
+ }
606
+ }
607
+ }
608
+
609
+ static void check_map_field_type(VALUE val, const upb_fielddef* field) {
610
+ const upb_fielddef* key_field = map_field_key(field);
611
+ const upb_fielddef* value_field = map_field_value(field);
612
+ Map* self;
613
+
614
+ if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
615
+ RTYPEDDATA_TYPE(val) != &Map_type) {
616
+ rb_raise(rb_eTypeError, "Expected Map instance");
617
+ }
618
+
619
+ self = ruby_to_Map(val);
620
+ if (self->key_type != upb_fielddef_type(key_field)) {
621
+ rb_raise(rb_eTypeError, "Map key type does not match field's key type");
622
+ }
623
+ if (self->value_type != upb_fielddef_type(value_field)) {
624
+ rb_raise(rb_eTypeError, "Map value type does not match field's value type");
625
+ }
626
+ if (upb_fielddef_type(value_field) == UPB_TYPE_MESSAGE ||
627
+ upb_fielddef_type(value_field) == UPB_TYPE_ENUM) {
628
+ if (self->value_type_class !=
629
+ get_def_obj(upb_fielddef_subdef(value_field))) {
630
+ rb_raise(rb_eTypeError,
631
+ "Map value type has wrong message/enum class");
632
+ }
633
+ }
634
+ }
635
+
636
+
637
+ void layout_set(MessageLayout* layout,
638
+ void* storage,
639
+ const upb_fielddef* field,
640
+ VALUE val) {
641
+ void* memory = slot_memory(layout, storage, field);
642
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
643
+
644
+ if (upb_fielddef_containingoneof(field)) {
645
+ if (val == Qnil) {
646
+ // Assigning nil to a oneof field clears the oneof completely.
647
+ *oneof_case = ONEOF_CASE_NONE;
648
+ memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
649
+ } else {
650
+ // The transition between field types for a single oneof (union) slot is
651
+ // somewhat complex because we need to ensure that a GC triggered at any
652
+ // point by a call into the Ruby VM sees a valid state for this field and
653
+ // does not either go off into the weeds (following what it thinks is a
654
+ // VALUE but is actually a different field type) or miss an object (seeing
655
+ // what it thinks is a primitive field but is actually a VALUE for the new
656
+ // field type).
657
+ //
658
+ // In order for the transition to be safe, the oneof case slot must be in
659
+ // sync with the value slot whenever the Ruby VM has been called. Thus, we
660
+ // use native_slot_set_value_and_case(), which ensures that both the value
661
+ // and case number are altered atomically (w.r.t. the Ruby VM).
662
+ native_slot_set_value_and_case(
663
+ upb_fielddef_type(field), field_type_class(field),
664
+ memory, val,
665
+ oneof_case, upb_fielddef_number(field));
666
+ }
667
+ } else if (is_map_field(field)) {
668
+ check_map_field_type(val, field);
669
+ DEREF(memory, VALUE) = val;
670
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
671
+ check_repeated_field_type(val, field);
672
+ DEREF(memory, VALUE) = val;
673
+ } else {
674
+ native_slot_set(upb_fielddef_type(field), field_type_class(field),
675
+ memory, val);
676
+ }
677
+ }
678
+
679
+ void layout_init(MessageLayout* layout,
680
+ void* storage) {
681
+ upb_msg_field_iter it;
682
+ for (upb_msg_field_begin(&it, layout->msgdef);
683
+ !upb_msg_field_done(&it);
684
+ upb_msg_field_next(&it)) {
685
+ const upb_fielddef* field = upb_msg_iter_field(&it);
686
+ void* memory = slot_memory(layout, storage, field);
687
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
688
+
689
+ if (upb_fielddef_containingoneof(field)) {
690
+ memset(memory, 0, NATIVE_SLOT_MAX_SIZE);
691
+ *oneof_case = ONEOF_CASE_NONE;
692
+ } else if (is_map_field(field)) {
693
+ VALUE map = Qnil;
694
+
695
+ const upb_fielddef* key_field = map_field_key(field);
696
+ const upb_fielddef* value_field = map_field_value(field);
697
+ VALUE type_class = field_type_class(value_field);
698
+
699
+ if (type_class != Qnil) {
700
+ VALUE args[3] = {
701
+ fieldtype_to_ruby(upb_fielddef_type(key_field)),
702
+ fieldtype_to_ruby(upb_fielddef_type(value_field)),
703
+ type_class,
704
+ };
705
+ map = rb_class_new_instance(3, args, cMap);
706
+ } else {
707
+ VALUE args[2] = {
708
+ fieldtype_to_ruby(upb_fielddef_type(key_field)),
709
+ fieldtype_to_ruby(upb_fielddef_type(value_field)),
710
+ };
711
+ map = rb_class_new_instance(2, args, cMap);
712
+ }
713
+
714
+ DEREF(memory, VALUE) = map;
715
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
716
+ VALUE ary = Qnil;
717
+
718
+ VALUE type_class = field_type_class(field);
719
+
720
+ if (type_class != Qnil) {
721
+ VALUE args[2] = {
722
+ fieldtype_to_ruby(upb_fielddef_type(field)),
723
+ type_class,
724
+ };
725
+ ary = rb_class_new_instance(2, args, cRepeatedField);
726
+ } else {
727
+ VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
728
+ ary = rb_class_new_instance(1, args, cRepeatedField);
729
+ }
730
+
731
+ DEREF(memory, VALUE) = ary;
732
+ } else {
733
+ native_slot_init(upb_fielddef_type(field), memory);
734
+ }
735
+ }
736
+ }
737
+
738
+ void layout_mark(MessageLayout* layout, void* storage) {
739
+ upb_msg_field_iter it;
740
+ for (upb_msg_field_begin(&it, layout->msgdef);
741
+ !upb_msg_field_done(&it);
742
+ upb_msg_field_next(&it)) {
743
+ const upb_fielddef* field = upb_msg_iter_field(&it);
744
+ void* memory = slot_memory(layout, storage, field);
745
+ uint32_t* oneof_case = slot_oneof_case(layout, storage, field);
746
+
747
+ if (upb_fielddef_containingoneof(field)) {
748
+ if (*oneof_case == upb_fielddef_number(field)) {
749
+ native_slot_mark(upb_fielddef_type(field), memory);
750
+ }
751
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
752
+ rb_gc_mark(DEREF(memory, VALUE));
753
+ } else {
754
+ native_slot_mark(upb_fielddef_type(field), memory);
755
+ }
756
+ }
757
+ }
758
+
759
+ void layout_dup(MessageLayout* layout, void* to, void* from) {
760
+ upb_msg_field_iter it;
761
+ for (upb_msg_field_begin(&it, layout->msgdef);
762
+ !upb_msg_field_done(&it);
763
+ upb_msg_field_next(&it)) {
764
+ const upb_fielddef* field = upb_msg_iter_field(&it);
765
+
766
+ void* to_memory = slot_memory(layout, to, field);
767
+ uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
768
+ void* from_memory = slot_memory(layout, from, field);
769
+ uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
770
+
771
+ if (upb_fielddef_containingoneof(field)) {
772
+ if (*from_oneof_case == upb_fielddef_number(field)) {
773
+ *to_oneof_case = *from_oneof_case;
774
+ native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
775
+ }
776
+ } else if (is_map_field(field)) {
777
+ DEREF(to_memory, VALUE) = Map_dup(DEREF(from_memory, VALUE));
778
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
779
+ DEREF(to_memory, VALUE) = RepeatedField_dup(DEREF(from_memory, VALUE));
780
+ } else {
781
+ native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
782
+ }
783
+ }
784
+ }
785
+
786
+ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
787
+ upb_msg_field_iter it;
788
+ for (upb_msg_field_begin(&it, layout->msgdef);
789
+ !upb_msg_field_done(&it);
790
+ upb_msg_field_next(&it)) {
791
+ const upb_fielddef* field = upb_msg_iter_field(&it);
792
+
793
+ void* to_memory = slot_memory(layout, to, field);
794
+ uint32_t* to_oneof_case = slot_oneof_case(layout, to, field);
795
+ void* from_memory = slot_memory(layout, from, field);
796
+ uint32_t* from_oneof_case = slot_oneof_case(layout, from, field);
797
+
798
+ if (upb_fielddef_containingoneof(field)) {
799
+ if (*from_oneof_case == upb_fielddef_number(field)) {
800
+ *to_oneof_case = *from_oneof_case;
801
+ native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
802
+ }
803
+ } else if (is_map_field(field)) {
804
+ DEREF(to_memory, VALUE) =
805
+ Map_deep_copy(DEREF(from_memory, VALUE));
806
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
807
+ DEREF(to_memory, VALUE) =
808
+ RepeatedField_deep_copy(DEREF(from_memory, VALUE));
809
+ } else {
810
+ native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
811
+ }
812
+ }
813
+ }
814
+
815
+ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
816
+ upb_msg_field_iter it;
817
+ for (upb_msg_field_begin(&it, layout->msgdef);
818
+ !upb_msg_field_done(&it);
819
+ upb_msg_field_next(&it)) {
820
+ const upb_fielddef* field = upb_msg_iter_field(&it);
821
+
822
+ void* msg1_memory = slot_memory(layout, msg1, field);
823
+ uint32_t* msg1_oneof_case = slot_oneof_case(layout, msg1, field);
824
+ void* msg2_memory = slot_memory(layout, msg2, field);
825
+ uint32_t* msg2_oneof_case = slot_oneof_case(layout, msg2, field);
826
+
827
+ if (upb_fielddef_containingoneof(field)) {
828
+ if (*msg1_oneof_case != *msg2_oneof_case ||
829
+ (*msg1_oneof_case == upb_fielddef_number(field) &&
830
+ !native_slot_eq(upb_fielddef_type(field),
831
+ msg1_memory,
832
+ msg2_memory))) {
833
+ return Qfalse;
834
+ }
835
+ } else if (is_map_field(field)) {
836
+ if (!Map_eq(DEREF(msg1_memory, VALUE),
837
+ DEREF(msg2_memory, VALUE))) {
838
+ return Qfalse;
839
+ }
840
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
841
+ if (!RepeatedField_eq(DEREF(msg1_memory, VALUE),
842
+ DEREF(msg2_memory, VALUE))) {
843
+ return Qfalse;
844
+ }
845
+ } else {
846
+ if (!native_slot_eq(upb_fielddef_type(field),
847
+ msg1_memory, msg2_memory)) {
848
+ return Qfalse;
849
+ }
850
+ }
851
+ }
852
+ return Qtrue;
853
+ }
854
+
855
+ VALUE layout_hash(MessageLayout* layout, void* storage) {
856
+ upb_msg_field_iter it;
857
+ st_index_t h = rb_hash_start(0);
858
+ VALUE hash_sym = rb_intern("hash");
859
+ for (upb_msg_field_begin(&it, layout->msgdef);
860
+ !upb_msg_field_done(&it);
861
+ upb_msg_field_next(&it)) {
862
+ const upb_fielddef* field = upb_msg_iter_field(&it);
863
+ VALUE field_val = layout_get(layout, storage, field);
864
+ h = rb_hash_uint(h, NUM2LONG(rb_funcall(field_val, hash_sym, 0)));
865
+ }
866
+ h = rb_hash_end(h);
867
+
868
+ return INT2FIX(h);
869
+ }
870
+
871
+ VALUE layout_inspect(MessageLayout* layout, void* storage) {
872
+ VALUE str = rb_str_new2("");
873
+
874
+ upb_msg_field_iter it;
875
+ bool first = true;
876
+ for (upb_msg_field_begin(&it, layout->msgdef);
877
+ !upb_msg_field_done(&it);
878
+ upb_msg_field_next(&it)) {
879
+ const upb_fielddef* field = upb_msg_iter_field(&it);
880
+ VALUE field_val = layout_get(layout, storage, field);
881
+
882
+ if (!first) {
883
+ str = rb_str_cat2(str, ", ");
884
+ } else {
885
+ first = false;
886
+ }
887
+ str = rb_str_cat2(str, upb_fielddef_name(field));
888
+ str = rb_str_cat2(str, ": ");
889
+
890
+ str = rb_str_append(str, rb_funcall(field_val, rb_intern("inspect"), 0));
891
+ }
892
+
893
+ return str;
894
+ }