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.
- checksums.yaml +4 -4
- data/README.md +175 -17
- data/benchmark/benchmark.rb +22 -8
- data/benchmark/client.rb +49 -6
- data/benchmark/server.rb +45 -7
- data/benchmark/thin_server.rb +1 -0
- data/ext/binary_protocol_accelerated.c +76 -19
- data/ext/compact_protocol.c +80 -15
- data/ext/constants.h +12 -0
- data/ext/extconf.rb +10 -9
- data/ext/memory_buffer.c +7 -7
- data/ext/protocol.c +29 -0
- data/ext/protocol.h +35 -0
- data/ext/struct.c +36 -5
- data/ext/thrift_native.c +27 -3
- data/lib/thrift/bytes.rb +68 -101
- data/lib/thrift/client.rb +61 -9
- data/lib/thrift/exceptions.rb +5 -5
- data/lib/thrift/multiplexed_processor.rb +6 -6
- data/lib/thrift/processor.rb +6 -6
- data/lib/thrift/protocol/base_protocol.rb +37 -15
- data/lib/thrift/protocol/binary_protocol.rb +25 -9
- data/lib/thrift/protocol/binary_protocol_accelerated.rb +5 -5
- data/lib/thrift/protocol/compact_protocol.rb +61 -37
- data/lib/thrift/protocol/header_protocol.rb +320 -0
- data/lib/thrift/protocol/json_protocol.rb +26 -16
- data/lib/thrift/protocol/multiplexed_protocol.rb +5 -5
- data/lib/thrift/protocol/protocol_decorator.rb +12 -4
- data/lib/thrift/serializer/deserializer.rb +5 -5
- data/lib/thrift/serializer/serializer.rb +4 -5
- data/lib/thrift/server/base_server.rb +4 -4
- data/lib/thrift/server/mongrel_http_server.rb +6 -6
- data/lib/thrift/server/nonblocking_server.rb +8 -8
- data/lib/thrift/server/simple_server.rb +4 -4
- data/lib/thrift/server/thin_http_server.rb +3 -3
- data/lib/thrift/server/thread_pool_server.rb +6 -6
- data/lib/thrift/server/threaded_server.rb +4 -4
- data/lib/thrift/struct.rb +11 -11
- data/lib/thrift/struct_union.rb +19 -9
- data/lib/thrift/thrift_native.rb +1 -1
- data/lib/thrift/transport/base_server_transport.rb +5 -5
- data/lib/thrift/transport/base_transport.rb +12 -12
- data/lib/thrift/transport/buffered_transport.rb +6 -6
- data/lib/thrift/transport/framed_transport.rb +7 -7
- data/lib/thrift/transport/header_transport.rb +516 -0
- data/lib/thrift/transport/http_client_transport.rb +1 -1
- data/lib/thrift/transport/io_stream_transport.rb +3 -3
- data/lib/thrift/transport/memory_buffer_transport.rb +6 -6
- data/lib/thrift/transport/server_socket.rb +8 -5
- data/lib/thrift/transport/socket.rb +58 -31
- data/lib/thrift/transport/ssl_server_socket.rb +1 -1
- data/lib/thrift/transport/ssl_socket.rb +2 -2
- data/lib/thrift/transport/unix_server_socket.rb +4 -4
- data/lib/thrift/transport/unix_socket.rb +6 -6
- data/lib/thrift/types.rb +9 -6
- data/lib/thrift/union.rb +14 -8
- data/lib/thrift/uuid.rb +49 -0
- data/lib/thrift.rb +3 -1
- data/spec/ThriftSpec.thrift +5 -1
- data/spec/base_protocol_spec.rb +1 -2
- data/spec/base_transport_spec.rb +6 -7
- data/spec/binary_protocol_spec.rb +0 -2
- data/spec/binary_protocol_spec_shared.rb +129 -142
- data/spec/bytes_spec.rb +57 -118
- data/spec/client_spec.rb +85 -19
- data/spec/compact_protocol_spec.rb +54 -16
- data/spec/constants_demo_spec.rb +101 -0
- data/spec/exception_spec.rb +0 -1
- data/spec/header_protocol_spec.rb +475 -0
- data/spec/header_transport_spec.rb +386 -0
- data/spec/http_client_spec.rb +4 -6
- data/spec/json_protocol_spec.rb +47 -47
- data/spec/namespaced_spec.rb +0 -1
- data/spec/nonblocking_server_spec.rb +102 -4
- data/spec/processor_spec.rb +0 -1
- data/spec/serializer_spec.rb +0 -1
- data/spec/server_socket_spec.rb +1 -1
- data/spec/server_spec.rb +8 -9
- data/spec/socket_spec.rb +0 -1
- data/spec/socket_spec_shared.rb +72 -9
- data/spec/spec_helper.rb +1 -1
- data/spec/ssl_server_socket_spec.rb +12 -1
- data/spec/ssl_socket_spec.rb +10 -1
- data/spec/struct_nested_containers_spec.rb +1 -2
- data/spec/struct_spec.rb +113 -9
- data/spec/support/header_protocol_helper.rb +54 -0
- data/spec/thin_http_server_spec.rb +3 -18
- data/spec/types_spec.rb +25 -26
- data/spec/union_spec.rb +69 -11
- data/spec/unix_socket_spec.rb +1 -2
- data/spec/uuid_validation_spec.rb +238 -0
- data/test/fuzz/Makefile.am +173 -0
- data/test/fuzz/README.md +149 -0
- data/test/fuzz/fuzz_common.rb +95 -0
- data/{lib/thrift/core_ext.rb → test/fuzz/fuzz_parse_binary_protocol.rb} +3 -4
- data/{lib/thrift/core_ext/fixnum.rb → test/fuzz/fuzz_parse_binary_protocol_accelerated.rb} +6 -13
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +22 -0
- data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +22 -0
- data/test/fuzz/fuzz_parse_compact_protocol.rb +22 -0
- data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +22 -0
- data/test/fuzz/fuzz_parse_json_protocol.rb +22 -0
- data/test/fuzz/fuzz_parse_json_protocol_harness.rb +22 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +22 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +22 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +22 -0
- data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +22 -0
- data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +22 -0
- data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +22 -0
- data/test/fuzz/fuzz_roundtrip_json_protocol.rb +22 -0
- data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +22 -0
- data/test/fuzz/fuzz_tracer.rb +28 -0
- 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(
|
|
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(
|
|
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
|
-
|
|
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);
|
data/ext/compact_protocol.c
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
25
|
+
append_cflags(["-fsigned-char", "-g", "-O2", "-Wall", "-Werror", "-Werror=old-style-definition"])
|
|
27
26
|
|
|
28
|
-
|
|
29
|
-
|
|
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
|
+
}
|