]> git.proxmox.com Git - ceph.git/blame - ceph/src/jaegertracing/thrift/lib/rb/ext/struct.c
buildsys: switch source download to quincy
[ceph.git] / ceph / src / jaegertracing / thrift / lib / rb / ext / struct.c
CommitLineData
f67539c2
TL
1/**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20#include "struct.h"
21#include "constants.h"
22#include "macros.h"
23#include "strlcpy.h"
24
25VALUE thrift_union_class;
26
27ID setfield_id;
28ID setvalue_id;
29
30ID to_s_method_id;
31ID name_to_id_method_id;
32static ID sorted_field_ids_method_id;
33
34#define IS_CONTAINER(ttype) ((ttype) == TTYPE_MAP || (ttype) == TTYPE_LIST || (ttype) == TTYPE_SET)
35#define STRUCT_FIELDS(obj) rb_const_get(CLASS_OF(obj), fields_const_id)
36
37//-------------------------------------------
38// Writing section
39//-------------------------------------------
40
41// default fn pointers for protocol stuff here
42
43VALUE default_write_bool(VALUE protocol, VALUE value) {
44 rb_funcall(protocol, write_boolean_method_id, 1, value);
45 return Qnil;
46}
47
48VALUE default_write_byte(VALUE protocol, VALUE value) {
49 rb_funcall(protocol, write_byte_method_id, 1, value);
50 return Qnil;
51}
52
53VALUE default_write_i16(VALUE protocol, VALUE value) {
54 rb_funcall(protocol, write_i16_method_id, 1, value);
55 return Qnil;
56}
57
58VALUE default_write_i32(VALUE protocol, VALUE value) {
59 rb_funcall(protocol, write_i32_method_id, 1, value);
60 return Qnil;
61}
62
63VALUE default_write_i64(VALUE protocol, VALUE value) {
64 rb_funcall(protocol, write_i64_method_id, 1, value);
65 return Qnil;
66}
67
68VALUE default_write_double(VALUE protocol, VALUE value) {
69 rb_funcall(protocol, write_double_method_id, 1, value);
70 return Qnil;
71}
72
73VALUE default_write_string(VALUE protocol, VALUE value) {
74 rb_funcall(protocol, write_string_method_id, 1, value);
75 return Qnil;
76}
77
78VALUE default_write_binary(VALUE protocol, VALUE value) {
79 rb_funcall(protocol, write_binary_method_id, 1, value);
80 return Qnil;
81}
82
83VALUE default_write_list_begin(VALUE protocol, VALUE etype, VALUE length) {
84 rb_funcall(protocol, write_list_begin_method_id, 2, etype, length);
85 return Qnil;
86}
87
88VALUE default_write_list_end(VALUE protocol) {
89 rb_funcall(protocol, write_list_end_method_id, 0);
90 return Qnil;
91}
92
93VALUE default_write_set_begin(VALUE protocol, VALUE etype, VALUE length) {
94 rb_funcall(protocol, write_set_begin_method_id, 2, etype, length);
95 return Qnil;
96}
97
98VALUE default_write_set_end(VALUE protocol) {
99 rb_funcall(protocol, write_set_end_method_id, 0);
100 return Qnil;
101}
102
103VALUE default_write_map_begin(VALUE protocol, VALUE ktype, VALUE vtype, VALUE length) {
104 rb_funcall(protocol, write_map_begin_method_id, 3, ktype, vtype, length);
105 return Qnil;
106}
107
108VALUE default_write_map_end(VALUE protocol) {
109 rb_funcall(protocol, write_map_end_method_id, 0);
110 return Qnil;
111}
112
113VALUE default_write_struct_begin(VALUE protocol, VALUE struct_name) {
114 rb_funcall(protocol, write_struct_begin_method_id, 1, struct_name);
115 return Qnil;
116}
117
118VALUE default_write_struct_end(VALUE protocol) {
119 rb_funcall(protocol, write_struct_end_method_id, 0);
120 return Qnil;
121}
122
123VALUE default_write_field_begin(VALUE protocol, VALUE name, VALUE type, VALUE id) {
124 rb_funcall(protocol, write_field_begin_method_id, 3, name, type, id);
125 return Qnil;
126}
127
128VALUE default_write_field_end(VALUE protocol) {
129 rb_funcall(protocol, write_field_end_method_id, 0);
130 return Qnil;
131}
132
133VALUE default_write_field_stop(VALUE protocol) {
134 rb_funcall(protocol, write_field_stop_method_id, 0);
135 return Qnil;
136}
137
138VALUE default_read_field_begin(VALUE protocol) {
139 return rb_funcall(protocol, read_field_begin_method_id, 0);
140}
141
142VALUE default_read_field_end(VALUE protocol) {
143 return rb_funcall(protocol, read_field_end_method_id, 0);
144}
145
146VALUE default_read_map_begin(VALUE protocol) {
147 return rb_funcall(protocol, read_map_begin_method_id, 0);
148}
149
150VALUE default_read_map_end(VALUE protocol) {
151 return rb_funcall(protocol, read_map_end_method_id, 0);
152}
153
154VALUE default_read_list_begin(VALUE protocol) {
155 return rb_funcall(protocol, read_list_begin_method_id, 0);
156}
157
158VALUE default_read_list_end(VALUE protocol) {
159 return rb_funcall(protocol, read_list_end_method_id, 0);
160}
161
162VALUE default_read_set_begin(VALUE protocol) {
163 return rb_funcall(protocol, read_set_begin_method_id, 0);
164}
165
166VALUE default_read_set_end(VALUE protocol) {
167 return rb_funcall(protocol, read_set_end_method_id, 0);
168}
169
170VALUE default_read_byte(VALUE protocol) {
171 return rb_funcall(protocol, read_byte_method_id, 0);
172}
173
174VALUE default_read_bool(VALUE protocol) {
175 return rb_funcall(protocol, read_bool_method_id, 0);
176}
177
178VALUE default_read_i16(VALUE protocol) {
179 return rb_funcall(protocol, read_i16_method_id, 0);
180}
181
182VALUE default_read_i32(VALUE protocol) {
183 return rb_funcall(protocol, read_i32_method_id, 0);
184}
185
186VALUE default_read_i64(VALUE protocol) {
187 return rb_funcall(protocol, read_i64_method_id, 0);
188}
189
190VALUE default_read_double(VALUE protocol) {
191 return rb_funcall(protocol, read_double_method_id, 0);
192}
193
194VALUE default_read_string(VALUE protocol) {
195 return rb_funcall(protocol, read_string_method_id, 0);
196}
197
198VALUE default_read_binary(VALUE protocol) {
199 return rb_funcall(protocol, read_binary_method_id, 0);
200}
201
202VALUE default_read_struct_begin(VALUE protocol) {
203 return rb_funcall(protocol, read_struct_begin_method_id, 0);
204}
205
206VALUE default_read_struct_end(VALUE protocol) {
207 return rb_funcall(protocol, read_struct_end_method_id, 0);
208}
209
210// end default protocol methods
211
212static VALUE rb_thrift_union_write (VALUE self, VALUE protocol);
213static VALUE rb_thrift_struct_write(VALUE self, VALUE protocol);
214static void write_anything(int ttype, VALUE value, VALUE protocol, VALUE field_info);
215
216VALUE get_field_value(VALUE obj, VALUE field_name) {
217 char name_buf[RSTRING_LEN(field_name) + 2];
218
219 name_buf[0] = '@';
220 strlcpy(&name_buf[1], RSTRING_PTR(field_name), RSTRING_LEN(field_name) + 1);
221
222 VALUE value = rb_ivar_get(obj, rb_intern(name_buf));
223
224 return value;
225}
226
227static void write_container(int ttype, VALUE field_info, VALUE value, VALUE protocol) {
228 int sz, i;
229
230 if (ttype == TTYPE_MAP) {
231 VALUE keys;
232 VALUE key;
233 VALUE val;
234
235 Check_Type(value, T_HASH);
236
237 VALUE key_info = rb_hash_aref(field_info, key_sym);
238 VALUE keytype_value = rb_hash_aref(key_info, type_sym);
239 int keytype = FIX2INT(keytype_value);
240
241 VALUE value_info = rb_hash_aref(field_info, value_sym);
242 VALUE valuetype_value = rb_hash_aref(value_info, type_sym);
243 int valuetype = FIX2INT(valuetype_value);
244
245 keys = rb_funcall(value, keys_method_id, 0);
246
247 sz = RARRAY_LEN(keys);
248
249 default_write_map_begin(protocol, keytype_value, valuetype_value, INT2FIX(sz));
250
251 for (i = 0; i < sz; i++) {
252 key = rb_ary_entry(keys, i);
253 val = rb_hash_aref(value, key);
254
255 if (IS_CONTAINER(keytype)) {
256 write_container(keytype, key_info, key, protocol);
257 } else {
258 write_anything(keytype, key, protocol, key_info);
259 }
260
261 if (IS_CONTAINER(valuetype)) {
262 write_container(valuetype, value_info, val, protocol);
263 } else {
264 write_anything(valuetype, val, protocol, value_info);
265 }
266 }
267
268 default_write_map_end(protocol);
269 } else if (ttype == TTYPE_LIST) {
270 Check_Type(value, T_ARRAY);
271
272 sz = RARRAY_LEN(value);
273
274 VALUE element_type_info = rb_hash_aref(field_info, element_sym);
275 VALUE element_type_value = rb_hash_aref(element_type_info, type_sym);
276 int element_type = FIX2INT(element_type_value);
277
278 default_write_list_begin(protocol, element_type_value, INT2FIX(sz));
279 for (i = 0; i < sz; ++i) {
280 VALUE val = rb_ary_entry(value, i);
281 if (IS_CONTAINER(element_type)) {
282 write_container(element_type, element_type_info, val, protocol);
283 } else {
284 write_anything(element_type, val, protocol, element_type_info);
285 }
286 }
287 default_write_list_end(protocol);
288 } else if (ttype == TTYPE_SET) {
289 VALUE items;
290
291 if (TYPE(value) == T_ARRAY) {
292 items = value;
293 } else {
294 if (rb_cSet == CLASS_OF(value)) {
295 items = rb_funcall(value, entries_method_id, 0);
296 } else {
297 Check_Type(value, T_HASH);
298 items = rb_funcall(value, keys_method_id, 0);
299 }
300 }
301
302 sz = RARRAY_LEN(items);
303
304 VALUE element_type_info = rb_hash_aref(field_info, element_sym);
305 VALUE element_type_value = rb_hash_aref(element_type_info, type_sym);
306 int element_type = FIX2INT(element_type_value);
307
308 default_write_set_begin(protocol, element_type_value, INT2FIX(sz));
309
310 for (i = 0; i < sz; i++) {
311 VALUE val = rb_ary_entry(items, i);
312 if (IS_CONTAINER(element_type)) {
313 write_container(element_type, element_type_info, val, protocol);
314 } else {
315 write_anything(element_type, val, protocol, element_type_info);
316 }
317 }
318
319 default_write_set_end(protocol);
320 } else {
321 rb_raise(rb_eNotImpError, "can't write container of type: %d", ttype);
322 }
323}
324
325static void write_anything(int ttype, VALUE value, VALUE protocol, VALUE field_info) {
326 if (ttype == TTYPE_BOOL) {
327 default_write_bool(protocol, value);
328 } else if (ttype == TTYPE_BYTE) {
329 default_write_byte(protocol, value);
330 } else if (ttype == TTYPE_I16) {
331 default_write_i16(protocol, value);
332 } else if (ttype == TTYPE_I32) {
333 default_write_i32(protocol, value);
334 } else if (ttype == TTYPE_I64) {
335 default_write_i64(protocol, value);
336 } else if (ttype == TTYPE_DOUBLE) {
337 default_write_double(protocol, value);
338 } else if (ttype == TTYPE_STRING) {
339 VALUE is_binary = rb_hash_aref(field_info, binary_sym);
340 if (is_binary != Qtrue) {
341 default_write_string(protocol, value);
342 } else {
343 default_write_binary(protocol, value);
344 }
345 } else if (IS_CONTAINER(ttype)) {
346 write_container(ttype, field_info, value, protocol);
347 } else if (ttype == TTYPE_STRUCT) {
348 if (rb_obj_is_kind_of(value, thrift_union_class)) {
349 rb_thrift_union_write(value, protocol);
350 } else {
351 rb_thrift_struct_write(value, protocol);
352 }
353 } else {
354 rb_raise(rb_eNotImpError, "Unknown type for binary_encoding: %d", ttype);
355 }
356}
357
358static VALUE rb_thrift_struct_write(VALUE self, VALUE protocol) {
359 // call validate
360 rb_funcall(self, validate_method_id, 0);
361
362 // write struct begin
363 default_write_struct_begin(protocol, rb_class_name(CLASS_OF(self)));
364
365 // iterate through all the fields here
366 VALUE struct_fields = STRUCT_FIELDS(self);
367 VALUE sorted_field_ids = rb_funcall(self, sorted_field_ids_method_id, 0);
368
369 int i = 0;
370 for (i=0; i < RARRAY_LEN(sorted_field_ids); i++) {
371 VALUE field_id = rb_ary_entry(sorted_field_ids, i);
372
373 VALUE field_info = rb_hash_aref(struct_fields, field_id);
374
375 VALUE ttype_value = rb_hash_aref(field_info, type_sym);
376 int ttype = FIX2INT(ttype_value);
377 VALUE field_name = rb_hash_aref(field_info, name_sym);
378
379 VALUE field_value = get_field_value(self, field_name);
380
381 if (!NIL_P(field_value)) {
382 default_write_field_begin(protocol, field_name, ttype_value, field_id);
383
384 write_anything(ttype, field_value, protocol, field_info);
385
386 default_write_field_end(protocol);
387 }
388 }
389
390 default_write_field_stop(protocol);
391
392 // write struct end
393 default_write_struct_end(protocol);
394
395 return Qnil;
396}
397
398//-------------------------------------------
399// Reading section
400//-------------------------------------------
401
402static VALUE rb_thrift_union_read(VALUE self, VALUE protocol);
403static VALUE rb_thrift_struct_read(VALUE self, VALUE protocol);
404static void skip_map_contents(VALUE protocol, VALUE key_type_value, VALUE value_type_value, int size);
405static void skip_list_or_set_contents(VALUE protocol, VALUE element_type_value, int size);
406
407static void set_field_value(VALUE obj, VALUE field_name, VALUE value) {
408 char name_buf[RSTRING_LEN(field_name) + 2];
409
410 name_buf[0] = '@';
411 strlcpy(&name_buf[1], RSTRING_PTR(field_name), RSTRING_LEN(field_name)+1);
412
413 rb_ivar_set(obj, rb_intern(name_buf), value);
414}
415
416// Helper method to skip the contents of a map (assumes the map header has been read).
417static void skip_map_contents(VALUE protocol, VALUE key_type_value, VALUE value_type_value, int size) {
418 int i;
419 for (i = 0; i < size; i++) {
420 rb_funcall(protocol, skip_method_id, 1, key_type_value);
421 rb_funcall(protocol, skip_method_id, 1, value_type_value);
422 }
423}
424
425// Helper method to skip the contents of a list or set (assumes the list/set header has been read).
426static void skip_list_or_set_contents(VALUE protocol, VALUE element_type_value, int size) {
427 int i;
428 for (i = 0; i < size; i++) {
429 rb_funcall(protocol, skip_method_id, 1, element_type_value);
430 }
431}
432
433static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
434 VALUE result = Qnil;
435
436 if (ttype == TTYPE_BOOL) {
437 result = default_read_bool(protocol);
438 } else if (ttype == TTYPE_BYTE) {
439 result = default_read_byte(protocol);
440 } else if (ttype == TTYPE_I16) {
441 result = default_read_i16(protocol);
442 } else if (ttype == TTYPE_I32) {
443 result = default_read_i32(protocol);
444 } else if (ttype == TTYPE_I64) {
445 result = default_read_i64(protocol);
446 } else if (ttype == TTYPE_STRING) {
447 VALUE is_binary = rb_hash_aref(field_info, binary_sym);
448 if (is_binary != Qtrue) {
449 result = default_read_string(protocol);
450 } else {
451 result = default_read_binary(protocol);
452 }
453 } else if (ttype == TTYPE_DOUBLE) {
454 result = default_read_double(protocol);
455 } else if (ttype == TTYPE_STRUCT) {
456 VALUE klass = rb_hash_aref(field_info, class_sym);
457 result = rb_class_new_instance(0, NULL, klass);
458
459 if (rb_obj_is_kind_of(result, thrift_union_class)) {
460 rb_thrift_union_read(result, protocol);
461 } else {
462 rb_thrift_struct_read(result, protocol);
463 }
464 } else if (ttype == TTYPE_MAP) {
465 int i;
466
467 VALUE map_header = default_read_map_begin(protocol);
468 int key_ttype = FIX2INT(rb_ary_entry(map_header, 0));
469 int value_ttype = FIX2INT(rb_ary_entry(map_header, 1));
470 int num_entries = FIX2INT(rb_ary_entry(map_header, 2));
471
472 // Check the declared key and value types against the expected ones and skip the map contents
473 // if the types don't match.
474 VALUE key_info = rb_hash_aref(field_info, key_sym);
475 VALUE value_info = rb_hash_aref(field_info, value_sym);
476
477 if (!NIL_P(key_info) && !NIL_P(value_info)) {
478 int specified_key_type = FIX2INT(rb_hash_aref(key_info, type_sym));
479 int specified_value_type = FIX2INT(rb_hash_aref(value_info, type_sym));
480 if (num_entries == 0 || (specified_key_type == key_ttype && specified_value_type == value_ttype)) {
481 result = rb_hash_new();
482
483 for (i = 0; i < num_entries; ++i) {
484 VALUE key, val;
485
486 key = read_anything(protocol, key_ttype, key_info);
487 val = read_anything(protocol, value_ttype, value_info);
488
489 rb_hash_aset(result, key, val);
490 }
491 } else {
492 skip_map_contents(protocol, INT2FIX(key_ttype), INT2FIX(value_ttype), num_entries);
493 }
494 } else {
495 skip_map_contents(protocol, INT2FIX(key_ttype), INT2FIX(value_ttype), num_entries);
496 }
497
498 default_read_map_end(protocol);
499 } else if (ttype == TTYPE_LIST) {
500 int i;
501
502 VALUE list_header = default_read_list_begin(protocol);
503 int element_ttype = FIX2INT(rb_ary_entry(list_header, 0));
504 int num_elements = FIX2INT(rb_ary_entry(list_header, 1));
505
506 // Check the declared element type against the expected one and skip the list contents
507 // if the types don't match.
508 VALUE element_info = rb_hash_aref(field_info, element_sym);
509 if (!NIL_P(element_info)) {
510 int specified_element_type = FIX2INT(rb_hash_aref(element_info, type_sym));
511 if (specified_element_type == element_ttype) {
512 result = rb_ary_new2(num_elements);
513
514 for (i = 0; i < num_elements; ++i) {
515 rb_ary_push(result, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym)));
516 }
517 } else {
518 skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements);
519 }
520 } else {
521 skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements);
522 }
523
524 default_read_list_end(protocol);
525 } else if (ttype == TTYPE_SET) {
526 VALUE items;
527 int i;
528
529 VALUE set_header = default_read_set_begin(protocol);
530 int element_ttype = FIX2INT(rb_ary_entry(set_header, 0));
531 int num_elements = FIX2INT(rb_ary_entry(set_header, 1));
532
533 // Check the declared element type against the expected one and skip the set contents
534 // if the types don't match.
535 VALUE element_info = rb_hash_aref(field_info, element_sym);
536 if (!NIL_P(element_info)) {
537 int specified_element_type = FIX2INT(rb_hash_aref(element_info, type_sym));
538 if (specified_element_type == element_ttype) {
539 items = rb_ary_new2(num_elements);
540
541 for (i = 0; i < num_elements; ++i) {
542 rb_ary_push(items, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym)));
543 }
544
545 result = rb_class_new_instance(1, &items, rb_cSet);
546 } else {
547 skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements);
548 }
549 } else {
550 skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements);
551 }
552
553 default_read_set_end(protocol);
554 } else {
555 rb_raise(rb_eNotImpError, "read_anything not implemented for type %d!", ttype);
556 }
557
558 return result;
559}
560
561static VALUE rb_thrift_struct_read(VALUE self, VALUE protocol) {
562 // read struct begin
563 default_read_struct_begin(protocol);
564
565 VALUE struct_fields = STRUCT_FIELDS(self);
566
567 // read each field
568 while (true) {
569 VALUE field_header = default_read_field_begin(protocol);
570 VALUE field_type_value = rb_ary_entry(field_header, 1);
571 int field_type = FIX2INT(field_type_value);
572
573 if (field_type == TTYPE_STOP) {
574 break;
575 }
576
577 // make sure we got a type we expected
578 VALUE field_info = rb_hash_aref(struct_fields, rb_ary_entry(field_header, 2));
579
580 if (!NIL_P(field_info)) {
581 int specified_type = FIX2INT(rb_hash_aref(field_info, type_sym));
582 if (field_type == specified_type) {
583 // read the value
584 VALUE name = rb_hash_aref(field_info, name_sym);
585 set_field_value(self, name, read_anything(protocol, field_type, field_info));
586 } else {
587 rb_funcall(protocol, skip_method_id, 1, field_type_value);
588 }
589 } else {
590 rb_funcall(protocol, skip_method_id, 1, field_type_value);
591 }
592
593 // read field end
594 default_read_field_end(protocol);
595 }
596
597 // read struct end
598 default_read_struct_end(protocol);
599
600 // call validate
601 rb_funcall(self, validate_method_id, 0);
602
603 return Qnil;
604}
605
606
607// --------------------------------
608// Union section
609// --------------------------------
610
611static VALUE rb_thrift_union_read(VALUE self, VALUE protocol) {
612 // read struct begin
613 default_read_struct_begin(protocol);
614
615 VALUE struct_fields = STRUCT_FIELDS(self);
616
617 VALUE field_header = default_read_field_begin(protocol);
618 VALUE field_type_value = rb_ary_entry(field_header, 1);
619 int field_type = FIX2INT(field_type_value);
620
621 // make sure we got a type we expected
622 VALUE field_info = rb_hash_aref(struct_fields, rb_ary_entry(field_header, 2));
623
624 if (!NIL_P(field_info)) {
625 int specified_type = FIX2INT(rb_hash_aref(field_info, type_sym));
626 if (field_type == specified_type) {
627 // read the value
628 VALUE name = rb_hash_aref(field_info, name_sym);
629 rb_iv_set(self, "@setfield", rb_str_intern(name));
630 rb_iv_set(self, "@value", read_anything(protocol, field_type, field_info));
631 } else {
632 rb_funcall(protocol, skip_method_id, 1, field_type_value);
633 }
634 } else {
635 rb_funcall(protocol, skip_method_id, 1, field_type_value);
636 }
637
638 // read field end
639 default_read_field_end(protocol);
640
641 field_header = default_read_field_begin(protocol);
642 field_type_value = rb_ary_entry(field_header, 1);
643 field_type = FIX2INT(field_type_value);
644
645 if (field_type != TTYPE_STOP) {
646 rb_raise(rb_eRuntimeError, "too many fields in union!");
647 }
648
649 // read struct end
650 default_read_struct_end(protocol);
651
652 // call validate
653 rb_funcall(self, validate_method_id, 0);
654
655 return Qnil;
656}
657
658static VALUE rb_thrift_union_write(VALUE self, VALUE protocol) {
659 // call validate
660 rb_funcall(self, validate_method_id, 0);
661
662 // write struct begin
663 default_write_struct_begin(protocol, rb_class_name(CLASS_OF(self)));
664
665 VALUE struct_fields = STRUCT_FIELDS(self);
666
667 VALUE setfield = rb_ivar_get(self, setfield_id);
668 VALUE setvalue = rb_ivar_get(self, setvalue_id);
669 VALUE field_id = rb_funcall(self, name_to_id_method_id, 1, rb_funcall(setfield, to_s_method_id, 0));
670
671 VALUE field_info = rb_hash_aref(struct_fields, field_id);
672
673 if(NIL_P(field_info)) {
674 rb_raise(rb_eRuntimeError, "set_field is not valid for this union!");
675 }
676
677 VALUE ttype_value = rb_hash_aref(field_info, type_sym);
678 int ttype = FIX2INT(ttype_value);
679
680 default_write_field_begin(protocol, setfield, ttype_value, field_id);
681
682 write_anything(ttype, setvalue, protocol, field_info);
683
684 default_write_field_end(protocol);
685
686 default_write_field_stop(protocol);
687
688 // write struct end
689 default_write_struct_end(protocol);
690
691 return Qnil;
692}
693
694void Init_struct() {
695 VALUE struct_module = rb_const_get(thrift_module, rb_intern("Struct"));
696
697 rb_define_method(struct_module, "write", rb_thrift_struct_write, 1);
698 rb_define_method(struct_module, "read", rb_thrift_struct_read, 1);
699
700 thrift_union_class = rb_const_get(thrift_module, rb_intern("Union"));
701
702 rb_define_method(thrift_union_class, "write", rb_thrift_union_write, 1);
703 rb_define_method(thrift_union_class, "read", rb_thrift_union_read, 1);
704
705 setfield_id = rb_intern("@setfield");
706 setvalue_id = rb_intern("@value");
707
708 to_s_method_id = rb_intern("to_s");
709 name_to_id_method_id = rb_intern("name_to_id");
710 sorted_field_ids_method_id = rb_intern("sorted_field_ids");
711}