thrift 0.22.0 → 0.24.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.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +235 -17
  3. data/benchmark/benchmark.rb +23 -8
  4. data/benchmark/client.rb +50 -6
  5. data/benchmark/server.rb +46 -7
  6. data/benchmark/thin_server.rb +2 -0
  7. data/ext/binary_protocol_accelerated.c +154 -42
  8. data/ext/bytes.c +14 -0
  9. data/ext/compact_protocol.c +138 -45
  10. data/ext/constants.h +12 -0
  11. data/ext/extconf.rb +17 -8
  12. data/ext/memory_buffer.c +44 -7
  13. data/ext/protocol.c +29 -0
  14. data/ext/protocol.h +35 -0
  15. data/ext/struct.c +48 -17
  16. data/ext/thrift_native.c +28 -3
  17. data/lib/thrift/bytes.rb +70 -100
  18. data/lib/thrift/client.rb +54 -13
  19. data/lib/thrift/exceptions.rb +6 -5
  20. data/lib/thrift/multiplexed_processor.rb +20 -10
  21. data/lib/thrift/processor.rb +7 -6
  22. data/lib/thrift/protocol/base_protocol.rb +52 -21
  23. data/lib/thrift/protocol/binary_protocol.rb +65 -20
  24. data/lib/thrift/protocol/binary_protocol_accelerated.rb +6 -5
  25. data/lib/thrift/protocol/compact_protocol.rb +76 -41
  26. data/lib/thrift/protocol/header_protocol.rb +321 -0
  27. data/lib/thrift/protocol/json_protocol.rb +44 -27
  28. data/lib/thrift/protocol/multiplexed_protocol.rb +6 -5
  29. data/lib/thrift/protocol/protocol_decorator.rb +13 -4
  30. data/lib/thrift/serializer/deserializer.rb +6 -5
  31. data/lib/thrift/serializer/serializer.rb +5 -5
  32. data/lib/thrift/server/base_server.rb +5 -4
  33. data/lib/thrift/server/mongrel_http_server.rb +7 -6
  34. data/lib/thrift/server/nonblocking_server.rb +35 -9
  35. data/lib/thrift/server/simple_server.rb +13 -5
  36. data/lib/thrift/server/thin_http_server.rb +4 -3
  37. data/lib/thrift/server/thread_pool_server.rb +7 -6
  38. data/lib/thrift/server/threaded_server.rb +13 -5
  39. data/lib/thrift/struct.rb +12 -11
  40. data/lib/thrift/struct_union.rb +14 -9
  41. data/lib/thrift/thrift_native.rb +3 -2
  42. data/lib/thrift/transport/base_server_transport.rb +8 -5
  43. data/lib/thrift/transport/base_transport.rb +18 -14
  44. data/lib/thrift/transport/buffered_transport.rb +7 -6
  45. data/lib/thrift/transport/framed_transport.rb +8 -7
  46. data/lib/thrift/transport/header_transport.rb +562 -0
  47. data/lib/thrift/transport/http_client_transport.rb +2 -1
  48. data/lib/thrift/transport/io_stream_transport.rb +4 -3
  49. data/lib/thrift/transport/memory_buffer_transport.rb +13 -6
  50. data/lib/thrift/transport/server_socket.rb +14 -8
  51. data/lib/thrift/transport/socket.rb +126 -60
  52. data/lib/thrift/transport/ssl_server_socket.rb +4 -3
  53. data/lib/thrift/transport/ssl_socket.rb +45 -13
  54. data/lib/thrift/transport/unix_server_socket.rb +9 -5
  55. data/lib/thrift/transport/unix_socket.rb +7 -6
  56. data/lib/thrift/types.rb +10 -6
  57. data/lib/thrift/union.rb +15 -8
  58. data/lib/thrift/uuid.rb +50 -0
  59. data/lib/thrift.rb +4 -1
  60. data/spec/ThriftSpec.thrift +21 -1
  61. data/spec/base_protocol_spec.rb +21 -2
  62. data/spec/base_transport_spec.rb +48 -8
  63. data/spec/binary_protocol_accelerated_spec.rb +1 -0
  64. data/spec/binary_protocol_spec.rb +1 -2
  65. data/spec/binary_protocol_spec_shared.rb +206 -155
  66. data/spec/bytes_spec.rb +71 -114
  67. data/spec/client_spec.rb +86 -19
  68. data/spec/compact_protocol_spec.rb +153 -16
  69. data/spec/constants_demo_spec.rb +102 -0
  70. data/spec/exception_spec.rb +1 -1
  71. data/spec/flat_spec.rb +1 -0
  72. data/spec/header_protocol_spec.rb +476 -0
  73. data/spec/header_transport_spec.rb +431 -0
  74. data/spec/http_client_spec.rb +5 -6
  75. data/spec/json_protocol_spec.rb +69 -47
  76. data/spec/multiplexed_processor_spec.rb +75 -0
  77. data/spec/namespaced_spec.rb +1 -1
  78. data/spec/nonblocking_server_spec.rb +174 -8
  79. data/spec/processor_spec.rb +1 -1
  80. data/spec/recursion_depth_spec.rb +223 -0
  81. data/spec/serializer_spec.rb +1 -1
  82. data/spec/server_socket_spec.rb +38 -1
  83. data/spec/server_spec.rb +60 -9
  84. data/spec/socket_spec.rb +119 -13
  85. data/spec/socket_spec_shared.rb +73 -9
  86. data/spec/spec_helper.rb +2 -1
  87. data/spec/ssl_server_socket_spec.rb +52 -1
  88. data/spec/ssl_socket_spec.rb +181 -11
  89. data/spec/struct_nested_containers_spec.rb +2 -2
  90. data/spec/struct_spec.rb +114 -9
  91. data/spec/support/header_protocol_helper.rb +55 -0
  92. data/spec/thin_http_server_spec.rb +4 -18
  93. data/spec/types_spec.rb +26 -26
  94. data/spec/union_spec.rb +70 -11
  95. data/spec/unix_socket_spec.rb +17 -2
  96. data/spec/uuid_validation_spec.rb +239 -0
  97. data/test/fuzz/Makefile +779 -0
  98. data/test/fuzz/Makefile.am +173 -0
  99. data/test/fuzz/Makefile.in +775 -0
  100. data/test/fuzz/README.md +149 -0
  101. data/test/fuzz/fuzz_common.rb +96 -0
  102. data/{lib/thrift/core_ext.rb → test/fuzz/fuzz_parse_binary_protocol.rb} +4 -4
  103. data/{lib/thrift/core_ext/fixnum.rb → test/fuzz/fuzz_parse_binary_protocol_accelerated.rb} +7 -13
  104. data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +23 -0
  105. data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +23 -0
  106. data/test/fuzz/fuzz_parse_compact_protocol.rb +23 -0
  107. data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +23 -0
  108. data/test/fuzz/fuzz_parse_json_protocol.rb +23 -0
  109. data/test/fuzz/fuzz_parse_json_protocol_harness.rb +23 -0
  110. data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +23 -0
  111. data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +23 -0
  112. data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +23 -0
  113. data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +23 -0
  114. data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +23 -0
  115. data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +23 -0
  116. data/test/fuzz/fuzz_roundtrip_json_protocol.rb +23 -0
  117. data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +23 -0
  118. data/test/fuzz/fuzz_tracer.rb +29 -0
  119. metadata +105 -70
@@ -20,30 +20,77 @@
20
20
  #include <ruby.h>
21
21
  #include <stdbool.h>
22
22
  #include <stdint.h>
23
+ #include <string.h>
23
24
  #include <constants.h>
24
25
  #include <struct.h>
25
26
  #include <macros.h>
26
27
  #include <bytes.h>
28
+ #include <protocol.h>
27
29
 
28
30
  VALUE rb_thrift_binary_proto_native_qmark(VALUE self) {
29
31
  return Qtrue;
30
32
  }
31
33
 
32
-
33
-
34
34
  static int VERSION_1;
35
35
  static int VERSION_MASK;
36
36
  static int TYPE_MASK;
37
- static int BAD_VERSION;
38
37
  static ID rbuf_ivar_id;
39
38
 
39
+ static int64_t checked_integer_value(VALUE value) {
40
+ if (!RB_INTEGER_TYPE_P(value)) {
41
+ rb_raise(rb_eTypeError, "integer argument expected");
42
+ }
43
+
44
+ return NUM2LL(value);
45
+ }
46
+
47
+ static int64_t checked_integer_range(VALUE value, int64_t min, int64_t max) {
48
+ int64_t integer = checked_integer_value(value);
49
+
50
+ if (integer < min || integer > max) {
51
+ rb_raise(rb_eRangeError, "integer out of bounds");
52
+ }
53
+
54
+ return integer;
55
+ }
56
+
57
+ static int8_t checked_byte_value(VALUE value) {
58
+ return (int8_t)checked_integer_range(value, INT8_MIN, INT8_MAX);
59
+ }
60
+
61
+ static int16_t checked_i16_value(VALUE value) {
62
+ return (int16_t)checked_integer_range(value, INT16_MIN, INT16_MAX);
63
+ }
64
+
65
+ static int32_t checked_i32_value(VALUE value) {
66
+ return (int32_t)checked_integer_range(value, INT32_MIN, INT32_MAX);
67
+ }
68
+
69
+ static int32_t checked_size_value(VALUE value) {
70
+ return (int32_t)checked_integer_range(value, 0, INT32_MAX);
71
+ }
72
+
73
+ static int64_t checked_i64_value(VALUE value) {
74
+ return checked_integer_range(value, INT64_MIN, INT64_MAX);
75
+ }
76
+
77
+ static int32_t checked_string_length(VALUE str) {
78
+ long length = RSTRING_LEN(str);
79
+
80
+ if (length > INT32_MAX) {
81
+ rb_raise(rb_eRangeError, "string too long");
82
+ }
83
+
84
+ return (int32_t)length;
85
+ }
86
+
40
87
  static void write_byte_direct(VALUE trans, int8_t b) {
41
88
  WRITE(trans, (char*)&b, 1);
42
89
  }
43
90
 
44
91
  static void write_i16_direct(VALUE trans, int16_t value) {
45
92
  char data[2];
46
-
93
+
47
94
  data[1] = value;
48
95
  data[0] = (value >> 8);
49
96
 
@@ -82,7 +129,7 @@ static void write_string_direct(VALUE trans, VALUE str) {
82
129
  rb_raise(rb_eStandardError, "Value should be a string");
83
130
  }
84
131
  str = convert_to_utf8_byte_buffer(str);
85
- write_i32_direct(trans, (int32_t)RSTRING_LEN(str));
132
+ write_i32_direct(trans, checked_string_length(str));
86
133
  rb_funcall(trans, write_method_id, 1, str);
87
134
  }
88
135
 
@@ -123,23 +170,24 @@ VALUE rb_thrift_binary_proto_write_message_begin(VALUE self, VALUE name, VALUE t
123
170
  VALUE strict_write = GET_STRICT_WRITE(self);
124
171
 
125
172
  if (strict_write == Qtrue) {
126
- write_i32_direct(trans, VERSION_1 | FIX2INT(type));
173
+ int8_t message_type = checked_byte_value(type);
174
+ write_i32_direct(trans, VERSION_1 | message_type);
127
175
  write_string_direct(trans, name);
128
- write_i32_direct(trans, FIX2INT(seqid));
176
+ write_i32_direct(trans, checked_i32_value(seqid));
129
177
  } else {
130
178
  write_string_direct(trans, name);
131
- write_byte_direct(trans, FIX2INT(type));
132
- write_i32_direct(trans, FIX2INT(seqid));
179
+ write_byte_direct(trans, checked_byte_value(type));
180
+ write_i32_direct(trans, checked_i32_value(seqid));
133
181
  }
134
-
182
+
135
183
  return Qnil;
136
184
  }
137
185
 
138
186
  VALUE rb_thrift_binary_proto_write_field_begin(VALUE self, VALUE name, VALUE type, VALUE id) {
139
187
  VALUE trans = GET_TRANSPORT(self);
140
- write_byte_direct(trans, FIX2INT(type));
141
- write_i16_direct(trans, FIX2INT(id));
142
-
188
+ write_byte_direct(trans, checked_byte_value(type));
189
+ write_i16_direct(trans, checked_i16_value(id));
190
+
143
191
  return Qnil;
144
192
  }
145
193
 
@@ -150,18 +198,18 @@ VALUE rb_thrift_binary_proto_write_field_stop(VALUE self) {
150
198
 
151
199
  VALUE rb_thrift_binary_proto_write_map_begin(VALUE self, VALUE ktype, VALUE vtype, VALUE size) {
152
200
  VALUE trans = GET_TRANSPORT(self);
153
- write_byte_direct(trans, FIX2INT(ktype));
154
- write_byte_direct(trans, FIX2INT(vtype));
155
- write_i32_direct(trans, FIX2INT(size));
156
-
201
+ write_byte_direct(trans, checked_byte_value(ktype));
202
+ write_byte_direct(trans, checked_byte_value(vtype));
203
+ write_i32_direct(trans, checked_size_value(size));
204
+
157
205
  return Qnil;
158
206
  }
159
207
 
160
208
  VALUE rb_thrift_binary_proto_write_list_begin(VALUE self, VALUE etype, VALUE size) {
161
209
  VALUE trans = GET_TRANSPORT(self);
162
- write_byte_direct(trans, FIX2INT(etype));
163
- write_i32_direct(trans, FIX2INT(size));
164
-
210
+ write_byte_direct(trans, checked_byte_value(etype));
211
+ write_i32_direct(trans, checked_size_value(size));
212
+
165
213
  return Qnil;
166
214
  }
167
215
 
@@ -177,25 +225,25 @@ VALUE rb_thrift_binary_proto_write_bool(VALUE self, VALUE b) {
177
225
 
178
226
  VALUE rb_thrift_binary_proto_write_byte(VALUE self, VALUE byte) {
179
227
  CHECK_NIL(byte);
180
- write_byte_direct(GET_TRANSPORT(self), NUM2INT(byte));
228
+ write_byte_direct(GET_TRANSPORT(self), checked_byte_value(byte));
181
229
  return Qnil;
182
230
  }
183
231
 
184
232
  VALUE rb_thrift_binary_proto_write_i16(VALUE self, VALUE i16) {
185
233
  CHECK_NIL(i16);
186
- write_i16_direct(GET_TRANSPORT(self), FIX2INT(i16));
234
+ write_i16_direct(GET_TRANSPORT(self), checked_i16_value(i16));
187
235
  return Qnil;
188
236
  }
189
237
 
190
238
  VALUE rb_thrift_binary_proto_write_i32(VALUE self, VALUE i32) {
191
239
  CHECK_NIL(i32);
192
- write_i32_direct(GET_TRANSPORT(self), NUM2INT(i32));
240
+ write_i32_direct(GET_TRANSPORT(self), checked_i32_value(i32));
193
241
  return Qnil;
194
242
  }
195
243
 
196
244
  VALUE rb_thrift_binary_proto_write_i64(VALUE self, VALUE i64) {
197
245
  CHECK_NIL(i64);
198
- write_i64_direct(GET_TRANSPORT(self), NUM2LL(i64));
246
+ write_i64_direct(GET_TRANSPORT(self), checked_i64_value(i64));
199
247
  return Qnil;
200
248
  }
201
249
 
@@ -223,11 +271,51 @@ VALUE rb_thrift_binary_proto_write_binary(VALUE self, VALUE buf) {
223
271
  CHECK_NIL(buf);
224
272
  VALUE trans = GET_TRANSPORT(self);
225
273
  buf = force_binary_encoding(buf);
226
- write_i32_direct(trans, (int32_t)RSTRING_LEN(buf));
274
+ write_i32_direct(trans, checked_string_length(buf));
227
275
  rb_funcall(trans, write_method_id, 1, buf);
228
276
  return Qnil;
229
277
  }
230
278
 
279
+ VALUE rb_thrift_binary_proto_write_uuid(VALUE self, VALUE uuid) {
280
+ if (NIL_P(uuid) || TYPE(uuid) != T_STRING) {
281
+ rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("UUID must be a string")));
282
+ }
283
+
284
+ VALUE trans = GET_TRANSPORT(self);
285
+ char bytes[16];
286
+ const char* str = RSTRING_PTR(uuid);
287
+ long len = RSTRING_LEN(uuid);
288
+
289
+ // Parse UUID string (format: "550e8400-e29b-41d4-a716-446655440000")
290
+ // Expected length: 36 characters (32 hex + 4 hyphens)
291
+ if (len != 36 || str[8] != '-' || str[13] != '-' || str[18] != '-' || str[23] != '-') {
292
+ rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("Invalid UUID format")));
293
+ }
294
+
295
+ // Parse hex string to bytes using direct conversion, skipping hyphens
296
+ int byte_idx = 0;
297
+ for (int i = 0; i < len && byte_idx < 16; i++) {
298
+ if (str[i] == '-') continue;
299
+ if (i + 1 >= len || str[i + 1] == '-') break;
300
+
301
+ // Convert two hex characters to one byte
302
+ int high = hex_char_to_int(str[i]);
303
+ int low = hex_char_to_int(str[i + 1]);
304
+
305
+ if (high < 0 || low < 0) break;
306
+
307
+ bytes[byte_idx++] = (unsigned char)((high << 4) | low);
308
+ i++; // skip next char since we processed two
309
+ }
310
+
311
+ if (byte_idx != 16) {
312
+ rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("Invalid UUID format")));
313
+ }
314
+
315
+ WRITE(trans, bytes, 16);
316
+ return Qnil;
317
+ }
318
+
231
319
  //---------------------------------------
232
320
  // interface reading methods
233
321
  //---------------------------------------
@@ -272,13 +360,6 @@ static int64_t read_i64_direct(VALUE self) {
272
360
  return (hi << 32) | lo;
273
361
  }
274
362
 
275
- static VALUE get_protocol_exception(VALUE code, VALUE message) {
276
- VALUE args[2];
277
- args[0] = code;
278
- args[1] = message;
279
- return rb_class_new_instance(2, (VALUE*)&args, protocol_exception_class);
280
- }
281
-
282
363
  VALUE rb_thrift_binary_proto_read_message_end(VALUE self) {
283
364
  return Qnil;
284
365
  }
@@ -311,25 +392,25 @@ VALUE rb_thrift_binary_proto_read_message_begin(VALUE self) {
311
392
  VALUE strict_read = GET_STRICT_READ(self);
312
393
  VALUE name, seqid;
313
394
  int type;
314
-
395
+
315
396
  int version = read_i32_direct(self);
316
-
397
+
317
398
  if (version < 0) {
318
399
  if ((version & VERSION_MASK) != VERSION_1) {
319
- rb_exc_raise(get_protocol_exception(INT2FIX(BAD_VERSION), rb_str_new2("Missing version identifier")));
400
+ rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_BAD_VERSION), rb_str_new2("Missing version identifier")));
320
401
  }
321
402
  type = version & TYPE_MASK;
322
403
  name = rb_thrift_binary_proto_read_string(self);
323
404
  seqid = rb_thrift_binary_proto_read_i32(self);
324
405
  } else {
325
406
  if (strict_read == Qtrue) {
326
- rb_exc_raise(get_protocol_exception(INT2FIX(BAD_VERSION), rb_str_new2("No version identifier, old protocol client?")));
407
+ rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_BAD_VERSION), rb_str_new2("No version identifier, old protocol client?")));
327
408
  }
328
409
  name = READ(self, version);
329
410
  type = read_byte_direct(self);
330
411
  seqid = rb_thrift_binary_proto_read_i32(self);
331
412
  }
332
-
413
+
333
414
  return rb_ary_new3(3, name, INT2FIX(type), seqid);
334
415
  }
335
416
 
@@ -343,17 +424,24 @@ VALUE rb_thrift_binary_proto_read_field_begin(VALUE self) {
343
424
  }
344
425
  }
345
426
 
427
+ #define CHECK_NEGATIVE_SIZE(size) \
428
+ if (RB_UNLIKELY((size) < 0)) { \
429
+ rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_NEGATIVE_SIZE), rb_str_new2("Negative size"))); \
430
+ }
431
+
346
432
  VALUE rb_thrift_binary_proto_read_map_begin(VALUE self) {
347
433
  VALUE ktype = rb_thrift_binary_proto_read_byte(self);
348
434
  VALUE vtype = rb_thrift_binary_proto_read_byte(self);
349
- VALUE size = rb_thrift_binary_proto_read_i32(self);
350
- return rb_ary_new3(3, ktype, vtype, size);
435
+ int size = read_i32_direct(self);
436
+ CHECK_NEGATIVE_SIZE(size);
437
+ return rb_ary_new3(3, ktype, vtype, INT2NUM(size));
351
438
  }
352
439
 
353
440
  VALUE rb_thrift_binary_proto_read_list_begin(VALUE self) {
354
441
  VALUE etype = rb_thrift_binary_proto_read_byte(self);
355
- VALUE size = rb_thrift_binary_proto_read_i32(self);
356
- return rb_ary_new3(2, etype, size);
442
+ int size = read_i32_direct(self);
443
+ CHECK_NEGATIVE_SIZE(size);
444
+ return rb_ary_new3(2, etype, INT2NUM(size));
357
445
  }
358
446
 
359
447
  VALUE rb_thrift_binary_proto_read_set_begin(VALUE self) {
@@ -397,10 +485,32 @@ VALUE rb_thrift_binary_proto_read_string(VALUE self) {
397
485
 
398
486
  VALUE rb_thrift_binary_proto_read_binary(VALUE self) {
399
487
  int size = read_i32_direct(self);
488
+ CHECK_NEGATIVE_SIZE(size);
400
489
  return READ(self, size);
401
490
  }
402
491
 
403
- void Init_binary_protocol_accelerated() {
492
+ VALUE rb_thrift_binary_proto_read_uuid(VALUE self) {
493
+ VALUE data = READ(self, 16);
494
+ const unsigned char* bytes = (const unsigned char*)RSTRING_PTR(data);
495
+
496
+ // Format as UUID string: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
497
+ char uuid_str[37];
498
+ char* p = uuid_str;
499
+
500
+ for (int i = 0; i < 16; i++) {
501
+ *p++ = int_to_hex_char((bytes[i] >> 4) & 0x0F);
502
+ *p++ = int_to_hex_char(bytes[i] & 0x0F);
503
+ if (i == 3 || i == 5 || i == 7 || i == 9) {
504
+ *p++ = '-';
505
+ }
506
+ }
507
+
508
+ *p = '\0';
509
+
510
+ return rb_str_new(uuid_str, 36);
511
+ }
512
+
513
+ void Init_binary_protocol_accelerated(void) {
404
514
  VALUE thrift_binary_protocol_class = rb_const_get(thrift_module, rb_intern("BinaryProtocol"));
405
515
 
406
516
  VERSION_1 = (int)rb_num2ll(rb_const_get(thrift_binary_protocol_class, rb_intern("VERSION_1")));
@@ -425,6 +535,7 @@ void Init_binary_protocol_accelerated() {
425
535
  rb_define_method(bpa_class, "write_double", rb_thrift_binary_proto_write_double, 1);
426
536
  rb_define_method(bpa_class, "write_string", rb_thrift_binary_proto_write_string, 1);
427
537
  rb_define_method(bpa_class, "write_binary", rb_thrift_binary_proto_write_binary, 1);
538
+ rb_define_method(bpa_class, "write_uuid", rb_thrift_binary_proto_write_uuid, 1);
428
539
  // unused methods
429
540
  rb_define_method(bpa_class, "write_message_end", rb_thrift_binary_proto_write_message_end, 0);
430
541
  rb_define_method(bpa_class, "write_struct_begin", rb_thrift_binary_proto_write_struct_begin, 1);
@@ -447,6 +558,7 @@ void Init_binary_protocol_accelerated() {
447
558
  rb_define_method(bpa_class, "read_double", rb_thrift_binary_proto_read_double, 0);
448
559
  rb_define_method(bpa_class, "read_string", rb_thrift_binary_proto_read_string, 0);
449
560
  rb_define_method(bpa_class, "read_binary", rb_thrift_binary_proto_read_binary, 0);
561
+ rb_define_method(bpa_class, "read_uuid", rb_thrift_binary_proto_read_uuid, 0);
450
562
  // unused methods
451
563
  rb_define_method(bpa_class, "read_message_end", rb_thrift_binary_proto_read_message_end, 0);
452
564
  rb_define_method(bpa_class, "read_struct_begin", rb_thrift_binary_proto_read_struct_begin, 0);
data/ext/bytes.c CHANGED
@@ -24,6 +24,20 @@
24
24
  #include <constants.h>
25
25
 
26
26
  VALUE force_binary_encoding(VALUE buffer) {
27
+ if (RB_TYPE_P(buffer, T_STRING)) {
28
+ if (rb_enc_get_index(buffer) == rb_ascii8bit_encindex()) {
29
+ return buffer;
30
+ }
31
+
32
+ if (RB_OBJ_FROZEN(buffer)) {
33
+ buffer = rb_obj_dup(buffer);
34
+ }
35
+
36
+ rb_enc_associate_index(buffer, rb_ascii8bit_encindex());
37
+
38
+ return buffer;
39
+ }
40
+
27
41
  return rb_funcall(thrift_bytes_module, force_binary_encoding_id, 1, buffer);
28
42
  }
29
43