google-protobuf 3.0.0.alpha.1.0 → 3.0.0.alpha.1.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of google-protobuf might be problematic. Click here for more details.
- checksums.yaml +8 -8
- data/ext/google/protobuf_c/defs.c +107 -6
- data/ext/google/protobuf_c/encode_decode.c +327 -90
- data/ext/google/protobuf_c/extconf.rb +1 -1
- data/ext/google/protobuf_c/map.c +805 -0
- data/ext/google/protobuf_c/message.c +12 -3
- data/ext/google/protobuf_c/protobuf.c +1 -0
- data/ext/google/protobuf_c/protobuf.h +82 -4
- data/ext/google/protobuf_c/repeated_field.c +5 -1
- data/ext/google/protobuf_c/storage.c +148 -41
- data/ext/google/protobuf_c/upb.c +810 -453
- data/ext/google/protobuf_c/upb.h +71 -12
- data/tests/basic.rb +262 -3
- metadata +3 -2
@@ -139,7 +139,14 @@ int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
|
139
139
|
"Unknown field name in initialization map entry.");
|
140
140
|
}
|
141
141
|
|
142
|
-
if (
|
142
|
+
if (is_map_field(f)) {
|
143
|
+
if (TYPE(val) != T_HASH) {
|
144
|
+
rb_raise(rb_eArgError,
|
145
|
+
"Expected Hash object as initializer value for map field.");
|
146
|
+
}
|
147
|
+
VALUE map = layout_get(self->descriptor->layout, Message_data(self), f);
|
148
|
+
Map_merge_into_self(map, val);
|
149
|
+
} else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
|
143
150
|
if (TYPE(val) != T_ARRAY) {
|
144
151
|
rb_raise(rb_eArgError,
|
145
152
|
"Expected array as initializer value for repeated field.");
|
@@ -450,13 +457,15 @@ VALUE build_module_from_enumdesc(EnumDescriptor* enumdesc) {
|
|
450
457
|
* call-seq:
|
451
458
|
* Google::Protobuf.deep_copy(obj) => copy_of_obj
|
452
459
|
*
|
453
|
-
* Performs a deep copy of
|
454
|
-
* recursively copying its members.
|
460
|
+
* Performs a deep copy of a RepeatedField instance, a Map instance, or a
|
461
|
+
* message object, recursively copying its members.
|
455
462
|
*/
|
456
463
|
VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) {
|
457
464
|
VALUE klass = CLASS_OF(obj);
|
458
465
|
if (klass == cRepeatedField) {
|
459
466
|
return RepeatedField_deep_copy(obj);
|
467
|
+
} else if (klass == cMap) {
|
468
|
+
return Map_deep_copy(obj);
|
460
469
|
} else {
|
461
470
|
return Message_deep_copy(obj);
|
462
471
|
}
|
@@ -82,6 +82,7 @@ void Init_protobuf_c() {
|
|
82
82
|
EnumBuilderContext_register(internal);
|
83
83
|
Builder_register(internal);
|
84
84
|
RepeatedField_register(protobuf);
|
85
|
+
Map_register(protobuf);
|
85
86
|
|
86
87
|
rb_define_singleton_method(protobuf, "encode", Google_Protobuf_encode, 1);
|
87
88
|
rb_define_singleton_method(protobuf, "decode", Google_Protobuf_decode, 2);
|
@@ -110,6 +110,10 @@ struct Descriptor {
|
|
110
110
|
const upb_pbdecodermethod* fill_method;
|
111
111
|
const upb_handlers* pb_serialize_handlers;
|
112
112
|
const upb_handlers* json_serialize_handlers;
|
113
|
+
// Handlers hold type class references for sub-message fields directly in some
|
114
|
+
// cases. We need to keep these rooted because they might otherwise be
|
115
|
+
// collected.
|
116
|
+
VALUE typeclass_references;
|
113
117
|
};
|
114
118
|
|
115
119
|
struct FieldDescriptor {
|
@@ -123,6 +127,7 @@ struct EnumDescriptor {
|
|
123
127
|
|
124
128
|
struct MessageBuilderContext {
|
125
129
|
VALUE descriptor;
|
130
|
+
VALUE builder;
|
126
131
|
};
|
127
132
|
|
128
133
|
struct EnumBuilderContext {
|
@@ -213,10 +218,13 @@ void MessageBuilderContext_free(void* _self);
|
|
213
218
|
VALUE MessageBuilderContext_alloc(VALUE klass);
|
214
219
|
void MessageBuilderContext_register(VALUE module);
|
215
220
|
MessageBuilderContext* ruby_to_MessageBuilderContext(VALUE value);
|
216
|
-
VALUE MessageBuilderContext_initialize(VALUE _self,
|
221
|
+
VALUE MessageBuilderContext_initialize(VALUE _self,
|
222
|
+
VALUE descriptor,
|
223
|
+
VALUE builder);
|
217
224
|
VALUE MessageBuilderContext_optional(int argc, VALUE* argv, VALUE _self);
|
218
225
|
VALUE MessageBuilderContext_required(int argc, VALUE* argv, VALUE _self);
|
219
226
|
VALUE MessageBuilderContext_repeated(int argc, VALUE* argv, VALUE _self);
|
227
|
+
VALUE MessageBuilderContext_map(int argc, VALUE* argv, VALUE _self);
|
220
228
|
|
221
229
|
void EnumBuilderContext_mark(void* _self);
|
222
230
|
void EnumBuilderContext_free(void* _self);
|
@@ -239,6 +247,8 @@ VALUE Builder_finalize_to_pool(VALUE _self, VALUE pool_rb);
|
|
239
247
|
// Native slot storage abstraction.
|
240
248
|
// -----------------------------------------------------------------------------
|
241
249
|
|
250
|
+
#define NATIVE_SLOT_MAX_SIZE sizeof(void*)
|
251
|
+
|
242
252
|
size_t native_slot_size(upb_fieldtype_t type);
|
243
253
|
void native_slot_set(upb_fieldtype_t type,
|
244
254
|
VALUE type_class,
|
@@ -246,7 +256,7 @@ void native_slot_set(upb_fieldtype_t type,
|
|
246
256
|
VALUE value);
|
247
257
|
VALUE native_slot_get(upb_fieldtype_t type,
|
248
258
|
VALUE type_class,
|
249
|
-
void* memory);
|
259
|
+
const void* memory);
|
250
260
|
void native_slot_init(upb_fieldtype_t type, void* memory);
|
251
261
|
void native_slot_mark(upb_fieldtype_t type, void* memory);
|
252
262
|
void native_slot_dup(upb_fieldtype_t type, void* to, void* from);
|
@@ -254,11 +264,27 @@ void native_slot_deep_copy(upb_fieldtype_t type, void* to, void* from);
|
|
254
264
|
bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2);
|
255
265
|
|
256
266
|
void native_slot_validate_string_encoding(upb_fieldtype_t type, VALUE value);
|
267
|
+
void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE value);
|
257
268
|
|
258
269
|
extern rb_encoding* kRubyStringUtf8Encoding;
|
259
270
|
extern rb_encoding* kRubyStringASCIIEncoding;
|
260
271
|
extern rb_encoding* kRubyString8bitEncoding;
|
261
272
|
|
273
|
+
VALUE field_type_class(const upb_fielddef* field);
|
274
|
+
|
275
|
+
#define MAP_KEY_FIELD 1
|
276
|
+
#define MAP_VALUE_FIELD 2
|
277
|
+
|
278
|
+
// These operate on a map field (i.e., a repeated field of submessages whose
|
279
|
+
// submessage type is a map-entry msgdef).
|
280
|
+
bool is_map_field(const upb_fielddef* field);
|
281
|
+
const upb_fielddef* map_field_key(const upb_fielddef* field);
|
282
|
+
const upb_fielddef* map_field_value(const upb_fielddef* field);
|
283
|
+
|
284
|
+
// These operate on a map-entry msgdef.
|
285
|
+
const upb_fielddef* map_entry_key(const upb_msgdef* msgdef);
|
286
|
+
const upb_fielddef* map_entry_value(const upb_msgdef* msgdef);
|
287
|
+
|
262
288
|
// -----------------------------------------------------------------------------
|
263
289
|
// Repeated field container type.
|
264
290
|
// -----------------------------------------------------------------------------
|
@@ -282,7 +308,6 @@ extern VALUE cRepeatedField;
|
|
282
308
|
|
283
309
|
RepeatedField* ruby_to_RepeatedField(VALUE value);
|
284
310
|
|
285
|
-
void RepeatedField_register(VALUE module);
|
286
311
|
VALUE RepeatedField_each(VALUE _self);
|
287
312
|
VALUE RepeatedField_index(VALUE _self, VALUE _index);
|
288
313
|
void* RepeatedField_index_native(VALUE _self, int index);
|
@@ -302,6 +327,59 @@ VALUE RepeatedField_hash(VALUE _self);
|
|
302
327
|
VALUE RepeatedField_inspect(VALUE _self);
|
303
328
|
VALUE RepeatedField_plus(VALUE _self, VALUE list);
|
304
329
|
|
330
|
+
// Defined in repeated_field.c; also used by Map.
|
331
|
+
void validate_type_class(upb_fieldtype_t type, VALUE klass);
|
332
|
+
|
333
|
+
// -----------------------------------------------------------------------------
|
334
|
+
// Map container type.
|
335
|
+
// -----------------------------------------------------------------------------
|
336
|
+
|
337
|
+
typedef struct {
|
338
|
+
upb_fieldtype_t key_type;
|
339
|
+
upb_fieldtype_t value_type;
|
340
|
+
VALUE value_type_class;
|
341
|
+
upb_strtable table;
|
342
|
+
} Map;
|
343
|
+
|
344
|
+
void Map_mark(void* self);
|
345
|
+
void Map_free(void* self);
|
346
|
+
VALUE Map_alloc(VALUE klass);
|
347
|
+
VALUE Map_init(int argc, VALUE* argv, VALUE self);
|
348
|
+
void Map_register(VALUE module);
|
349
|
+
|
350
|
+
extern const rb_data_type_t Map_type;
|
351
|
+
extern VALUE cMap;
|
352
|
+
|
353
|
+
Map* ruby_to_Map(VALUE value);
|
354
|
+
|
355
|
+
VALUE Map_each(VALUE _self);
|
356
|
+
VALUE Map_keys(VALUE _self);
|
357
|
+
VALUE Map_values(VALUE _self);
|
358
|
+
VALUE Map_index(VALUE _self, VALUE key);
|
359
|
+
VALUE Map_index_set(VALUE _self, VALUE key, VALUE value);
|
360
|
+
VALUE Map_has_key(VALUE _self, VALUE key);
|
361
|
+
VALUE Map_delete(VALUE _self, VALUE key);
|
362
|
+
VALUE Map_clear(VALUE _self);
|
363
|
+
VALUE Map_length(VALUE _self);
|
364
|
+
VALUE Map_dup(VALUE _self);
|
365
|
+
VALUE Map_deep_copy(VALUE _self);
|
366
|
+
VALUE Map_eq(VALUE _self, VALUE _other);
|
367
|
+
VALUE Map_hash(VALUE _self);
|
368
|
+
VALUE Map_inspect(VALUE _self);
|
369
|
+
VALUE Map_merge(VALUE _self, VALUE hashmap);
|
370
|
+
VALUE Map_merge_into_self(VALUE _self, VALUE hashmap);
|
371
|
+
|
372
|
+
typedef struct {
|
373
|
+
Map* self;
|
374
|
+
upb_strtable_iter it;
|
375
|
+
} Map_iter;
|
376
|
+
|
377
|
+
void Map_begin(VALUE _self, Map_iter* iter);
|
378
|
+
void Map_next(Map_iter* iter);
|
379
|
+
bool Map_done(Map_iter* iter);
|
380
|
+
VALUE Map_iter_key(Map_iter* iter);
|
381
|
+
VALUE Map_iter_value(Map_iter* iter);
|
382
|
+
|
305
383
|
// -----------------------------------------------------------------------------
|
306
384
|
// Message layout / storage.
|
307
385
|
// -----------------------------------------------------------------------------
|
@@ -315,7 +393,7 @@ struct MessageLayout {
|
|
315
393
|
MessageLayout* create_layout(const upb_msgdef* msgdef);
|
316
394
|
void free_layout(MessageLayout* layout);
|
317
395
|
VALUE layout_get(MessageLayout* layout,
|
318
|
-
void* storage,
|
396
|
+
const void* storage,
|
319
397
|
const upb_fielddef* field);
|
320
398
|
void layout_set(MessageLayout* layout,
|
321
399
|
void* storage,
|
@@ -324,6 +324,10 @@ VALUE RepeatedField_deep_copy(VALUE _self) {
|
|
324
324
|
* element types are equal, their lengths are equal, and each element is equal.
|
325
325
|
* Elements are compared as per normal Ruby semantics, by calling their :==
|
326
326
|
* methods (or performing a more efficient comparison for primitive types).
|
327
|
+
*
|
328
|
+
* Repeated fields with dissimilar element types are never equal, even if value
|
329
|
+
* comparison (for example, between integers and floats) would have otherwise
|
330
|
+
* indicated that every element has equal value.
|
327
331
|
*/
|
328
332
|
VALUE RepeatedField_eq(VALUE _self, VALUE _other) {
|
329
333
|
if (_self == _other) {
|
@@ -458,7 +462,7 @@ VALUE RepeatedField_plus(VALUE _self, VALUE list) {
|
|
458
462
|
return dupped;
|
459
463
|
}
|
460
464
|
|
461
|
-
|
465
|
+
void validate_type_class(upb_fieldtype_t type, VALUE klass) {
|
462
466
|
if (rb_iv_get(klass, kDescriptorInstanceVar) == Qnil) {
|
463
467
|
rb_raise(rb_eArgError,
|
464
468
|
"Type class has no descriptor. Please pass a "
|
@@ -57,7 +57,17 @@ size_t native_slot_size(upb_fieldtype_t type) {
|
|
57
57
|
}
|
58
58
|
}
|
59
59
|
|
60
|
-
static
|
60
|
+
static bool is_ruby_num(VALUE value) {
|
61
|
+
return (TYPE(value) == T_FLOAT ||
|
62
|
+
TYPE(value) == T_FIXNUM ||
|
63
|
+
TYPE(value) == T_BIGNUM);
|
64
|
+
}
|
65
|
+
|
66
|
+
void native_slot_check_int_range_precision(upb_fieldtype_t type, VALUE val) {
|
67
|
+
if (!is_ruby_num(val)) {
|
68
|
+
rb_raise(rb_eTypeError, "Expected number type for integral field.");
|
69
|
+
}
|
70
|
+
|
61
71
|
// NUM2{INT,UINT,LL,ULL} macros do the appropriate range checks on upper
|
62
72
|
// bound; we just need to do precision checks (i.e., disallow rounding) and
|
63
73
|
// check for < 0 on unsigned types.
|
@@ -76,12 +86,6 @@ static void check_int_range_precision(upb_fieldtype_t type, VALUE val) {
|
|
76
86
|
}
|
77
87
|
}
|
78
88
|
|
79
|
-
static bool is_ruby_num(VALUE value) {
|
80
|
-
return (TYPE(value) == T_FLOAT ||
|
81
|
-
TYPE(value) == T_FIXNUM ||
|
82
|
-
TYPE(value) == T_BIGNUM);
|
83
|
-
}
|
84
|
-
|
85
89
|
void native_slot_validate_string_encoding(upb_fieldtype_t type, VALUE value) {
|
86
90
|
bool bad_encoding = false;
|
87
91
|
rb_encoding* string_encoding = rb_enc_from_index(ENCODING_GET(value));
|
@@ -156,14 +160,14 @@ void native_slot_set(upb_fieldtype_t type, VALUE type_class,
|
|
156
160
|
int32_t int_val = 0;
|
157
161
|
if (TYPE(value) == T_SYMBOL) {
|
158
162
|
// Ensure that the given symbol exists in the enum module.
|
159
|
-
VALUE lookup =
|
163
|
+
VALUE lookup = rb_funcall(type_class, rb_intern("resolve"), 1, value);
|
160
164
|
if (lookup == Qnil) {
|
161
165
|
rb_raise(rb_eRangeError, "Unknown symbol value for enum field.");
|
162
166
|
} else {
|
163
167
|
int_val = NUM2INT(lookup);
|
164
168
|
}
|
165
169
|
} else {
|
166
|
-
|
170
|
+
native_slot_check_int_range_precision(UPB_TYPE_INT32, value);
|
167
171
|
int_val = NUM2INT(value);
|
168
172
|
}
|
169
173
|
DEREF(memory, int32_t) = int_val;
|
@@ -173,10 +177,7 @@ void native_slot_set(upb_fieldtype_t type, VALUE type_class,
|
|
173
177
|
case UPB_TYPE_INT64:
|
174
178
|
case UPB_TYPE_UINT32:
|
175
179
|
case UPB_TYPE_UINT64:
|
176
|
-
|
177
|
-
rb_raise(rb_eTypeError, "Expected number type for integral field.");
|
178
|
-
}
|
179
|
-
check_int_range_precision(type, value);
|
180
|
+
native_slot_check_int_range_precision(type, value);
|
180
181
|
switch (type) {
|
181
182
|
case UPB_TYPE_INT32:
|
182
183
|
DEREF(memory, int32_t) = NUM2INT(value);
|
@@ -199,7 +200,9 @@ void native_slot_set(upb_fieldtype_t type, VALUE type_class,
|
|
199
200
|
}
|
200
201
|
}
|
201
202
|
|
202
|
-
VALUE native_slot_get(upb_fieldtype_t type,
|
203
|
+
VALUE native_slot_get(upb_fieldtype_t type,
|
204
|
+
VALUE type_class,
|
205
|
+
const void* memory) {
|
203
206
|
switch (type) {
|
204
207
|
case UPB_TYPE_FLOAT:
|
205
208
|
return DBL2NUM(DEREF(memory, float));
|
@@ -210,7 +213,7 @@ VALUE native_slot_get(upb_fieldtype_t type, VALUE type_class, void* memory) {
|
|
210
213
|
case UPB_TYPE_STRING:
|
211
214
|
case UPB_TYPE_BYTES:
|
212
215
|
case UPB_TYPE_MESSAGE:
|
213
|
-
return
|
216
|
+
return DEREF(memory, VALUE);
|
214
217
|
case UPB_TYPE_ENUM: {
|
215
218
|
int32_t val = DEREF(memory, int32_t);
|
216
219
|
VALUE symbol = enum_lookup(type_class, INT2NUM(val));
|
@@ -246,8 +249,9 @@ void native_slot_init(upb_fieldtype_t type, void* memory) {
|
|
246
249
|
break;
|
247
250
|
case UPB_TYPE_STRING:
|
248
251
|
case UPB_TYPE_BYTES:
|
249
|
-
// TODO(cfallin): set encoding appropriately
|
250
252
|
DEREF(memory, VALUE) = rb_str_new2("");
|
253
|
+
rb_enc_associate(DEREF(memory, VALUE), (type == UPB_TYPE_BYTES) ?
|
254
|
+
kRubyString8bitEncoding : kRubyStringUtf8Encoding);
|
251
255
|
break;
|
252
256
|
case UPB_TYPE_MESSAGE:
|
253
257
|
DEREF(memory, VALUE) = Qnil;
|
@@ -321,6 +325,43 @@ bool native_slot_eq(upb_fieldtype_t type, void* mem1, void* mem2) {
|
|
321
325
|
}
|
322
326
|
}
|
323
327
|
|
328
|
+
// -----------------------------------------------------------------------------
|
329
|
+
// Map field utilities.
|
330
|
+
// -----------------------------------------------------------------------------
|
331
|
+
|
332
|
+
bool is_map_field(const upb_fielddef* field) {
|
333
|
+
if (upb_fielddef_label(field) != UPB_LABEL_REPEATED ||
|
334
|
+
upb_fielddef_type(field) != UPB_TYPE_MESSAGE) {
|
335
|
+
return false;
|
336
|
+
}
|
337
|
+
const upb_msgdef* subdef = upb_fielddef_msgsubdef(field);
|
338
|
+
return upb_msgdef_mapentry(subdef);
|
339
|
+
}
|
340
|
+
|
341
|
+
const upb_fielddef* map_field_key(const upb_fielddef* field) {
|
342
|
+
assert(is_map_field(field));
|
343
|
+
const upb_msgdef* subdef = upb_fielddef_msgsubdef(field);
|
344
|
+
return map_entry_key(subdef);
|
345
|
+
}
|
346
|
+
|
347
|
+
const upb_fielddef* map_field_value(const upb_fielddef* field) {
|
348
|
+
assert(is_map_field(field));
|
349
|
+
const upb_msgdef* subdef = upb_fielddef_msgsubdef(field);
|
350
|
+
return map_entry_value(subdef);
|
351
|
+
}
|
352
|
+
|
353
|
+
const upb_fielddef* map_entry_key(const upb_msgdef* msgdef) {
|
354
|
+
const upb_fielddef* key_field = upb_msgdef_itof(msgdef, MAP_KEY_FIELD);
|
355
|
+
assert(key_field != NULL);
|
356
|
+
return key_field;
|
357
|
+
}
|
358
|
+
|
359
|
+
const upb_fielddef* map_entry_value(const upb_msgdef* msgdef) {
|
360
|
+
const upb_fielddef* value_field = upb_msgdef_itof(msgdef, MAP_VALUE_FIELD);
|
361
|
+
assert(value_field != NULL);
|
362
|
+
return value_field;
|
363
|
+
}
|
364
|
+
|
324
365
|
// -----------------------------------------------------------------------------
|
325
366
|
// Memory layout management.
|
326
367
|
// -----------------------------------------------------------------------------
|
@@ -334,9 +375,12 @@ MessageLayout* create_layout(const upb_msgdef* msgdef) {
|
|
334
375
|
size_t off = 0;
|
335
376
|
for (upb_msg_begin(&it, msgdef); !upb_msg_done(&it); upb_msg_next(&it)) {
|
336
377
|
const upb_fielddef* field = upb_msg_iter_field(&it);
|
337
|
-
size_t field_size =
|
338
|
-
|
339
|
-
|
378
|
+
size_t field_size = 0;
|
379
|
+
if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
380
|
+
field_size = sizeof(VALUE);
|
381
|
+
} else {
|
382
|
+
field_size = native_slot_size(upb_fielddef_type(field));
|
383
|
+
}
|
340
384
|
// align current offset
|
341
385
|
off = (off + field_size - 1) & ~(field_size - 1);
|
342
386
|
layout->offsets[upb_fielddef_index(field)] = off;
|
@@ -357,7 +401,7 @@ void free_layout(MessageLayout* layout) {
|
|
357
401
|
xfree(layout);
|
358
402
|
}
|
359
403
|
|
360
|
-
|
404
|
+
VALUE field_type_class(const upb_fielddef* field) {
|
361
405
|
VALUE type_class = Qnil;
|
362
406
|
if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
|
363
407
|
VALUE submsgdesc =
|
@@ -372,7 +416,7 @@ static VALUE get_type_class(const upb_fielddef* field) {
|
|
372
416
|
}
|
373
417
|
|
374
418
|
VALUE layout_get(MessageLayout* layout,
|
375
|
-
void* storage,
|
419
|
+
const void* storage,
|
376
420
|
const upb_fielddef* field) {
|
377
421
|
void* memory = ((uint8_t *)storage) +
|
378
422
|
layout->offsets[upb_fielddef_index(field)];
|
@@ -380,7 +424,7 @@ VALUE layout_get(MessageLayout* layout,
|
|
380
424
|
return *((VALUE *)memory);
|
381
425
|
} else {
|
382
426
|
return native_slot_get(upb_fielddef_type(field),
|
383
|
-
|
427
|
+
field_type_class(field),
|
384
428
|
memory);
|
385
429
|
}
|
386
430
|
}
|
@@ -398,9 +442,8 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
|
|
398
442
|
rb_raise(rb_eTypeError, "Repeated field array has wrong element type");
|
399
443
|
}
|
400
444
|
|
401
|
-
if (
|
402
|
-
|
403
|
-
RepeatedField* self = ruby_to_RepeatedField(val);
|
445
|
+
if (self->field_type == UPB_TYPE_MESSAGE ||
|
446
|
+
self->field_type == UPB_TYPE_ENUM) {
|
404
447
|
if (self->field_type_class !=
|
405
448
|
get_def_obj(upb_fielddef_subdef(field))) {
|
406
449
|
rb_raise(rb_eTypeError,
|
@@ -409,17 +452,48 @@ static void check_repeated_field_type(VALUE val, const upb_fielddef* field) {
|
|
409
452
|
}
|
410
453
|
}
|
411
454
|
|
455
|
+
static void check_map_field_type(VALUE val, const upb_fielddef* field) {
|
456
|
+
assert(is_map_field(field));
|
457
|
+
const upb_fielddef* key_field = map_field_key(field);
|
458
|
+
const upb_fielddef* value_field = map_field_value(field);
|
459
|
+
|
460
|
+
if (!RB_TYPE_P(val, T_DATA) || !RTYPEDDATA_P(val) ||
|
461
|
+
RTYPEDDATA_TYPE(val) != &Map_type) {
|
462
|
+
rb_raise(rb_eTypeError, "Expected Map instance");
|
463
|
+
}
|
464
|
+
|
465
|
+
Map* self = ruby_to_Map(val);
|
466
|
+
if (self->key_type != upb_fielddef_type(key_field)) {
|
467
|
+
rb_raise(rb_eTypeError, "Map key type does not match field's key type");
|
468
|
+
}
|
469
|
+
if (self->value_type != upb_fielddef_type(value_field)) {
|
470
|
+
rb_raise(rb_eTypeError, "Map value type does not match field's value type");
|
471
|
+
}
|
472
|
+
if (upb_fielddef_type(value_field) == UPB_TYPE_MESSAGE ||
|
473
|
+
upb_fielddef_type(value_field) == UPB_TYPE_ENUM) {
|
474
|
+
if (self->value_type_class !=
|
475
|
+
get_def_obj(upb_fielddef_subdef(value_field))) {
|
476
|
+
rb_raise(rb_eTypeError,
|
477
|
+
"Map value type has wrong message/enum class");
|
478
|
+
}
|
479
|
+
}
|
480
|
+
}
|
481
|
+
|
482
|
+
|
412
483
|
void layout_set(MessageLayout* layout,
|
413
484
|
void* storage,
|
414
485
|
const upb_fielddef* field,
|
415
486
|
VALUE val) {
|
416
487
|
void* memory = ((uint8_t *)storage) +
|
417
488
|
layout->offsets[upb_fielddef_index(field)];
|
418
|
-
if (
|
489
|
+
if (is_map_field(field)) {
|
490
|
+
check_map_field_type(val, field);
|
491
|
+
DEREF(memory, VALUE) = val;
|
492
|
+
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
419
493
|
check_repeated_field_type(val, field);
|
420
|
-
|
494
|
+
DEREF(memory, VALUE) = val;
|
421
495
|
} else {
|
422
|
-
native_slot_set(upb_fielddef_type(field),
|
496
|
+
native_slot_set(upb_fielddef_type(field), field_type_class(field),
|
423
497
|
memory, val);
|
424
498
|
}
|
425
499
|
}
|
@@ -434,9 +508,34 @@ void layout_init(MessageLayout* layout,
|
|
434
508
|
void* memory = ((uint8_t *)storage) +
|
435
509
|
layout->offsets[upb_fielddef_index(field)];
|
436
510
|
|
437
|
-
if (
|
511
|
+
if (is_map_field(field)) {
|
512
|
+
VALUE map = Qnil;
|
513
|
+
|
514
|
+
const upb_fielddef* key_field = map_field_key(field);
|
515
|
+
const upb_fielddef* value_field = map_field_value(field);
|
516
|
+
VALUE type_class = field_type_class(value_field);
|
517
|
+
|
518
|
+
if (type_class != Qnil) {
|
519
|
+
VALUE args[3] = {
|
520
|
+
fieldtype_to_ruby(upb_fielddef_type(key_field)),
|
521
|
+
fieldtype_to_ruby(upb_fielddef_type(value_field)),
|
522
|
+
type_class,
|
523
|
+
};
|
524
|
+
map = rb_class_new_instance(3, args, cMap);
|
525
|
+
} else {
|
526
|
+
VALUE args[2] = {
|
527
|
+
fieldtype_to_ruby(upb_fielddef_type(key_field)),
|
528
|
+
fieldtype_to_ruby(upb_fielddef_type(value_field)),
|
529
|
+
};
|
530
|
+
map = rb_class_new_instance(2, args, cMap);
|
531
|
+
}
|
532
|
+
|
533
|
+
DEREF(memory, VALUE) = map;
|
534
|
+
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
438
535
|
VALUE ary = Qnil;
|
439
|
-
|
536
|
+
|
537
|
+
VALUE type_class = field_type_class(field);
|
538
|
+
|
440
539
|
if (type_class != Qnil) {
|
441
540
|
VALUE args[2] = {
|
442
541
|
fieldtype_to_ruby(upb_fielddef_type(field)),
|
@@ -447,7 +546,8 @@ void layout_init(MessageLayout* layout,
|
|
447
546
|
VALUE args[1] = { fieldtype_to_ruby(upb_fielddef_type(field)) };
|
448
547
|
ary = rb_class_new_instance(1, args, cRepeatedField);
|
449
548
|
}
|
450
|
-
|
549
|
+
|
550
|
+
DEREF(memory, VALUE) = ary;
|
451
551
|
} else {
|
452
552
|
native_slot_init(upb_fielddef_type(field), memory);
|
453
553
|
}
|
@@ -464,7 +564,7 @@ void layout_mark(MessageLayout* layout, void* storage) {
|
|
464
564
|
layout->offsets[upb_fielddef_index(field)];
|
465
565
|
|
466
566
|
if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
467
|
-
rb_gc_mark(
|
567
|
+
rb_gc_mark(DEREF(memory, VALUE));
|
468
568
|
} else {
|
469
569
|
native_slot_mark(upb_fielddef_type(field), memory);
|
470
570
|
}
|
@@ -482,8 +582,10 @@ void layout_dup(MessageLayout* layout, void* to, void* from) {
|
|
482
582
|
void* from_memory = ((uint8_t *)from) +
|
483
583
|
layout->offsets[upb_fielddef_index(field)];
|
484
584
|
|
485
|
-
if (
|
486
|
-
|
585
|
+
if (is_map_field(field)) {
|
586
|
+
DEREF(to_memory, VALUE) = Map_dup(DEREF(from_memory, VALUE));
|
587
|
+
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
588
|
+
DEREF(to_memory, VALUE) = RepeatedField_dup(DEREF(from_memory, VALUE));
|
487
589
|
} else {
|
488
590
|
native_slot_dup(upb_fielddef_type(field), to_memory, from_memory);
|
489
591
|
}
|
@@ -501,8 +603,12 @@ void layout_deep_copy(MessageLayout* layout, void* to, void* from) {
|
|
501
603
|
void* from_memory = ((uint8_t *)from) +
|
502
604
|
layout->offsets[upb_fielddef_index(field)];
|
503
605
|
|
504
|
-
if (
|
505
|
-
|
606
|
+
if (is_map_field(field)) {
|
607
|
+
DEREF(to_memory, VALUE) =
|
608
|
+
Map_deep_copy(DEREF(from_memory, VALUE));
|
609
|
+
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
610
|
+
DEREF(to_memory, VALUE) =
|
611
|
+
RepeatedField_deep_copy(DEREF(from_memory, VALUE));
|
506
612
|
} else {
|
507
613
|
native_slot_deep_copy(upb_fielddef_type(field), to_memory, from_memory);
|
508
614
|
}
|
@@ -520,11 +626,12 @@ VALUE layout_eq(MessageLayout* layout, void* msg1, void* msg2) {
|
|
520
626
|
void* msg2_memory = ((uint8_t *)msg2) +
|
521
627
|
layout->offsets[upb_fielddef_index(field)];
|
522
628
|
|
523
|
-
if (
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
629
|
+
if (is_map_field(field)) {
|
630
|
+
return Map_eq(DEREF(msg1_memory, VALUE),
|
631
|
+
DEREF(msg2_memory, VALUE));
|
632
|
+
} else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
633
|
+
return RepeatedField_eq(DEREF(msg1_memory, VALUE),
|
634
|
+
DEREF(msg2_memory, VALUE));
|
528
635
|
} else {
|
529
636
|
if (!native_slot_eq(upb_fielddef_type(field),
|
530
637
|
msg1_memory, msg2_memory)) {
|