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.
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