thrift 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/InstalledFiles +1 -0
- data/Makefile +512 -0
- data/Makefile.am +3 -1
- data/Makefile.in +117 -45
- data/Manifest +17 -0
- data/Rakefile +6 -8
- data/benchmark/gen-rb/benchmark_constants.rb +10 -0
- data/benchmark/gen-rb/benchmark_service.rb +80 -0
- data/benchmark/gen-rb/benchmark_types.rb +9 -0
- data/debug_proto_test/gen-rb/debug_proto_test_constants.rb +273 -0
- data/debug_proto_test/gen-rb/debug_proto_test_types.rb +705 -0
- data/debug_proto_test/gen-rb/empty_service.rb +24 -0
- data/debug_proto_test/gen-rb/inherited.rb +79 -0
- data/debug_proto_test/gen-rb/reverse_order_service.rb +82 -0
- data/debug_proto_test/gen-rb/service_for_exception_with_a_map.rb +81 -0
- data/debug_proto_test/gen-rb/srv.rb +330 -0
- data/ext/binary_protocol_accelerated.c +24 -11
- data/ext/compact_protocol.c +14 -11
- data/ext/constants.h +1 -0
- data/ext/memory_buffer.c +56 -1
- data/ext/struct.c +76 -19
- data/ext/thrift_native.c +2 -0
- data/lib/thrift/exceptions.rb +3 -1
- data/lib/thrift/protocol/binary_protocol.rb +14 -10
- data/lib/thrift/protocol/compact_protocol.rb +7 -4
- data/lib/thrift/server/nonblocking_server.rb +15 -5
- data/lib/thrift/struct.rb +9 -6
- data/lib/thrift/struct_union.rb +47 -14
- data/lib/thrift/transport/base_transport.rb +39 -2
- data/lib/thrift/transport/buffered_transport.rb +31 -0
- data/lib/thrift/transport/framed_transport.rb +26 -0
- data/lib/thrift/transport/memory_buffer_transport.rb +29 -0
- data/spec/binary_protocol_spec.rb +2 -4
- data/spec/gen-rb/nonblocking_service.rb +272 -0
- data/spec/gen-rb/thrift_spec_constants.rb +10 -0
- data/spec/gen-rb/thrift_spec_types.rb +345 -0
- data/spec/spec_helper.rb +1 -3
- data/thrift.gemspec +10 -11
- data/tmp/thrift-0.7.0.gem +0 -0
- metadata +22 -8
data/ext/constants.h
CHANGED
data/ext/memory_buffer.c
CHANGED
@@ -30,6 +30,11 @@ int GARBAGE_BUFFER_SIZE;
|
|
30
30
|
|
31
31
|
#define GET_BUF(self) rb_ivar_get(self, buf_ivar_id)
|
32
32
|
|
33
|
+
VALUE rb_thrift_memory_buffer_write(VALUE self, VALUE str);
|
34
|
+
VALUE rb_thrift_memory_buffer_read(VALUE self, VALUE length_value);
|
35
|
+
VALUE rb_thrift_memory_buffer_read_byte(VALUE self);
|
36
|
+
VALUE rb_thrift_memory_buffer_read_into_buffer(VALUE self, VALUE buffer_value, VALUE size_value);
|
37
|
+
|
33
38
|
VALUE rb_thrift_memory_buffer_write(VALUE self, VALUE str) {
|
34
39
|
VALUE buf = GET_BUF(self);
|
35
40
|
rb_str_buf_cat(buf, RSTRING_PTR(str), RSTRING_LEN(str));
|
@@ -53,19 +58,69 @@ VALUE rb_thrift_memory_buffer_read(VALUE self, VALUE length_value) {
|
|
53
58
|
rb_ivar_set(self, buf_ivar_id, rb_funcall(buf, slice_method_id, 2, INT2FIX(index), INT2FIX(RSTRING_LEN(buf) - 1)));
|
54
59
|
index = 0;
|
55
60
|
}
|
61
|
+
rb_ivar_set(self, index_ivar_id, INT2FIX(index));
|
56
62
|
|
57
63
|
if (RSTRING_LEN(data) < length) {
|
58
64
|
rb_raise(rb_eEOFError, "Not enough bytes remain in memory buffer");
|
59
65
|
}
|
60
66
|
|
61
|
-
rb_ivar_set(self, index_ivar_id, INT2FIX(index));
|
62
67
|
return data;
|
63
68
|
}
|
64
69
|
|
70
|
+
VALUE rb_thrift_memory_buffer_read_byte(VALUE self) {
|
71
|
+
VALUE index_value = rb_ivar_get(self, index_ivar_id);
|
72
|
+
int index = FIX2INT(index_value);
|
73
|
+
|
74
|
+
VALUE buf = GET_BUF(self);
|
75
|
+
if (index >= RSTRING_LEN(buf)) {
|
76
|
+
rb_raise(rb_eEOFError, "Not enough bytes remain in memory buffer");
|
77
|
+
}
|
78
|
+
char byte = RSTRING_PTR(buf)[index++];
|
79
|
+
|
80
|
+
if (index >= GARBAGE_BUFFER_SIZE) {
|
81
|
+
rb_ivar_set(self, buf_ivar_id, rb_funcall(buf, slice_method_id, 2, INT2FIX(index), INT2FIX(RSTRING_LEN(buf) - 1)));
|
82
|
+
index = 0;
|
83
|
+
}
|
84
|
+
rb_ivar_set(self, index_ivar_id, INT2FIX(index));
|
85
|
+
|
86
|
+
int result = (int) byte;
|
87
|
+
return INT2FIX(result);
|
88
|
+
}
|
89
|
+
|
90
|
+
VALUE rb_thrift_memory_buffer_read_into_buffer(VALUE self, VALUE buffer_value, VALUE size_value) {
|
91
|
+
int i = 0;
|
92
|
+
int size = FIX2INT(size_value);
|
93
|
+
int index;
|
94
|
+
VALUE buf = GET_BUF(self);
|
95
|
+
|
96
|
+
while (i < size) {
|
97
|
+
index = FIX2INT(rb_ivar_get(self, index_ivar_id));
|
98
|
+
if (index >= RSTRING_LEN(buf)) {
|
99
|
+
rb_raise(rb_eEOFError, "Not enough bytes remain in memory buffer");
|
100
|
+
}
|
101
|
+
char byte = RSTRING_PTR(buf)[index++];
|
102
|
+
|
103
|
+
if (index >= GARBAGE_BUFFER_SIZE) {
|
104
|
+
rb_ivar_set(self, buf_ivar_id, rb_funcall(buf, slice_method_id, 2, INT2FIX(index), INT2FIX(RSTRING_LEN(buf) - 1)));
|
105
|
+
index = 0;
|
106
|
+
}
|
107
|
+
rb_ivar_set(self, index_ivar_id, INT2FIX(index));
|
108
|
+
|
109
|
+
if (i >= RSTRING_LEN(buffer_value)) {
|
110
|
+
rb_raise(rb_eIndexError, "index %d out of string", i);
|
111
|
+
}
|
112
|
+
((char*)RSTRING_PTR(buffer_value))[i] = byte;
|
113
|
+
i++;
|
114
|
+
}
|
115
|
+
return INT2FIX(i);
|
116
|
+
}
|
117
|
+
|
65
118
|
void Init_memory_buffer() {
|
66
119
|
VALUE thrift_memory_buffer_class = rb_const_get(thrift_module, rb_intern("MemoryBufferTransport"));
|
67
120
|
rb_define_method(thrift_memory_buffer_class, "write", rb_thrift_memory_buffer_write, 1);
|
68
121
|
rb_define_method(thrift_memory_buffer_class, "read", rb_thrift_memory_buffer_read, 1);
|
122
|
+
rb_define_method(thrift_memory_buffer_class, "read_byte", rb_thrift_memory_buffer_read_byte, 0);
|
123
|
+
rb_define_method(thrift_memory_buffer_class, "read_into_buffer", rb_thrift_memory_buffer_read_into_buffer, 2);
|
69
124
|
|
70
125
|
buf_ivar_id = rb_intern("@buf");
|
71
126
|
index_ivar_id = rb_intern("@index");
|
data/ext/struct.c
CHANGED
@@ -55,6 +55,7 @@ ID setvalue_id;
|
|
55
55
|
|
56
56
|
ID to_s_method_id;
|
57
57
|
ID name_to_id_method_id;
|
58
|
+
static ID sorted_field_ids_method_id;
|
58
59
|
|
59
60
|
#define IS_CONTAINER(ttype) ((ttype) == TTYPE_MAP || (ttype) == TTYPE_LIST || (ttype) == TTYPE_SET)
|
60
61
|
#define STRUCT_FIELDS(obj) rb_const_get(CLASS_OF(obj), fields_const_id)
|
@@ -375,13 +376,11 @@ static VALUE rb_thrift_struct_write(VALUE self, VALUE protocol) {
|
|
375
376
|
|
376
377
|
// iterate through all the fields here
|
377
378
|
VALUE struct_fields = STRUCT_FIELDS(self);
|
378
|
-
|
379
|
-
VALUE struct_field_ids_unordered = rb_funcall(struct_fields, keys_method_id, 0);
|
380
|
-
VALUE struct_field_ids_ordered = rb_funcall(struct_field_ids_unordered, sort_method_id, 0);
|
379
|
+
VALUE sorted_field_ids = rb_funcall(self, sorted_field_ids_method_id, 0);
|
381
380
|
|
382
381
|
int i = 0;
|
383
|
-
for (i=0; i < RARRAY_LEN(
|
384
|
-
VALUE field_id = rb_ary_entry(
|
382
|
+
for (i=0; i < RARRAY_LEN(sorted_field_ids); i++) {
|
383
|
+
VALUE field_id = rb_ary_entry(sorted_field_ids, i);
|
385
384
|
|
386
385
|
VALUE field_info = rb_hash_aref(struct_fields, field_id);
|
387
386
|
|
@@ -414,6 +413,8 @@ static VALUE rb_thrift_struct_write(VALUE self, VALUE protocol) {
|
|
414
413
|
|
415
414
|
static VALUE rb_thrift_union_read(VALUE self, VALUE protocol);
|
416
415
|
static VALUE rb_thrift_struct_read(VALUE self, VALUE protocol);
|
416
|
+
static void skip_map_contents(VALUE protocol, VALUE key_type_value, VALUE value_type_value, int size);
|
417
|
+
static void skip_list_or_set_contents(VALUE protocol, VALUE element_type_value, int size);
|
417
418
|
|
418
419
|
static void set_field_value(VALUE obj, VALUE field_name, VALUE value) {
|
419
420
|
char name_buf[RSTRING_LEN(field_name) + 1];
|
@@ -424,6 +425,23 @@ static void set_field_value(VALUE obj, VALUE field_name, VALUE value) {
|
|
424
425
|
rb_ivar_set(obj, rb_intern(name_buf), value);
|
425
426
|
}
|
426
427
|
|
428
|
+
// Helper method to skip the contents of a map (assumes the map header has been read).
|
429
|
+
static void skip_map_contents(VALUE protocol, VALUE key_type_value, VALUE value_type_value, int size) {
|
430
|
+
int i;
|
431
|
+
for (i = 0; i < size; i++) {
|
432
|
+
rb_funcall(protocol, skip_method_id, 1, key_type_value);
|
433
|
+
rb_funcall(protocol, skip_method_id, 1, value_type_value);
|
434
|
+
}
|
435
|
+
}
|
436
|
+
|
437
|
+
// Helper method to skip the contents of a list or set (assumes the list/set header has been read).
|
438
|
+
static void skip_list_or_set_contents(VALUE protocol, VALUE element_type_value, int size) {
|
439
|
+
int i;
|
440
|
+
for (i = 0; i < size; i++) {
|
441
|
+
rb_funcall(protocol, skip_method_id, 1, element_type_value);
|
442
|
+
}
|
443
|
+
}
|
444
|
+
|
427
445
|
static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
428
446
|
VALUE result = Qnil;
|
429
447
|
|
@@ -458,18 +476,30 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
458
476
|
int value_ttype = FIX2INT(rb_ary_entry(map_header, 1));
|
459
477
|
int num_entries = FIX2INT(rb_ary_entry(map_header, 2));
|
460
478
|
|
479
|
+
// Check the declared key and value types against the expected ones and skip the map contents
|
480
|
+
// if the types don't match.
|
461
481
|
VALUE key_info = rb_hash_aref(field_info, key_sym);
|
462
482
|
VALUE value_info = rb_hash_aref(field_info, value_sym);
|
463
483
|
|
464
|
-
|
484
|
+
if (!NIL_P(key_info) && !NIL_P(value_info)) {
|
485
|
+
int specified_key_type = FIX2INT(rb_hash_aref(key_info, type_sym));
|
486
|
+
int specified_value_type = FIX2INT(rb_hash_aref(value_info, type_sym));
|
487
|
+
if (specified_key_type == key_ttype && specified_value_type == value_ttype) {
|
488
|
+
result = rb_hash_new();
|
465
489
|
|
466
|
-
|
467
|
-
|
490
|
+
for (i = 0; i < num_entries; ++i) {
|
491
|
+
VALUE key, val;
|
468
492
|
|
469
|
-
|
470
|
-
|
493
|
+
key = read_anything(protocol, key_ttype, key_info);
|
494
|
+
val = read_anything(protocol, value_ttype, value_info);
|
471
495
|
|
472
|
-
|
496
|
+
rb_hash_aset(result, key, val);
|
497
|
+
}
|
498
|
+
} else {
|
499
|
+
skip_map_contents(protocol, INT2FIX(key_ttype), INT2FIX(value_ttype), num_entries);
|
500
|
+
}
|
501
|
+
} else {
|
502
|
+
skip_map_contents(protocol, INT2FIX(key_ttype), INT2FIX(value_ttype), num_entries);
|
473
503
|
}
|
474
504
|
|
475
505
|
default_read_map_end(protocol);
|
@@ -479,10 +509,23 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
479
509
|
VALUE list_header = default_read_list_begin(protocol);
|
480
510
|
int element_ttype = FIX2INT(rb_ary_entry(list_header, 0));
|
481
511
|
int num_elements = FIX2INT(rb_ary_entry(list_header, 1));
|
482
|
-
result = rb_ary_new2(num_elements);
|
483
512
|
|
484
|
-
|
485
|
-
|
513
|
+
// Check the declared element type against the expected one and skip the list contents
|
514
|
+
// if the types don't match.
|
515
|
+
VALUE element_info = rb_hash_aref(field_info, element_sym);
|
516
|
+
if (!NIL_P(element_info)) {
|
517
|
+
int specified_element_type = FIX2INT(rb_hash_aref(element_info, type_sym));
|
518
|
+
if (specified_element_type == element_ttype) {
|
519
|
+
result = rb_ary_new2(num_elements);
|
520
|
+
|
521
|
+
for (i = 0; i < num_elements; ++i) {
|
522
|
+
rb_ary_push(result, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym)));
|
523
|
+
}
|
524
|
+
} else {
|
525
|
+
skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements);
|
526
|
+
}
|
527
|
+
} else {
|
528
|
+
skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements);
|
486
529
|
}
|
487
530
|
|
488
531
|
default_read_list_end(protocol);
|
@@ -493,15 +536,28 @@ static VALUE read_anything(VALUE protocol, int ttype, VALUE field_info) {
|
|
493
536
|
VALUE set_header = default_read_set_begin(protocol);
|
494
537
|
int element_ttype = FIX2INT(rb_ary_entry(set_header, 0));
|
495
538
|
int num_elements = FIX2INT(rb_ary_entry(set_header, 1));
|
496
|
-
items = rb_ary_new2(num_elements);
|
497
539
|
|
498
|
-
|
499
|
-
|
540
|
+
// Check the declared element type against the expected one and skip the set contents
|
541
|
+
// if the types don't match.
|
542
|
+
VALUE element_info = rb_hash_aref(field_info, element_sym);
|
543
|
+
if (!NIL_P(element_info)) {
|
544
|
+
int specified_element_type = FIX2INT(rb_hash_aref(element_info, type_sym));
|
545
|
+
if (specified_element_type == element_ttype) {
|
546
|
+
items = rb_ary_new2(num_elements);
|
547
|
+
|
548
|
+
for (i = 0; i < num_elements; ++i) {
|
549
|
+
rb_ary_push(items, read_anything(protocol, element_ttype, rb_hash_aref(field_info, element_sym)));
|
550
|
+
}
|
551
|
+
|
552
|
+
result = rb_class_new_instance(1, &items, rb_cSet);
|
553
|
+
} else {
|
554
|
+
skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements);
|
555
|
+
}
|
556
|
+
} else {
|
557
|
+
skip_list_or_set_contents(protocol, INT2FIX(element_ttype), num_elements);
|
500
558
|
}
|
501
559
|
|
502
560
|
default_read_set_end(protocol);
|
503
|
-
|
504
|
-
result = rb_class_new_instance(1, &items, rb_cSet);
|
505
561
|
} else {
|
506
562
|
rb_raise(rb_eNotImpError, "read_anything not implemented for type %d!", ttype);
|
507
563
|
}
|
@@ -657,4 +713,5 @@ void Init_struct() {
|
|
657
713
|
|
658
714
|
to_s_method_id = rb_intern("to_s");
|
659
715
|
name_to_id_method_id = rb_intern("name_to_id");
|
716
|
+
sorted_field_ids_method_id = rb_intern("sorted_field_ids");
|
660
717
|
}
|
data/ext/thrift_native.c
CHANGED
@@ -88,6 +88,7 @@ ID write_field_stop_method_id;
|
|
88
88
|
ID skip_method_id;
|
89
89
|
ID write_method_id;
|
90
90
|
ID read_all_method_id;
|
91
|
+
ID read_into_buffer_method_id;
|
91
92
|
ID native_qmark_method_id;
|
92
93
|
|
93
94
|
// constant ids
|
@@ -170,6 +171,7 @@ void Init_thrift_native() {
|
|
170
171
|
skip_method_id = rb_intern("skip");
|
171
172
|
write_method_id = rb_intern("write");
|
172
173
|
read_all_method_id = rb_intern("read_all");
|
174
|
+
read_into_buffer_method_id = rb_intern("read_into_buffer");
|
173
175
|
native_qmark_method_id = rb_intern("native?");
|
174
176
|
|
175
177
|
// constant ids
|
data/lib/thrift/exceptions.rb
CHANGED
@@ -29,6 +29,11 @@ module Thrift
|
|
29
29
|
super(trans)
|
30
30
|
@strict_read = strict_read
|
31
31
|
@strict_write = strict_write
|
32
|
+
|
33
|
+
# Pre-allocated read buffer for fixed-size read methods. Needs to be at least 8 bytes long for
|
34
|
+
# read_i64() and read_double().
|
35
|
+
@rbuf = "\0" * 8
|
36
|
+
@rbuf.force_encoding("BINARY") if @rbuf.respond_to?(:force_encoding)
|
32
37
|
end
|
33
38
|
|
34
39
|
def write_message_begin(name, type, seqid)
|
@@ -165,8 +170,7 @@ module Thrift
|
|
165
170
|
end
|
166
171
|
|
167
172
|
def read_byte
|
168
|
-
|
169
|
-
val = dat[0].ord
|
173
|
+
val = trans.read_byte
|
170
174
|
if (val > 0x7f)
|
171
175
|
val = 0 - ((val - 1) ^ 0xff)
|
172
176
|
end
|
@@ -174,8 +178,8 @@ module Thrift
|
|
174
178
|
end
|
175
179
|
|
176
180
|
def read_i16
|
177
|
-
|
178
|
-
val, =
|
181
|
+
trans.read_into_buffer(@rbuf, 2)
|
182
|
+
val, = @rbuf.unpack('n')
|
179
183
|
if (val > 0x7fff)
|
180
184
|
val = 0 - ((val - 1) ^ 0xffff)
|
181
185
|
end
|
@@ -183,8 +187,8 @@ module Thrift
|
|
183
187
|
end
|
184
188
|
|
185
189
|
def read_i32
|
186
|
-
|
187
|
-
val, =
|
190
|
+
trans.read_into_buffer(@rbuf, 4)
|
191
|
+
val, = @rbuf.unpack('N')
|
188
192
|
if (val > 0x7fffffff)
|
189
193
|
val = 0 - ((val - 1) ^ 0xffffffff)
|
190
194
|
end
|
@@ -192,8 +196,8 @@ module Thrift
|
|
192
196
|
end
|
193
197
|
|
194
198
|
def read_i64
|
195
|
-
|
196
|
-
hi, lo =
|
199
|
+
trans.read_into_buffer(@rbuf, 8)
|
200
|
+
hi, lo = @rbuf.unpack('N2')
|
197
201
|
if (hi > 0x7fffffff)
|
198
202
|
hi ^= 0xffffffff
|
199
203
|
lo ^= 0xffffffff
|
@@ -204,8 +208,8 @@ module Thrift
|
|
204
208
|
end
|
205
209
|
|
206
210
|
def read_double
|
207
|
-
|
208
|
-
val =
|
211
|
+
trans.read_into_buffer(@rbuf, 8)
|
212
|
+
val = @rbuf.unpack('G').first
|
209
213
|
val
|
210
214
|
end
|
211
215
|
|
@@ -98,6 +98,10 @@ module Thrift
|
|
98
98
|
|
99
99
|
@last_field = [0]
|
100
100
|
@boolean_value = nil
|
101
|
+
|
102
|
+
# Pre-allocated read buffer for read_double().
|
103
|
+
@rbuf = "\0" * 8
|
104
|
+
@rbuf.force_encoding("BINARY") if @rbuf.respond_to?(:force_encoding)
|
101
105
|
end
|
102
106
|
|
103
107
|
def write_message_begin(name, type, seqid)
|
@@ -302,8 +306,7 @@ module Thrift
|
|
302
306
|
end
|
303
307
|
|
304
308
|
def read_byte
|
305
|
-
|
306
|
-
val = dat[0]
|
309
|
+
val = trans.read_byte
|
307
310
|
if (val > 0x7f)
|
308
311
|
val = 0 - ((val - 1) ^ 0xff)
|
309
312
|
end
|
@@ -323,8 +326,8 @@ module Thrift
|
|
323
326
|
end
|
324
327
|
|
325
328
|
def read_double
|
326
|
-
|
327
|
-
val =
|
329
|
+
trans.read_into_buffer(@rbuf, 8)
|
330
|
+
val = @rbuf.reverse.unpack('G').first
|
328
331
|
val
|
329
332
|
end
|
330
333
|
|
@@ -44,7 +44,13 @@ module Thrift
|
|
44
44
|
begin
|
45
45
|
loop do
|
46
46
|
break if @server_transport.closed?
|
47
|
-
|
47
|
+
begin
|
48
|
+
rd, = select([@server_transport], nil, nil, 0.1)
|
49
|
+
rescue Errno::EBADF => e
|
50
|
+
# In Ruby 1.9, calling @server_transport.close in shutdown paths causes the select() to raise an
|
51
|
+
# Errno::EBADF. If this happens, ignore it and retry the loop.
|
52
|
+
break
|
53
|
+
end
|
48
54
|
next if rd.nil?
|
49
55
|
socket = @server_transport.accept
|
50
56
|
@logger.debug "Accepted socket: #{socket.inspect}"
|
@@ -146,10 +152,14 @@ module Thrift
|
|
146
152
|
break if read_signals == :shutdown
|
147
153
|
end
|
148
154
|
rd.each do |fd|
|
149
|
-
|
155
|
+
begin
|
156
|
+
if fd.handle.eof?
|
157
|
+
remove_connection fd
|
158
|
+
else
|
159
|
+
read_connection fd
|
160
|
+
end
|
161
|
+
rescue Errno::ECONNRESET
|
150
162
|
remove_connection fd
|
151
|
-
else
|
152
|
-
read_connection fd
|
153
163
|
end
|
154
164
|
end
|
155
165
|
end
|
@@ -292,4 +302,4 @@ module Thrift
|
|
292
302
|
end
|
293
303
|
end
|
294
304
|
end
|
295
|
-
end
|
305
|
+
end
|
data/lib/thrift/struct.rb
CHANGED
@@ -55,7 +55,7 @@ module Thrift
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def fields_with_default_values
|
58
|
-
fields_with_default_values = self.class.instance_variable_get(
|
58
|
+
fields_with_default_values = self.class.instance_variable_get(:@fields_with_default_values)
|
59
59
|
unless fields_with_default_values
|
60
60
|
fields_with_default_values = {}
|
61
61
|
struct_fields.each do |fid, field_def|
|
@@ -63,7 +63,7 @@ module Thrift
|
|
63
63
|
fields_with_default_values[field_def[:name]] = field_def[:default]
|
64
64
|
end
|
65
65
|
end
|
66
|
-
self.class.instance_variable_set(
|
66
|
+
self.class.instance_variable_set(:@fields_with_default_values, fields_with_default_values)
|
67
67
|
end
|
68
68
|
fields_with_default_values
|
69
69
|
end
|
@@ -114,9 +114,10 @@ module Thrift
|
|
114
114
|
end
|
115
115
|
|
116
116
|
def ==(other)
|
117
|
+
return false if other.nil?
|
117
118
|
each_field do |fid, field_info|
|
118
119
|
name = field_info[:name]
|
119
|
-
return false unless self.
|
120
|
+
return false unless other.respond_to?(name) && self.send(name) == other.send(name)
|
120
121
|
end
|
121
122
|
true
|
122
123
|
end
|
@@ -125,13 +126,15 @@ module Thrift
|
|
125
126
|
self.class == other.class && self == other
|
126
127
|
end
|
127
128
|
|
129
|
+
# This implementation of hash() is inspired by Apache's Java HashCodeBuilder class.
|
128
130
|
def hash
|
129
|
-
|
131
|
+
total = 17
|
130
132
|
each_field do |fid, field_info|
|
131
133
|
name = field_info[:name]
|
132
|
-
|
134
|
+
value = self.send(name)
|
135
|
+
total = (total * 37 + value.hash) & 0xffffffff
|
133
136
|
end
|
134
|
-
|
137
|
+
total
|
135
138
|
end
|
136
139
|
|
137
140
|
def differences(other)
|
data/lib/thrift/struct_union.rb
CHANGED
@@ -21,19 +21,28 @@ require 'set'
|
|
21
21
|
module Thrift
|
22
22
|
module Struct_Union
|
23
23
|
def name_to_id(name)
|
24
|
-
names_to_ids = self.class.instance_variable_get(
|
24
|
+
names_to_ids = self.class.instance_variable_get(:@names_to_ids)
|
25
25
|
unless names_to_ids
|
26
26
|
names_to_ids = {}
|
27
27
|
struct_fields.each do |fid, field_def|
|
28
28
|
names_to_ids[field_def[:name]] = fid
|
29
29
|
end
|
30
|
-
self.class.instance_variable_set(
|
30
|
+
self.class.instance_variable_set(:@names_to_ids, names_to_ids)
|
31
31
|
end
|
32
32
|
names_to_ids[name]
|
33
33
|
end
|
34
34
|
|
35
|
+
def sorted_field_ids
|
36
|
+
sorted_field_ids = self.class.instance_variable_get(:@sorted_field_ids)
|
37
|
+
unless sorted_field_ids
|
38
|
+
sorted_field_ids = struct_fields.keys.sort
|
39
|
+
self.class.instance_variable_set(:@sorted_field_ids, sorted_field_ids)
|
40
|
+
end
|
41
|
+
sorted_field_ids
|
42
|
+
end
|
43
|
+
|
35
44
|
def each_field
|
36
|
-
|
45
|
+
sorted_field_ids.each do |fid|
|
37
46
|
data = struct_fields[fid]
|
38
47
|
yield fid, data
|
39
48
|
end
|
@@ -46,25 +55,49 @@ module Thrift
|
|
46
55
|
value.read(iprot)
|
47
56
|
when Types::MAP
|
48
57
|
key_type, val_type, size = iprot.read_map_begin
|
49
|
-
value
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
58
|
+
# Skip the map contents if the declared key or value types don't match the expected ones.
|
59
|
+
if (key_type != field[:key][:type] || val_type != field[:value][:type])
|
60
|
+
size.times do
|
61
|
+
iprot.skip(key_type)
|
62
|
+
iprot.skip(val_type)
|
63
|
+
end
|
64
|
+
value = nil
|
65
|
+
else
|
66
|
+
value = {}
|
67
|
+
size.times do
|
68
|
+
k = read_field(iprot, field_info(field[:key]))
|
69
|
+
v = read_field(iprot, field_info(field[:value]))
|
70
|
+
value[k] = v
|
71
|
+
end
|
54
72
|
end
|
55
73
|
iprot.read_map_end
|
56
74
|
when Types::LIST
|
57
75
|
e_type, size = iprot.read_list_begin
|
58
|
-
|
59
|
-
|
76
|
+
# Skip the list contents if the declared element type doesn't match the expected one.
|
77
|
+
if (e_type != field[:element][:type])
|
78
|
+
size.times do
|
79
|
+
iprot.skip(e_type)
|
80
|
+
end
|
81
|
+
value = nil
|
82
|
+
else
|
83
|
+
value = Array.new(size) do |n|
|
84
|
+
read_field(iprot, field_info(field[:element]))
|
85
|
+
end
|
60
86
|
end
|
61
87
|
iprot.read_list_end
|
62
88
|
when Types::SET
|
63
89
|
e_type, size = iprot.read_set_begin
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
90
|
+
# Skip the set contents if the declared element type doesn't match the expected one.
|
91
|
+
if (e_type != field[:element][:type])
|
92
|
+
size.times do
|
93
|
+
iprot.skip(e_type)
|
94
|
+
end
|
95
|
+
else
|
96
|
+
value = Set.new
|
97
|
+
size.times do
|
98
|
+
element = read_field(iprot, field_info(field[:element]))
|
99
|
+
value << element
|
100
|
+
end
|
68
101
|
end
|
69
102
|
iprot.read_set_end
|
70
103
|
else
|
@@ -34,6 +34,26 @@ module Thrift
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
+
module TransportUtils
|
38
|
+
if RUBY_VERSION >= '1.9'
|
39
|
+
def self.get_string_byte(string, index)
|
40
|
+
string.getbyte(index)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.set_string_byte(string, index, byte)
|
44
|
+
string.setbyte(index, byte)
|
45
|
+
end
|
46
|
+
else
|
47
|
+
def self.get_string_byte(string, index)
|
48
|
+
string[index]
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.set_string_byte(string, index, byte)
|
52
|
+
string[index] = byte
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
37
57
|
class BaseTransport
|
38
58
|
def open?; end
|
39
59
|
|
@@ -45,9 +65,26 @@ module Thrift
|
|
45
65
|
raise NotImplementedError
|
46
66
|
end
|
47
67
|
|
68
|
+
# Returns an unsigned byte as a Fixnum in the range (0..255).
|
69
|
+
def read_byte
|
70
|
+
buf = read_all(1)
|
71
|
+
return ::Thrift::TransportUtils.get_string_byte(buf, 0)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Reads size bytes and copies them into buffer[0..size].
|
75
|
+
def read_into_buffer(buffer, size)
|
76
|
+
tmp = read_all(size)
|
77
|
+
i = 0
|
78
|
+
tmp.each_byte do |byte|
|
79
|
+
::Thrift::TransportUtils.set_string_byte(buffer, i, byte)
|
80
|
+
i += 1
|
81
|
+
end
|
82
|
+
i
|
83
|
+
end
|
84
|
+
|
48
85
|
def read_all(size)
|
49
|
-
|
50
|
-
|
86
|
+
return '' if size <= 0
|
87
|
+
buf = read(size)
|
51
88
|
while (buf.length < size)
|
52
89
|
chunk = read(size - buf.length)
|
53
90
|
buf << chunk
|
@@ -55,6 +55,37 @@ module Thrift
|
|
55
55
|
ret
|
56
56
|
end
|
57
57
|
|
58
|
+
def read_byte
|
59
|
+
# If the read buffer is exhausted, try to read up to DEFAULT_BUFFER more bytes into it.
|
60
|
+
if @index >= @rbuf.size
|
61
|
+
@rbuf = @transport.read(DEFAULT_BUFFER)
|
62
|
+
@index = 0
|
63
|
+
end
|
64
|
+
|
65
|
+
# The read buffer has some data now, read a single byte. Using get_string_byte() avoids
|
66
|
+
# allocating a temp string of size 1 unnecessarily.
|
67
|
+
@index += 1
|
68
|
+
return ::Thrift::TransportUtils.get_string_byte(@rbuf, @index - 1)
|
69
|
+
end
|
70
|
+
|
71
|
+
def read_into_buffer(buffer, size)
|
72
|
+
i = 0
|
73
|
+
while i < size
|
74
|
+
# If the read buffer is exhausted, try to read up to DEFAULT_BUFFER more bytes into it.
|
75
|
+
if @index >= @rbuf.size
|
76
|
+
@rbuf = @transport.read(DEFAULT_BUFFER)
|
77
|
+
@index = 0
|
78
|
+
end
|
79
|
+
|
80
|
+
# The read buffer has some data now, so copy bytes over to the output buffer.
|
81
|
+
byte = ::Thrift::TransportUtils.get_string_byte(@rbuf, @index)
|
82
|
+
::Thrift::TransportUtils.set_string_byte(buffer, i, byte)
|
83
|
+
@index += 1
|
84
|
+
i += 1
|
85
|
+
end
|
86
|
+
i
|
87
|
+
end
|
88
|
+
|
58
89
|
def write(buf)
|
59
90
|
@wbuf << buf
|
60
91
|
end
|