thrift 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|