google-protobuf-z 3.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,734 @@
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
+ // -----------------------------------------------------------------------------
34
+ // Class/module creation from msgdefs and enumdefs, respectively.
35
+ // -----------------------------------------------------------------------------
36
+
37
+ void* Message_data(void* msg) {
38
+ return ((uint8_t *)msg) + sizeof(MessageHeader);
39
+ }
40
+
41
+ void Message_mark(void* _self) {
42
+ MessageHeader* self = (MessageHeader *)_self;
43
+ layout_mark(self->descriptor->layout, Message_data(self));
44
+ }
45
+
46
+ void Message_free(void* self) {
47
+ stringsink* unknown = ((MessageHeader *)self)->unknown_fields;
48
+ if (unknown != NULL) {
49
+ stringsink_uninit(unknown);
50
+ free(unknown);
51
+ }
52
+ xfree(self);
53
+ }
54
+
55
+ rb_data_type_t Message_type = {
56
+ "Message",
57
+ { Message_mark, Message_free, NULL },
58
+ };
59
+
60
+ VALUE Message_alloc(VALUE klass) {
61
+ VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
62
+ Descriptor* desc = ruby_to_Descriptor(descriptor);
63
+ MessageHeader* msg = (MessageHeader*)ALLOC_N(
64
+ uint8_t, sizeof(MessageHeader) + desc->layout->size);
65
+ VALUE ret;
66
+
67
+ memset(Message_data(msg), 0, desc->layout->size);
68
+
69
+ // We wrap first so that everything in the message object is GC-rooted in case
70
+ // a collection happens during object creation in layout_init().
71
+ ret = TypedData_Wrap_Struct(klass, &Message_type, msg);
72
+ msg->descriptor = desc;
73
+ rb_ivar_set(ret, descriptor_instancevar_interned, descriptor);
74
+
75
+ msg->unknown_fields = NULL;
76
+
77
+ layout_init(desc->layout, Message_data(msg));
78
+
79
+ return ret;
80
+ }
81
+
82
+ static const upb_fielddef* which_oneof_field(MessageHeader* self, const upb_oneofdef* o) {
83
+ upb_oneof_iter it;
84
+ size_t case_ofs;
85
+ uint32_t oneof_case;
86
+ const upb_fielddef* first_field;
87
+ const upb_fielddef* f;
88
+
89
+ // If no fields in the oneof, always nil.
90
+ if (upb_oneofdef_numfields(o) == 0) {
91
+ return NULL;
92
+ }
93
+ // Grab the first field in the oneof so we can get its layout info to find the
94
+ // oneof_case field.
95
+ upb_oneof_begin(&it, o);
96
+ assert(!upb_oneof_done(&it));
97
+ first_field = upb_oneof_iter_field(&it);
98
+ assert(upb_fielddef_containingoneof(first_field) != NULL);
99
+
100
+ case_ofs =
101
+ self->descriptor->layout->
102
+ fields[upb_fielddef_index(first_field)].case_offset;
103
+ oneof_case = *((uint32_t*)((char*)Message_data(self) + case_ofs));
104
+
105
+ if (oneof_case == ONEOF_CASE_NONE) {
106
+ return NULL;
107
+ }
108
+
109
+ // oneof_case is a field index, so find that field.
110
+ f = upb_oneofdef_itof(o, oneof_case);
111
+ assert(f != NULL);
112
+
113
+ return f;
114
+ }
115
+
116
+ enum {
117
+ METHOD_UNKNOWN = 0,
118
+ METHOD_GETTER = 1,
119
+ METHOD_SETTER = 2,
120
+ METHOD_CLEAR = 3,
121
+ METHOD_PRESENCE = 4
122
+ };
123
+
124
+ static int extract_method_call(VALUE method_name, MessageHeader* self,
125
+ const upb_fielddef **f, const upb_oneofdef **o) {
126
+ Check_Type(method_name, T_SYMBOL);
127
+
128
+ VALUE method_str = rb_id2str(SYM2ID(method_name));
129
+ char* name = RSTRING_PTR(method_str);
130
+ size_t name_len = RSTRING_LEN(method_str);
131
+ int accessor_type;
132
+ const upb_oneofdef* test_o;
133
+ const upb_fielddef* test_f;
134
+
135
+ if (name[name_len - 1] == '=') {
136
+ accessor_type = METHOD_SETTER;
137
+ name_len--;
138
+ // We want to ensure if the proto has something named clear_foo or has_foo?,
139
+ // we don't strip the prefix.
140
+ } else if (strncmp("clear_", name, 6) == 0 &&
141
+ !upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len,
142
+ &test_f, &test_o)) {
143
+ accessor_type = METHOD_CLEAR;
144
+ name = name + 6;
145
+ name_len = name_len - 6;
146
+ } else if (strncmp("has_", name, 4) == 0 && name[name_len - 1] == '?' &&
147
+ !upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len,
148
+ &test_f, &test_o)) {
149
+ accessor_type = METHOD_PRESENCE;
150
+ name = name + 4;
151
+ name_len = name_len - 5;
152
+ } else {
153
+ accessor_type = METHOD_GETTER;
154
+ }
155
+
156
+ // Verify the name corresponds to a oneof or field in this message.
157
+ if (!upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len,
158
+ &test_f, &test_o)) {
159
+ return METHOD_UNKNOWN;
160
+ }
161
+
162
+ // Method calls like 'has_foo?' are not allowed if field "foo" does not have
163
+ // a hasbit (e.g. repeated fields or non-message type fields for proto3
164
+ // syntax).
165
+ if (accessor_type == METHOD_PRESENCE && test_f != NULL &&
166
+ !upb_fielddef_haspresence(test_f)) {
167
+ return METHOD_UNKNOWN;
168
+ }
169
+
170
+ *o = test_o;
171
+ *f = test_f;
172
+ return accessor_type;
173
+ }
174
+
175
+ /*
176
+ * call-seq:
177
+ * Message.method_missing(*args)
178
+ *
179
+ * Provides accessors and setters and methods to clear and check for presence of
180
+ * message fields according to their field names.
181
+ *
182
+ * For any field whose name does not conflict with a built-in method, an
183
+ * accessor is provided with the same name as the field, and a setter is
184
+ * provided with the name of the field plus the '=' suffix. Thus, given a
185
+ * message instance 'msg' with field 'foo', the following code is valid:
186
+ *
187
+ * msg.foo = 42
188
+ * puts msg.foo
189
+ *
190
+ * This method also provides read-only accessors for oneofs. If a oneof exists
191
+ * with name 'my_oneof', then msg.my_oneof will return a Ruby symbol equal to
192
+ * the name of the field in that oneof that is currently set, or nil if none.
193
+ *
194
+ * It also provides methods of the form 'clear_fieldname' to clear the value
195
+ * of the field 'fieldname'. For basic data types, this will set the default
196
+ * value of the field.
197
+ *
198
+ * Additionally, it provides methods of the form 'has_fieldname?', which returns
199
+ * true if the field 'fieldname' is set in the message object, else false. For
200
+ * 'proto3' syntax, calling this for a basic type field will result in an error.
201
+ */
202
+ VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
203
+ MessageHeader* self;
204
+ const upb_oneofdef* o;
205
+ const upb_fielddef* f;
206
+
207
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
208
+ if (argc < 1) {
209
+ rb_raise(rb_eArgError, "Expected method name as first argument.");
210
+ }
211
+
212
+ int accessor_type = extract_method_call(argv[0], self, &f, &o);
213
+ if (accessor_type == METHOD_UNKNOWN || (o == NULL && f == NULL) ) {
214
+ return rb_call_super(argc, argv);
215
+ } else if (accessor_type == METHOD_SETTER) {
216
+ if (argc != 2) {
217
+ rb_raise(rb_eArgError, "Expected 2 arguments, received %d", argc);
218
+ }
219
+ } else if (argc != 1) {
220
+ rb_raise(rb_eArgError, "Expected 1 argument, received %d", argc);
221
+ }
222
+
223
+ // Return which of the oneof fields are set
224
+ if (o != NULL) {
225
+ if (accessor_type == METHOD_SETTER) {
226
+ rb_raise(rb_eRuntimeError, "Oneof accessors are read-only.");
227
+ }
228
+
229
+ const upb_fielddef* oneof_field = which_oneof_field(self, o);
230
+ if (accessor_type == METHOD_PRESENCE) {
231
+ return oneof_field == NULL ? Qfalse : Qtrue;
232
+ } else if (accessor_type == METHOD_CLEAR) {
233
+ if (oneof_field != NULL) {
234
+ layout_clear(self->descriptor->layout, Message_data(self), oneof_field);
235
+ }
236
+ return Qnil;
237
+ } else {
238
+ // METHOD_ACCESSOR
239
+ return oneof_field == NULL ? Qnil :
240
+ ID2SYM(rb_intern(upb_fielddef_name(oneof_field)));
241
+ }
242
+ // Otherwise we're operating on a single proto field
243
+ } else if (accessor_type == METHOD_SETTER) {
244
+ layout_set(self->descriptor->layout, Message_data(self), f, argv[1]);
245
+ return Qnil;
246
+ } else if (accessor_type == METHOD_CLEAR) {
247
+ layout_clear(self->descriptor->layout, Message_data(self), f);
248
+ return Qnil;
249
+ } else if (accessor_type == METHOD_PRESENCE) {
250
+ return layout_has(self->descriptor->layout, Message_data(self), f);
251
+ } else {
252
+ return layout_get(self->descriptor->layout, Message_data(self), f);
253
+ }
254
+ }
255
+
256
+
257
+ VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
258
+ MessageHeader* self;
259
+ const upb_oneofdef* o;
260
+ const upb_fielddef* f;
261
+
262
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
263
+ if (argc < 1) {
264
+ rb_raise(rb_eArgError, "Expected method name as first argument.");
265
+ }
266
+
267
+ int accessor_type = extract_method_call(argv[0], self, &f, &o);
268
+ if (accessor_type == METHOD_UNKNOWN) {
269
+ return rb_call_super(argc, argv);
270
+ } else if (o != NULL) {
271
+ return accessor_type == METHOD_SETTER ? Qfalse : Qtrue;
272
+ } else {
273
+ return Qtrue;
274
+ }
275
+ }
276
+
277
+ VALUE create_submsg_from_hash(const upb_fielddef *f, VALUE hash) {
278
+ const upb_def *d = upb_fielddef_subdef(f);
279
+ assert(d != NULL);
280
+
281
+ VALUE descriptor = get_def_obj(d);
282
+ VALUE msgclass = rb_funcall(descriptor, rb_intern("msgclass"), 0, NULL);
283
+
284
+ VALUE args[1] = { hash };
285
+ return rb_class_new_instance(1, args, msgclass);
286
+ }
287
+
288
+ int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
289
+ MessageHeader* self;
290
+ char *name;
291
+ const upb_fielddef* f;
292
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
293
+
294
+ if (TYPE(key) == T_STRING) {
295
+ name = RSTRING_PTR(key);
296
+ } else if (TYPE(key) == T_SYMBOL) {
297
+ name = RSTRING_PTR(rb_id2str(SYM2ID(key)));
298
+ } else {
299
+ rb_raise(rb_eArgError,
300
+ "Expected string or symbols as hash keys when initializing proto from hash.");
301
+ }
302
+
303
+ f = upb_msgdef_ntofz(self->descriptor->msgdef, name);
304
+ if (f == NULL) {
305
+ rb_raise(rb_eArgError,
306
+ "Unknown field name '%s' in initialization map entry.", name);
307
+ }
308
+
309
+ if (TYPE(val) == T_NIL) {
310
+ return 0;
311
+ }
312
+
313
+ if (is_map_field(f)) {
314
+ VALUE map;
315
+
316
+ if (TYPE(val) != T_HASH) {
317
+ rb_raise(rb_eArgError,
318
+ "Expected Hash object as initializer value for map field '%s'.", name);
319
+ }
320
+ map = layout_get(self->descriptor->layout, Message_data(self), f);
321
+ Map_merge_into_self(map, val);
322
+ } else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
323
+ VALUE ary;
324
+
325
+ if (TYPE(val) != T_ARRAY) {
326
+ rb_raise(rb_eArgError,
327
+ "Expected array as initializer value for repeated field '%s'.", name);
328
+ }
329
+ ary = layout_get(self->descriptor->layout, Message_data(self), f);
330
+ for (int i = 0; i < RARRAY_LEN(val); i++) {
331
+ VALUE entry = rb_ary_entry(val, i);
332
+ if (TYPE(entry) == T_HASH && upb_fielddef_issubmsg(f)) {
333
+ entry = create_submsg_from_hash(f, entry);
334
+ }
335
+
336
+ RepeatedField_push(ary, entry);
337
+ }
338
+ } else {
339
+ if (TYPE(val) == T_HASH && upb_fielddef_issubmsg(f)) {
340
+ val = create_submsg_from_hash(f, val);
341
+ }
342
+
343
+ layout_set(self->descriptor->layout, Message_data(self), f, val);
344
+ }
345
+ return 0;
346
+ }
347
+
348
+ /*
349
+ * call-seq:
350
+ * Message.new(kwargs) => new_message
351
+ *
352
+ * Creates a new instance of the given message class. Keyword arguments may be
353
+ * provided with keywords corresponding to field names.
354
+ *
355
+ * Note that no literal Message class exists. Only concrete classes per message
356
+ * type exist, as provided by the #msgclass method on Descriptors after they
357
+ * have been added to a pool. The method definitions described here on the
358
+ * Message class are provided on each concrete message class.
359
+ */
360
+ VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
361
+ VALUE hash_args;
362
+
363
+ if (argc == 0) {
364
+ return Qnil;
365
+ }
366
+ if (argc != 1) {
367
+ rb_raise(rb_eArgError, "Expected 0 or 1 arguments.");
368
+ }
369
+ hash_args = argv[0];
370
+ if (TYPE(hash_args) != T_HASH) {
371
+ rb_raise(rb_eArgError, "Expected hash arguments.");
372
+ }
373
+
374
+ rb_hash_foreach(hash_args, Message_initialize_kwarg, _self);
375
+ return Qnil;
376
+ }
377
+
378
+ /*
379
+ * call-seq:
380
+ * Message.dup => new_message
381
+ *
382
+ * Performs a shallow copy of this message and returns the new copy.
383
+ */
384
+ VALUE Message_dup(VALUE _self) {
385
+ MessageHeader* self;
386
+ VALUE new_msg;
387
+ MessageHeader* new_msg_self;
388
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
389
+
390
+ new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
391
+ TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self);
392
+
393
+ layout_dup(self->descriptor->layout,
394
+ Message_data(new_msg_self),
395
+ Message_data(self));
396
+
397
+ return new_msg;
398
+ }
399
+
400
+ // Internal only; used by Google::Protobuf.deep_copy.
401
+ VALUE Message_deep_copy(VALUE _self) {
402
+ MessageHeader* self;
403
+ MessageHeader* new_msg_self;
404
+ VALUE new_msg;
405
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
406
+
407
+ new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
408
+ TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self);
409
+
410
+ layout_deep_copy(self->descriptor->layout,
411
+ Message_data(new_msg_self),
412
+ Message_data(self));
413
+
414
+ return new_msg;
415
+ }
416
+
417
+ /*
418
+ * call-seq:
419
+ * Message.==(other) => boolean
420
+ *
421
+ * Performs a deep comparison of this message with another. Messages are equal
422
+ * if they have the same type and if each field is equal according to the :==
423
+ * method's semantics (a more efficient comparison may actually be done if the
424
+ * field is of a primitive type).
425
+ */
426
+ VALUE Message_eq(VALUE _self, VALUE _other) {
427
+ MessageHeader* self;
428
+ MessageHeader* other;
429
+ if (TYPE(_self) != TYPE(_other)) {
430
+ return Qfalse;
431
+ }
432
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
433
+ TypedData_Get_Struct(_other, MessageHeader, &Message_type, other);
434
+
435
+ if (self->descriptor != other->descriptor) {
436
+ return Qfalse;
437
+ }
438
+
439
+ return layout_eq(self->descriptor->layout,
440
+ Message_data(self),
441
+ Message_data(other));
442
+ }
443
+
444
+ /*
445
+ * call-seq:
446
+ * Message.hash => hash_value
447
+ *
448
+ * Returns a hash value that represents this message's field values.
449
+ */
450
+ VALUE Message_hash(VALUE _self) {
451
+ MessageHeader* self;
452
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
453
+
454
+ return layout_hash(self->descriptor->layout, Message_data(self));
455
+ }
456
+
457
+ /*
458
+ * call-seq:
459
+ * Message.inspect => string
460
+ *
461
+ * Returns a human-readable string representing this message. It will be
462
+ * formatted as "<MessageType: field1: value1, field2: value2, ...>". Each
463
+ * field's value is represented according to its own #inspect method.
464
+ */
465
+ VALUE Message_inspect(VALUE _self) {
466
+ MessageHeader* self;
467
+ VALUE str;
468
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
469
+
470
+ str = rb_str_new2("<");
471
+ str = rb_str_append(str, rb_str_new2(rb_class2name(CLASS_OF(_self))));
472
+ str = rb_str_cat2(str, ": ");
473
+ str = rb_str_append(str, layout_inspect(
474
+ self->descriptor->layout, Message_data(self)));
475
+ str = rb_str_cat2(str, ">");
476
+ return str;
477
+ }
478
+
479
+ /*
480
+ * call-seq:
481
+ * Message.to_h => {}
482
+ *
483
+ * Returns the message as a Ruby Hash object, with keys as symbols.
484
+ */
485
+ VALUE Message_to_h(VALUE _self) {
486
+ MessageHeader* self;
487
+ VALUE hash;
488
+ upb_msg_field_iter it;
489
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
490
+
491
+ hash = rb_hash_new();
492
+
493
+ for (upb_msg_field_begin(&it, self->descriptor->msgdef);
494
+ !upb_msg_field_done(&it);
495
+ upb_msg_field_next(&it)) {
496
+ const upb_fielddef* field = upb_msg_iter_field(&it);
497
+
498
+ // For proto2, do not include fields which are not set.
499
+ if (upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2 &&
500
+ field_contains_hasbit(self->descriptor->layout, field) &&
501
+ !layout_has(self->descriptor->layout, Message_data(self), field)) {
502
+ continue;
503
+ }
504
+
505
+ VALUE msg_value = layout_get(self->descriptor->layout, Message_data(self),
506
+ field);
507
+ VALUE msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
508
+ if (is_map_field(field)) {
509
+ msg_value = Map_to_h(msg_value);
510
+ } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
511
+ msg_value = RepeatedField_to_ary(msg_value);
512
+ if (upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2 &&
513
+ RARRAY_LEN(msg_value) == 0) {
514
+ continue;
515
+ }
516
+
517
+ if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
518
+ for (int i = 0; i < RARRAY_LEN(msg_value); i++) {
519
+ VALUE elem = rb_ary_entry(msg_value, i);
520
+ rb_ary_store(msg_value, i, Message_to_h(elem));
521
+ }
522
+ }
523
+
524
+ } else if (msg_value != Qnil &&
525
+ upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
526
+ msg_value = Message_to_h(msg_value);
527
+ }
528
+ rb_hash_aset(hash, msg_key, msg_value);
529
+ }
530
+ return hash;
531
+ }
532
+
533
+
534
+
535
+ /*
536
+ * call-seq:
537
+ * Message.[](index) => value
538
+ *
539
+ * Accesses a field's value by field name. The provided field name should be a
540
+ * string.
541
+ */
542
+ VALUE Message_index(VALUE _self, VALUE field_name) {
543
+ MessageHeader* self;
544
+ const upb_fielddef* field;
545
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
546
+ Check_Type(field_name, T_STRING);
547
+ field = upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
548
+ if (field == NULL) {
549
+ return Qnil;
550
+ }
551
+ return layout_get(self->descriptor->layout, Message_data(self), field);
552
+ }
553
+
554
+ /*
555
+ * call-seq:
556
+ * Message.[]=(index, value)
557
+ *
558
+ * Sets a field's value by field name. The provided field name should be a
559
+ * string.
560
+ */
561
+ VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
562
+ MessageHeader* self;
563
+ const upb_fielddef* field;
564
+ TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
565
+ Check_Type(field_name, T_STRING);
566
+ field = upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
567
+ if (field == NULL) {
568
+ rb_raise(rb_eArgError, "Unknown field: %s", RSTRING_PTR(field_name));
569
+ }
570
+ layout_set(self->descriptor->layout, Message_data(self), field, value);
571
+ return Qnil;
572
+ }
573
+
574
+ /*
575
+ * call-seq:
576
+ * Message.descriptor => descriptor
577
+ *
578
+ * Class method that returns the Descriptor instance corresponding to this
579
+ * message class's type.
580
+ */
581
+ VALUE Message_descriptor(VALUE klass) {
582
+ return rb_ivar_get(klass, descriptor_instancevar_interned);
583
+ }
584
+
585
+ VALUE build_class_from_descriptor(Descriptor* desc) {
586
+ const char *name;
587
+ VALUE klass;
588
+
589
+ if (desc->layout == NULL) {
590
+ desc->layout = create_layout(desc->msgdef);
591
+ }
592
+ if (desc->fill_method == NULL) {
593
+ desc->fill_method = new_fillmsg_decodermethod(desc, &desc->fill_method);
594
+ }
595
+
596
+ name = upb_msgdef_fullname(desc->msgdef);
597
+ if (name == NULL) {
598
+ rb_raise(rb_eRuntimeError, "Descriptor does not have assigned name.");
599
+ }
600
+
601
+ klass = rb_define_class_id(
602
+ // Docs say this parameter is ignored. User will assign return value to
603
+ // their own toplevel constant class name.
604
+ rb_intern("Message"),
605
+ rb_cObject);
606
+ rb_ivar_set(klass, descriptor_instancevar_interned,
607
+ get_def_obj(desc->msgdef));
608
+ rb_define_alloc_func(klass, Message_alloc);
609
+ rb_require("google/protobuf/message_exts");
610
+ rb_include_module(klass, rb_eval_string("::Google::Protobuf::MessageExts"));
611
+ rb_extend_object(
612
+ klass, rb_eval_string("::Google::Protobuf::MessageExts::ClassMethods"));
613
+
614
+ rb_define_method(klass, "method_missing",
615
+ Message_method_missing, -1);
616
+ rb_define_method(klass, "respond_to_missing?",
617
+ Message_respond_to_missing, -1);
618
+ rb_define_method(klass, "initialize", Message_initialize, -1);
619
+ rb_define_method(klass, "dup", Message_dup, 0);
620
+ // Also define #clone so that we don't inherit Object#clone.
621
+ rb_define_method(klass, "clone", Message_dup, 0);
622
+ rb_define_method(klass, "==", Message_eq, 1);
623
+ rb_define_method(klass, "hash", Message_hash, 0);
624
+ rb_define_method(klass, "to_h", Message_to_h, 0);
625
+ rb_define_method(klass, "to_hash", Message_to_h, 0);
626
+ rb_define_method(klass, "inspect", Message_inspect, 0);
627
+ rb_define_method(klass, "[]", Message_index, 1);
628
+ rb_define_method(klass, "[]=", Message_index_set, 2);
629
+ rb_define_singleton_method(klass, "decode", Message_decode, 1);
630
+ rb_define_singleton_method(klass, "encode", Message_encode, 1);
631
+ rb_define_singleton_method(klass, "decode_json", Message_decode_json, 1);
632
+ rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
633
+ rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
634
+
635
+ return klass;
636
+ }
637
+
638
+ /*
639
+ * call-seq:
640
+ * Enum.lookup(number) => name
641
+ *
642
+ * This module method, provided on each generated enum module, looks up an enum
643
+ * value by number and returns its name as a Ruby symbol, or nil if not found.
644
+ */
645
+ VALUE enum_lookup(VALUE self, VALUE number) {
646
+ int32_t num = NUM2INT(number);
647
+ VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
648
+ EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc);
649
+
650
+ const char* name = upb_enumdef_iton(enumdesc->enumdef, num);
651
+ if (name == NULL) {
652
+ return Qnil;
653
+ } else {
654
+ return ID2SYM(rb_intern(name));
655
+ }
656
+ }
657
+
658
+ /*
659
+ * call-seq:
660
+ * Enum.resolve(name) => number
661
+ *
662
+ * This module method, provided on each generated enum module, looks up an enum
663
+ * value by name (as a Ruby symbol) and returns its name, or nil if not found.
664
+ */
665
+ VALUE enum_resolve(VALUE self, VALUE sym) {
666
+ const char* name = rb_id2name(SYM2ID(sym));
667
+ VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
668
+ EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc);
669
+
670
+ int32_t num = 0;
671
+ bool found = upb_enumdef_ntoiz(enumdesc->enumdef, name, &num);
672
+ if (!found) {
673
+ return Qnil;
674
+ } else {
675
+ return INT2NUM(num);
676
+ }
677
+ }
678
+
679
+ /*
680
+ * call-seq:
681
+ * Enum.descriptor
682
+ *
683
+ * This module method, provided on each generated enum module, returns the
684
+ * EnumDescriptor corresponding to this enum type.
685
+ */
686
+ VALUE enum_descriptor(VALUE self) {
687
+ return rb_ivar_get(self, descriptor_instancevar_interned);
688
+ }
689
+
690
+ VALUE build_module_from_enumdesc(EnumDescriptor* enumdesc) {
691
+ VALUE mod = rb_define_module_id(
692
+ rb_intern(upb_enumdef_fullname(enumdesc->enumdef)));
693
+
694
+ upb_enum_iter it;
695
+ for (upb_enum_begin(&it, enumdesc->enumdef);
696
+ !upb_enum_done(&it);
697
+ upb_enum_next(&it)) {
698
+ const char* name = upb_enum_iter_name(&it);
699
+ int32_t value = upb_enum_iter_number(&it);
700
+ if (name[0] < 'A' || name[0] > 'Z') {
701
+ rb_raise(cTypeError,
702
+ "Enum value '%s' does not start with an uppercase letter "
703
+ "as is required for Ruby constants.",
704
+ name);
705
+ }
706
+ rb_define_const(mod, name, INT2NUM(value));
707
+ }
708
+
709
+ rb_define_singleton_method(mod, "lookup", enum_lookup, 1);
710
+ rb_define_singleton_method(mod, "resolve", enum_resolve, 1);
711
+ rb_define_singleton_method(mod, "descriptor", enum_descriptor, 0);
712
+ rb_ivar_set(mod, descriptor_instancevar_interned,
713
+ get_def_obj(enumdesc->enumdef));
714
+
715
+ return mod;
716
+ }
717
+
718
+ /*
719
+ * call-seq:
720
+ * Google::Protobuf.deep_copy(obj) => copy_of_obj
721
+ *
722
+ * Performs a deep copy of a RepeatedField instance, a Map instance, or a
723
+ * message object, recursively copying its members.
724
+ */
725
+ VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) {
726
+ VALUE klass = CLASS_OF(obj);
727
+ if (klass == cRepeatedField) {
728
+ return RepeatedField_deep_copy(obj);
729
+ } else if (klass == cMap) {
730
+ return Map_deep_copy(obj);
731
+ } else {
732
+ return Message_deep_copy(obj);
733
+ }
734
+ }