slayer-thrift 0.7.0

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