upfluence-thrift 1.0.1
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 +7 -0
- data/README.md +43 -0
- data/benchmark/Benchmark.thrift +24 -0
- data/benchmark/benchmark.rb +271 -0
- data/benchmark/client.rb +74 -0
- data/benchmark/gen-rb/benchmark_constants.rb +11 -0
- data/benchmark/gen-rb/benchmark_service.rb +80 -0
- data/benchmark/gen-rb/benchmark_types.rb +10 -0
- data/benchmark/server.rb +82 -0
- data/benchmark/thin_server.rb +44 -0
- data/ext/binary_protocol_accelerated.c +460 -0
- data/ext/binary_protocol_accelerated.h +20 -0
- data/ext/bytes.c +36 -0
- data/ext/bytes.h +31 -0
- data/ext/compact_protocol.c +637 -0
- data/ext/compact_protocol.h +20 -0
- data/ext/constants.h +99 -0
- data/ext/extconf.rb +34 -0
- data/ext/macros.h +41 -0
- data/ext/memory_buffer.c +134 -0
- data/ext/memory_buffer.h +20 -0
- data/ext/protocol.c +0 -0
- data/ext/protocol.h +0 -0
- data/ext/strlcpy.c +41 -0
- data/ext/strlcpy.h +34 -0
- data/ext/struct.c +707 -0
- data/ext/struct.h +25 -0
- data/ext/thrift_native.c +201 -0
- data/lib/thrift.rb +68 -0
- data/lib/thrift/bytes.rb +131 -0
- data/lib/thrift/client.rb +71 -0
- data/lib/thrift/core_ext.rb +23 -0
- data/lib/thrift/core_ext/fixnum.rb +29 -0
- data/lib/thrift/exceptions.rb +87 -0
- data/lib/thrift/multiplexed_processor.rb +76 -0
- data/lib/thrift/processor.rb +57 -0
- data/lib/thrift/protocol/base_protocol.rb +379 -0
- data/lib/thrift/protocol/binary_protocol.rb +237 -0
- data/lib/thrift/protocol/binary_protocol_accelerated.rb +39 -0
- data/lib/thrift/protocol/compact_protocol.rb +435 -0
- data/lib/thrift/protocol/json_protocol.rb +769 -0
- data/lib/thrift/protocol/multiplexed_protocol.rb +40 -0
- data/lib/thrift/protocol/protocol_decorator.rb +194 -0
- data/lib/thrift/serializer/deserializer.rb +33 -0
- data/lib/thrift/serializer/serializer.rb +34 -0
- data/lib/thrift/server/base_server.rb +31 -0
- data/lib/thrift/server/mongrel_http_server.rb +60 -0
- data/lib/thrift/server/nonblocking_server.rb +305 -0
- data/lib/thrift/server/rack_application.rb +61 -0
- data/lib/thrift/server/simple_server.rb +43 -0
- data/lib/thrift/server/thin_http_server.rb +51 -0
- data/lib/thrift/server/thread_pool_server.rb +75 -0
- data/lib/thrift/server/threaded_server.rb +47 -0
- data/lib/thrift/struct.rb +237 -0
- data/lib/thrift/struct_union.rb +192 -0
- data/lib/thrift/thrift_native.rb +24 -0
- data/lib/thrift/transport/base_server_transport.rb +37 -0
- data/lib/thrift/transport/base_transport.rb +109 -0
- data/lib/thrift/transport/buffered_transport.rb +114 -0
- data/lib/thrift/transport/framed_transport.rb +117 -0
- data/lib/thrift/transport/http_client_transport.rb +56 -0
- data/lib/thrift/transport/io_stream_transport.rb +39 -0
- data/lib/thrift/transport/memory_buffer_transport.rb +125 -0
- data/lib/thrift/transport/server_socket.rb +63 -0
- data/lib/thrift/transport/socket.rb +139 -0
- data/lib/thrift/transport/unix_server_socket.rb +60 -0
- data/lib/thrift/transport/unix_socket.rb +40 -0
- data/lib/thrift/types.rb +101 -0
- data/lib/thrift/union.rb +179 -0
- data/spec/BaseService.thrift +27 -0
- data/spec/ExtendedService.thrift +25 -0
- data/spec/Referenced.thrift +44 -0
- data/spec/ThriftNamespacedSpec.thrift +53 -0
- data/spec/ThriftSpec.thrift +183 -0
- data/spec/base_protocol_spec.rb +217 -0
- data/spec/base_transport_spec.rb +350 -0
- data/spec/binary_protocol_accelerated_spec.rb +42 -0
- data/spec/binary_protocol_spec.rb +66 -0
- data/spec/binary_protocol_spec_shared.rb +455 -0
- data/spec/bytes_spec.rb +160 -0
- data/spec/client_spec.rb +99 -0
- data/spec/compact_protocol_spec.rb +143 -0
- data/spec/exception_spec.rb +141 -0
- data/spec/flat_spec.rb +62 -0
- data/spec/gen-rb/base/base_service.rb +80 -0
- data/spec/gen-rb/base/base_service_constants.rb +11 -0
- data/spec/gen-rb/base/base_service_types.rb +26 -0
- data/spec/gen-rb/extended/extended_service.rb +78 -0
- data/spec/gen-rb/extended/extended_service_constants.rb +11 -0
- data/spec/gen-rb/extended/extended_service_types.rb +12 -0
- data/spec/gen-rb/flat/namespaced_nonblocking_service.rb +272 -0
- data/spec/gen-rb/flat/referenced_constants.rb +11 -0
- data/spec/gen-rb/flat/referenced_types.rb +17 -0
- data/spec/gen-rb/flat/thrift_namespaced_spec_constants.rb +11 -0
- data/spec/gen-rb/flat/thrift_namespaced_spec_types.rb +28 -0
- data/spec/gen-rb/namespaced_spec_namespace/namespaced_nonblocking_service.rb +272 -0
- data/spec/gen-rb/namespaced_spec_namespace/thrift_namespaced_spec_constants.rb +11 -0
- data/spec/gen-rb/namespaced_spec_namespace/thrift_namespaced_spec_types.rb +28 -0
- data/spec/gen-rb/nonblocking_service.rb +272 -0
- data/spec/gen-rb/other_namespace/referenced_constants.rb +11 -0
- data/spec/gen-rb/other_namespace/referenced_types.rb +17 -0
- data/spec/gen-rb/thrift_spec_constants.rb +11 -0
- data/spec/gen-rb/thrift_spec_types.rb +538 -0
- data/spec/http_client_spec.rb +120 -0
- data/spec/json_protocol_spec.rb +513 -0
- data/spec/namespaced_spec.rb +67 -0
- data/spec/nonblocking_server_spec.rb +263 -0
- data/spec/processor_spec.rb +80 -0
- data/spec/serializer_spec.rb +67 -0
- data/spec/server_socket_spec.rb +79 -0
- data/spec/server_spec.rb +147 -0
- data/spec/socket_spec.rb +61 -0
- data/spec/socket_spec_shared.rb +104 -0
- data/spec/spec_helper.rb +64 -0
- data/spec/struct_nested_containers_spec.rb +191 -0
- data/spec/struct_spec.rb +293 -0
- data/spec/thin_http_server_spec.rb +141 -0
- data/spec/types_spec.rb +115 -0
- data/spec/union_spec.rb +203 -0
- data/spec/unix_socket_spec.rb +107 -0
- data/test/debug_proto/gen-rb/debug_proto_test_constants.rb +274 -0
- data/test/debug_proto/gen-rb/debug_proto_test_types.rb +761 -0
- data/test/debug_proto/gen-rb/empty_service.rb +24 -0
- data/test/debug_proto/gen-rb/inherited.rb +79 -0
- data/test/debug_proto/gen-rb/reverse_order_service.rb +82 -0
- data/test/debug_proto/gen-rb/service_for_exception_with_a_map.rb +81 -0
- data/test/debug_proto/gen-rb/srv.rb +330 -0
- 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
|