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
Message_data(void * msg)37 void* Message_data(void* msg) {
38 return ((uint8_t *)msg) + sizeof(MessageHeader);
39 }
40
Message_mark(void * _self)41 void Message_mark(void* _self) {
42 MessageHeader* self = (MessageHeader *)_self;
43 layout_mark(self->descriptor->layout, Message_data(self));
44 }
45
Message_free(void * self)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
Message_alloc(VALUE klass)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
which_oneof_field(MessageHeader * self,const upb_oneofdef * o)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 METHOD_ENUM_GETTER = 5,
123 METHOD_WRAPPER_GETTER = 6,
124 METHOD_WRAPPER_SETTER = 7
125 };
126
127 // Check if the field is a well known wrapper type
is_wrapper_type_field(const upb_fielddef * field)128 static bool is_wrapper_type_field(const upb_fielddef* field) {
129 char* field_type_name = rb_class2name(field_type_class(field));
130
131 return strcmp(field_type_name, "Google::Protobuf::DoubleValue") == 0 ||
132 strcmp(field_type_name, "Google::Protobuf::FloatValue") == 0 ||
133 strcmp(field_type_name, "Google::Protobuf::Int32Value") == 0 ||
134 strcmp(field_type_name, "Google::Protobuf::Int64Value") == 0 ||
135 strcmp(field_type_name, "Google::Protobuf::UInt32Value") == 0 ||
136 strcmp(field_type_name, "Google::Protobuf::UInt64Value") == 0 ||
137 strcmp(field_type_name, "Google::Protobuf::BoolValue") == 0 ||
138 strcmp(field_type_name, "Google::Protobuf::StringValue") == 0 ||
139 strcmp(field_type_name, "Google::Protobuf::BytesValue") == 0;
140 }
141
142 // Get a new Ruby wrapper type and set the initial value
ruby_wrapper_type(const upb_fielddef * field,const VALUE * value)143 static VALUE ruby_wrapper_type(const upb_fielddef* field, const VALUE* value) {
144 if (is_wrapper_type_field(field) && value != Qnil) {
145 VALUE hash = rb_hash_new();
146 rb_hash_aset(hash, rb_str_new2("value"), value);
147 VALUE args[1] = { hash };
148 return rb_class_new_instance(1, args, field_type_class(field));
149 }
150 return Qnil;
151 }
152
extract_method_call(VALUE method_name,MessageHeader * self,const upb_fielddef ** f,const upb_oneofdef ** o)153 static int extract_method_call(VALUE method_name, MessageHeader* self,
154 const upb_fielddef **f, const upb_oneofdef **o) {
155 Check_Type(method_name, T_SYMBOL);
156
157 VALUE method_str = rb_id2str(SYM2ID(method_name));
158 char* name = RSTRING_PTR(method_str);
159 size_t name_len = RSTRING_LEN(method_str);
160 int accessor_type;
161 const upb_oneofdef* test_o;
162 const upb_fielddef* test_f;
163
164 if (name[name_len - 1] == '=') {
165 accessor_type = METHOD_SETTER;
166 name_len--;
167 // We want to ensure if the proto has something named clear_foo or has_foo?,
168 // we don't strip the prefix.
169 } else if (strncmp("clear_", name, 6) == 0 &&
170 !upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len,
171 &test_f, &test_o)) {
172 accessor_type = METHOD_CLEAR;
173 name = name + 6;
174 name_len = name_len - 6;
175 } else if (strncmp("has_", name, 4) == 0 && name[name_len - 1] == '?' &&
176 !upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len,
177 &test_f, &test_o)) {
178 accessor_type = METHOD_PRESENCE;
179 name = name + 4;
180 name_len = name_len - 5;
181 } else {
182 accessor_type = METHOD_GETTER;
183 }
184
185 bool has_field = upb_msgdef_lookupname(self->descriptor->msgdef, name, name_len,
186 &test_f, &test_o);
187
188 // Look for wrapper type accessor of the form <field_name>_as_value
189 if (!has_field &&
190 (accessor_type == METHOD_GETTER || accessor_type == METHOD_SETTER) &&
191 name_len > 9 && strncmp(name + name_len - 9, "_as_value", 9) == 0) {
192 // Find the field name
193 char wrapper_field_name[name_len - 8];
194 strncpy(wrapper_field_name, name, name_len - 9);
195 wrapper_field_name[name_len - 7] = '\0';
196
197 // Check if field exists and is a wrapper type
198 const upb_oneofdef* test_o_wrapper;
199 const upb_fielddef* test_f_wrapper;
200 if (upb_msgdef_lookupname(self->descriptor->msgdef, wrapper_field_name, name_len - 9,
201 &test_f_wrapper, &test_o_wrapper) &&
202 upb_fielddef_type(test_f_wrapper) == UPB_TYPE_MESSAGE &&
203 is_wrapper_type_field(test_f_wrapper)) {
204 // It does exist!
205 has_field = true;
206 if (accessor_type == METHOD_SETTER) {
207 accessor_type = METHOD_WRAPPER_SETTER;
208 } else {
209 accessor_type = METHOD_WRAPPER_GETTER;
210 }
211 test_o = test_o_wrapper;
212 test_f = test_f_wrapper;
213 }
214 }
215
216 // Look for enum accessor of the form <enum_name>_const
217 if (!has_field && accessor_type == METHOD_GETTER &&
218 name_len > 6 && strncmp(name + name_len - 6, "_const", 6) == 0) {
219
220 // Find enum field name
221 char enum_name[name_len - 5];
222 strncpy(enum_name, name, name_len - 6);
223 enum_name[name_len - 4] = '\0';
224
225 // Check if enum field exists
226 const upb_oneofdef* test_o_enum;
227 const upb_fielddef* test_f_enum;
228 if (upb_msgdef_lookupname(self->descriptor->msgdef, enum_name, name_len - 6,
229 &test_f_enum, &test_o_enum) &&
230 upb_fielddef_type(test_f_enum) == UPB_TYPE_ENUM) {
231 // It does exist!
232 has_field = true;
233 accessor_type = METHOD_ENUM_GETTER;
234 test_o = test_o_enum;
235 test_f = test_f_enum;
236 }
237 }
238
239 // Verify the name corresponds to a oneof or field in this message.
240 if (!has_field) {
241 return METHOD_UNKNOWN;
242 }
243
244 // Method calls like 'has_foo?' are not allowed if field "foo" does not have
245 // a hasbit (e.g. repeated fields or non-message type fields for proto3
246 // syntax).
247 if (accessor_type == METHOD_PRESENCE && test_f != NULL &&
248 !upb_fielddef_haspresence(test_f)) {
249 return METHOD_UNKNOWN;
250 }
251
252 *o = test_o;
253 *f = test_f;
254 return accessor_type;
255 }
256
257 /*
258 * call-seq:
259 * Message.method_missing(*args)
260 *
261 * Provides accessors and setters and methods to clear and check for presence of
262 * message fields according to their field names.
263 *
264 * For any field whose name does not conflict with a built-in method, an
265 * accessor is provided with the same name as the field, and a setter is
266 * provided with the name of the field plus the '=' suffix. Thus, given a
267 * message instance 'msg' with field 'foo', the following code is valid:
268 *
269 * msg.foo = 42
270 * puts msg.foo
271 *
272 * This method also provides read-only accessors for oneofs. If a oneof exists
273 * with name 'my_oneof', then msg.my_oneof will return a Ruby symbol equal to
274 * the name of the field in that oneof that is currently set, or nil if none.
275 *
276 * It also provides methods of the form 'clear_fieldname' to clear the value
277 * of the field 'fieldname'. For basic data types, this will set the default
278 * value of the field.
279 *
280 * Additionally, it provides methods of the form 'has_fieldname?', which returns
281 * true if the field 'fieldname' is set in the message object, else false. For
282 * 'proto3' syntax, calling this for a basic type field will result in an error.
283 */
Message_method_missing(int argc,VALUE * argv,VALUE _self)284 VALUE Message_method_missing(int argc, VALUE* argv, VALUE _self) {
285 MessageHeader* self;
286 const upb_oneofdef* o;
287 const upb_fielddef* f;
288
289 TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
290 if (argc < 1) {
291 rb_raise(rb_eArgError, "Expected method name as first argument.");
292 }
293
294 int accessor_type = extract_method_call(argv[0], self, &f, &o);
295 if (accessor_type == METHOD_UNKNOWN || (o == NULL && f == NULL) ) {
296 return rb_call_super(argc, argv);
297 } else if (accessor_type == METHOD_SETTER || accessor_type == METHOD_WRAPPER_SETTER) {
298 if (argc != 2) {
299 rb_raise(rb_eArgError, "Expected 2 arguments, received %d", argc);
300 }
301 rb_check_frozen(_self);
302 } else if (argc != 1) {
303 rb_raise(rb_eArgError, "Expected 1 argument, received %d", argc);
304 }
305
306 // Return which of the oneof fields are set
307 if (o != NULL) {
308 if (accessor_type == METHOD_SETTER) {
309 rb_raise(rb_eRuntimeError, "Oneof accessors are read-only.");
310 }
311
312 const upb_fielddef* oneof_field = which_oneof_field(self, o);
313 if (accessor_type == METHOD_PRESENCE) {
314 return oneof_field == NULL ? Qfalse : Qtrue;
315 } else if (accessor_type == METHOD_CLEAR) {
316 if (oneof_field != NULL) {
317 layout_clear(self->descriptor->layout, Message_data(self), oneof_field);
318 }
319 return Qnil;
320 } else {
321 // METHOD_ACCESSOR
322 return oneof_field == NULL ? Qnil :
323 ID2SYM(rb_intern(upb_fielddef_name(oneof_field)));
324 }
325 // Otherwise we're operating on a single proto field
326 } else if (accessor_type == METHOD_SETTER) {
327 layout_set(self->descriptor->layout, Message_data(self), f, argv[1]);
328 return Qnil;
329 } else if (accessor_type == METHOD_CLEAR) {
330 layout_clear(self->descriptor->layout, Message_data(self), f);
331 return Qnil;
332 } else if (accessor_type == METHOD_PRESENCE) {
333 return layout_has(self->descriptor->layout, Message_data(self), f);
334 } else if (accessor_type == METHOD_WRAPPER_GETTER) {
335 VALUE value = layout_get(self->descriptor->layout, Message_data(self), f);
336 if (value != Qnil) {
337 value = rb_funcall(value, rb_intern("value"), 0);
338 }
339 return value;
340 } else if (accessor_type == METHOD_WRAPPER_SETTER) {
341 VALUE wrapper = ruby_wrapper_type(f, argv[1]);
342 layout_set(self->descriptor->layout, Message_data(self), f, wrapper);
343 return Qnil;
344 } else if (accessor_type == METHOD_ENUM_GETTER) {
345 VALUE enum_type = field_type_class(f);
346 VALUE method = rb_intern("const_get");
347 VALUE raw_value = layout_get(self->descriptor->layout, Message_data(self), f);
348
349 // Map repeated fields to a new type with ints
350 if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
351 int array_size = FIX2INT(rb_funcall(raw_value, rb_intern("length"), 0));
352 VALUE array_args[1] = { ID2SYM(rb_intern("int64")) };
353 VALUE array = rb_class_new_instance(1, array_args, CLASS_OF(raw_value));
354 for (int i = 0; i < array_size; i++) {
355 VALUE entry = rb_funcall(enum_type, method, 1, rb_funcall(raw_value,
356 rb_intern("at"), 1, INT2NUM(i)));
357 rb_funcall(array, rb_intern("push"), 1, entry);
358 }
359 return array;
360 }
361 // Convert the value for singular fields
362 return rb_funcall(enum_type, method, 1, raw_value);
363 } else {
364 return layout_get(self->descriptor->layout, Message_data(self), f);
365 }
366 }
367
368
Message_respond_to_missing(int argc,VALUE * argv,VALUE _self)369 VALUE Message_respond_to_missing(int argc, VALUE* argv, VALUE _self) {
370 MessageHeader* self;
371 const upb_oneofdef* o;
372 const upb_fielddef* f;
373
374 TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
375 if (argc < 1) {
376 rb_raise(rb_eArgError, "Expected method name as first argument.");
377 }
378
379 int accessor_type = extract_method_call(argv[0], self, &f, &o);
380 if (accessor_type == METHOD_UNKNOWN) {
381 return rb_call_super(argc, argv);
382 } else if (o != NULL) {
383 return accessor_type == METHOD_SETTER ? Qfalse : Qtrue;
384 } else {
385 return Qtrue;
386 }
387 }
388
create_submsg_from_hash(const upb_fielddef * f,VALUE hash)389 VALUE create_submsg_from_hash(const upb_fielddef *f, VALUE hash) {
390 const upb_def *d = upb_fielddef_subdef(f);
391 assert(d != NULL);
392
393 VALUE descriptor = get_def_obj(d);
394 VALUE msgclass = rb_funcall(descriptor, rb_intern("msgclass"), 0, NULL);
395
396 VALUE args[1] = { hash };
397 return rb_class_new_instance(1, args, msgclass);
398 }
399
Message_initialize_kwarg(VALUE key,VALUE val,VALUE _self)400 int Message_initialize_kwarg(VALUE key, VALUE val, VALUE _self) {
401 MessageHeader* self;
402 char *name;
403 const upb_fielddef* f;
404 TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
405
406 if (TYPE(key) == T_STRING) {
407 name = RSTRING_PTR(key);
408 } else if (TYPE(key) == T_SYMBOL) {
409 name = RSTRING_PTR(rb_id2str(SYM2ID(key)));
410 } else {
411 rb_raise(rb_eArgError,
412 "Expected string or symbols as hash keys when initializing proto from hash.");
413 }
414
415 f = upb_msgdef_ntofz(self->descriptor->msgdef, name);
416 if (f == NULL) {
417 rb_raise(rb_eArgError,
418 "Unknown field name '%s' in initialization map entry.", name);
419 }
420
421 if (TYPE(val) == T_NIL) {
422 return 0;
423 }
424
425 if (is_map_field(f)) {
426 VALUE map;
427
428 if (TYPE(val) != T_HASH) {
429 rb_raise(rb_eArgError,
430 "Expected Hash object as initializer value for map field '%s' (given %s).",
431 name, rb_class2name(CLASS_OF(val)));
432 }
433 map = layout_get(self->descriptor->layout, Message_data(self), f);
434 Map_merge_into_self(map, val);
435 } else if (upb_fielddef_label(f) == UPB_LABEL_REPEATED) {
436 VALUE ary;
437
438 if (TYPE(val) != T_ARRAY) {
439 rb_raise(rb_eArgError,
440 "Expected array as initializer value for repeated field '%s' (given %s).",
441 name, rb_class2name(CLASS_OF(val)));
442 }
443 ary = layout_get(self->descriptor->layout, Message_data(self), f);
444 for (int i = 0; i < RARRAY_LEN(val); i++) {
445 VALUE entry = rb_ary_entry(val, i);
446 if (TYPE(entry) == T_HASH && upb_fielddef_issubmsg(f)) {
447 entry = create_submsg_from_hash(f, entry);
448 }
449
450 RepeatedField_push(ary, entry);
451 }
452 } else {
453 if (TYPE(val) == T_HASH && upb_fielddef_issubmsg(f)) {
454 val = create_submsg_from_hash(f, val);
455 }
456
457 layout_set(self->descriptor->layout, Message_data(self), f, val);
458 }
459 return 0;
460 }
461
462 /*
463 * call-seq:
464 * Message.new(kwargs) => new_message
465 *
466 * Creates a new instance of the given message class. Keyword arguments may be
467 * provided with keywords corresponding to field names.
468 *
469 * Note that no literal Message class exists. Only concrete classes per message
470 * type exist, as provided by the #msgclass method on Descriptors after they
471 * have been added to a pool. The method definitions described here on the
472 * Message class are provided on each concrete message class.
473 */
Message_initialize(int argc,VALUE * argv,VALUE _self)474 VALUE Message_initialize(int argc, VALUE* argv, VALUE _self) {
475 VALUE hash_args;
476
477 if (argc == 0) {
478 return Qnil;
479 }
480 if (argc != 1) {
481 rb_raise(rb_eArgError, "Expected 0 or 1 arguments.");
482 }
483 hash_args = argv[0];
484 if (TYPE(hash_args) != T_HASH) {
485 rb_raise(rb_eArgError, "Expected hash arguments.");
486 }
487
488 rb_hash_foreach(hash_args, Message_initialize_kwarg, _self);
489 return Qnil;
490 }
491
492 /*
493 * call-seq:
494 * Message.dup => new_message
495 *
496 * Performs a shallow copy of this message and returns the new copy.
497 */
Message_dup(VALUE _self)498 VALUE Message_dup(VALUE _self) {
499 MessageHeader* self;
500 VALUE new_msg;
501 MessageHeader* new_msg_self;
502 TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
503
504 new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
505 TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self);
506
507 layout_dup(self->descriptor->layout,
508 Message_data(new_msg_self),
509 Message_data(self));
510
511 return new_msg;
512 }
513
514 // Internal only; used by Google::Protobuf.deep_copy.
Message_deep_copy(VALUE _self)515 VALUE Message_deep_copy(VALUE _self) {
516 MessageHeader* self;
517 MessageHeader* new_msg_self;
518 VALUE new_msg;
519 TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
520
521 new_msg = rb_class_new_instance(0, NULL, CLASS_OF(_self));
522 TypedData_Get_Struct(new_msg, MessageHeader, &Message_type, new_msg_self);
523
524 layout_deep_copy(self->descriptor->layout,
525 Message_data(new_msg_self),
526 Message_data(self));
527
528 return new_msg;
529 }
530
531 /*
532 * call-seq:
533 * Message.==(other) => boolean
534 *
535 * Performs a deep comparison of this message with another. Messages are equal
536 * if they have the same type and if each field is equal according to the :==
537 * method's semantics (a more efficient comparison may actually be done if the
538 * field is of a primitive type).
539 */
Message_eq(VALUE _self,VALUE _other)540 VALUE Message_eq(VALUE _self, VALUE _other) {
541 MessageHeader* self;
542 MessageHeader* other;
543 if (TYPE(_self) != TYPE(_other)) {
544 return Qfalse;
545 }
546 TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
547 TypedData_Get_Struct(_other, MessageHeader, &Message_type, other);
548
549 if (self->descriptor != other->descriptor) {
550 return Qfalse;
551 }
552
553 return layout_eq(self->descriptor->layout,
554 Message_data(self),
555 Message_data(other));
556 }
557
558 /*
559 * call-seq:
560 * Message.hash => hash_value
561 *
562 * Returns a hash value that represents this message's field values.
563 */
Message_hash(VALUE _self)564 VALUE Message_hash(VALUE _self) {
565 MessageHeader* self;
566 TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
567
568 return layout_hash(self->descriptor->layout, Message_data(self));
569 }
570
571 /*
572 * call-seq:
573 * Message.inspect => string
574 *
575 * Returns a human-readable string representing this message. It will be
576 * formatted as "<MessageType: field1: value1, field2: value2, ...>". Each
577 * field's value is represented according to its own #inspect method.
578 */
Message_inspect(VALUE _self)579 VALUE Message_inspect(VALUE _self) {
580 MessageHeader* self;
581 VALUE str;
582 TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
583
584 str = rb_str_new2("<");
585 str = rb_str_append(str, rb_str_new2(rb_class2name(CLASS_OF(_self))));
586 str = rb_str_cat2(str, ": ");
587 str = rb_str_append(str, layout_inspect(
588 self->descriptor->layout, Message_data(self)));
589 str = rb_str_cat2(str, ">");
590 return str;
591 }
592
593 /*
594 * call-seq:
595 * Message.to_h => {}
596 *
597 * Returns the message as a Ruby Hash object, with keys as symbols.
598 */
Message_to_h(VALUE _self)599 VALUE Message_to_h(VALUE _self) {
600 MessageHeader* self;
601 VALUE hash;
602 upb_msg_field_iter it;
603 TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
604
605 hash = rb_hash_new();
606
607 for (upb_msg_field_begin(&it, self->descriptor->msgdef);
608 !upb_msg_field_done(&it);
609 upb_msg_field_next(&it)) {
610 const upb_fielddef* field = upb_msg_iter_field(&it);
611
612 // For proto2, do not include fields which are not set.
613 if (upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2 &&
614 field_contains_hasbit(self->descriptor->layout, field) &&
615 !layout_has(self->descriptor->layout, Message_data(self), field)) {
616 continue;
617 }
618
619 VALUE msg_value = layout_get(self->descriptor->layout, Message_data(self),
620 field);
621 VALUE msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
622 if (is_map_field(field)) {
623 msg_value = Map_to_h(msg_value);
624 } else if (upb_fielddef_label(field) == UPB_LABEL_REPEATED) {
625 msg_value = RepeatedField_to_ary(msg_value);
626 if (upb_msgdef_syntax(self->descriptor->msgdef) == UPB_SYNTAX_PROTO2 &&
627 RARRAY_LEN(msg_value) == 0) {
628 continue;
629 }
630
631 if (upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
632 for (int i = 0; i < RARRAY_LEN(msg_value); i++) {
633 VALUE elem = rb_ary_entry(msg_value, i);
634 rb_ary_store(msg_value, i, Message_to_h(elem));
635 }
636 }
637
638 } else if (msg_value != Qnil &&
639 upb_fielddef_type(field) == UPB_TYPE_MESSAGE) {
640 msg_value = Message_to_h(msg_value);
641 }
642 rb_hash_aset(hash, msg_key, msg_value);
643 }
644 return hash;
645 }
646
647
648
649 /*
650 * call-seq:
651 * Message.[](index) => value
652 *
653 * Accesses a field's value by field name. The provided field name should be a
654 * string.
655 */
Message_index(VALUE _self,VALUE field_name)656 VALUE Message_index(VALUE _self, VALUE field_name) {
657 MessageHeader* self;
658 const upb_fielddef* field;
659 TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
660 Check_Type(field_name, T_STRING);
661 field = upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
662 if (field == NULL) {
663 return Qnil;
664 }
665 return layout_get(self->descriptor->layout, Message_data(self), field);
666 }
667
668 /*
669 * call-seq:
670 * Message.[]=(index, value)
671 *
672 * Sets a field's value by field name. The provided field name should be a
673 * string.
674 */
Message_index_set(VALUE _self,VALUE field_name,VALUE value)675 VALUE Message_index_set(VALUE _self, VALUE field_name, VALUE value) {
676 MessageHeader* self;
677 const upb_fielddef* field;
678 TypedData_Get_Struct(_self, MessageHeader, &Message_type, self);
679 Check_Type(field_name, T_STRING);
680 field = upb_msgdef_ntofz(self->descriptor->msgdef, RSTRING_PTR(field_name));
681 if (field == NULL) {
682 rb_raise(rb_eArgError, "Unknown field: %s", RSTRING_PTR(field_name));
683 }
684 layout_set(self->descriptor->layout, Message_data(self), field, value);
685 return Qnil;
686 }
687
688 /*
689 * call-seq:
690 * Message.descriptor => descriptor
691 *
692 * Class method that returns the Descriptor instance corresponding to this
693 * message class's type.
694 */
Message_descriptor(VALUE klass)695 VALUE Message_descriptor(VALUE klass) {
696 return rb_ivar_get(klass, descriptor_instancevar_interned);
697 }
698
build_class_from_descriptor(Descriptor * desc)699 VALUE build_class_from_descriptor(Descriptor* desc) {
700 const char *name;
701 VALUE klass;
702
703 if (desc->layout == NULL) {
704 desc->layout = create_layout(desc->msgdef);
705 }
706 if (desc->fill_method == NULL) {
707 desc->fill_method = new_fillmsg_decodermethod(desc, &desc->fill_method);
708 }
709
710 name = upb_msgdef_fullname(desc->msgdef);
711 if (name == NULL) {
712 rb_raise(rb_eRuntimeError, "Descriptor does not have assigned name.");
713 }
714
715 klass = rb_define_class_id(
716 // Docs say this parameter is ignored. User will assign return value to
717 // their own toplevel constant class name.
718 rb_intern("Message"),
719 rb_cObject);
720 rb_ivar_set(klass, descriptor_instancevar_interned,
721 get_def_obj(desc->msgdef));
722 rb_define_alloc_func(klass, Message_alloc);
723 rb_require("google/protobuf/message_exts");
724 rb_include_module(klass, rb_eval_string("::Google::Protobuf::MessageExts"));
725 rb_extend_object(
726 klass, rb_eval_string("::Google::Protobuf::MessageExts::ClassMethods"));
727
728 rb_define_method(klass, "method_missing",
729 Message_method_missing, -1);
730 rb_define_method(klass, "respond_to_missing?",
731 Message_respond_to_missing, -1);
732 rb_define_method(klass, "initialize", Message_initialize, -1);
733 rb_define_method(klass, "dup", Message_dup, 0);
734 // Also define #clone so that we don't inherit Object#clone.
735 rb_define_method(klass, "clone", Message_dup, 0);
736 rb_define_method(klass, "==", Message_eq, 1);
737 rb_define_method(klass, "eql?", Message_eq, 1);
738 rb_define_method(klass, "hash", Message_hash, 0);
739 rb_define_method(klass, "to_h", Message_to_h, 0);
740 rb_define_method(klass, "inspect", Message_inspect, 0);
741 rb_define_method(klass, "to_s", Message_inspect, 0);
742 rb_define_method(klass, "[]", Message_index, 1);
743 rb_define_method(klass, "[]=", Message_index_set, 2);
744 rb_define_singleton_method(klass, "decode", Message_decode, 1);
745 rb_define_singleton_method(klass, "encode", Message_encode, 1);
746 rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1);
747 rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
748 rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
749
750 return klass;
751 }
752
753 /*
754 * call-seq:
755 * Enum.lookup(number) => name
756 *
757 * This module method, provided on each generated enum module, looks up an enum
758 * value by number and returns its name as a Ruby symbol, or nil if not found.
759 */
enum_lookup(VALUE self,VALUE number)760 VALUE enum_lookup(VALUE self, VALUE number) {
761 int32_t num = NUM2INT(number);
762 VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
763 EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc);
764
765 const char* name = upb_enumdef_iton(enumdesc->enumdef, num);
766 if (name == NULL) {
767 return Qnil;
768 } else {
769 return ID2SYM(rb_intern(name));
770 }
771 }
772
773 /*
774 * call-seq:
775 * Enum.resolve(name) => number
776 *
777 * This module method, provided on each generated enum module, looks up an enum
778 * value by name (as a Ruby symbol) and returns its name, or nil if not found.
779 */
enum_resolve(VALUE self,VALUE sym)780 VALUE enum_resolve(VALUE self, VALUE sym) {
781 const char* name = rb_id2name(SYM2ID(sym));
782 VALUE desc = rb_ivar_get(self, descriptor_instancevar_interned);
783 EnumDescriptor* enumdesc = ruby_to_EnumDescriptor(desc);
784
785 int32_t num = 0;
786 bool found = upb_enumdef_ntoiz(enumdesc->enumdef, name, &num);
787 if (!found) {
788 return Qnil;
789 } else {
790 return INT2NUM(num);
791 }
792 }
793
794 /*
795 * call-seq:
796 * Enum.descriptor
797 *
798 * This module method, provided on each generated enum module, returns the
799 * EnumDescriptor corresponding to this enum type.
800 */
enum_descriptor(VALUE self)801 VALUE enum_descriptor(VALUE self) {
802 return rb_ivar_get(self, descriptor_instancevar_interned);
803 }
804
build_module_from_enumdesc(EnumDescriptor * enumdesc)805 VALUE build_module_from_enumdesc(EnumDescriptor* enumdesc) {
806 VALUE mod = rb_define_module_id(
807 rb_intern(upb_enumdef_fullname(enumdesc->enumdef)));
808
809 upb_enum_iter it;
810 for (upb_enum_begin(&it, enumdesc->enumdef);
811 !upb_enum_done(&it);
812 upb_enum_next(&it)) {
813 const char* name = upb_enum_iter_name(&it);
814 int32_t value = upb_enum_iter_number(&it);
815 if (name[0] < 'A' || name[0] > 'Z') {
816 rb_warn("Enum value '%s' does not start with an uppercase letter "
817 "as is required for Ruby constants.",
818 name);
819 }
820 rb_define_const(mod, name, INT2NUM(value));
821 }
822
823 rb_define_singleton_method(mod, "lookup", enum_lookup, 1);
824 rb_define_singleton_method(mod, "resolve", enum_resolve, 1);
825 rb_define_singleton_method(mod, "descriptor", enum_descriptor, 0);
826 rb_ivar_set(mod, descriptor_instancevar_interned,
827 get_def_obj(enumdesc->enumdef));
828
829 return mod;
830 }
831
832 /*
833 * call-seq:
834 * Google::Protobuf.deep_copy(obj) => copy_of_obj
835 *
836 * Performs a deep copy of a RepeatedField instance, a Map instance, or a
837 * message object, recursively copying its members.
838 */
Google_Protobuf_deep_copy(VALUE self,VALUE obj)839 VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj) {
840 VALUE klass = CLASS_OF(obj);
841 if (klass == cRepeatedField) {
842 return RepeatedField_deep_copy(obj);
843 } else if (klass == cMap) {
844 return Map_deep_copy(obj);
845 } else {
846 return Message_deep_copy(obj);
847 }
848 }
849