thrift 0.0.751142

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. data/CHANGELOG +2 -0
  2. data/COPYING +14 -0
  3. data/LICENSE +14 -0
  4. data/Makefile.am +15 -0
  5. data/Manifest +78 -0
  6. data/README +30 -0
  7. data/Rakefile +102 -0
  8. data/benchmark/Benchmark.thrift +5 -0
  9. data/benchmark/benchmark.rb +254 -0
  10. data/benchmark/client.rb +56 -0
  11. data/benchmark/gen-rb/BenchmarkService.rb +81 -0
  12. data/benchmark/gen-rb/Benchmark_constants.rb +11 -0
  13. data/benchmark/gen-rb/Benchmark_types.rb +10 -0
  14. data/benchmark/server.rb +64 -0
  15. data/benchmark/thin_server.rb +26 -0
  16. data/ext/binary_protocol_accelerated.c +463 -0
  17. data/ext/binary_protocol_accelerated.h +1 -0
  18. data/ext/constants.h +77 -0
  19. data/ext/extconf.rb +7 -0
  20. data/ext/memory_buffer.c +52 -0
  21. data/ext/memory_buffer.h +1 -0
  22. data/ext/protocol.c +166 -0
  23. data/ext/protocol.h +1 -0
  24. data/ext/struct.c +574 -0
  25. data/ext/struct.h +48 -0
  26. data/ext/thrift_native.c +173 -0
  27. data/lib/thrift/client.rb +44 -0
  28. data/lib/thrift/deprecation.rb +155 -0
  29. data/lib/thrift/exceptions.rb +65 -0
  30. data/lib/thrift/processor.rb +39 -0
  31. data/lib/thrift/protocol/binaryprotocol.rb +213 -0
  32. data/lib/thrift/protocol/binaryprotocolaccelerated.rb +19 -0
  33. data/lib/thrift/protocol/tbinaryprotocol.rb +2 -0
  34. data/lib/thrift/protocol/tprotocol.rb +2 -0
  35. data/lib/thrift/protocol.rb +270 -0
  36. data/lib/thrift/serializer.rb +27 -0
  37. data/lib/thrift/server/httpserver.rb +44 -0
  38. data/lib/thrift/server/nonblockingserver.rb +278 -0
  39. data/lib/thrift/server/thttpserver.rb +2 -0
  40. data/lib/thrift/server/tserver.rb +2 -0
  41. data/lib/thrift/server.rb +135 -0
  42. data/lib/thrift/struct.rb +272 -0
  43. data/lib/thrift/thrift.rb +14 -0
  44. data/lib/thrift/transport/httpclient.rb +29 -0
  45. data/lib/thrift/transport/socket.rb +167 -0
  46. data/lib/thrift/transport/thttpclient.rb +2 -0
  47. data/lib/thrift/transport/tsocket.rb +2 -0
  48. data/lib/thrift/transport/ttransport.rb +2 -0
  49. data/lib/thrift/transport/unixsocket.rb +58 -0
  50. data/lib/thrift/transport.rb +319 -0
  51. data/lib/thrift/types.rb +83 -0
  52. data/lib/thrift.rb +28 -0
  53. data/setup.rb +1585 -0
  54. data/spec/ThriftSpec.thrift +46 -0
  55. data/spec/backwards_compatibility_spec.rb +136 -0
  56. data/spec/binaryprotocol_spec.rb +45 -0
  57. data/spec/binaryprotocol_spec_shared.rb +274 -0
  58. data/spec/binaryprotocolaccelerated_spec.rb +101 -0
  59. data/spec/client_spec.rb +81 -0
  60. data/spec/deprecation_spec.rb +443 -0
  61. data/spec/exception_spec.rb +123 -0
  62. data/spec/gen-rb/NonblockingService.rb +268 -0
  63. data/spec/gen-rb/ThriftSpec_constants.rb +11 -0
  64. data/spec/gen-rb/ThriftSpec_types.rb +134 -0
  65. data/spec/httpclient_spec.rb +31 -0
  66. data/spec/httpserver_spec.rb +98 -0
  67. data/spec/nonblockingserver_spec.rb +245 -0
  68. data/spec/processor_spec.rb +64 -0
  69. data/spec/protocol_spec.rb +142 -0
  70. data/spec/serializer_spec.rb +52 -0
  71. data/spec/server_spec.rb +141 -0
  72. data/spec/socket_spec.rb +97 -0
  73. data/spec/socket_spec_shared.rb +85 -0
  74. data/spec/spec_helper.rb +35 -0
  75. data/spec/struct_spec.rb +244 -0
  76. data/spec/transport_spec.rb +359 -0
  77. data/spec/types_spec.rb +98 -0
  78. data/spec/unixsocket_spec.rb +90 -0
  79. data/thrift.gemspec +33 -0
  80. data.tar.gz.sig +0 -0
  81. metadata +200 -0
  82. metadata.gz.sig +0 -0
data/ext/struct.c ADDED
@@ -0,0 +1,574 @@
1
+ #include <struct.h>
2
+ #include <constants.h>
3
+
4
+ #ifndef HAVE_STRLCPY
5
+
6
+ static
7
+ size_t
8
+ strlcpy (char *dst, const char *src, size_t dst_sz)
9
+ {
10
+ size_t n;
11
+
12
+ for (n = 0; n < dst_sz; n++) {
13
+ if ((*dst++ = *src++) == '\0')
14
+ break;
15
+ }
16
+
17
+ if (n < dst_sz)
18
+ return n;
19
+ if (n > 0)
20
+ *(dst - 1) = '\0';
21
+ return n + strlen (src);
22
+ }
23
+
24
+ #endif
25
+
26
+ static native_proto_method_table *mt;
27
+
28
+ #define IS_CONTAINER(ttype) ((ttype) == TTYPE_MAP || (ttype) == TTYPE_LIST || (ttype) == TTYPE_SET)
29
+ #define STRUCT_FIELDS(obj) rb_const_get(CLASS_OF(obj), fields_const_id)
30
+
31
+ //-------------------------------------------
32
+ // Writing section
33
+ //-------------------------------------------
34
+
35
+ // default fn pointers for protocol stuff here
36
+
37
+ VALUE default_write_bool(VALUE protocol, VALUE value) {
38
+ rb_funcall(protocol, write_boolean_method_id, 1, value);
39
+ return Qnil;
40
+ }
41
+
42
+ VALUE default_write_byte(VALUE protocol, VALUE value) {
43
+ rb_funcall(protocol, write_byte_method_id, 1, value);
44
+ return Qnil;
45
+ }
46
+
47
+ VALUE default_write_i16(VALUE protocol, VALUE value) {
48
+ rb_funcall(protocol, write_i16_method_id, 1, value);
49
+ return Qnil;
50
+ }
51
+
52
+ VALUE default_write_i32(VALUE protocol, VALUE value) {
53
+ rb_funcall(protocol, write_i32_method_id, 1, value);
54
+ return Qnil;
55
+ }
56
+
57
+ VALUE default_write_i64(VALUE protocol, VALUE value) {
58
+ rb_funcall(protocol, write_i64_method_id, 1, value);
59
+ return Qnil;
60
+ }
61
+
62
+ VALUE default_write_double(VALUE protocol, VALUE value) {
63
+ rb_funcall(protocol, write_double_method_id, 1, value);
64
+ return Qnil;
65
+ }
66
+
67
+ VALUE default_write_string(VALUE protocol, VALUE value) {
68
+ rb_funcall(protocol, write_string_method_id, 1, value);
69
+ return Qnil;
70
+ }
71
+
72
+ VALUE default_write_list_begin(VALUE protocol, VALUE etype, VALUE length) {
73
+ rb_funcall(protocol, write_list_begin_method_id, 2, etype, length);
74
+ return Qnil;
75
+ }
76
+
77
+ VALUE default_write_list_end(VALUE protocol) {
78
+ rb_funcall(protocol, write_list_end_method_id, 0);
79
+ return Qnil;
80
+ }
81
+
82
+ VALUE default_write_set_begin(VALUE protocol, VALUE etype, VALUE length) {
83
+ rb_funcall(protocol, write_set_begin_method_id, 2, etype, length);
84
+ return Qnil;
85
+ }
86
+
87
+ VALUE default_write_set_end(VALUE protocol) {
88
+ rb_funcall(protocol, write_set_end_method_id, 0);
89
+ return Qnil;
90
+ }
91
+
92
+ VALUE default_write_map_begin(VALUE protocol, VALUE ktype, VALUE vtype, VALUE length) {
93
+ rb_funcall(protocol, write_map_begin_method_id, 3, ktype, vtype, length);
94
+ return Qnil;
95
+ }
96
+
97
+ VALUE default_write_map_end(VALUE protocol) {
98
+ rb_funcall(protocol, write_map_end_method_id, 0);
99
+ return Qnil;
100
+ }
101
+
102
+ VALUE default_write_struct_begin(VALUE protocol, VALUE struct_name) {
103
+ rb_funcall(protocol, write_struct_begin_method_id, 1, struct_name);
104
+ return Qnil;
105
+ }
106
+
107
+ VALUE default_write_struct_end(VALUE protocol) {
108
+ rb_funcall(protocol, write_struct_end_method_id, 0);
109
+ return Qnil;
110
+ }
111
+
112
+ VALUE default_write_field_begin(VALUE protocol, VALUE name, VALUE type, VALUE id) {
113
+ rb_funcall(protocol, write_field_begin_method_id, 3, name, type, id);
114
+ return Qnil;
115
+ }
116
+
117
+ VALUE default_write_field_end(VALUE protocol) {
118
+ rb_funcall(protocol, write_field_end_method_id, 0);
119
+ return Qnil;
120
+ }
121
+
122
+ VALUE default_write_field_stop(VALUE protocol) {
123
+ rb_funcall(protocol, write_field_stop_method_id, 0);
124
+ return Qnil;
125
+ }
126
+
127
+ VALUE default_read_field_begin(VALUE protocol) {
128
+ return rb_funcall(protocol, read_field_begin_method_id, 0);
129
+ }
130
+
131
+ VALUE default_read_field_end(VALUE protocol) {
132
+ return rb_funcall(protocol, read_field_end_method_id, 0);
133
+ }
134
+
135
+ VALUE default_read_map_begin(VALUE protocol) {
136
+ return rb_funcall(protocol, read_map_begin_method_id, 0);
137
+ }
138
+
139
+ VALUE default_read_map_end(VALUE protocol) {
140
+ return rb_funcall(protocol, read_map_end_method_id, 0);
141
+ }
142
+
143
+ VALUE default_read_list_begin(VALUE protocol) {
144
+ return rb_funcall(protocol, read_list_begin_method_id, 0);
145
+ }
146
+
147
+ VALUE default_read_list_end(VALUE protocol) {
148
+ return rb_funcall(protocol, read_list_end_method_id, 0);
149
+ }
150
+
151
+ VALUE default_read_set_begin(VALUE protocol) {
152
+ return rb_funcall(protocol, read_set_begin_method_id, 0);
153
+ }
154
+
155
+ VALUE default_read_set_end(VALUE protocol) {
156
+ return rb_funcall(protocol, read_set_end_method_id, 0);
157
+ }
158
+
159
+ VALUE default_read_byte(VALUE protocol) {
160
+ return rb_funcall(protocol, read_byte_method_id, 0);
161
+ }
162
+
163
+ VALUE default_read_bool(VALUE protocol) {
164
+ return rb_funcall(protocol, read_bool_method_id, 0);
165
+ }
166
+
167
+ VALUE default_read_i16(VALUE protocol) {
168
+ return rb_funcall(protocol, read_i16_method_id, 0);
169
+ }
170
+
171
+ VALUE default_read_i32(VALUE protocol) {
172
+ return rb_funcall(protocol, read_i32_method_id, 0);
173
+ }
174
+
175
+ VALUE default_read_i64(VALUE protocol) {
176
+ return rb_funcall(protocol, read_i64_method_id, 0);
177
+ }
178
+
179
+ VALUE default_read_double(VALUE protocol) {
180
+ return rb_funcall(protocol, read_double_method_id, 0);
181
+ }
182
+
183
+ VALUE default_read_string(VALUE protocol) {
184
+ return rb_funcall(protocol, read_string_method_id, 0);
185
+ }
186
+
187
+ VALUE default_read_struct_begin(VALUE protocol) {
188
+ return rb_funcall(protocol, read_struct_begin_method_id, 0);
189
+ }
190
+
191
+ VALUE default_read_struct_end(VALUE protocol) {
192
+ return rb_funcall(protocol, read_struct_end_method_id, 0);
193
+ }
194
+
195
+ static void set_default_proto_function_pointers() {
196
+ mt = ALLOC(native_proto_method_table);
197
+
198
+ mt->write_field_begin = default_write_field_begin;
199
+ mt->write_field_stop = default_write_field_stop;
200
+ mt->write_map_begin = default_write_map_begin;
201
+ mt->write_map_end = default_write_map_end;
202
+ mt->write_list_begin = default_write_list_begin;
203
+ mt->write_list_end = default_write_list_end;
204
+ mt->write_set_begin = default_write_set_begin;
205
+ mt->write_set_end = default_write_set_end;
206
+ mt->write_byte = default_write_byte;
207
+ mt->write_bool = default_write_bool;
208
+ mt->write_i16 = default_write_i16;
209
+ mt->write_i32 = default_write_i32;
210
+ mt->write_i64 = default_write_i64;
211
+ mt->write_double = default_write_double;
212
+ mt->write_string = default_write_string;
213
+ mt->write_struct_begin = default_write_struct_begin;
214
+ mt->write_struct_end = default_write_struct_end;
215
+ mt->write_field_end = default_write_field_end;
216
+
217
+ mt->read_struct_begin = default_read_struct_begin;
218
+ mt->read_struct_end = default_read_struct_end;
219
+ mt->read_field_begin = default_read_field_begin;
220
+ mt->read_field_end = default_read_field_end;
221
+ mt->read_map_begin = default_read_map_begin;
222
+ mt->read_map_end = default_read_map_end;
223
+ mt->read_list_begin = default_read_list_begin;
224
+ mt->read_list_end = default_read_list_end;
225
+ mt->read_set_begin = default_read_set_begin;
226
+ mt->read_set_end = default_read_set_end;
227
+ mt->read_byte = default_read_byte;
228
+ mt->read_bool = default_read_bool;
229
+ mt->read_i16 = default_read_i16;
230
+ mt->read_i32 = default_read_i32;
231
+ mt->read_i64 = default_read_i64;
232
+ mt->read_double = default_read_double;
233
+ mt->read_string = default_read_string;
234
+
235
+ }
236
+
237
+ static void set_native_proto_function_pointers(VALUE protocol) {
238
+ VALUE method_table_object = rb_const_get(CLASS_OF(protocol), rb_intern("@native_method_table"));
239
+ // TODO: check nil?
240
+ Data_Get_Struct(method_table_object, native_proto_method_table, mt);
241
+ }
242
+
243
+ // end default protocol methods
244
+
245
+
246
+ static VALUE rb_thrift_struct_write(VALUE self, VALUE protocol);
247
+ static void write_anything(int ttype, VALUE value, VALUE protocol, VALUE field_info);
248
+
249
+ VALUE get_field_value(VALUE obj, VALUE field_name) {
250
+ char name_buf[RSTRING(field_name)->len + 1];
251
+
252
+ name_buf[0] = '@';
253
+ strlcpy(&name_buf[1], RSTRING(field_name)->ptr, sizeof(name_buf));
254
+
255
+ VALUE value = rb_ivar_get(obj, rb_intern(name_buf));
256
+
257
+ return value;
258
+ }
259
+
260
+ static void write_container(int ttype, VALUE field_info, VALUE value, VALUE protocol) {
261
+ int sz, i;
262
+
263
+ if (ttype == TTYPE_MAP) {
264
+ VALUE keys;
265
+ VALUE key;
266
+ VALUE val;
267
+
268
+ Check_Type(value, T_HASH);
269
+
270
+ VALUE key_info = rb_hash_aref(field_info, key_sym);
271
+ VALUE keytype_value = rb_hash_aref(key_info, type_sym);
272
+ int keytype = FIX2INT(keytype_value);
273
+
274
+ VALUE value_info = rb_hash_aref(field_info, value_sym);
275
+ VALUE valuetype_value = rb_hash_aref(value_info, type_sym);
276
+ int valuetype = FIX2INT(valuetype_value);
277
+
278
+ keys = rb_funcall(value, keys_method_id, 0);
279
+
280
+ sz = RARRAY(keys)->len;
281
+
282
+ mt->write_map_begin(protocol, keytype_value, valuetype_value, INT2FIX(sz));
283
+
284
+ for (i = 0; i < sz; i++) {
285
+ key = rb_ary_entry(keys, i);
286
+ val = rb_hash_aref(value, key);
287
+
288
+ if (IS_CONTAINER(keytype)) {
289
+ write_container(keytype, key_info, key, protocol);
290
+ } else {
291
+ write_anything(keytype, key, protocol, key_info);
292
+ }
293
+
294
+ if (IS_CONTAINER(valuetype)) {
295
+ write_container(valuetype, value_info, val, protocol);
296
+ } else {
297
+ write_anything(valuetype, val, protocol, value_info);
298
+ }
299
+ }
300
+
301
+ mt->write_map_end(protocol);
302
+ } else if (ttype == TTYPE_LIST) {
303
+ Check_Type(value, T_ARRAY);
304
+
305
+ sz = RARRAY(value)->len;
306
+
307
+ VALUE element_type_info = rb_hash_aref(field_info, element_sym);
308
+ VALUE element_type_value = rb_hash_aref(element_type_info, type_sym);
309
+ int element_type = FIX2INT(element_type_value);
310
+
311
+ mt->write_list_begin(protocol, element_type_value, INT2FIX(sz));
312
+ for (i = 0; i < sz; ++i) {
313
+ VALUE val = rb_ary_entry(value, i);
314
+ if (IS_CONTAINER(element_type)) {
315
+ write_container(element_type, element_type_info, val, protocol);
316
+ } else {
317
+ write_anything(element_type, val, protocol, element_type_info);
318
+ }
319
+ }
320
+ mt->write_list_end(protocol);
321
+ } else if (ttype == TTYPE_SET) {
322
+ VALUE items;
323
+
324
+ if (TYPE(value) == T_ARRAY) {
325
+ items = value;
326
+ } else {
327
+ if (rb_cSet == CLASS_OF(value)) {
328
+ items = rb_funcall(value, entries_method_id, 0);
329
+ } else {
330
+ Check_Type(value, T_HASH);
331
+ items = rb_funcall(value, keys_method_id, 0);
332
+ }
333
+ }
334
+
335
+ sz = RARRAY(items)->len;
336
+
337
+ VALUE element_type_info = rb_hash_aref(field_info, element_sym);
338
+ VALUE element_type_value = rb_hash_aref(element_type_info, type_sym);
339
+ int element_type = FIX2INT(element_type_value);
340
+
341
+ mt->write_set_begin(protocol, element_type_value, INT2FIX(sz));
342
+
343
+ for (i = 0; i < sz; i++) {
344
+ VALUE val = rb_ary_entry(items, i);
345
+ if (IS_CONTAINER(element_type)) {
346
+ write_container(element_type, element_type_info, val, protocol);
347
+ } else {
348
+ write_anything(element_type, val, protocol, element_type_info);
349
+ }
350
+ }
351
+
352
+ mt->write_set_end(protocol);
353
+ } else {
354
+ rb_raise(rb_eNotImpError, "can't write container of type: %d", ttype);
355
+ }
356
+ }
357
+
358
+ static void write_anything(int ttype, VALUE value, VALUE protocol, VALUE field_info) {
359
+ if (ttype == TTYPE_BOOL) {
360
+ mt->write_bool(protocol, value);
361
+ } else if (ttype == TTYPE_BYTE) {
362
+ mt->write_byte(protocol, value);
363
+ } else if (ttype == TTYPE_I16) {
364
+ mt->write_i16(protocol, value);
365
+ } else if (ttype == TTYPE_I32) {
366
+ mt->write_i32(protocol, value);
367
+ } else if (ttype == TTYPE_I64) {
368
+ mt->write_i64(protocol, value);
369
+ } else if (ttype == TTYPE_DOUBLE) {
370
+ mt->write_double(protocol, value);
371
+ } else if (ttype == TTYPE_STRING) {
372
+ mt->write_string(protocol, value);
373
+ } else if (IS_CONTAINER(ttype)) {
374
+ write_container(ttype, field_info, value, protocol);
375
+ } else if (ttype == TTYPE_STRUCT) {
376
+ rb_thrift_struct_write(value, protocol);
377
+ } else {
378
+ rb_raise(rb_eNotImpError, "Unknown type for binary_encoding: %d", ttype);
379
+ }
380
+ }
381
+
382
+ static VALUE rb_thrift_struct_write(VALUE self, VALUE protocol) {
383
+ // call validate
384
+ rb_funcall(self, validate_method_id, 0);
385
+
386
+ if (RTEST(rb_funcall(protocol, native_qmark_method_id, 0))) {
387
+ set_native_proto_function_pointers(protocol);
388
+ } else {
389
+ set_default_proto_function_pointers();
390
+ }
391
+
392
+ // write struct begin
393
+ mt->write_struct_begin(protocol, rb_class_name(CLASS_OF(self)));
394
+
395
+ // iterate through all the fields here
396
+ VALUE struct_fields = STRUCT_FIELDS(self);
397
+ VALUE struct_field_ids_unordered = rb_funcall(struct_fields, keys_method_id, 0);
398
+ VALUE struct_field_ids_ordered = rb_funcall(struct_field_ids_unordered, sort_method_id, 0);
399
+
400
+ int i = 0;
401
+ for (i=0; i < RARRAY(struct_field_ids_ordered)->len; i++) {
402
+ VALUE field_id = rb_ary_entry(struct_field_ids_ordered, i);
403
+ VALUE field_info = rb_hash_aref(struct_fields, field_id);
404
+
405
+ VALUE ttype_value = rb_hash_aref(field_info, type_sym);
406
+ int ttype = FIX2INT(ttype_value);
407
+ VALUE field_name = rb_hash_aref(field_info, name_sym);
408
+ VALUE field_value = get_field_value(self, field_name);
409
+
410
+ if (!NIL_P(field_value)) {
411
+ mt->write_field_begin(protocol, field_name, ttype_value, field_id);
412
+
413
+ write_anything(ttype, field_value, protocol, field_info);
414
+
415
+ mt->write_field_end(protocol);
416
+ }
417
+ }
418
+
419
+ mt->write_field_stop(protocol);
420
+
421
+ // write struct end
422
+ mt->write_struct_end(protocol);
423
+
424
+ return Qnil;
425
+ }
426
+
427
+ //-------------------------------------------
428
+ // Reading section
429
+ //-------------------------------------------
430
+
431
+ static VALUE rb_thrift_struct_read(VALUE self, VALUE protocol);
432
+
433
+ static void set_field_value(VALUE obj, VALUE field_name, VALUE value) {
434
+ char name_buf[RSTRING(field_name)->len + 1];
435
+
436
+ name_buf[0] = '@';
437
+ strlcpy(&name_buf[1], RSTRING(field_name)->ptr, sizeof(name_buf));
438
+
439
+ rb_ivar_set(obj, rb_intern(name_buf), value);
440
+ }
441
+
442
+ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
443
+ VALUE result = Qnil;
444
+
445
+ if (ttype == TTYPE_BOOL) {
446
+ result = mt->read_bool(protocol);
447
+ } else if (ttype == TTYPE_BYTE) {
448
+ result = mt->read_byte(protocol);
449
+ } else if (ttype == TTYPE_I16) {
450
+ result = mt->read_i16(protocol);
451
+ } else if (ttype == TTYPE_I32) {
452
+ result = mt->read_i32(protocol);
453
+ } else if (ttype == TTYPE_I64) {
454
+ result = mt->read_i64(protocol);
455
+ } else if (ttype == TTYPE_STRING) {
456
+ result = mt->read_string(protocol);
457
+ } else if (ttype == TTYPE_DOUBLE) {
458
+ result = mt->read_double(protocol);
459
+ } else if (ttype == TTYPE_STRUCT) {
460
+ VALUE klass = rb_hash_aref(field_info, class_sym);
461
+ result = rb_class_new_instance(0, NULL, klass);
462
+ rb_thrift_struct_read(result, protocol);
463
+ } else if (ttype == TTYPE_MAP) {
464
+ int i;
465
+
466
+ VALUE map_header = mt->read_map_begin(protocol);
467
+ int key_ttype = FIX2INT(rb_ary_entry(map_header, 0));
468
+ int value_ttype = FIX2INT(rb_ary_entry(map_header, 1));
469
+ int num_entries = FIX2INT(rb_ary_entry(map_header, 2));
470
+
471
+ VALUE key_info = rb_hash_aref(field_info, key_sym);
472
+ VALUE value_info = rb_hash_aref(field_info, value_sym);
473
+
474
+ result = rb_hash_new();
475
+
476
+ for (i = 0; i < num_entries; ++i) {
477
+ VALUE key, val;
478
+
479
+ key = read_anything(protocol, key_ttype, key_info);
480
+ val = read_anything(protocol, value_ttype, value_info);
481
+
482
+ rb_hash_aset(result, key, val);
483
+ }
484
+
485
+ mt->read_map_end(protocol);
486
+ } else if (ttype == TTYPE_LIST) {
487
+ int i;
488
+
489
+ VALUE list_header = mt->read_list_begin(protocol);
490
+ int element_ttype = FIX2INT(rb_ary_entry(list_header, 0));
491
+ int num_elements = FIX2INT(rb_ary_entry(list_header, 1));
492
+ result = rb_ary_new2(num_elements);
493
+
494
+ for (i = 0; i < num_elements; ++i) {
495
+ rb_ary_push(result, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym)));
496
+ }
497
+
498
+
499
+ mt->read_list_end(protocol);
500
+ } else if (ttype == TTYPE_SET) {
501
+ VALUE items;
502
+ int i;
503
+
504
+ VALUE set_header = mt->read_set_begin(protocol);
505
+ int element_ttype = FIX2INT(rb_ary_entry(set_header, 0));
506
+ int num_elements = FIX2INT(rb_ary_entry(set_header, 1));
507
+ items = rb_ary_new2(num_elements);
508
+
509
+ for (i = 0; i < num_elements; ++i) {
510
+ rb_ary_push(items, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym)));
511
+ }
512
+
513
+
514
+ mt->read_set_end(protocol);
515
+
516
+ result = rb_class_new_instance(1, &items, rb_cSet);
517
+ } else {
518
+ rb_raise(rb_eNotImpError, "read_anything not implemented for type %d!", ttype);
519
+ }
520
+
521
+ return result;
522
+ }
523
+
524
+ static VALUE rb_thrift_struct_read(VALUE self, VALUE protocol) {
525
+ // read struct begin
526
+ mt->read_struct_begin(protocol);
527
+
528
+ VALUE struct_fields = STRUCT_FIELDS(self);
529
+
530
+ // read each field
531
+ while (true) {
532
+ VALUE field_header = rb_funcall(protocol, read_field_begin_method_id, 0);
533
+ VALUE field_type_value = rb_ary_entry(field_header, 1);
534
+ int field_type = FIX2INT(field_type_value);
535
+
536
+ if (field_type == TTYPE_STOP) {
537
+ break;
538
+ }
539
+
540
+ // make sure we got a type we expected
541
+ VALUE field_info = rb_hash_aref(struct_fields, rb_ary_entry(field_header, 2));
542
+
543
+ if (!NIL_P(field_info)) {
544
+ int specified_type = FIX2INT(rb_hash_aref(field_info, type_sym));
545
+ if (field_type == specified_type) {
546
+ // read the value
547
+ VALUE name = rb_hash_aref(field_info, name_sym);
548
+ set_field_value(self, name, read_anything(protocol, field_type, field_info));
549
+ } else {
550
+ rb_funcall(protocol, skip_method_id, 1, field_type_value);
551
+ }
552
+ } else {
553
+ rb_funcall(protocol, skip_method_id, 1, field_type_value);
554
+ }
555
+
556
+ // read field end
557
+ mt->read_field_end(protocol);
558
+ }
559
+
560
+ // read struct end
561
+ mt->read_struct_end(protocol);
562
+
563
+ return Qnil;
564
+ }
565
+
566
+ void Init_struct() {
567
+ VALUE struct_module = rb_const_get(thrift_module, rb_intern("Struct"));
568
+
569
+ rb_define_method(struct_module, "write", rb_thrift_struct_write, 1);
570
+ rb_define_method(struct_module, "read", rb_thrift_struct_read, 1);
571
+
572
+ set_default_proto_function_pointers();
573
+ }
574
+
data/ext/struct.h ADDED
@@ -0,0 +1,48 @@
1
+ #include <stdbool.h>
2
+ #include <ruby.h>
3
+
4
+ typedef struct native_proto_method_table {
5
+ VALUE (*write_bool)(VALUE, VALUE);
6
+ VALUE (*write_byte)(VALUE, VALUE);
7
+ VALUE (*write_i16)(VALUE, VALUE);
8
+ VALUE (*write_i32)(VALUE, VALUE);
9
+ VALUE (*write_i64)(VALUE, VALUE);
10
+ VALUE (*write_double)(VALUE, VALUE);
11
+ VALUE (*write_string)(VALUE, VALUE);
12
+ VALUE (*write_list_begin)(VALUE, VALUE, VALUE);
13
+ VALUE (*write_list_end)(VALUE);
14
+ VALUE (*write_set_begin)(VALUE, VALUE, VALUE);
15
+ VALUE (*write_set_end)(VALUE);
16
+ VALUE (*write_map_begin)(VALUE, VALUE, VALUE, VALUE);
17
+ VALUE (*write_map_end)(VALUE);
18
+ VALUE (*write_struct_begin)(VALUE, VALUE);
19
+ VALUE (*write_struct_end)(VALUE);
20
+ VALUE (*write_field_begin)(VALUE, VALUE, VALUE, VALUE);
21
+ VALUE (*write_field_end)(VALUE);
22
+ VALUE (*write_field_stop)(VALUE);
23
+ VALUE (*write_message_begin)(VALUE, VALUE, VALUE, VALUE);
24
+ VALUE (*write_message_end)(VALUE);
25
+
26
+ VALUE (*read_message_begin)(VALUE);
27
+ VALUE (*read_message_end)(VALUE);
28
+ VALUE (*read_field_begin)(VALUE);
29
+ VALUE (*read_field_end)(VALUE);
30
+ VALUE (*read_map_begin)(VALUE);
31
+ VALUE (*read_map_end)(VALUE);
32
+ VALUE (*read_list_begin)(VALUE);
33
+ VALUE (*read_list_end)(VALUE);
34
+ VALUE (*read_set_begin)(VALUE);
35
+ VALUE (*read_set_end)(VALUE);
36
+ VALUE (*read_byte)(VALUE);
37
+ VALUE (*read_bool)(VALUE);
38
+ VALUE (*read_i16)(VALUE);
39
+ VALUE (*read_i32)(VALUE);
40
+ VALUE (*read_i64)(VALUE);
41
+ VALUE (*read_double)(VALUE);
42
+ VALUE (*read_string)(VALUE);
43
+ VALUE (*read_struct_begin)(VALUE);
44
+ VALUE (*read_struct_end)(VALUE);
45
+
46
+ } native_proto_method_table;
47
+
48
+ void Init_struct();