google-protobuf 3.0.0.alpha.1.0 → 3.0.0.alpha.1.1
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 +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)) {
|