google-protobuf 3.0.0.alpha.3.1.pre → 3.0.0.alpha.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of google-protobuf might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/ext/google/protobuf_c/defs.c +160 -83
- data/ext/google/protobuf_c/encode_decode.c +177 -144
- data/ext/google/protobuf_c/extconf.rb +1 -1
- data/ext/google/protobuf_c/map.c +15 -12
- data/ext/google/protobuf_c/message.c +104 -40
- data/ext/google/protobuf_c/protobuf.c +16 -6
- data/ext/google/protobuf_c/protobuf.h +11 -8
- data/ext/google/protobuf_c/repeated_field.c +138 -85
- data/ext/google/protobuf_c/storage.c +35 -20
- data/ext/google/protobuf_c/upb.c +3443 -2673
- data/ext/google/protobuf_c/upb.h +5086 -4919
- data/lib/google/protobuf.rb +36 -0
- data/lib/google/protobuf/message_exts.rb +53 -0
- data/lib/google/protobuf/repeated_field.rb +188 -0
- data/tests/basic.rb +119 -9
- metadata +6 -4
data/ext/google/protobuf_c/map.c
CHANGED
@@ -120,7 +120,7 @@ static VALUE table_key_to_ruby(Map* self, const char* buf, size_t length) {
|
|
120
120
|
}
|
121
121
|
|
122
122
|
static void* value_memory(upb_value* v) {
|
123
|
-
return (void*)(&v->val
|
123
|
+
return (void*)(&v->val);
|
124
124
|
}
|
125
125
|
|
126
126
|
// -----------------------------------------------------------------------------
|
@@ -169,8 +169,7 @@ VALUE Map_alloc(VALUE klass) {
|
|
169
169
|
Map* self = ALLOC(Map);
|
170
170
|
memset(self, 0, sizeof(Map));
|
171
171
|
self->value_type_class = Qnil;
|
172
|
-
|
173
|
-
return ret;
|
172
|
+
return TypedData_Wrap_Struct(klass, &Map_type, self);
|
174
173
|
}
|
175
174
|
|
176
175
|
static bool needs_typeclass(upb_fieldtype_t type) {
|
@@ -215,6 +214,7 @@ static bool needs_typeclass(upb_fieldtype_t type) {
|
|
215
214
|
*/
|
216
215
|
VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
|
217
216
|
Map* self = ruby_to_Map(_self);
|
217
|
+
int init_value_arg;
|
218
218
|
|
219
219
|
// We take either two args (:key_type, :value_type), three args (:key_type,
|
220
220
|
// :value_type, "ValueMessageType"), or four args (the above plus an initial
|
@@ -241,7 +241,7 @@ VALUE Map_init(int argc, VALUE* argv, VALUE _self) {
|
|
241
241
|
rb_raise(rb_eArgError, "Invalid key type for map.");
|
242
242
|
}
|
243
243
|
|
244
|
-
|
244
|
+
init_value_arg = 2;
|
245
245
|
if (needs_typeclass(self->value_type) && argc > 2) {
|
246
246
|
self->value_type_class = argv[2];
|
247
247
|
validate_type_class(self->value_type, self->value_type_class);
|
@@ -356,9 +356,9 @@ VALUE Map_index(VALUE _self, VALUE key) {
|
|
356
356
|
char keybuf[TABLE_KEY_BUF_LENGTH];
|
357
357
|
const char* keyval = NULL;
|
358
358
|
size_t length = 0;
|
359
|
+
upb_value v;
|
359
360
|
table_key(self, key, keybuf, &keyval, &length);
|
360
361
|
|
361
|
-
upb_value v;
|
362
362
|
if (upb_strtable_lookup2(&self->table, keyval, length, &v)) {
|
363
363
|
void* mem = value_memory(&v);
|
364
364
|
return native_slot_get(self->value_type, self->value_type_class, mem);
|
@@ -381,10 +381,11 @@ VALUE Map_index_set(VALUE _self, VALUE key, VALUE value) {
|
|
381
381
|
char keybuf[TABLE_KEY_BUF_LENGTH];
|
382
382
|
const char* keyval = NULL;
|
383
383
|
size_t length = 0;
|
384
|
+
upb_value v;
|
385
|
+
void* mem;
|
384
386
|
table_key(self, key, keybuf, &keyval, &length);
|
385
387
|
|
386
|
-
|
387
|
-
void* mem = value_memory(&v);
|
388
|
+
mem = value_memory(&v);
|
388
389
|
native_slot_set(self->value_type, self->value_type_class, mem, value);
|
389
390
|
|
390
391
|
// Replace any existing value by issuing a 'remove' operation first.
|
@@ -432,9 +433,9 @@ VALUE Map_delete(VALUE _self, VALUE key) {
|
|
432
433
|
char keybuf[TABLE_KEY_BUF_LENGTH];
|
433
434
|
const char* keyval = NULL;
|
434
435
|
size_t length = 0;
|
436
|
+
upb_value v;
|
435
437
|
table_key(self, key, keybuf, &keyval, &length);
|
436
438
|
|
437
|
-
upb_value v;
|
438
439
|
if (upb_strtable_remove2(&self->table, keyval, length, &v)) {
|
439
440
|
void* mem = value_memory(&v);
|
440
441
|
return native_slot_get(self->value_type, self->value_type_class, mem);
|
@@ -564,6 +565,8 @@ VALUE Map_deep_copy(VALUE _self) {
|
|
564
565
|
*/
|
565
566
|
VALUE Map_eq(VALUE _self, VALUE _other) {
|
566
567
|
Map* self = ruby_to_Map(_self);
|
568
|
+
Map* other;
|
569
|
+
upb_strtable_iter it;
|
567
570
|
|
568
571
|
// Allow comparisons to Ruby hashmaps by converting to a temporary Map
|
569
572
|
// instance. Slow, but workable.
|
@@ -573,7 +576,7 @@ VALUE Map_eq(VALUE _self, VALUE _other) {
|
|
573
576
|
_other = other_map;
|
574
577
|
}
|
575
578
|
|
576
|
-
|
579
|
+
other = ruby_to_Map(_other);
|
577
580
|
|
578
581
|
if (self == other) {
|
579
582
|
return Qtrue;
|
@@ -589,7 +592,6 @@ VALUE Map_eq(VALUE _self, VALUE _other) {
|
|
589
592
|
|
590
593
|
// For each member of self, check that an equal member exists at the same key
|
591
594
|
// in other.
|
592
|
-
upb_strtable_iter it;
|
593
595
|
for (upb_strtable_begin(&it, &self->table);
|
594
596
|
!upb_strtable_done(&it);
|
595
597
|
upb_strtable_next(&it)) {
|
@@ -719,6 +721,7 @@ VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
|
|
719
721
|
|
720
722
|
Map* self = ruby_to_Map(_self);
|
721
723
|
Map* other = ruby_to_Map(hashmap);
|
724
|
+
upb_strtable_iter it;
|
722
725
|
|
723
726
|
if (self->key_type != other->key_type ||
|
724
727
|
self->value_type != other->value_type ||
|
@@ -726,19 +729,19 @@ VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
|
|
726
729
|
rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types");
|
727
730
|
}
|
728
731
|
|
729
|
-
upb_strtable_iter it;
|
730
732
|
for (upb_strtable_begin(&it, &other->table);
|
731
733
|
!upb_strtable_done(&it);
|
732
734
|
upb_strtable_next(&it)) {
|
733
735
|
|
734
736
|
// Replace any existing value by issuing a 'remove' operation first.
|
737
|
+
upb_value v;
|
735
738
|
upb_value oldv;
|
736
739
|
upb_strtable_remove2(&self->table,
|
737
740
|
upb_strtable_iter_key(&it),
|
738
741
|
upb_strtable_iter_keylength(&it),
|
739
742
|
&oldv);
|
740
743
|
|
741
|
-
|
744
|
+
v = upb_strtable_iter_value(&it);
|
742
745
|
upb_strtable_insert2(&self->table,
|
743
746
|
upb_strtable_iter_key(&it),
|
744
747
|
upb_strtable_iter_keylength(&it),
|
@@ -53,17 +53,19 @@ rb_data_type_t Message_type = {
|
|
53
53
|
};
|
54
54
|
|
55
55
|
VALUE Message_alloc(VALUE klass) {
|
56
|
-
VALUE descriptor =
|
56
|
+
VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
|
57
57
|
Descriptor* desc = ruby_to_Descriptor(descriptor);
|
58
58
|
MessageHeader* msg = (MessageHeader*)ALLOC_N(
|
59
59
|
uint8_t, sizeof(MessageHeader) + desc->layout->size);
|
60
|
+
VALUE ret;
|
61
|
+
|
60
62
|
memset(Message_data(msg), 0, desc->layout->size);
|
61
63
|
|
62
64
|
// We wrap first so that everything in the message object is GC-rooted in case
|
63
65
|
// a collection happens during object creation in layout_init().
|
64
|
-
|
66
|
+
ret = TypedData_Wrap_Struct(klass, &Message_type, msg);
|
65
67
|
msg->descriptor = desc;
|
66
|
-
|
68
|
+
rb_ivar_set(ret, descriptor_instancevar_interned, descriptor);
|
67
69
|
|
68
70
|
layout_init(desc->layout, Message_data(msg));
|
69
71
|
|
@@ -71,29 +73,34 @@ VALUE Message_alloc(VALUE klass) {
|
|
71
73
|
}
|
72
74
|
|
73
75
|
static VALUE which_oneof_field(MessageHeader* self, const upb_oneofdef* o) {
|
76
|
+
upb_oneof_iter it;
|
77
|
+
size_t case_ofs;
|
78
|
+
uint32_t oneof_case;
|
79
|
+
const upb_fielddef* first_field;
|
80
|
+
const upb_fielddef* f;
|
81
|
+
|
74
82
|
// If no fields in the oneof, always nil.
|
75
83
|
if (upb_oneofdef_numfields(o) == 0) {
|
76
84
|
return Qnil;
|
77
85
|
}
|
78
86
|
// Grab the first field in the oneof so we can get its layout info to find the
|
79
87
|
// oneof_case field.
|
80
|
-
upb_oneof_iter it;
|
81
88
|
upb_oneof_begin(&it, o);
|
82
89
|
assert(!upb_oneof_done(&it));
|
83
|
-
|
90
|
+
first_field = upb_oneof_iter_field(&it);
|
84
91
|
assert(upb_fielddef_containingoneof(first_field) != NULL);
|
85
92
|
|
86
|
-
|
93
|
+
case_ofs =
|
87
94
|
self->descriptor->layout->
|
88
95
|
fields[upb_fielddef_index(first_field)].case_offset;
|
89
|
-
|
96
|
+
oneof_case = *((uint32_t*)((char*)Message_data(self) + case_ofs));
|
90
97
|
|
91
98
|
if (oneof_case == ONEOF_CASE_NONE) {
|
92
99
|
return Qnil;
|
93
100
|
}
|
94
101
|
|
95
102
|
// oneof_case is a field index, so find that field.
|
96
|
-
|
103
|
+
f = upb_oneofdef_itof(o, oneof_case);
|
97
104
|
assert(f != NULL);
|
98
105
|
|
99
106
|
return ID2SYM(rb_intern(upb_fielddef_name(f)));
|
@@ -118,18 +125,25 @@ static VALUE which_oneof_field(MessageHeader* self, const upb_oneofdef* o) {
|
|
118
125
|
*/
|
119
126
|
VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
120
127
|
MessageHeader* self;
|
128
|
+
VALUE method_name, method_str;
|
129
|
+
char* name;
|
130
|
+
size_t name_len;
|
131
|
+
bool setter;
|
132
|
+
const upb_oneofdef* o;
|
133
|
+
const upb_fielddef* f;
|
134
|
+
|
121
135
|
TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
|
122
136
|
if (argc < 1) {
|
123
137
|
rb_raise(rb_eArgError, "Expected method name as first argument.");
|
124
138
|
}
|
125
|
-
|
139
|
+
method_name = argv[0];
|
126
140
|
if (!SYMBOL_P(method_name)) {
|
127
141
|
rb_raise(rb_eArgError, "Expected symbol as method name.");
|
128
142
|
}
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
143
|
+
method_str = rb_id2str(SYM2ID(method_name));
|
144
|
+
name = RSTRING_PTR(method_str);
|
145
|
+
name_len = RSTRING_LEN(method_str);
|
146
|
+
setter = false;
|
133
147
|
|
134
148
|
// Setters have names that end in '='.
|
135
149
|
if (name[name_len - 1] == '=') {
|
@@ -138,7 +152,7 @@ VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
|
138
152
|
}
|
139
153
|
|
140
154
|
// Check for a oneof name first.
|
141
|
-
|
155
|
+
o = upb_msgdef_ntoo(self->descriptor->msgdef,
|
142
156
|
name, name_len);
|
143
157
|
if (o != NULL) {
|
144
158
|
if (setter) {
|
@@ -148,7 +162,7 @@ VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
|
148
162
|
}
|
149
163
|
|
150
164
|
// Otherwise, check for a field with that name.
|
151
|
-
|
165
|
+
f = upb_msgdef_ntof(self->descriptor->msgdef,
|
152
166
|
name, name_len);
|
153
167
|
|
154
168
|
if (f == NULL) {
|
@@ -168,6 +182,9 @@ VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
|
|
168
182
|
|
169
183
|
int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
170
184
|
MessageHeader* self;
|
185
|
+
VALUE method_str;
|
186
|
+
char* name;
|
187
|
+
const upb_fielddef* f;
|
171
188
|
TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
|
172
189
|
|
173
190
|
if (!SYMBOL_P(key)) {
|
@@ -175,27 +192,31 @@ int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
|
175
192
|
"Expected symbols as hash keys in initialization map.");
|
176
193
|
}
|
177
194
|
|
178
|
-
|
179
|
-
|
180
|
-
|
195
|
+
method_str = rb_id2str(SYM2ID(key));
|
196
|
+
name = RSTRING_PTR(method_str);
|
197
|
+
f = upb_msgdef_ntofz(self->descriptor->msgdef, name);
|
181
198
|
if (f == NULL) {
|
182
199
|
rb_raise(rb_eArgError,
|
183
200
|
"Unknown field name in initialization map entry.");
|
184
201
|
}
|
185
202
|
|
186
203
|
if (is_map_field(f)) {
|
204
|
+
VALUE map;
|
205
|
+
|
187
206
|
if (TYPE(val) != T_HASH) {
|
188
207
|
rb_raise(rb_eArgError,
|
189
208
|
"Expected Hash object as initializer value for map field.");
|
190
209
|
}
|
191
|
-
|
210
|
+
map = layout_get(self->descriptor->layout, Message_data(self), f);
|
192
211
|
Map_merge_into_self(map, val);
|
193
212
|
} else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
|
213
|
+
VALUE ary;
|
214
|
+
|
194
215
|
if (TYPE(val) != T_ARRAY) {
|
195
216
|
rb_raise(rb_eArgError,
|
196
217
|
"Expected array as initializer value for repeated field.");
|
197
218
|
}
|
198
|
-
|
219
|
+
ary = layout_get(self->descriptor->layout, Message_data(self), f);
|
199
220
|
for (int i = 0; i < RARRAY_LEN(val); i++) {
|
200
221
|
RepeatedField_push(ary, rb_ary_entry(val, i));
|
201
222
|
}
|
@@ -218,13 +239,15 @@ int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
|
|
218
239
|
* Message class are provided on each concrete message class.
|
219
240
|
*/
|
220
241
|
VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
|
242
|
+
VALUE hash_args;
|
243
|
+
|
221
244
|
if (argc == 0) {
|
222
245
|
return Qnil;
|
223
246
|
}
|
224
247
|
if (argc != 1) {
|
225
248
|
rb_raise(rb_eArgError, "Expected 0 or 1 arguments.");
|
226
249
|
}
|
227
|
-
|
250
|
+
hash_args = argv[0];
|
228
251
|
if (TYPE(hash_args) != T_HASH) {
|
229
252
|
rb_raise(rb_eArgError, "Expected hash arguments.");
|
230
253
|
}
|
@@ -241,10 +264,11 @@ VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
|
|
241
264
|
*/
|
242
265
|
VALUE Message_dup(VALUE _self) {
|
243
266
|
MessageHeader* self;
|
267
|
+
VALUE new_msg;
|
268
|
+
MessageHeader* new_msg_self;
|
244
269
|
TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
|
245
270
|
|
246
|
-
|
247
|
-
MessageHeader* new_msg_self;
|
271
|
+
new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
|
248
272
|
TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self);
|
249
273
|
|
250
274
|
layout_dup(self->descriptor->layout,
|
@@ -257,10 +281,11 @@ VALUE Message_dup(VALUE _self) {
|
|
257
281
|
// Internal only; used by Google::Protobuf.deep_copy.
|
258
282
|
VALUE Message_deep_copy(VALUE _self) {
|
259
283
|
MessageHeader* self;
|
284
|
+
MessageHeader* new_msg_self;
|
285
|
+
VALUE new_msg;
|
260
286
|
TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
|
261
287
|
|
262
|
-
|
263
|
-
MessageHeader* new_msg_self;
|
288
|
+
new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
|
264
289
|
TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self);
|
265
290
|
|
266
291
|
layout_deep_copy(self->descriptor->layout,
|
@@ -281,9 +306,8 @@ VALUE Message_deep_copy(VALUE _self) {
|
|
281
306
|
*/
|
282
307
|
VALUE Message_eq(VALUE _self, VALUE _other) {
|
283
308
|
MessageHeader* self;
|
284
|
-
TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
|
285
|
-
|
286
309
|
MessageHeader* other;
|
310
|
+
TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
|
287
311
|
TypedData_Get_Struct(_other, MessageHeader, &Message_type, other);
|
288
312
|
|
289
313
|
if (self->descriptor != other->descriptor) {
|
@@ -318,9 +342,10 @@ VALUE Message_hash(VALUE _self) {
|
|
318
342
|
*/
|
319
343
|
VALUE Message_inspect(VALUE _self) {
|
320
344
|
MessageHeader* self;
|
345
|
+
VALUE str;
|
321
346
|
TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
|
322
347
|
|
323
|
-
|
348
|
+
str = rb_str_new2("<");
|
324
349
|
str = rb_str_append(str, rb_str_new2(rb_class2name(CLASS_OF(_self))));
|
325
350
|
str = rb_str_cat2(str, ": ");
|
326
351
|
str = rb_str_append(str, layout_inspect(
|
@@ -329,6 +354,32 @@ VALUE Message_inspect(VALUE _self) {
|
|
329
354
|
return str;
|
330
355
|
}
|
331
356
|
|
357
|
+
|
358
|
+
VALUE Message_to_h(VALUE _self) {
|
359
|
+
MessageHeader* self;
|
360
|
+
VALUE hash;
|
361
|
+
upb_msg_field_iter it;
|
362
|
+
TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
|
363
|
+
|
364
|
+
hash = rb_hash_new();
|
365
|
+
|
366
|
+
for (upb_msg_field_begin(&it, self->descriptor->msgdef);
|
367
|
+
!upb_msg_field_done(&it);
|
368
|
+
upb_msg_field_next(&it)) {
|
369
|
+
const upb_fielddef* field = upb_msg_iter_field(&it);
|
370
|
+
VALUE msg_value = layout_get(self->descriptor->layout, Message_data(self),
|
371
|
+
field);
|
372
|
+
VALUE msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
|
373
|
+
if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
|
374
|
+
msg_value = RepeatedField_to_ary(msg_value);
|
375
|
+
}
|
376
|
+
rb_hash_aset(hash, msg_key, msg_value);
|
377
|
+
}
|
378
|
+
return hash;
|
379
|
+
}
|
380
|
+
|
381
|
+
|
382
|
+
|
332
383
|
/*
|
333
384
|
* call-seq:
|
334
385
|
* Message.[](index) => value
|
@@ -338,10 +389,10 @@ VALUE Message_inspect(VALUE _self) {
|
|
338
389
|
*/
|
339
390
|
VALUE Message_index(VALUE _self, VALUE field_name) {
|
340
391
|
MessageHeader* self;
|
392
|
+
const upb_fielddef* field;
|
341
393
|
TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
|
342
394
|
Check_Type(field_name, T_STRING);
|
343
|
-
|
344
|
-
upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
|
395
|
+
field = upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
|
345
396
|
if (field == NULL) {
|
346
397
|
return Qnil;
|
347
398
|
}
|
@@ -357,10 +408,10 @@ VALUE Message_index(VALUE _self, VALUE field_name) {
|
|
357
408
|
*/
|
358
409
|
VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
|
359
410
|
MessageHeader* self;
|
411
|
+
const upb_fielddef* field;
|
360
412
|
TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
|
361
413
|
Check_Type(field_name, T_STRING);
|
362
|
-
|
363
|
-
upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
|
414
|
+
field = upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
|
364
415
|
if (field == NULL) {
|
365
416
|
rb_raise(rb_eArgError, "Unknown field: %s", RSTRING_PTR(field_name));
|
366
417
|
}
|
@@ -376,10 +427,13 @@ VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
|
|
376
427
|
* message class's type.
|
377
428
|
*/
|
378
429
|
VALUE Message_descriptor(VALUE klass) {
|
379
|
-
return
|
430
|
+
return rb_ivar_get(klass, descriptor_instancevar_interned);
|
380
431
|
}
|
381
432
|
|
382
433
|
VALUE build_class_from_descriptor(Descriptor* desc) {
|
434
|
+
const char *name;
|
435
|
+
VALUE klass;
|
436
|
+
|
383
437
|
if (desc->layout == NULL) {
|
384
438
|
desc->layout = create_layout(desc->msgdef);
|
385
439
|
}
|
@@ -387,18 +441,24 @@ VALUE build_class_from_descriptor(Descriptor* desc) {
|
|
387
441
|
desc->fill_method = new_fillmsg_decodermethod(desc, &desc->fill_method);
|
388
442
|
}
|
389
443
|
|
390
|
-
|
444
|
+
name = upb_msgdef_fullname(desc->msgdef);
|
391
445
|
if (name == NULL) {
|
392
446
|
rb_raise(rb_eRuntimeError, "Descriptor does not have assigned name.");
|
393
447
|
}
|
394
448
|
|
395
|
-
|
449
|
+
klass = rb_define_class_id(
|
396
450
|
// Docs say this parameter is ignored. User will assign return value to
|
397
451
|
// their own toplevel constant class name.
|
398
452
|
rb_intern("Message"),
|
399
453
|
rb_cObject);
|
400
|
-
|
454
|
+
rb_ivar_set(klass, descriptor_instancevar_interned,
|
455
|
+
get_def_obj(desc->msgdef));
|
401
456
|
rb_define_alloc_func(klass, Message_alloc);
|
457
|
+
rb_require("google/protobuf/message_exts");
|
458
|
+
rb_include_module(klass, rb_eval_string("Google::Protobuf::MessageExts"));
|
459
|
+
rb_extend_object(
|
460
|
+
klass, rb_eval_string("Google::Protobuf::MessageExts::ClassMethods"));
|
461
|
+
|
402
462
|
rb_define_method(klass, "method_missing",
|
403
463
|
Message_method_missing, -1);
|
404
464
|
rb_define_method(klass, "initialize", Message_initialize, -1);
|
@@ -407,6 +467,8 @@ VALUE build_class_from_descriptor(Descriptor* desc) {
|
|
407
467
|
rb_define_method(klass, "clone", Message_dup, 0);
|
408
468
|
rb_define_method(klass, "==", Message_eq, 1);
|
409
469
|
rb_define_method(klass, "hash", Message_hash, 0);
|
470
|
+
rb_define_method(klass, "to_h", Message_to_h, 0);
|
471
|
+
rb_define_method(klass, "to_hash", Message_to_h, 0);
|
410
472
|
rb_define_method(klass, "inspect", Message_inspect, 0);
|
411
473
|
rb_define_method(klass, "[]", Message_index, 1);
|
412
474
|
rb_define_method(klass, "[]=", Message_index_set, 2);
|
@@ -415,6 +477,7 @@ VALUE build_class_from_descriptor(Descriptor* desc) {
|
|
415
477
|
rb_define_singleton_method(klass, "decode_json", Message_decode_json, 1);
|
416
478
|
rb_define_singleton_method(klass, "encode_json", Message_encode_json, 1);
|
417
479
|
rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
|
480
|
+
|
418
481
|
return klass;
|
419
482
|
}
|
420
483
|
|
@@ -427,7 +490,7 @@ VALUE build_class_from_descriptor(Descriptor* desc) {
|
|
427
490
|
*/
|
428
491
|
VALUE enum_lookup(VALUE self, VALUE number) {
|
429
492
|
int32_t num = NUM2INT(number);
|
430
|
-
VALUE desc =
|
493
|
+
VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
|
431
494
|
EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc);
|
432
495
|
|
433
496
|
const char* name = upb_enumdef_iton(enumdesc->enumdef, num);
|
@@ -447,7 +510,7 @@ VALUE enum_lookup(VALUE self, VALUE number) {
|
|
447
510
|
*/
|
448
511
|
VALUE enum_resolve(VALUE self, VALUE sym) {
|
449
512
|
const char* name = rb_id2name(SYM2ID(sym));
|
450
|
-
VALUE desc =
|
513
|
+
VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
|
451
514
|
EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc);
|
452
515
|
|
453
516
|
int32_t num = 0;
|
@@ -467,7 +530,7 @@ VALUE enum_resolve(VALUE self, VALUE sym) {
|
|
467
530
|
* EnumDescriptor corresponding to this enum type.
|
468
531
|
*/
|
469
532
|
VALUE enum_descriptor(VALUE self) {
|
470
|
-
return
|
533
|
+
return rb_ivar_get(self, descriptor_instancevar_interned);
|
471
534
|
}
|
472
535
|
|
473
536
|
VALUE build_module_from_enumdesc(EnumDescriptor* enumdesc) {
|
@@ -492,7 +555,8 @@ VALUE build_module_from_enumdesc(EnumDescriptor* enumdesc) {
|
|
492
555
|
rb_define_singleton_method(mod, "lookup", enum_lookup, 1);
|
493
556
|
rb_define_singleton_method(mod, "resolve", enum_resolve, 1);
|
494
557
|
rb_define_singleton_method(mod, "descriptor", enum_descriptor, 0);
|
495
|
-
|
558
|
+
rb_ivar_set(mod, descriptor_instancevar_interned,
|
559
|
+
get_def_obj(enumdesc->enumdef));
|
496
560
|
|
497
561
|
return mod;
|
498
562
|
}
|