upfluence-thrift 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +43 -0
  3. data/benchmark/Benchmark.thrift +24 -0
  4. data/benchmark/benchmark.rb +271 -0
  5. data/benchmark/client.rb +74 -0
  6. data/benchmark/gen-rb/benchmark_constants.rb +11 -0
  7. data/benchmark/gen-rb/benchmark_service.rb +80 -0
  8. data/benchmark/gen-rb/benchmark_types.rb +10 -0
  9. data/benchmark/server.rb +82 -0
  10. data/benchmark/thin_server.rb +44 -0
  11. data/ext/binary_protocol_accelerated.c +460 -0
  12. data/ext/binary_protocol_accelerated.h +20 -0
  13. data/ext/bytes.c +36 -0
  14. data/ext/bytes.h +31 -0
  15. data/ext/compact_protocol.c +637 -0
  16. data/ext/compact_protocol.h +20 -0
  17. data/ext/constants.h +99 -0
  18. data/ext/extconf.rb +34 -0
  19. data/ext/macros.h +41 -0
  20. data/ext/memory_buffer.c +134 -0
  21. data/ext/memory_buffer.h +20 -0
  22. data/ext/protocol.c +0 -0
  23. data/ext/protocol.h +0 -0
  24. data/ext/strlcpy.c +41 -0
  25. data/ext/strlcpy.h +34 -0
  26. data/ext/struct.c +707 -0
  27. data/ext/struct.h +25 -0
  28. data/ext/thrift_native.c +201 -0
  29. data/lib/thrift.rb +68 -0
  30. data/lib/thrift/bytes.rb +131 -0
  31. data/lib/thrift/client.rb +71 -0
  32. data/lib/thrift/core_ext.rb +23 -0
  33. data/lib/thrift/core_ext/fixnum.rb +29 -0
  34. data/lib/thrift/exceptions.rb +87 -0
  35. data/lib/thrift/multiplexed_processor.rb +76 -0
  36. data/lib/thrift/processor.rb +57 -0
  37. data/lib/thrift/protocol/base_protocol.rb +379 -0
  38. data/lib/thrift/protocol/binary_protocol.rb +237 -0
  39. data/lib/thrift/protocol/binary_protocol_accelerated.rb +39 -0
  40. data/lib/thrift/protocol/compact_protocol.rb +435 -0
  41. data/lib/thrift/protocol/json_protocol.rb +769 -0
  42. data/lib/thrift/protocol/multiplexed_protocol.rb +40 -0
  43. data/lib/thrift/protocol/protocol_decorator.rb +194 -0
  44. data/lib/thrift/serializer/deserializer.rb +33 -0
  45. data/lib/thrift/serializer/serializer.rb +34 -0
  46. data/lib/thrift/server/base_server.rb +31 -0
  47. data/lib/thrift/server/mongrel_http_server.rb +60 -0
  48. data/lib/thrift/server/nonblocking_server.rb +305 -0
  49. data/lib/thrift/server/rack_application.rb +61 -0
  50. data/lib/thrift/server/simple_server.rb +43 -0
  51. data/lib/thrift/server/thin_http_server.rb +51 -0
  52. data/lib/thrift/server/thread_pool_server.rb +75 -0
  53. data/lib/thrift/server/threaded_server.rb +47 -0
  54. data/lib/thrift/struct.rb +237 -0
  55. data/lib/thrift/struct_union.rb +192 -0
  56. data/lib/thrift/thrift_native.rb +24 -0
  57. data/lib/thrift/transport/base_server_transport.rb +37 -0
  58. data/lib/thrift/transport/base_transport.rb +109 -0
  59. data/lib/thrift/transport/buffered_transport.rb +114 -0
  60. data/lib/thrift/transport/framed_transport.rb +117 -0
  61. data/lib/thrift/transport/http_client_transport.rb +56 -0
  62. data/lib/thrift/transport/io_stream_transport.rb +39 -0
  63. data/lib/thrift/transport/memory_buffer_transport.rb +125 -0
  64. data/lib/thrift/transport/server_socket.rb +63 -0
  65. data/lib/thrift/transport/socket.rb +139 -0
  66. data/lib/thrift/transport/unix_server_socket.rb +60 -0
  67. data/lib/thrift/transport/unix_socket.rb +40 -0
  68. data/lib/thrift/types.rb +101 -0
  69. data/lib/thrift/union.rb +179 -0
  70. data/spec/BaseService.thrift +27 -0
  71. data/spec/ExtendedService.thrift +25 -0
  72. data/spec/Referenced.thrift +44 -0
  73. data/spec/ThriftNamespacedSpec.thrift +53 -0
  74. data/spec/ThriftSpec.thrift +183 -0
  75. data/spec/base_protocol_spec.rb +217 -0
  76. data/spec/base_transport_spec.rb +350 -0
  77. data/spec/binary_protocol_accelerated_spec.rb +42 -0
  78. data/spec/binary_protocol_spec.rb +66 -0
  79. data/spec/binary_protocol_spec_shared.rb +455 -0
  80. data/spec/bytes_spec.rb +160 -0
  81. data/spec/client_spec.rb +99 -0
  82. data/spec/compact_protocol_spec.rb +143 -0
  83. data/spec/exception_spec.rb +141 -0
  84. data/spec/flat_spec.rb +62 -0
  85. data/spec/gen-rb/base/base_service.rb +80 -0
  86. data/spec/gen-rb/base/base_service_constants.rb +11 -0
  87. data/spec/gen-rb/base/base_service_types.rb +26 -0
  88. data/spec/gen-rb/extended/extended_service.rb +78 -0
  89. data/spec/gen-rb/extended/extended_service_constants.rb +11 -0
  90. data/spec/gen-rb/extended/extended_service_types.rb +12 -0
  91. data/spec/gen-rb/flat/namespaced_nonblocking_service.rb +272 -0
  92. data/spec/gen-rb/flat/referenced_constants.rb +11 -0
  93. data/spec/gen-rb/flat/referenced_types.rb +17 -0
  94. data/spec/gen-rb/flat/thrift_namespaced_spec_constants.rb +11 -0
  95. data/spec/gen-rb/flat/thrift_namespaced_spec_types.rb +28 -0
  96. data/spec/gen-rb/namespaced_spec_namespace/namespaced_nonblocking_service.rb +272 -0
  97. data/spec/gen-rb/namespaced_spec_namespace/thrift_namespaced_spec_constants.rb +11 -0
  98. data/spec/gen-rb/namespaced_spec_namespace/thrift_namespaced_spec_types.rb +28 -0
  99. data/spec/gen-rb/nonblocking_service.rb +272 -0
  100. data/spec/gen-rb/other_namespace/referenced_constants.rb +11 -0
  101. data/spec/gen-rb/other_namespace/referenced_types.rb +17 -0
  102. data/spec/gen-rb/thrift_spec_constants.rb +11 -0
  103. data/spec/gen-rb/thrift_spec_types.rb +538 -0
  104. data/spec/http_client_spec.rb +120 -0
  105. data/spec/json_protocol_spec.rb +513 -0
  106. data/spec/namespaced_spec.rb +67 -0
  107. data/spec/nonblocking_server_spec.rb +263 -0
  108. data/spec/processor_spec.rb +80 -0
  109. data/spec/serializer_spec.rb +67 -0
  110. data/spec/server_socket_spec.rb +79 -0
  111. data/spec/server_spec.rb +147 -0
  112. data/spec/socket_spec.rb +61 -0
  113. data/spec/socket_spec_shared.rb +104 -0
  114. data/spec/spec_helper.rb +64 -0
  115. data/spec/struct_nested_containers_spec.rb +191 -0
  116. data/spec/struct_spec.rb +293 -0
  117. data/spec/thin_http_server_spec.rb +141 -0
  118. data/spec/types_spec.rb +115 -0
  119. data/spec/union_spec.rb +203 -0
  120. data/spec/unix_socket_spec.rb +107 -0
  121. data/test/debug_proto/gen-rb/debug_proto_test_constants.rb +274 -0
  122. data/test/debug_proto/gen-rb/debug_proto_test_types.rb +761 -0
  123. data/test/debug_proto/gen-rb/empty_service.rb +24 -0
  124. data/test/debug_proto/gen-rb/inherited.rb +79 -0
  125. data/test/debug_proto/gen-rb/reverse_order_service.rb +82 -0
  126. data/test/debug_proto/gen-rb/service_for_exception_with_a_map.rb +81 -0
  127. data/test/debug_proto/gen-rb/srv.rb +330 -0
  128. metadata +388 -0
@@ -0,0 +1,237 @@
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
+ module Thrift
21
+ class BinaryProtocol < BaseProtocol
22
+ VERSION_MASK = 0xffff0000
23
+ VERSION_1 = 0x80010000
24
+ TYPE_MASK = 0x000000ff
25
+
26
+ attr_reader :strict_read, :strict_write
27
+
28
+ def initialize(trans, strict_read=true, strict_write=true)
29
+ super(trans)
30
+ @strict_read = strict_read
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 = Bytes.empty_byte_buffer(8)
36
+ end
37
+
38
+ def write_message_begin(name, type, seqid)
39
+ # this is necessary because we added (needed) bounds checking to
40
+ # write_i32, and 0x80010000 is too big for that.
41
+ if strict_write
42
+ write_i16(VERSION_1 >> 16)
43
+ write_i16(type)
44
+ write_string(name)
45
+ write_i32(seqid)
46
+ else
47
+ write_string(name)
48
+ write_byte(type)
49
+ write_i32(seqid)
50
+ end
51
+ end
52
+
53
+ def write_struct_begin(name); nil; end
54
+
55
+ def write_field_begin(name, type, id)
56
+ write_byte(type)
57
+ write_i16(id)
58
+ end
59
+
60
+ def write_field_stop
61
+ write_byte(Thrift::Types::STOP)
62
+ end
63
+
64
+ def write_map_begin(ktype, vtype, size)
65
+ write_byte(ktype)
66
+ write_byte(vtype)
67
+ write_i32(size)
68
+ end
69
+
70
+ def write_list_begin(etype, size)
71
+ write_byte(etype)
72
+ write_i32(size)
73
+ end
74
+
75
+ def write_set_begin(etype, size)
76
+ write_byte(etype)
77
+ write_i32(size)
78
+ end
79
+
80
+ def write_bool(bool)
81
+ write_byte(bool ? 1 : 0)
82
+ end
83
+
84
+ def write_byte(byte)
85
+ raise RangeError if byte < -2**31 || byte >= 2**32
86
+ trans.write([byte].pack('c'))
87
+ end
88
+
89
+ def write_i16(i16)
90
+ trans.write([i16].pack('n'))
91
+ end
92
+
93
+ def write_i32(i32)
94
+ raise RangeError if i32 < -2**31 || i32 >= 2**31
95
+ trans.write([i32].pack('N'))
96
+ end
97
+
98
+ def write_i64(i64)
99
+ raise RangeError if i64 < -2**63 || i64 >= 2**64
100
+ hi = i64 >> 32
101
+ lo = i64 & 0xffffffff
102
+ trans.write([hi, lo].pack('N2'))
103
+ end
104
+
105
+ def write_double(dub)
106
+ trans.write([dub].pack('G'))
107
+ end
108
+
109
+ def write_string(str)
110
+ buf = Bytes.convert_to_utf8_byte_buffer(str)
111
+ write_binary(buf)
112
+ end
113
+
114
+ def write_binary(buf)
115
+ write_i32(buf.bytesize)
116
+ trans.write(buf)
117
+ end
118
+
119
+ def read_message_begin
120
+ version = read_i32
121
+ if version < 0
122
+ if (version & VERSION_MASK != VERSION_1)
123
+ raise ProtocolException.new(ProtocolException::BAD_VERSION, 'Missing version identifier')
124
+ end
125
+ type = version & TYPE_MASK
126
+ name = read_string
127
+ seqid = read_i32
128
+ [name, type, seqid]
129
+ else
130
+ if strict_read
131
+ raise ProtocolException.new(ProtocolException::BAD_VERSION, 'No version identifier, old protocol client?')
132
+ end
133
+ name = trans.read_all(version)
134
+ type = read_byte
135
+ seqid = read_i32
136
+ [name, type, seqid]
137
+ end
138
+ end
139
+
140
+ def read_struct_begin; nil; end
141
+
142
+ def read_field_begin
143
+ type = read_byte
144
+ if (type == Types::STOP)
145
+ [nil, type, 0]
146
+ else
147
+ id = read_i16
148
+ [nil, type, id]
149
+ end
150
+ end
151
+
152
+ def read_map_begin
153
+ ktype = read_byte
154
+ vtype = read_byte
155
+ size = read_i32
156
+ [ktype, vtype, size]
157
+ end
158
+
159
+ def read_list_begin
160
+ etype = read_byte
161
+ size = read_i32
162
+ [etype, size]
163
+ end
164
+
165
+ def read_set_begin
166
+ etype = read_byte
167
+ size = read_i32
168
+ [etype, size]
169
+ end
170
+
171
+ def read_bool
172
+ byte = read_byte
173
+ byte != 0
174
+ end
175
+
176
+ def read_byte
177
+ val = trans.read_byte
178
+ if (val > 0x7f)
179
+ val = 0 - ((val - 1) ^ 0xff)
180
+ end
181
+ val
182
+ end
183
+
184
+ def read_i16
185
+ trans.read_into_buffer(@rbuf, 2)
186
+ val, = @rbuf.unpack('n')
187
+ if (val > 0x7fff)
188
+ val = 0 - ((val - 1) ^ 0xffff)
189
+ end
190
+ val
191
+ end
192
+
193
+ def read_i32
194
+ trans.read_into_buffer(@rbuf, 4)
195
+ val, = @rbuf.unpack('N')
196
+ if (val > 0x7fffffff)
197
+ val = 0 - ((val - 1) ^ 0xffffffff)
198
+ end
199
+ val
200
+ end
201
+
202
+ def read_i64
203
+ trans.read_into_buffer(@rbuf, 8)
204
+ hi, lo = @rbuf.unpack('N2')
205
+ if (hi > 0x7fffffff)
206
+ hi ^= 0xffffffff
207
+ lo ^= 0xffffffff
208
+ 0 - (hi << 32) - lo - 1
209
+ else
210
+ (hi << 32) + lo
211
+ end
212
+ end
213
+
214
+ def read_double
215
+ trans.read_into_buffer(@rbuf, 8)
216
+ val = @rbuf.unpack('G').first
217
+ val
218
+ end
219
+
220
+ def read_string
221
+ buffer = read_binary
222
+ Bytes.convert_to_string(buffer)
223
+ end
224
+
225
+ def read_binary
226
+ size = read_i32
227
+ trans.read_all(size)
228
+ end
229
+
230
+ end
231
+
232
+ class BinaryProtocolFactory < BaseProtocolFactory
233
+ def get_protocol(trans)
234
+ return Thrift::BinaryProtocol.new(trans)
235
+ end
236
+ end
237
+ end
@@ -0,0 +1,39 @@
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
+ =begin
21
+ The only change required for a transport to support BinaryProtocolAccelerated is to implement 2 methods:
22
+ * borrow(size), which takes an optional argument and returns atleast _size_ bytes from the transport,
23
+ or the default buffer size if no argument is given
24
+ * consume!(size), which removes size bytes from the front of the buffer
25
+
26
+ See MemoryBuffer and BufferedTransport for examples.
27
+ =end
28
+
29
+ module Thrift
30
+ class BinaryProtocolAcceleratedFactory < BaseProtocolFactory
31
+ def get_protocol(trans)
32
+ if (defined? BinaryProtocolAccelerated)
33
+ BinaryProtocolAccelerated.new(trans)
34
+ else
35
+ BinaryProtocol.new(trans)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,435 @@
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
+ module Thrift
21
+ class CompactProtocol < BaseProtocol
22
+
23
+ PROTOCOL_ID = [0x82].pack('c').unpack('c').first
24
+ VERSION = 1
25
+ VERSION_MASK = 0x1f
26
+ TYPE_MASK = 0xE0
27
+ TYPE_BITS = 0x07
28
+ TYPE_SHIFT_AMOUNT = 5
29
+
30
+ TSTOP = ["", Types::STOP, 0]
31
+
32
+ #
33
+ # All of the on-wire type codes.
34
+ #
35
+ class CompactTypes
36
+ BOOLEAN_TRUE = 0x01
37
+ BOOLEAN_FALSE = 0x02
38
+ BYTE = 0x03
39
+ I16 = 0x04
40
+ I32 = 0x05
41
+ I64 = 0x06
42
+ DOUBLE = 0x07
43
+ BINARY = 0x08
44
+ LIST = 0x09
45
+ SET = 0x0A
46
+ MAP = 0x0B
47
+ STRUCT = 0x0C
48
+
49
+ def self.is_bool_type?(b)
50
+ (b & 0x0f) == BOOLEAN_TRUE || (b & 0x0f) == BOOLEAN_FALSE
51
+ end
52
+
53
+ COMPACT_TO_TTYPE = {
54
+ Types::STOP => Types::STOP,
55
+ BOOLEAN_FALSE => Types::BOOL,
56
+ BOOLEAN_TRUE => Types::BOOL,
57
+ BYTE => Types::BYTE,
58
+ I16 => Types::I16,
59
+ I32 => Types::I32,
60
+ I64 => Types::I64,
61
+ DOUBLE => Types::DOUBLE,
62
+ BINARY => Types::STRING,
63
+ LIST => Types::LIST,
64
+ SET => Types::SET,
65
+ MAP => Types::MAP,
66
+ STRUCT => Types::STRUCT
67
+ }
68
+
69
+ TTYPE_TO_COMPACT = {
70
+ Types::STOP => Types::STOP,
71
+ Types::BOOL => BOOLEAN_TRUE,
72
+ Types::BYTE => BYTE,
73
+ Types::I16 => I16,
74
+ Types::I32 => I32,
75
+ Types::I64 => I64,
76
+ Types::DOUBLE => DOUBLE,
77
+ Types::STRING => BINARY,
78
+ Types::LIST => LIST,
79
+ Types::SET => SET,
80
+ Types::MAP => MAP,
81
+ Types::STRUCT => STRUCT
82
+ }
83
+
84
+ def self.get_ttype(compact_type)
85
+ val = COMPACT_TO_TTYPE[compact_type & 0x0f]
86
+ raise "don't know what type: #{compact_type & 0x0f}" unless val
87
+ val
88
+ end
89
+
90
+ def self.get_compact_type(ttype)
91
+ val = TTYPE_TO_COMPACT[ttype]
92
+ raise "don't know what type: #{ttype & 0x0f}" unless val
93
+ val
94
+ end
95
+ end
96
+
97
+ def initialize(transport)
98
+ super(transport)
99
+
100
+ @last_field = [0]
101
+ @boolean_value = nil
102
+
103
+ # Pre-allocated read buffer for read_double().
104
+ @rbuf = Bytes.empty_byte_buffer(8)
105
+ end
106
+
107
+ def write_message_begin(name, type, seqid)
108
+ write_byte(PROTOCOL_ID)
109
+ write_byte((VERSION & VERSION_MASK) | ((type << TYPE_SHIFT_AMOUNT) & TYPE_MASK))
110
+ write_varint32(seqid)
111
+ write_string(name)
112
+ nil
113
+ end
114
+
115
+ def write_struct_begin(name)
116
+ @last_field.push(0)
117
+ nil
118
+ end
119
+
120
+ def write_struct_end
121
+ @last_field.pop
122
+ nil
123
+ end
124
+
125
+ def write_field_begin(name, type, id)
126
+ if type == Types::BOOL
127
+ # we want to possibly include the value, so we'll wait.
128
+ @boolean_field = [type, id]
129
+ else
130
+ write_field_begin_internal(type, id)
131
+ end
132
+ nil
133
+ end
134
+
135
+ #
136
+ # The workhorse of writeFieldBegin. It has the option of doing a
137
+ # 'type override' of the type header. This is used specifically in the
138
+ # boolean field case.
139
+ #
140
+ def write_field_begin_internal(type, id, type_override=nil)
141
+ last_id = @last_field.pop
142
+
143
+ # if there's a type override, use that.
144
+ typeToWrite = type_override || CompactTypes.get_compact_type(type)
145
+
146
+ # check if we can use delta encoding for the field id
147
+ if id > last_id && id - last_id <= 15
148
+ # write them together
149
+ write_byte((id - last_id) << 4 | typeToWrite)
150
+ else
151
+ # write them separate
152
+ write_byte(typeToWrite)
153
+ write_i16(id)
154
+ end
155
+
156
+ @last_field.push(id)
157
+ nil
158
+ end
159
+
160
+ def write_field_stop
161
+ write_byte(Types::STOP)
162
+ end
163
+
164
+ def write_map_begin(ktype, vtype, size)
165
+ if (size == 0)
166
+ write_byte(0)
167
+ else
168
+ write_varint32(size)
169
+ write_byte(CompactTypes.get_compact_type(ktype) << 4 | CompactTypes.get_compact_type(vtype))
170
+ end
171
+ end
172
+
173
+ def write_list_begin(etype, size)
174
+ write_collection_begin(etype, size)
175
+ end
176
+
177
+ def write_set_begin(etype, size)
178
+ write_collection_begin(etype, size);
179
+ end
180
+
181
+ def write_bool(bool)
182
+ type = bool ? CompactTypes::BOOLEAN_TRUE : CompactTypes::BOOLEAN_FALSE
183
+ unless @boolean_field.nil?
184
+ # we haven't written the field header yet
185
+ write_field_begin_internal(@boolean_field.first, @boolean_field.last, type)
186
+ @boolean_field = nil
187
+ else
188
+ # we're not part of a field, so just write the value.
189
+ write_byte(type)
190
+ end
191
+ end
192
+
193
+ def write_byte(byte)
194
+ @trans.write([byte].pack('c'))
195
+ end
196
+
197
+ def write_i16(i16)
198
+ write_varint32(int_to_zig_zag(i16))
199
+ end
200
+
201
+ def write_i32(i32)
202
+ write_varint32(int_to_zig_zag(i32))
203
+ end
204
+
205
+ def write_i64(i64)
206
+ write_varint64(long_to_zig_zag(i64))
207
+ end
208
+
209
+ def write_double(dub)
210
+ @trans.write([dub].pack("G").reverse)
211
+ end
212
+
213
+ def write_string(str)
214
+ buf = Bytes.convert_to_utf8_byte_buffer(str)
215
+ write_binary(buf)
216
+ end
217
+
218
+ def write_binary(buf)
219
+ write_varint32(buf.bytesize)
220
+ @trans.write(buf)
221
+ end
222
+
223
+ def read_message_begin
224
+ protocol_id = read_byte()
225
+ if protocol_id != PROTOCOL_ID
226
+ raise ProtocolException.new("Expected protocol id #{PROTOCOL_ID} but got #{protocol_id}")
227
+ end
228
+
229
+ version_and_type = read_byte()
230
+ version = version_and_type & VERSION_MASK
231
+ if (version != VERSION)
232
+ raise ProtocolException.new("Expected version #{VERSION} but got #{version}");
233
+ end
234
+
235
+ type = (version_and_type >> TYPE_SHIFT_AMOUNT) & TYPE_BITS
236
+ seqid = read_varint32()
237
+ messageName = read_string()
238
+ [messageName, type, seqid]
239
+ end
240
+
241
+ def read_struct_begin
242
+ @last_field.push(0)
243
+ ""
244
+ end
245
+
246
+ def read_struct_end
247
+ @last_field.pop()
248
+ nil
249
+ end
250
+
251
+ def read_field_begin
252
+ type = read_byte()
253
+
254
+ # if it's a stop, then we can return immediately, as the struct is over.
255
+ if (type & 0x0f) == Types::STOP
256
+ TSTOP
257
+ else
258
+ field_id = nil
259
+
260
+ # mask off the 4 MSB of the type header. it could contain a field id delta.
261
+ modifier = (type & 0xf0) >> 4
262
+ if modifier == 0
263
+ # not a delta. look ahead for the zigzag varint field id.
264
+ @last_field.pop
265
+ field_id = read_i16()
266
+ else
267
+ # has a delta. add the delta to the last read field id.
268
+ field_id = @last_field.pop + modifier
269
+ end
270
+
271
+ # if this happens to be a boolean field, the value is encoded in the type
272
+ if CompactTypes.is_bool_type?(type)
273
+ # save the boolean value in a special instance variable.
274
+ @bool_value = (type & 0x0f) == CompactTypes::BOOLEAN_TRUE
275
+ end
276
+
277
+ # push the new field onto the field stack so we can keep the deltas going.
278
+ @last_field.push(field_id)
279
+ ["", CompactTypes.get_ttype(type & 0x0f), field_id]
280
+ end
281
+ end
282
+
283
+ def read_map_begin
284
+ size = read_varint32()
285
+ key_and_value_type = size == 0 ? 0 : read_byte()
286
+ [CompactTypes.get_ttype(key_and_value_type >> 4), CompactTypes.get_ttype(key_and_value_type & 0xf), size]
287
+ end
288
+
289
+ def read_list_begin
290
+ size_and_type = read_byte()
291
+ size = (size_and_type >> 4) & 0x0f
292
+ if size == 15
293
+ size = read_varint32()
294
+ end
295
+ type = CompactTypes.get_ttype(size_and_type)
296
+ [type, size]
297
+ end
298
+
299
+ def read_set_begin
300
+ read_list_begin
301
+ end
302
+
303
+ def read_bool
304
+ unless @bool_value.nil?
305
+ bv = @bool_value
306
+ @bool_value = nil
307
+ bv
308
+ else
309
+ read_byte() == CompactTypes::BOOLEAN_TRUE
310
+ end
311
+ end
312
+
313
+ def read_byte
314
+ val = trans.read_byte
315
+ if (val > 0x7f)
316
+ val = 0 - ((val - 1) ^ 0xff)
317
+ end
318
+ val
319
+ end
320
+
321
+ def read_i16
322
+ zig_zag_to_int(read_varint32())
323
+ end
324
+
325
+ def read_i32
326
+ zig_zag_to_int(read_varint32())
327
+ end
328
+
329
+ def read_i64
330
+ zig_zag_to_long(read_varint64())
331
+ end
332
+
333
+ def read_double
334
+ trans.read_into_buffer(@rbuf, 8)
335
+ val = @rbuf.reverse.unpack('G').first
336
+ val
337
+ end
338
+
339
+ def read_string
340
+ buffer = read_binary
341
+ Bytes.convert_to_string(buffer)
342
+ end
343
+
344
+ def read_binary
345
+ size = read_varint32()
346
+ trans.read_all(size)
347
+ end
348
+
349
+ private
350
+
351
+ #
352
+ # Abstract method for writing the start of lists and sets. List and sets on
353
+ # the wire differ only by the type indicator.
354
+ #
355
+ def write_collection_begin(elem_type, size)
356
+ if size <= 14
357
+ write_byte(size << 4 | CompactTypes.get_compact_type(elem_type))
358
+ else
359
+ write_byte(0xf0 | CompactTypes.get_compact_type(elem_type))
360
+ write_varint32(size)
361
+ end
362
+ end
363
+
364
+ def write_varint32(n)
365
+ # int idx = 0;
366
+ while true
367
+ if (n & ~0x7F) == 0
368
+ # i32buf[idx++] = (byte)n;
369
+ write_byte(n)
370
+ break
371
+ # return;
372
+ else
373
+ # i32buf[idx++] = (byte)((n & 0x7F) | 0x80);
374
+ write_byte((n & 0x7F) | 0x80)
375
+ n = n >> 7
376
+ end
377
+ end
378
+ # trans_.write(i32buf, 0, idx);
379
+ end
380
+
381
+ SEVEN_BIT_MASK = 0x7F
382
+ EVERYTHING_ELSE_MASK = ~SEVEN_BIT_MASK
383
+
384
+ def write_varint64(n)
385
+ while true
386
+ if (n & EVERYTHING_ELSE_MASK) == 0 #TODO need to find a way to make this into a long...
387
+ write_byte(n)
388
+ break
389
+ else
390
+ write_byte((n & SEVEN_BIT_MASK) | 0x80)
391
+ n >>= 7
392
+ end
393
+ end
394
+ end
395
+
396
+ def read_varint32()
397
+ read_varint64()
398
+ end
399
+
400
+ def read_varint64()
401
+ shift = 0
402
+ result = 0
403
+ while true
404
+ b = read_byte()
405
+ result |= (b & 0x7f) << shift
406
+ break if (b & 0x80) != 0x80
407
+ shift += 7
408
+ end
409
+ result
410
+ end
411
+
412
+ def int_to_zig_zag(n)
413
+ (n << 1) ^ (n >> 31)
414
+ end
415
+
416
+ def long_to_zig_zag(l)
417
+ # puts "zz encoded #{l} to #{(l << 1) ^ (l >> 63)}"
418
+ (l << 1) ^ (l >> 63)
419
+ end
420
+
421
+ def zig_zag_to_int(n)
422
+ (n >> 1) ^ -(n & 1)
423
+ end
424
+
425
+ def zig_zag_to_long(n)
426
+ (n >> 1) ^ -(n & 1)
427
+ end
428
+ end
429
+
430
+ class CompactProtocolFactory < BaseProtocolFactory
431
+ def get_protocol(trans)
432
+ CompactProtocol.new(trans)
433
+ end
434
+ end
435
+ end