thrift 0.22.0 → 0.23.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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +175 -17
  3. data/benchmark/benchmark.rb +22 -8
  4. data/benchmark/client.rb +49 -6
  5. data/benchmark/server.rb +45 -7
  6. data/benchmark/thin_server.rb +1 -0
  7. data/ext/binary_protocol_accelerated.c +76 -19
  8. data/ext/compact_protocol.c +80 -15
  9. data/ext/constants.h +12 -0
  10. data/ext/extconf.rb +10 -9
  11. data/ext/memory_buffer.c +7 -7
  12. data/ext/protocol.c +29 -0
  13. data/ext/protocol.h +35 -0
  14. data/ext/struct.c +36 -5
  15. data/ext/thrift_native.c +27 -3
  16. data/lib/thrift/bytes.rb +68 -101
  17. data/lib/thrift/client.rb +61 -9
  18. data/lib/thrift/exceptions.rb +5 -5
  19. data/lib/thrift/multiplexed_processor.rb +6 -6
  20. data/lib/thrift/processor.rb +6 -6
  21. data/lib/thrift/protocol/base_protocol.rb +37 -15
  22. data/lib/thrift/protocol/binary_protocol.rb +25 -9
  23. data/lib/thrift/protocol/binary_protocol_accelerated.rb +5 -5
  24. data/lib/thrift/protocol/compact_protocol.rb +61 -37
  25. data/lib/thrift/protocol/header_protocol.rb +320 -0
  26. data/lib/thrift/protocol/json_protocol.rb +26 -16
  27. data/lib/thrift/protocol/multiplexed_protocol.rb +5 -5
  28. data/lib/thrift/protocol/protocol_decorator.rb +12 -4
  29. data/lib/thrift/serializer/deserializer.rb +5 -5
  30. data/lib/thrift/serializer/serializer.rb +4 -5
  31. data/lib/thrift/server/base_server.rb +4 -4
  32. data/lib/thrift/server/mongrel_http_server.rb +6 -6
  33. data/lib/thrift/server/nonblocking_server.rb +8 -8
  34. data/lib/thrift/server/simple_server.rb +4 -4
  35. data/lib/thrift/server/thin_http_server.rb +3 -3
  36. data/lib/thrift/server/thread_pool_server.rb +6 -6
  37. data/lib/thrift/server/threaded_server.rb +4 -4
  38. data/lib/thrift/struct.rb +11 -11
  39. data/lib/thrift/struct_union.rb +19 -9
  40. data/lib/thrift/thrift_native.rb +1 -1
  41. data/lib/thrift/transport/base_server_transport.rb +5 -5
  42. data/lib/thrift/transport/base_transport.rb +12 -12
  43. data/lib/thrift/transport/buffered_transport.rb +6 -6
  44. data/lib/thrift/transport/framed_transport.rb +7 -7
  45. data/lib/thrift/transport/header_transport.rb +516 -0
  46. data/lib/thrift/transport/http_client_transport.rb +1 -1
  47. data/lib/thrift/transport/io_stream_transport.rb +3 -3
  48. data/lib/thrift/transport/memory_buffer_transport.rb +6 -6
  49. data/lib/thrift/transport/server_socket.rb +8 -5
  50. data/lib/thrift/transport/socket.rb +58 -31
  51. data/lib/thrift/transport/ssl_server_socket.rb +1 -1
  52. data/lib/thrift/transport/ssl_socket.rb +2 -2
  53. data/lib/thrift/transport/unix_server_socket.rb +4 -4
  54. data/lib/thrift/transport/unix_socket.rb +6 -6
  55. data/lib/thrift/types.rb +9 -6
  56. data/lib/thrift/union.rb +14 -8
  57. data/lib/thrift/uuid.rb +49 -0
  58. data/lib/thrift.rb +3 -1
  59. data/spec/ThriftSpec.thrift +5 -1
  60. data/spec/base_protocol_spec.rb +1 -2
  61. data/spec/base_transport_spec.rb +6 -7
  62. data/spec/binary_protocol_spec.rb +0 -2
  63. data/spec/binary_protocol_spec_shared.rb +129 -142
  64. data/spec/bytes_spec.rb +57 -118
  65. data/spec/client_spec.rb +85 -19
  66. data/spec/compact_protocol_spec.rb +54 -16
  67. data/spec/constants_demo_spec.rb +101 -0
  68. data/spec/exception_spec.rb +0 -1
  69. data/spec/header_protocol_spec.rb +475 -0
  70. data/spec/header_transport_spec.rb +386 -0
  71. data/spec/http_client_spec.rb +4 -6
  72. data/spec/json_protocol_spec.rb +47 -47
  73. data/spec/namespaced_spec.rb +0 -1
  74. data/spec/nonblocking_server_spec.rb +102 -4
  75. data/spec/processor_spec.rb +0 -1
  76. data/spec/serializer_spec.rb +0 -1
  77. data/spec/server_socket_spec.rb +1 -1
  78. data/spec/server_spec.rb +8 -9
  79. data/spec/socket_spec.rb +0 -1
  80. data/spec/socket_spec_shared.rb +72 -9
  81. data/spec/spec_helper.rb +1 -1
  82. data/spec/ssl_server_socket_spec.rb +12 -1
  83. data/spec/ssl_socket_spec.rb +10 -1
  84. data/spec/struct_nested_containers_spec.rb +1 -2
  85. data/spec/struct_spec.rb +113 -9
  86. data/spec/support/header_protocol_helper.rb +54 -0
  87. data/spec/thin_http_server_spec.rb +3 -18
  88. data/spec/types_spec.rb +25 -26
  89. data/spec/union_spec.rb +69 -11
  90. data/spec/unix_socket_spec.rb +1 -2
  91. data/spec/uuid_validation_spec.rb +238 -0
  92. data/test/fuzz/Makefile.am +173 -0
  93. data/test/fuzz/README.md +149 -0
  94. data/test/fuzz/fuzz_common.rb +95 -0
  95. data/{lib/thrift/core_ext.rb → test/fuzz/fuzz_parse_binary_protocol.rb} +3 -4
  96. data/{lib/thrift/core_ext/fixnum.rb → test/fuzz/fuzz_parse_binary_protocol_accelerated.rb} +6 -13
  97. data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +22 -0
  98. data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +22 -0
  99. data/test/fuzz/fuzz_parse_compact_protocol.rb +22 -0
  100. data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +22 -0
  101. data/test/fuzz/fuzz_parse_json_protocol.rb +22 -0
  102. data/test/fuzz/fuzz_parse_json_protocol_harness.rb +22 -0
  103. data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +22 -0
  104. data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +22 -0
  105. data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +22 -0
  106. data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +22 -0
  107. data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +22 -0
  108. data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +22 -0
  109. data/test/fuzz/fuzz_roundtrip_json_protocol.rb +22 -0
  110. data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +22 -0
  111. data/test/fuzz/fuzz_tracer.rb +28 -0
  112. metadata +106 -37
@@ -20,10 +20,12 @@
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;
@@ -34,7 +36,6 @@ VALUE rb_thrift_binary_proto_native_qmark(VALUE self) {
34
36
  static int VERSION_1;
35
37
  static int VERSION_MASK;
36
38
  static int TYPE_MASK;
37
- static int BAD_VERSION;
38
39
  static ID rbuf_ivar_id;
39
40
 
40
41
  static void write_byte_direct(VALUE trans, int8_t b) {
@@ -43,7 +44,7 @@ static void write_byte_direct(VALUE trans, int8_t b) {
43
44
 
44
45
  static void write_i16_direct(VALUE trans, int16_t value) {
45
46
  char data[2];
46
-
47
+
47
48
  data[1] = value;
48
49
  data[0] = (value >> 8);
49
50
 
@@ -131,7 +132,7 @@ VALUE rb_thrift_binary_proto_write_message_begin(VALUE self, VALUE name, VALUE t
131
132
  write_byte_direct(trans, FIX2INT(type));
132
133
  write_i32_direct(trans, FIX2INT(seqid));
133
134
  }
134
-
135
+
135
136
  return Qnil;
136
137
  }
137
138
 
@@ -139,7 +140,7 @@ VALUE rb_thrift_binary_proto_write_field_begin(VALUE self, VALUE name, VALUE typ
139
140
  VALUE trans = GET_TRANSPORT(self);
140
141
  write_byte_direct(trans, FIX2INT(type));
141
142
  write_i16_direct(trans, FIX2INT(id));
142
-
143
+
143
144
  return Qnil;
144
145
  }
145
146
 
@@ -153,7 +154,7 @@ VALUE rb_thrift_binary_proto_write_map_begin(VALUE self, VALUE ktype, VALUE vtyp
153
154
  write_byte_direct(trans, FIX2INT(ktype));
154
155
  write_byte_direct(trans, FIX2INT(vtype));
155
156
  write_i32_direct(trans, FIX2INT(size));
156
-
157
+
157
158
  return Qnil;
158
159
  }
159
160
 
@@ -161,7 +162,7 @@ VALUE rb_thrift_binary_proto_write_list_begin(VALUE self, VALUE etype, VALUE siz
161
162
  VALUE trans = GET_TRANSPORT(self);
162
163
  write_byte_direct(trans, FIX2INT(etype));
163
164
  write_i32_direct(trans, FIX2INT(size));
164
-
165
+
165
166
  return Qnil;
166
167
  }
167
168
 
@@ -228,6 +229,46 @@ VALUE rb_thrift_binary_proto_write_binary(VALUE self, VALUE buf) {
228
229
  return Qnil;
229
230
  }
230
231
 
232
+ VALUE rb_thrift_binary_proto_write_uuid(VALUE self, VALUE uuid) {
233
+ if (NIL_P(uuid) || TYPE(uuid) != T_STRING) {
234
+ rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("UUID must be a string")));
235
+ }
236
+
237
+ VALUE trans = GET_TRANSPORT(self);
238
+ char bytes[16];
239
+ const char* str = RSTRING_PTR(uuid);
240
+ long len = RSTRING_LEN(uuid);
241
+
242
+ // Parse UUID string (format: "550e8400-e29b-41d4-a716-446655440000")
243
+ // Expected length: 36 characters (32 hex + 4 hyphens)
244
+ if (len != 36 || str[8] != '-' || str[13] != '-' || str[18] != '-' || str[23] != '-') {
245
+ rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("Invalid UUID format")));
246
+ }
247
+
248
+ // Parse hex string to bytes using direct conversion, skipping hyphens
249
+ int byte_idx = 0;
250
+ for (int i = 0; i < len && byte_idx < 16; i++) {
251
+ if (str[i] == '-') continue;
252
+ if (i + 1 >= len || str[i + 1] == '-') break;
253
+
254
+ // Convert two hex characters to one byte
255
+ int high = hex_char_to_int(str[i]);
256
+ int low = hex_char_to_int(str[i + 1]);
257
+
258
+ if (high < 0 || low < 0) break;
259
+
260
+ bytes[byte_idx++] = (unsigned char)((high << 4) | low);
261
+ i++; // skip next char since we processed two
262
+ }
263
+
264
+ if (byte_idx != 16) {
265
+ rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("Invalid UUID format")));
266
+ }
267
+
268
+ WRITE(trans, bytes, 16);
269
+ return Qnil;
270
+ }
271
+
231
272
  //---------------------------------------
232
273
  // interface reading methods
233
274
  //---------------------------------------
@@ -272,13 +313,6 @@ static int64_t read_i64_direct(VALUE self) {
272
313
  return (hi << 32) | lo;
273
314
  }
274
315
 
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
316
  VALUE rb_thrift_binary_proto_read_message_end(VALUE self) {
283
317
  return Qnil;
284
318
  }
@@ -311,25 +345,25 @@ VALUE rb_thrift_binary_proto_read_message_begin(VALUE self) {
311
345
  VALUE strict_read = GET_STRICT_READ(self);
312
346
  VALUE name, seqid;
313
347
  int type;
314
-
348
+
315
349
  int version = read_i32_direct(self);
316
-
350
+
317
351
  if (version < 0) {
318
352
  if ((version & VERSION_MASK) != VERSION_1) {
319
- rb_exc_raise(get_protocol_exception(INT2FIX(BAD_VERSION), rb_str_new2("Missing version identifier")));
353
+ rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_BAD_VERSION), rb_str_new2("Missing version identifier")));
320
354
  }
321
355
  type = version & TYPE_MASK;
322
356
  name = rb_thrift_binary_proto_read_string(self);
323
357
  seqid = rb_thrift_binary_proto_read_i32(self);
324
358
  } else {
325
359
  if (strict_read == Qtrue) {
326
- rb_exc_raise(get_protocol_exception(INT2FIX(BAD_VERSION), rb_str_new2("No version identifier, old protocol client?")));
360
+ rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_BAD_VERSION), rb_str_new2("No version identifier, old protocol client?")));
327
361
  }
328
362
  name = READ(self, version);
329
363
  type = read_byte_direct(self);
330
364
  seqid = rb_thrift_binary_proto_read_i32(self);
331
365
  }
332
-
366
+
333
367
  return rb_ary_new3(3, name, INT2FIX(type), seqid);
334
368
  }
335
369
 
@@ -400,7 +434,28 @@ VALUE rb_thrift_binary_proto_read_binary(VALUE self) {
400
434
  return READ(self, size);
401
435
  }
402
436
 
403
- void Init_binary_protocol_accelerated() {
437
+ VALUE rb_thrift_binary_proto_read_uuid(VALUE self) {
438
+ VALUE data = READ(self, 16);
439
+ const unsigned char* bytes = (const unsigned char*)RSTRING_PTR(data);
440
+
441
+ // Format as UUID string: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
442
+ char uuid_str[37];
443
+ char* p = uuid_str;
444
+
445
+ for (int i = 0; i < 16; i++) {
446
+ *p++ = int_to_hex_char((bytes[i] >> 4) & 0x0F);
447
+ *p++ = int_to_hex_char(bytes[i] & 0x0F);
448
+ if (i == 3 || i == 5 || i == 7 || i == 9) {
449
+ *p++ = '-';
450
+ }
451
+ }
452
+
453
+ *p = '\0';
454
+
455
+ return rb_str_new(uuid_str, 36);
456
+ }
457
+
458
+ void Init_binary_protocol_accelerated(void) {
404
459
  VALUE thrift_binary_protocol_class = rb_const_get(thrift_module, rb_intern("BinaryProtocol"));
405
460
 
406
461
  VERSION_1 = (int)rb_num2ll(rb_const_get(thrift_binary_protocol_class, rb_intern("VERSION_1")));
@@ -425,6 +480,7 @@ void Init_binary_protocol_accelerated() {
425
480
  rb_define_method(bpa_class, "write_double", rb_thrift_binary_proto_write_double, 1);
426
481
  rb_define_method(bpa_class, "write_string", rb_thrift_binary_proto_write_string, 1);
427
482
  rb_define_method(bpa_class, "write_binary", rb_thrift_binary_proto_write_binary, 1);
483
+ rb_define_method(bpa_class, "write_uuid", rb_thrift_binary_proto_write_uuid, 1);
428
484
  // unused methods
429
485
  rb_define_method(bpa_class, "write_message_end", rb_thrift_binary_proto_write_message_end, 0);
430
486
  rb_define_method(bpa_class, "write_struct_begin", rb_thrift_binary_proto_write_struct_begin, 1);
@@ -447,6 +503,7 @@ void Init_binary_protocol_accelerated() {
447
503
  rb_define_method(bpa_class, "read_double", rb_thrift_binary_proto_read_double, 0);
448
504
  rb_define_method(bpa_class, "read_string", rb_thrift_binary_proto_read_string, 0);
449
505
  rb_define_method(bpa_class, "read_binary", rb_thrift_binary_proto_read_binary, 0);
506
+ rb_define_method(bpa_class, "read_uuid", rb_thrift_binary_proto_read_uuid, 0);
450
507
  // unused methods
451
508
  rb_define_method(bpa_class, "read_message_end", rb_thrift_binary_proto_read_message_end, 0);
452
509
  rb_define_method(bpa_class, "read_struct_begin", rb_thrift_binary_proto_read_struct_begin, 0);
@@ -20,10 +20,12 @@
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
  #define LAST_ID(obj) FIX2INT(rb_ary_pop(rb_ivar_get(obj, last_field_id)))
29
31
  #define SET_LAST_ID(obj, val) rb_ary_push(rb_ivar_get(obj, last_field_id), val)
@@ -58,6 +60,7 @@ static int CTYPE_LIST = 0x09;
58
60
  static int CTYPE_SET = 0x0A;
59
61
  static int CTYPE_MAP = 0x0B;
60
62
  static int CTYPE_STRUCT = 0x0C;
63
+ static int CTYPE_UUID = 0x0D;
61
64
 
62
65
  VALUE rb_thrift_compact_proto_write_i16(VALUE self, VALUE i16);
63
66
 
@@ -86,6 +89,8 @@ static int get_compact_type(VALUE type_value) {
86
89
  return CTYPE_MAP;
87
90
  } else if (type == TTYPE_STRUCT) {
88
91
  return CTYPE_STRUCT;
92
+ } else if (type == TTYPE_UUID) {
93
+ return CTYPE_UUID;
89
94
  } else {
90
95
  char str[50];
91
96
  sprintf(str, "don't know what type: %d", type);
@@ -102,7 +107,7 @@ static void write_field_begin_internal(VALUE self, VALUE type, VALUE id_value, V
102
107
  int id = FIX2INT(id_value);
103
108
  int last_id = LAST_ID(self);
104
109
  VALUE transport = GET_TRANSPORT(self);
105
-
110
+
106
111
  // if there's a type override, use that.
107
112
  int8_t type_to_write = RTEST(type_override) ? FIX2INT(type_override) : get_compact_type(type);
108
113
  // check if we can use delta encoding for the field id
@@ -169,6 +174,7 @@ static void write_collection_begin(VALUE transport, VALUE elem_type, VALUE size_
169
174
  VALUE rb_thrift_compact_proto_write_i32(VALUE self, VALUE i32);
170
175
  VALUE rb_thrift_compact_proto_write_string(VALUE self, VALUE str);
171
176
  VALUE rb_thrift_compact_proto_write_binary(VALUE self, VALUE buf);
177
+ VALUE rb_thrift_compact_proto_write_uuid(VALUE self, VALUE uuid);
172
178
 
173
179
  VALUE rb_thrift_compact_proto_write_message_end(VALUE self) {
174
180
  return Qnil;
@@ -206,7 +212,7 @@ VALUE rb_thrift_compact_proto_write_message_begin(VALUE self, VALUE name, VALUE
206
212
  write_byte_direct(transport, (VERSION & VERSION_MASK) | ((FIX2INT(type) << TYPE_SHIFT_AMOUNT) & TYPE_MASK));
207
213
  write_varint32(transport, FIX2INT(seqid));
208
214
  rb_thrift_compact_proto_write_string(self, name);
209
-
215
+
210
216
  return Qnil;
211
217
  }
212
218
 
@@ -320,6 +326,46 @@ VALUE rb_thrift_compact_proto_write_binary(VALUE self, VALUE buf) {
320
326
  return Qnil;
321
327
  }
322
328
 
329
+ VALUE rb_thrift_compact_proto_write_uuid(VALUE self, VALUE uuid) {
330
+ if (NIL_P(uuid) || TYPE(uuid) != T_STRING) {
331
+ rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("UUID must be a string")));
332
+ }
333
+
334
+ VALUE transport = GET_TRANSPORT(self);
335
+ char bytes[16];
336
+ const char* str = RSTRING_PTR(uuid);
337
+ long len = RSTRING_LEN(uuid);
338
+
339
+ // Parse UUID string (format: "550e8400-e29b-41d4-a716-446655440000")
340
+ // Expected length: 36 characters (32 hex + 4 hyphens)
341
+ if (len != 36 || str[8] != '-' || str[13] != '-' || str[18] != '-' || str[23] != '-') {
342
+ rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("Invalid UUID format")));
343
+ }
344
+
345
+ // Parse hex string to bytes using direct conversion, skipping hyphens
346
+ int byte_idx = 0;
347
+ for (int i = 0; i < len && byte_idx < 16; i++) {
348
+ if (str[i] == '-') continue;
349
+ if (i + 1 >= len || str[i + 1] == '-') break;
350
+
351
+ // Convert two hex characters to one byte
352
+ int high = hex_char_to_int(str[i]);
353
+ int low = hex_char_to_int(str[i + 1]);
354
+
355
+ if (high < 0 || low < 0) break;
356
+
357
+ bytes[byte_idx++] = (unsigned char)((high << 4) | low);
358
+ i++; // skip next char since we processed two
359
+ }
360
+
361
+ if (byte_idx != 16) {
362
+ rb_exc_raise(get_protocol_exception(INT2FIX(PROTOERR_INVALID_DATA), rb_str_new2("Invalid UUID format")));
363
+ }
364
+
365
+ WRITE(transport, bytes, 16);
366
+ return Qnil;
367
+ }
368
+
323
369
  //---------------------------------------
324
370
  // interface reading methods
325
371
  //---------------------------------------
@@ -331,6 +377,7 @@ VALUE rb_thrift_compact_proto_read_binary(VALUE self);
331
377
  VALUE rb_thrift_compact_proto_read_byte(VALUE self);
332
378
  VALUE rb_thrift_compact_proto_read_i32(VALUE self);
333
379
  VALUE rb_thrift_compact_proto_read_i16(VALUE self);
380
+ VALUE rb_thrift_compact_proto_read_uuid(VALUE self);
334
381
 
335
382
  static int8_t get_ttype(int8_t ctype) {
336
383
  if (ctype == TTYPE_STOP) {
@@ -357,6 +404,8 @@ static int8_t get_ttype(int8_t ctype) {
357
404
  return TTYPE_MAP;
358
405
  } else if (ctype == CTYPE_STRUCT) {
359
406
  return TTYPE_STRUCT;
407
+ } else if (ctype == CTYPE_UUID) {
408
+ return TTYPE_UUID;
360
409
  } else {
361
410
  char str[50];
362
411
  sprintf(str, "don't know what type: %d", ctype);
@@ -396,13 +445,6 @@ static int16_t read_i16(VALUE self) {
396
445
  return zig_zag_to_int((int32_t)read_varint64(self));
397
446
  }
398
447
 
399
- static VALUE get_protocol_exception(VALUE code, VALUE message) {
400
- VALUE args[2];
401
- args[0] = code;
402
- args[1] = message;
403
- return rb_class_new_instance(2, (VALUE*)&args, protocol_exception_class);
404
- }
405
-
406
448
  VALUE rb_thrift_compact_proto_read_message_end(VALUE self) {
407
449
  return Qnil;
408
450
  }
@@ -441,7 +483,7 @@ VALUE rb_thrift_compact_proto_read_message_begin(VALUE self) {
441
483
  buf[len] = 0;
442
484
  rb_exc_raise(get_protocol_exception(INT2FIX(-1), rb_str_new2(buf)));
443
485
  }
444
-
486
+
445
487
  int8_t version_and_type = read_byte_direct(self);
446
488
  int8_t version = version_and_type & VERSION_MASK;
447
489
  if (version != VERSION) {
@@ -450,7 +492,7 @@ VALUE rb_thrift_compact_proto_read_message_begin(VALUE self) {
450
492
  buf[len] = 0;
451
493
  rb_exc_raise(get_protocol_exception(INT2FIX(-1), rb_str_new2(buf)));
452
494
  }
453
-
495
+
454
496
  int8_t type = (version_and_type >> TYPE_SHIFT_AMOUNT) & TYPE_BITS;
455
497
  int32_t seqid = (int32_t)read_varint64(self);
456
498
  VALUE messageName = rb_thrift_compact_proto_read_string(self);
@@ -467,7 +509,7 @@ VALUE rb_thrift_compact_proto_read_field_begin(VALUE self) {
467
509
 
468
510
  // mask off the 4 MSB of the type header. it could contain a field id delta.
469
511
  uint8_t modifier = ((type & 0xf0) >> 4);
470
-
512
+
471
513
  if (modifier == 0) {
472
514
  // not a delta. look ahead for the zigzag varint field id.
473
515
  (void) LAST_ID(self);
@@ -565,7 +607,28 @@ VALUE rb_thrift_compact_proto_read_binary(VALUE self) {
565
607
  return READ(self, size);
566
608
  }
567
609
 
568
- static void Init_constants() {
610
+ VALUE rb_thrift_compact_proto_read_uuid(VALUE self) {
611
+ VALUE data = READ(self, 16);
612
+ const unsigned char* bytes = (const unsigned char*)RSTRING_PTR(data);
613
+
614
+ // Format as UUID string: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
615
+ char uuid_str[37];
616
+ char* p = uuid_str;
617
+
618
+ for (int i = 0; i < 16; i++) {
619
+ *p++ = int_to_hex_char((bytes[i] >> 4) & 0x0F);
620
+ *p++ = int_to_hex_char(bytes[i] & 0x0F);
621
+ if (i == 3 || i == 5 || i == 7 || i == 9) {
622
+ *p++ = '-';
623
+ }
624
+ }
625
+
626
+ *p = '\0';
627
+
628
+ return rb_str_new(uuid_str, 36);
629
+ }
630
+
631
+ static void Init_constants(void) {
569
632
  thrift_compact_protocol_class = rb_const_get(thrift_module, rb_intern("CompactProtocol"));
570
633
  rb_global_variable(&thrift_compact_protocol_class);
571
634
 
@@ -582,7 +645,7 @@ static void Init_constants() {
582
645
  rbuf_ivar_id = rb_intern("@rbuf");
583
646
  }
584
647
 
585
- static void Init_rb_methods() {
648
+ static void Init_rb_methods(void) {
586
649
  rb_define_method(thrift_compact_protocol_class, "native?", rb_thrift_compact_proto_native_qmark, 0);
587
650
 
588
651
  rb_define_method(thrift_compact_protocol_class, "write_message_begin", rb_thrift_compact_proto_write_message_begin, 3);
@@ -599,6 +662,7 @@ static void Init_rb_methods() {
599
662
  rb_define_method(thrift_compact_protocol_class, "write_double", rb_thrift_compact_proto_write_double, 1);
600
663
  rb_define_method(thrift_compact_protocol_class, "write_string", rb_thrift_compact_proto_write_string, 1);
601
664
  rb_define_method(thrift_compact_protocol_class, "write_binary", rb_thrift_compact_proto_write_binary, 1);
665
+ rb_define_method(thrift_compact_protocol_class, "write_uuid", rb_thrift_compact_proto_write_uuid, 1);
602
666
 
603
667
  rb_define_method(thrift_compact_protocol_class, "write_message_end", rb_thrift_compact_proto_write_message_end, 0);
604
668
  rb_define_method(thrift_compact_protocol_class, "write_struct_begin", rb_thrift_compact_proto_write_struct_begin, 1);
@@ -622,6 +686,7 @@ static void Init_rb_methods() {
622
686
  rb_define_method(thrift_compact_protocol_class, "read_double", rb_thrift_compact_proto_read_double, 0);
623
687
  rb_define_method(thrift_compact_protocol_class, "read_string", rb_thrift_compact_proto_read_string, 0);
624
688
  rb_define_method(thrift_compact_protocol_class, "read_binary", rb_thrift_compact_proto_read_binary, 0);
689
+ rb_define_method(thrift_compact_protocol_class, "read_uuid", rb_thrift_compact_proto_read_uuid, 0);
625
690
 
626
691
  rb_define_method(thrift_compact_protocol_class, "read_message_end", rb_thrift_compact_proto_read_message_end, 0);
627
692
  rb_define_method(thrift_compact_protocol_class, "read_struct_begin", rb_thrift_compact_proto_read_struct_begin, 0);
@@ -632,7 +697,7 @@ static void Init_rb_methods() {
632
697
  rb_define_method(thrift_compact_protocol_class, "read_set_end", rb_thrift_compact_proto_read_set_end, 0);
633
698
  }
634
699
 
635
- void Init_compact_protocol() {
700
+ void Init_compact_protocol(void) {
636
701
  Init_constants();
637
702
  Init_rb_methods();
638
703
  }
data/ext/constants.h CHANGED
@@ -29,6 +29,7 @@ extern int TTYPE_MAP;
29
29
  extern int TTYPE_SET;
30
30
  extern int TTYPE_LIST;
31
31
  extern int TTYPE_STRUCT;
32
+ extern int TTYPE_UUID;
32
33
 
33
34
  extern ID validate_method_id;
34
35
  extern ID write_struct_begin_method_id;
@@ -49,6 +50,7 @@ extern ID write_list_begin_method_id;
49
50
  extern ID write_list_end_method_id;
50
51
  extern ID write_set_begin_method_id;
51
52
  extern ID write_set_end_method_id;
53
+ extern ID write_uuid_method_id;
52
54
  extern ID read_bool_method_id;
53
55
  extern ID read_byte_method_id;
54
56
  extern ID read_i16_method_id;
@@ -63,6 +65,7 @@ extern ID read_list_begin_method_id;
63
65
  extern ID read_list_end_method_id;
64
66
  extern ID read_set_begin_method_id;
65
67
  extern ID read_set_end_method_id;
68
+ extern ID read_uuid_method_id;
66
69
  extern ID read_struct_begin_method_id;
67
70
  extern ID read_struct_end_method_id;
68
71
  extern ID read_field_begin_method_id;
@@ -97,3 +100,12 @@ extern VALUE thrift_types_module;
97
100
  extern VALUE thrift_bytes_module;
98
101
  extern VALUE class_thrift_protocol;
99
102
  extern VALUE protocol_exception_class;
103
+
104
+ // protocol errors
105
+ extern int PROTOERR_UNKNOWN;
106
+ extern int PROTOERR_INVALID_DATA;
107
+ extern int PROTOERR_NEGATIVE_SIZE;
108
+ extern int PROTOERR_SIZE_LIMIT;
109
+ extern int PROTOERR_BAD_VERSION;
110
+ extern int PROTOERR_NOT_IMPLEMENTED;
111
+ extern int PROTOERR_DEPTH_LIMIT;
data/ext/extconf.rb CHANGED
@@ -1,4 +1,4 @@
1
- #
1
+ #
2
2
  # Licensed to the Apache Software Foundation (ASF) under one
3
3
  # or more contributor license agreements. See the NOTICE file
4
4
  # distributed with this work for additional information
@@ -6,27 +6,28 @@
6
6
  # to you under the Apache License, Version 2.0 (the
7
7
  # "License"); you may not use this file except in compliance
8
8
  # with the License. You may obtain a copy of the License at
9
- #
9
+ #
10
10
  # http://www.apache.org/licenses/LICENSE-2.0
11
- #
11
+ #
12
12
  # Unless required by applicable law or agreed to in writing,
13
13
  # software distributed under the License is distributed on an
14
14
  # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
15
  # KIND, either express or implied. See the License for the
16
16
  # specific language governing permissions and limitations
17
17
  # under the License.
18
- #
18
+ #
19
19
 
20
20
  if defined?(RUBY_ENGINE) && RUBY_ENGINE =~ /jruby/
21
- File.open('Makefile', 'w'){|f| f.puts "all:\n\ninstall:\n" }
21
+ File.open('Makefile', 'w'){ |f| f.puts "all:\n\ninstall:\n" }
22
22
  else
23
23
  require 'mkmf'
24
- require 'rbconfig'
25
24
 
26
- $ARCH_FLAGS = RbConfig::CONFIG['CFLAGS'].scan( /(-arch )(\S+)/ ).map{|x,y| x + y + ' ' }.join('')
25
+ append_cflags(["-fsigned-char", "-g", "-O2", "-Wall", "-Werror", "-Werror=old-style-definition"])
27
26
 
28
-
29
- $CFLAGS = "-fsigned-char -g -O2 -Wall -Werror " + $ARCH_FLAGS
27
+ # Makes all symbols private by default to avoid unintended conflict
28
+ # with other gems. To explicitly export symbols you can use RUBY_FUNC_EXPORTED
29
+ # selectively, or entirely remove this flag.
30
+ append_cflags("-fvisibility=hidden")
30
31
 
31
32
  have_func("strlcpy", "string.h")
32
33
 
data/ext/memory_buffer.c CHANGED
@@ -45,13 +45,13 @@ VALUE rb_thrift_memory_buffer_write(VALUE self, VALUE str) {
45
45
 
46
46
  VALUE rb_thrift_memory_buffer_read(VALUE self, VALUE length_value) {
47
47
  int length = FIX2INT(length_value);
48
-
48
+
49
49
  VALUE index_value = rb_ivar_get(self, index_ivar_id);
50
50
  int index = FIX2INT(index_value);
51
-
51
+
52
52
  VALUE buf = GET_BUF(self);
53
53
  VALUE data = rb_funcall(buf, slice_method_id, 2, index_value, length_value);
54
-
54
+
55
55
  index += length;
56
56
  if (index > RSTRING_LEN(buf)) {
57
57
  index = (int)RSTRING_LEN(buf);
@@ -118,17 +118,17 @@ VALUE rb_thrift_memory_buffer_read_into_buffer(VALUE self, VALUE buffer_value, V
118
118
  return INT2FIX(i);
119
119
  }
120
120
 
121
- void Init_memory_buffer() {
121
+ void Init_memory_buffer(void) {
122
122
  VALUE thrift_memory_buffer_class = rb_const_get(thrift_module, rb_intern("MemoryBufferTransport"));
123
123
  rb_define_method(thrift_memory_buffer_class, "write", rb_thrift_memory_buffer_write, 1);
124
124
  rb_define_method(thrift_memory_buffer_class, "read", rb_thrift_memory_buffer_read, 1);
125
125
  rb_define_method(thrift_memory_buffer_class, "read_byte", rb_thrift_memory_buffer_read_byte, 0);
126
126
  rb_define_method(thrift_memory_buffer_class, "read_into_buffer", rb_thrift_memory_buffer_read_into_buffer, 2);
127
-
127
+
128
128
  buf_ivar_id = rb_intern("@buf");
129
129
  index_ivar_id = rb_intern("@index");
130
-
130
+
131
131
  slice_method_id = rb_intern("slice");
132
-
132
+
133
133
  GARBAGE_BUFFER_SIZE = FIX2INT(rb_const_get(thrift_memory_buffer_class, rb_intern("GARBAGE_BUFFER_SIZE")));
134
134
  }
data/ext/protocol.c CHANGED
@@ -0,0 +1,29 @@
1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+
20
+ #include <ruby.h>
21
+ #include <constants.h>
22
+ #include <protocol.h>
23
+
24
+ VALUE get_protocol_exception(VALUE code, VALUE message) {
25
+ VALUE args[2];
26
+ args[0] = code;
27
+ args[1] = message;
28
+ return rb_class_new_instance(2, (VALUE*)&args, protocol_exception_class);
29
+ }
data/ext/protocol.h CHANGED
@@ -0,0 +1,35 @@
1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+
20
+ #include <ruby.h>
21
+
22
+ VALUE get_protocol_exception(VALUE code, VALUE message);
23
+
24
+ // Efficient hex character to integer conversion
25
+ static inline int hex_char_to_int(char c) {
26
+ if (c >= '0' && c <= '9') return c - '0';
27
+ if (c >= 'a' && c <= 'f') return c - 'a' + 10;
28
+ if (c >= 'A' && c <= 'F') return c - 'A' + 10;
29
+ return -1; // invalid hex character
30
+ }
31
+
32
+ // Efficient integer to hex character conversion
33
+ static inline char int_to_hex_char(int val) {
34
+ return val < 10 ? ('0' + val) : ('a' + val - 10);
35
+ }