thrift 0.23.0 → 0.25.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 +203 -40
- data/ext/binary_protocol_accelerated.c +130 -40
- data/ext/bytes.c +14 -0
- data/ext/compact_protocol.c +184 -91
- data/ext/constants.h +3 -0
- data/ext/extconf.rb +12 -4
- data/ext/macros.h +11 -0
- data/ext/memory_buffer.c +67 -12
- data/ext/struct.c +192 -71
- data/ext/thrift_native.c +7 -0
- data/lib/thrift/bytes.rb +6 -3
- data/lib/thrift/client.rb +31 -33
- data/lib/thrift/exceptions.rb +11 -8
- data/lib/thrift/multiplexed_processor.rb +17 -8
- data/lib/thrift/processor.rb +25 -3
- data/lib/thrift/protocol/base_protocol.rb +66 -31
- data/lib/thrift/protocol/binary_protocol.rb +80 -37
- data/lib/thrift/protocol/binary_protocol_accelerated.rb +7 -2
- data/lib/thrift/protocol/compact_protocol.rb +204 -88
- data/lib/thrift/protocol/header_protocol.rb +15 -3
- data/lib/thrift/protocol/json_protocol.rb +158 -109
- data/lib/thrift/protocol/multiplexed_protocol.rb +3 -3
- data/lib/thrift/protocol/protocol_decorator.rb +6 -2
- data/lib/thrift/serializer/deserializer.rb +1 -0
- data/lib/thrift/serializer/serializer.rb +7 -0
- data/lib/thrift/server/base_server.rb +11 -2
- data/lib/thrift/server/nonblocking_server.rb +69 -20
- data/lib/thrift/server/rack_application.rb +69 -0
- data/lib/thrift/server/simple_server.rb +27 -15
- data/lib/thrift/server/thin_http_server.rb +21 -44
- data/lib/thrift/server/thread_pool_server.rb +21 -17
- data/lib/thrift/server/threaded_server.rb +22 -18
- data/lib/thrift/struct.rb +34 -18
- data/lib/thrift/struct_union.rb +37 -36
- data/lib/thrift/thrift_native.rb +2 -1
- data/lib/thrift/transport/base_server_transport.rb +3 -0
- data/lib/thrift/transport/base_transport.rb +26 -4
- data/lib/thrift/transport/buffered_transport.rb +5 -4
- data/lib/thrift/transport/framed_transport.rb +33 -7
- data/lib/thrift/transport/header_transport.rb +159 -33
- data/lib/thrift/transport/http_client_transport.rb +28 -14
- data/lib/thrift/transport/io_stream_transport.rb +3 -1
- data/lib/thrift/transport/memory_buffer_transport.rb +14 -9
- data/lib/thrift/transport/server_socket.rb +10 -8
- data/lib/thrift/transport/socket.rb +85 -48
- data/lib/thrift/transport/ssl_server_socket.rb +67 -6
- data/lib/thrift/transport/ssl_socket.rb +73 -14
- data/lib/thrift/transport/unix_server_socket.rb +6 -2
- data/lib/thrift/transport/unix_socket.rb +5 -6
- data/lib/thrift/types.rb +23 -22
- data/lib/thrift/union.rb +21 -11
- data/lib/thrift/uuid.rb +9 -8
- data/lib/thrift.rb +40 -39
- metadata +7 -266
- data/benchmark/Benchmark.thrift +0 -24
- data/benchmark/benchmark.rb +0 -285
- data/benchmark/client.rb +0 -117
- data/benchmark/server.rb +0 -120
- data/benchmark/thin_server.rb +0 -45
- data/lib/thrift/server/mongrel_http_server.rb +0 -60
- data/spec/BaseService.thrift +0 -27
- data/spec/ExtendedService.thrift +0 -25
- data/spec/Referenced.thrift +0 -44
- data/spec/ThriftNamespacedSpec.thrift +0 -53
- data/spec/ThriftSpec.thrift +0 -187
- data/spec/base_protocol_spec.rb +0 -224
- data/spec/base_transport_spec.rb +0 -387
- data/spec/binary_protocol_accelerated_spec.rb +0 -46
- data/spec/binary_protocol_spec.rb +0 -72
- data/spec/binary_protocol_spec_shared.rb +0 -445
- data/spec/bytes_spec.rb +0 -99
- data/spec/client_spec.rb +0 -166
- data/spec/compact_protocol_spec.rb +0 -196
- data/spec/constants_demo_spec.rb +0 -101
- data/spec/exception_spec.rb +0 -140
- data/spec/flat_spec.rb +0 -62
- data/spec/header_protocol_spec.rb +0 -475
- data/spec/header_transport_spec.rb +0 -386
- data/spec/http_client_spec.rb +0 -159
- data/spec/json_protocol_spec.rb +0 -552
- data/spec/namespaced_spec.rb +0 -66
- data/spec/nonblocking_server_spec.rb +0 -361
- data/spec/processor_spec.rb +0 -79
- data/spec/serializer_spec.rb +0 -66
- data/spec/server_socket_spec.rb +0 -84
- data/spec/server_spec.rb +0 -186
- data/spec/socket_spec.rb +0 -67
- data/spec/socket_spec_shared.rb +0 -167
- data/spec/spec_helper.rb +0 -69
- data/spec/ssl_server_socket_spec.rb +0 -45
- data/spec/ssl_socket_spec.rb +0 -87
- data/spec/struct_nested_containers_spec.rb +0 -190
- data/spec/struct_spec.rb +0 -397
- data/spec/support/header_protocol_helper.rb +0 -54
- data/spec/thin_http_server_spec.rb +0 -126
- data/spec/types_spec.rb +0 -117
- data/spec/union_spec.rb +0 -272
- data/spec/unix_socket_spec.rb +0 -115
- data/spec/uuid_validation_spec.rb +0 -238
- data/test/fuzz/Makefile.am +0 -173
- data/test/fuzz/README.md +0 -149
- data/test/fuzz/fuzz_common.rb +0 -95
- data/test/fuzz/fuzz_parse_binary_protocol.rb +0 -22
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated.rb +0 -22
- data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +0 -22
- data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_parse_compact_protocol.rb +0 -22
- data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_parse_json_protocol.rb +0 -22
- data/test/fuzz/fuzz_parse_json_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_json_protocol.rb +0 -22
- data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +0 -22
- data/test/fuzz/fuzz_tracer.rb +0 -28
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
|
+
# frozen_string_literal: true
|
|
2
3
|
#
|
|
3
4
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
4
5
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -33,7 +34,7 @@ module Thrift
|
|
|
33
34
|
@data = @trans.read(1)
|
|
34
35
|
end
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
@data
|
|
37
38
|
end
|
|
38
39
|
|
|
39
40
|
def peek
|
|
@@ -41,7 +42,7 @@ module Thrift
|
|
|
41
42
|
@data = @trans.read(1)
|
|
42
43
|
end
|
|
43
44
|
@hasData = true
|
|
44
|
-
|
|
45
|
+
@data
|
|
45
46
|
end
|
|
46
47
|
end
|
|
47
48
|
|
|
@@ -50,7 +51,7 @@ module Thrift
|
|
|
50
51
|
# implementations
|
|
51
52
|
#
|
|
52
53
|
class JSONContext
|
|
53
|
-
@@kJSONElemSeparator =
|
|
54
|
+
@@kJSONElemSeparator = ","
|
|
54
55
|
#
|
|
55
56
|
# Write context data to the trans. Default is to do nothing.
|
|
56
57
|
#
|
|
@@ -68,13 +69,13 @@ module Thrift
|
|
|
68
69
|
# Default behavior is to return false.
|
|
69
70
|
#
|
|
70
71
|
def escapeNum
|
|
71
|
-
|
|
72
|
+
false
|
|
72
73
|
end
|
|
73
74
|
end
|
|
74
75
|
|
|
75
76
|
# Context class for object member key-value pairs
|
|
76
77
|
class JSONPairContext < JSONContext
|
|
77
|
-
@@kJSONPairSeparator =
|
|
78
|
+
@@kJSONPairSeparator = ":"
|
|
78
79
|
|
|
79
80
|
def initialize
|
|
80
81
|
@first = true
|
|
@@ -82,7 +83,7 @@ module Thrift
|
|
|
82
83
|
end
|
|
83
84
|
|
|
84
85
|
def write(trans)
|
|
85
|
-
if
|
|
86
|
+
if @first
|
|
86
87
|
@first = false
|
|
87
88
|
@colon = true
|
|
88
89
|
else
|
|
@@ -92,7 +93,7 @@ module Thrift
|
|
|
92
93
|
end
|
|
93
94
|
|
|
94
95
|
def read(reader)
|
|
95
|
-
if
|
|
96
|
+
if @first
|
|
96
97
|
@first = false
|
|
97
98
|
@colon = true
|
|
98
99
|
else
|
|
@@ -104,19 +105,18 @@ module Thrift
|
|
|
104
105
|
|
|
105
106
|
# Numbers must be turned into strings if they are the key part of a pair
|
|
106
107
|
def escapeNum
|
|
107
|
-
|
|
108
|
+
@colon
|
|
108
109
|
end
|
|
109
110
|
end
|
|
110
111
|
|
|
111
112
|
# Context class for lists
|
|
112
113
|
class JSONListContext < JSONContext
|
|
113
|
-
|
|
114
114
|
def initialize
|
|
115
115
|
@first = true
|
|
116
116
|
end
|
|
117
117
|
|
|
118
118
|
def write(trans)
|
|
119
|
-
if
|
|
119
|
+
if @first
|
|
120
120
|
@first = false
|
|
121
121
|
else
|
|
122
122
|
trans.write(@@kJSONElemSeparator)
|
|
@@ -124,7 +124,7 @@ module Thrift
|
|
|
124
124
|
end
|
|
125
125
|
|
|
126
126
|
def read(reader)
|
|
127
|
-
if
|
|
127
|
+
if @first
|
|
128
128
|
@first = false
|
|
129
129
|
else
|
|
130
130
|
JsonProtocol::read_syntax_char(reader, @@kJSONElemSeparator)
|
|
@@ -133,13 +133,14 @@ module Thrift
|
|
|
133
133
|
end
|
|
134
134
|
|
|
135
135
|
class JsonProtocol < BaseProtocol
|
|
136
|
+
attr_reader :max_string_size
|
|
136
137
|
|
|
137
|
-
@@kJSONObjectStart =
|
|
138
|
-
@@kJSONObjectEnd =
|
|
139
|
-
@@kJSONArrayStart =
|
|
140
|
-
@@kJSONArrayEnd =
|
|
138
|
+
@@kJSONObjectStart = "{"
|
|
139
|
+
@@kJSONObjectEnd = "}"
|
|
140
|
+
@@kJSONArrayStart = "["
|
|
141
|
+
@@kJSONArrayEnd = "]"
|
|
141
142
|
@@kJSONNewline = '\n'
|
|
142
|
-
@@kJSONBackslash =
|
|
143
|
+
@@kJSONBackslash = "\\"
|
|
143
144
|
@@kJSONStringDelimiter = '"'
|
|
144
145
|
|
|
145
146
|
@@kThriftVersion1 = 1
|
|
@@ -148,8 +149,10 @@ module Thrift
|
|
|
148
149
|
@@kThriftInfinity = "Infinity"
|
|
149
150
|
@@kThriftNegativeInfinity = "-Infinity"
|
|
150
151
|
|
|
151
|
-
def initialize(trans)
|
|
152
|
+
def initialize(trans, max_string_size: DEFAULT_MAX_STRING_SIZE)
|
|
153
|
+
BaseProtocol.validate_max_string_size(max_string_size)
|
|
152
154
|
super(trans)
|
|
155
|
+
@max_string_size = max_string_size
|
|
153
156
|
@context = JSONContext.new
|
|
154
157
|
@contexts = Array.new
|
|
155
158
|
@reader = LookaheadReader.new(trans)
|
|
@@ -182,42 +185,27 @@ module Thrift
|
|
|
182
185
|
when Types::UUID
|
|
183
186
|
"uid"
|
|
184
187
|
else
|
|
185
|
-
raise
|
|
188
|
+
raise ProtocolException.new(ProtocolException::INVALID_DATA, "Unknown type id: #{id}")
|
|
186
189
|
end
|
|
187
190
|
end
|
|
188
191
|
|
|
189
192
|
def get_type_id_for_type_name(name)
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
result = Types::STRING
|
|
204
|
-
elsif (name == "rec")
|
|
205
|
-
result = Types::STRUCT
|
|
206
|
-
elsif (name == "map")
|
|
207
|
-
result = Types::MAP
|
|
208
|
-
elsif (name == "set")
|
|
209
|
-
result = Types::SET
|
|
210
|
-
elsif (name == "lst")
|
|
211
|
-
result = Types::LIST
|
|
212
|
-
elsif (name == "uid")
|
|
213
|
-
result = Types::UUID
|
|
193
|
+
case name
|
|
194
|
+
when "tf" then Types::BOOL
|
|
195
|
+
when "i8" then Types::BYTE
|
|
196
|
+
when "i16" then Types::I16
|
|
197
|
+
when "i32" then Types::I32
|
|
198
|
+
when "i64" then Types::I64
|
|
199
|
+
when "dbl" then Types::DOUBLE
|
|
200
|
+
when "str" then Types::STRING
|
|
201
|
+
when "rec" then Types::STRUCT
|
|
202
|
+
when "map" then Types::MAP
|
|
203
|
+
when "set" then Types::SET
|
|
204
|
+
when "lst" then Types::LIST
|
|
205
|
+
when "uid" then Types::UUID
|
|
214
206
|
else
|
|
215
|
-
|
|
207
|
+
raise ProtocolException.new(ProtocolException::INVALID_DATA, "Unknown type name: #{name.inspect}")
|
|
216
208
|
end
|
|
217
|
-
if (result == Types::STOP)
|
|
218
|
-
raise NotImplementedError
|
|
219
|
-
end
|
|
220
|
-
return result
|
|
221
209
|
end
|
|
222
210
|
|
|
223
211
|
# Static helper functions
|
|
@@ -227,17 +215,17 @@ module Thrift
|
|
|
227
215
|
def self.read_syntax_char(reader, ch)
|
|
228
216
|
ch2 = reader.read
|
|
229
217
|
if (ch2 != ch)
|
|
230
|
-
raise ProtocolException.new(ProtocolException::INVALID_DATA, "Expected
|
|
218
|
+
raise ProtocolException.new(ProtocolException::INVALID_DATA, "Expected '#{ch}' got '#{ch2}'.")
|
|
231
219
|
end
|
|
232
220
|
end
|
|
233
221
|
|
|
234
|
-
|
|
222
|
+
# Return true if the character ch is in [-+0-9.Ee]; false otherwise
|
|
235
223
|
def is_json_numeric(ch)
|
|
236
224
|
case ch
|
|
237
|
-
when
|
|
238
|
-
|
|
225
|
+
when "+", "-", ".", "0".."9", "E", "e"
|
|
226
|
+
true
|
|
239
227
|
else
|
|
240
|
-
|
|
228
|
+
false
|
|
241
229
|
end
|
|
242
230
|
end
|
|
243
231
|
|
|
@@ -257,7 +245,7 @@ module Thrift
|
|
|
257
245
|
if (ch_value.kind_of? String)
|
|
258
246
|
ch_value = ch.bytes.first
|
|
259
247
|
end
|
|
260
|
-
trans.write(ch_value.to_s(16).rjust(4,
|
|
248
|
+
trans.write(ch_value.to_s(16).rjust(4, "0"))
|
|
261
249
|
end
|
|
262
250
|
|
|
263
251
|
# Write the character ch as part of a JSON string, escaping as appropriate.
|
|
@@ -267,10 +255,10 @@ module Thrift
|
|
|
267
255
|
# 1 : just output index
|
|
268
256
|
# <other> : escape using "\<other>" notation
|
|
269
257
|
kJSONCharTable = [
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
258
|
+
# 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
259
|
+
0, 0, 0, 0, 0, 0, 0, 0, "b", "t", "n", 0, "f", "r", 0, 0, # 0
|
|
260
|
+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, # 1
|
|
261
|
+
1, 1, '"', 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, # 2
|
|
274
262
|
]
|
|
275
263
|
|
|
276
264
|
ch_value = ch[0]
|
|
@@ -300,9 +288,10 @@ module Thrift
|
|
|
300
288
|
|
|
301
289
|
# Write out the contents of the string str as a JSON string, escaping characters as appropriate.
|
|
302
290
|
def write_json_string(str)
|
|
291
|
+
str = normalize_json_string(str)
|
|
303
292
|
@context.write(trans)
|
|
304
293
|
trans.write(@@kJSONStringDelimiter)
|
|
305
|
-
str.
|
|
294
|
+
str.each_char do |ch|
|
|
306
295
|
write_json_char(ch)
|
|
307
296
|
end
|
|
308
297
|
trans.write(@@kJSONStringDelimiter)
|
|
@@ -313,7 +302,7 @@ module Thrift
|
|
|
313
302
|
def write_json_base64(str)
|
|
314
303
|
@context.write(trans)
|
|
315
304
|
trans.write(@@kJSONStringDelimiter)
|
|
316
|
-
trans.write([str].pack(
|
|
305
|
+
trans.write([str].pack("m0"))
|
|
317
306
|
trans.write(@@kJSONStringDelimiter)
|
|
318
307
|
end
|
|
319
308
|
|
|
@@ -322,11 +311,11 @@ module Thrift
|
|
|
322
311
|
def write_json_integer(num)
|
|
323
312
|
@context.write(trans)
|
|
324
313
|
escapeNum = @context.escapeNum
|
|
325
|
-
if
|
|
314
|
+
if escapeNum
|
|
326
315
|
trans.write(@@kJSONStringDelimiter)
|
|
327
316
|
end
|
|
328
317
|
trans.write(num.to_s);
|
|
329
|
-
if
|
|
318
|
+
if escapeNum
|
|
330
319
|
trans.write(@@kJSONStringDelimiter)
|
|
331
320
|
end
|
|
332
321
|
end
|
|
@@ -337,10 +326,10 @@ module Thrift
|
|
|
337
326
|
@context.write(trans)
|
|
338
327
|
# Normalize output of thrift::to_string for NaNs and Infinities
|
|
339
328
|
special = false;
|
|
340
|
-
if
|
|
329
|
+
if num.nan?
|
|
341
330
|
special = true;
|
|
342
331
|
val = @@kThriftNan;
|
|
343
|
-
elsif
|
|
332
|
+
elsif num.infinite?
|
|
344
333
|
special = true;
|
|
345
334
|
val = @@kThriftInfinity;
|
|
346
335
|
if (num < 0.0)
|
|
@@ -351,11 +340,11 @@ module Thrift
|
|
|
351
340
|
end
|
|
352
341
|
|
|
353
342
|
escapeNum = special || @context.escapeNum
|
|
354
|
-
if
|
|
343
|
+
if escapeNum
|
|
355
344
|
trans.write(@@kJSONStringDelimiter)
|
|
356
345
|
end
|
|
357
346
|
trans.write(val)
|
|
358
|
-
if
|
|
347
|
+
if escapeNum
|
|
359
348
|
trans.write(@@kJSONStringDelimiter)
|
|
360
349
|
end
|
|
361
350
|
end
|
|
@@ -493,59 +482,65 @@ module Thrift
|
|
|
493
482
|
JsonProtocol::read_syntax_char(@reader, ch)
|
|
494
483
|
end
|
|
495
484
|
|
|
496
|
-
# Decodes the four hex parts of a JSON escaped string character and returns
|
|
497
|
-
# the character via out.
|
|
498
|
-
#
|
|
499
|
-
# Note - this only supports Unicode characters in the BMP (U+0000 to U+FFFF);
|
|
500
|
-
# characters above the BMP are encoded as two escape sequences (surrogate pairs),
|
|
501
|
-
# which is not yet implemented
|
|
502
485
|
def read_json_escape_char
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
486
|
+
code_unit = read_unicode_code_unit
|
|
487
|
+
|
|
488
|
+
if code_unit.between?(0xD800, 0xDBFF)
|
|
489
|
+
slash = @reader.read
|
|
490
|
+
marker = @reader.read
|
|
491
|
+
invalid_unicode!("Unpaired UTF-16 high surrogate") unless slash == "\\" && marker == "u"
|
|
492
|
+
|
|
493
|
+
low_surrogate = read_unicode_code_unit
|
|
494
|
+
invalid_unicode!("Unpaired UTF-16 high surrogate") unless low_surrogate.between?(0xDC00, 0xDFFF)
|
|
495
|
+
codepoint = 0x10000 + ((code_unit - 0xD800) << 10) + (low_surrogate - 0xDC00)
|
|
496
|
+
[codepoint].pack("U")
|
|
497
|
+
elsif code_unit.between?(0xDC00, 0xDFFF)
|
|
498
|
+
invalid_unicode!("Unpaired UTF-16 low surrogate")
|
|
499
|
+
else
|
|
500
|
+
[code_unit].pack("U")
|
|
501
|
+
end
|
|
502
|
+
rescue EOFError
|
|
503
|
+
invalid_unicode!("Incomplete Unicode escape")
|
|
508
504
|
end
|
|
509
505
|
|
|
510
506
|
# Decodes a JSON string, including unescaping, and returns the string via str
|
|
511
507
|
def read_json_string(skipContext = false)
|
|
512
508
|
# This string's characters must match up with the elements in escape_char_vals.
|
|
513
|
-
#
|
|
514
|
-
# it is not in the RFC -> it is. See RFC 4627
|
|
509
|
+
# JSON permits the optional solidus escape "\/"; see RFC 8259, section 7.
|
|
515
510
|
escape_chars = "\"\\/bfnrt"
|
|
516
511
|
|
|
517
512
|
# The elements of this array must match up with the sequence of characters in
|
|
518
513
|
# escape_chars
|
|
519
514
|
escape_char_vals = [
|
|
520
|
-
"\"", "\\", "
|
|
515
|
+
"\"", "\\", "/", "\b", "\f", "\n", "\r", "\t",
|
|
521
516
|
]
|
|
522
517
|
|
|
523
518
|
if !skipContext
|
|
524
519
|
@context.read(@reader)
|
|
525
520
|
end
|
|
526
521
|
read_json_syntax_char(@@kJSONStringDelimiter)
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
while (true)
|
|
522
|
+
str = Bytes.empty_byte_buffer
|
|
523
|
+
while true
|
|
530
524
|
ch = @reader.read
|
|
531
525
|
if (ch == @@kJSONStringDelimiter)
|
|
532
526
|
break
|
|
533
527
|
end
|
|
534
528
|
if (ch == @@kJSONBackslash)
|
|
535
529
|
ch = @reader.read
|
|
536
|
-
if (ch ==
|
|
530
|
+
if (ch == "u")
|
|
537
531
|
ch = read_json_escape_char
|
|
538
532
|
else
|
|
539
533
|
pos = escape_chars.index(ch);
|
|
540
|
-
if
|
|
541
|
-
raise ProtocolException.new(ProtocolException::INVALID_DATA, "Expected control char, got
|
|
534
|
+
if pos.nil? # not found
|
|
535
|
+
raise ProtocolException.new(ProtocolException::INVALID_DATA, "Expected control char, got '#{ch}'.")
|
|
542
536
|
end
|
|
543
537
|
ch = escape_char_vals[pos]
|
|
544
538
|
end
|
|
545
539
|
end
|
|
546
|
-
str
|
|
540
|
+
str << Bytes.force_binary_encoding(ch)
|
|
541
|
+
check_string_size(str.bytesize)
|
|
547
542
|
end
|
|
548
|
-
|
|
543
|
+
decode_json_string(str)
|
|
549
544
|
end
|
|
550
545
|
|
|
551
546
|
# Reads a block of base64 characters, decoding it, and returns via str
|
|
@@ -555,32 +550,37 @@ module Thrift
|
|
|
555
550
|
if m != 0
|
|
556
551
|
# Add missing padding
|
|
557
552
|
(4 - m).times do
|
|
558
|
-
str +=
|
|
553
|
+
str += "="
|
|
559
554
|
end
|
|
560
555
|
end
|
|
561
|
-
|
|
556
|
+
begin
|
|
557
|
+
str.unpack1("m0")
|
|
558
|
+
rescue ArgumentError
|
|
559
|
+
raise ProtocolException.new(ProtocolException::INVALID_DATA, "Invalid Base64 data")
|
|
560
|
+
end
|
|
562
561
|
end
|
|
563
562
|
|
|
564
563
|
# Reads a sequence of characters, stopping at the first one that is not
|
|
565
564
|
# a valid JSON numeric character.
|
|
566
565
|
def read_json_numeric_chars
|
|
567
|
-
str =
|
|
568
|
-
while
|
|
566
|
+
str = String.new(encoding: Encoding::UTF_8)
|
|
567
|
+
while true
|
|
569
568
|
ch = @reader.peek
|
|
570
|
-
if
|
|
569
|
+
if !is_json_numeric(ch)
|
|
571
570
|
break;
|
|
572
571
|
end
|
|
573
572
|
ch = @reader.read
|
|
574
|
-
str
|
|
573
|
+
str << ch
|
|
574
|
+
check_string_size(str.bytesize)
|
|
575
575
|
end
|
|
576
|
-
|
|
576
|
+
str
|
|
577
577
|
end
|
|
578
578
|
|
|
579
579
|
# Reads a sequence of characters and assembles them into a number,
|
|
580
580
|
# returning them via num
|
|
581
581
|
def read_json_integer
|
|
582
582
|
@context.read(@reader)
|
|
583
|
-
if
|
|
583
|
+
if @context.escapeNum
|
|
584
584
|
read_json_syntax_char(@@kJSONStringDelimiter)
|
|
585
585
|
end
|
|
586
586
|
str = read_json_numeric_chars
|
|
@@ -591,11 +591,11 @@ module Thrift
|
|
|
591
591
|
raise ProtocolException.new(ProtocolException::INVALID_DATA, "Expected numeric value; got \"#{str}\"")
|
|
592
592
|
end
|
|
593
593
|
|
|
594
|
-
if
|
|
594
|
+
if @context.escapeNum
|
|
595
595
|
read_json_syntax_char(@@kJSONStringDelimiter)
|
|
596
596
|
end
|
|
597
597
|
|
|
598
|
-
|
|
598
|
+
num
|
|
599
599
|
end
|
|
600
600
|
|
|
601
601
|
# Reads a JSON number or string and interprets it as a double.
|
|
@@ -606,13 +606,13 @@ module Thrift
|
|
|
606
606
|
str = read_json_string(true)
|
|
607
607
|
# Check for NaN, Infinity and -Infinity
|
|
608
608
|
if (str == @@kThriftNan)
|
|
609
|
-
num = (+1.0/0.0)/(+1.0/0.0)
|
|
609
|
+
num = (+1.0 / 0.0) / (+1.0 / 0.0)
|
|
610
610
|
elsif (str == @@kThriftInfinity)
|
|
611
|
-
num = +1.0/0.0
|
|
611
|
+
num = +1.0 / 0.0
|
|
612
612
|
elsif (str == @@kThriftNegativeInfinity)
|
|
613
|
-
num = -1.0/0.0
|
|
613
|
+
num = -1.0 / 0.0
|
|
614
614
|
else
|
|
615
|
-
if
|
|
615
|
+
if !@context.escapeNum
|
|
616
616
|
# Raise exception -- we should not be in a string in this case
|
|
617
617
|
raise ProtocolException.new(ProtocolException::INVALID_DATA, "Numeric data unexpectedly quoted")
|
|
618
618
|
end
|
|
@@ -623,7 +623,7 @@ module Thrift
|
|
|
623
623
|
end
|
|
624
624
|
end
|
|
625
625
|
else
|
|
626
|
-
if
|
|
626
|
+
if @context.escapeNum
|
|
627
627
|
# This will throw - we should have had a quote if escapeNum == true
|
|
628
628
|
read_json_syntax_char(@@kJSONStringDelimiter)
|
|
629
629
|
end
|
|
@@ -634,7 +634,7 @@ module Thrift
|
|
|
634
634
|
raise ProtocolException.new(ProtocolException::INVALID_DATA, "Expected numeric value; got \"#{str}\"")
|
|
635
635
|
end
|
|
636
636
|
end
|
|
637
|
-
|
|
637
|
+
num
|
|
638
638
|
end
|
|
639
639
|
|
|
640
640
|
def read_json_object_start
|
|
@@ -667,7 +667,7 @@ module Thrift
|
|
|
667
667
|
read_json_array_start
|
|
668
668
|
version = read_json_integer
|
|
669
669
|
if (version != @@kThriftVersion1)
|
|
670
|
-
raise ProtocolException.new(ProtocolException::BAD_VERSION,
|
|
670
|
+
raise ProtocolException.new(ProtocolException::BAD_VERSION, "Message contained bad version.")
|
|
671
671
|
end
|
|
672
672
|
name = read_json_string
|
|
673
673
|
message_type = read_json_integer
|
|
@@ -712,6 +712,7 @@ module Thrift
|
|
|
712
712
|
key_type = get_type_id_for_type_name(read_json_string)
|
|
713
713
|
val_type = get_type_id_for_type_name(read_json_string)
|
|
714
714
|
size = read_json_integer
|
|
715
|
+
validate_container_size(size)
|
|
715
716
|
read_json_object_start
|
|
716
717
|
[key_type, val_type, size]
|
|
717
718
|
end
|
|
@@ -723,7 +724,10 @@ module Thrift
|
|
|
723
724
|
|
|
724
725
|
def read_list_begin
|
|
725
726
|
read_json_array_start
|
|
726
|
-
|
|
727
|
+
type = get_type_id_for_type_name(read_json_string)
|
|
728
|
+
size = read_json_integer
|
|
729
|
+
validate_container_size(size)
|
|
730
|
+
[type, size]
|
|
727
731
|
end
|
|
728
732
|
|
|
729
733
|
def read_list_end
|
|
@@ -732,7 +736,10 @@ module Thrift
|
|
|
732
736
|
|
|
733
737
|
def read_set_begin
|
|
734
738
|
read_json_array_start
|
|
735
|
-
|
|
739
|
+
type = get_type_id_for_type_name(read_json_string)
|
|
740
|
+
size = read_json_integer
|
|
741
|
+
validate_container_size(size)
|
|
742
|
+
[type, size]
|
|
736
743
|
end
|
|
737
744
|
|
|
738
745
|
def read_set_end
|
|
@@ -772,21 +779,63 @@ module Thrift
|
|
|
772
779
|
read_json_base64
|
|
773
780
|
end
|
|
774
781
|
|
|
782
|
+
def skip_string
|
|
783
|
+
read_string
|
|
784
|
+
end
|
|
785
|
+
|
|
775
786
|
def read_uuid
|
|
776
787
|
uuid = read_json_string
|
|
777
|
-
raise EOFError.new if uuid.length < 36
|
|
778
788
|
UUID.validate_uuid!(uuid)
|
|
779
789
|
uuid.tap(&:downcase!)
|
|
780
790
|
end
|
|
781
791
|
|
|
782
792
|
def to_s
|
|
783
|
-
"json(#{super
|
|
793
|
+
"json(#{super})"
|
|
794
|
+
end
|
|
795
|
+
|
|
796
|
+
private
|
|
797
|
+
|
|
798
|
+
def normalize_json_string(str)
|
|
799
|
+
utf8 = if str.encoding == Encoding::UTF_8
|
|
800
|
+
str
|
|
801
|
+
elsif str.encoding == Encoding::BINARY
|
|
802
|
+
str.ascii_only? ? str : str.dup.force_encoding(Encoding::UTF_8)
|
|
803
|
+
else
|
|
804
|
+
str.encode(Encoding::UTF_8)
|
|
805
|
+
end
|
|
806
|
+
invalid_unicode!("Invalid UTF-8 string") unless utf8.valid_encoding?
|
|
807
|
+
utf8
|
|
808
|
+
rescue EncodingError
|
|
809
|
+
invalid_unicode!("Invalid UTF-8 string")
|
|
810
|
+
end
|
|
811
|
+
|
|
812
|
+
def decode_json_string(bytes)
|
|
813
|
+
bytes.force_encoding(Encoding::UTF_8)
|
|
814
|
+
invalid_unicode!("Invalid UTF-8 string") unless bytes.valid_encoding?
|
|
815
|
+
bytes
|
|
816
|
+
end
|
|
817
|
+
|
|
818
|
+
def read_unicode_code_unit
|
|
819
|
+
hex = Bytes.empty_byte_buffer
|
|
820
|
+
4.times { hex << @reader.read }
|
|
821
|
+
invalid_unicode!("Invalid Unicode escape") unless hex.match?(/\A[0-9a-fA-F]{4}\z/)
|
|
822
|
+
hex.to_i(16)
|
|
823
|
+
rescue EOFError
|
|
824
|
+
invalid_unicode!("Incomplete Unicode escape")
|
|
825
|
+
end
|
|
826
|
+
|
|
827
|
+
def invalid_unicode!(message)
|
|
828
|
+
raise ProtocolException.new(ProtocolException::INVALID_DATA, message)
|
|
784
829
|
end
|
|
785
830
|
end
|
|
786
831
|
|
|
787
832
|
class JsonProtocolFactory < BaseProtocolFactory
|
|
833
|
+
def initialize(max_string_size: BaseProtocol::DEFAULT_MAX_STRING_SIZE)
|
|
834
|
+
@max_string_size = max_string_size
|
|
835
|
+
end
|
|
836
|
+
|
|
788
837
|
def get_protocol(trans)
|
|
789
|
-
|
|
838
|
+
Thrift::JsonProtocol.new(trans, max_string_size: @max_string_size)
|
|
790
839
|
end
|
|
791
840
|
|
|
792
841
|
def to_s
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
#
|
|
2
3
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
4
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -16,11 +17,10 @@
|
|
|
16
17
|
# specific language governing permissions and limitations
|
|
17
18
|
# under the License.
|
|
18
19
|
|
|
19
|
-
require
|
|
20
|
+
require "thrift/protocol/protocol_decorator"
|
|
20
21
|
|
|
21
22
|
module Thrift
|
|
22
23
|
class MultiplexedProtocol < BaseProtocol
|
|
23
|
-
|
|
24
24
|
include ProtocolDecorator
|
|
25
25
|
|
|
26
26
|
def initialize(protocol, service_name)
|
|
@@ -38,7 +38,7 @@ module Thrift
|
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def to_s
|
|
41
|
-
"multiplexed(#{@
|
|
41
|
+
"multiplexed(#{@protocol})"
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
#
|
|
2
3
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
4
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -18,7 +19,6 @@
|
|
|
18
19
|
|
|
19
20
|
module Thrift
|
|
20
21
|
module ProtocolDecorator
|
|
21
|
-
|
|
22
22
|
def initialize(protocol)
|
|
23
23
|
@protocol = protocol
|
|
24
24
|
end
|
|
@@ -28,7 +28,7 @@ module Thrift
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def write_message_begin(name, type, seqid)
|
|
31
|
-
@protocol.write_message_begin
|
|
31
|
+
@protocol.write_message_begin(name, type, seqid)
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def write_message_end
|
|
@@ -195,6 +195,10 @@ module Thrift
|
|
|
195
195
|
@protocol.read_binary
|
|
196
196
|
end
|
|
197
197
|
|
|
198
|
+
def skip_string
|
|
199
|
+
@protocol.skip_string
|
|
200
|
+
end
|
|
201
|
+
|
|
198
202
|
def read_uuid
|
|
199
203
|
@protocol.read_uuid
|
|
200
204
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
#
|
|
2
3
|
# Licensed to the Apache Software Foundation (ASF) under one
|
|
3
4
|
# or more contributor license agreements. See the NOTICE file
|
|
@@ -20,14 +21,20 @@
|
|
|
20
21
|
module Thrift
|
|
21
22
|
class Serializer
|
|
22
23
|
def initialize(protocol_factory = BinaryProtocolFactory.new)
|
|
24
|
+
@protocol_factory = protocol_factory
|
|
23
25
|
@transport = MemoryBufferTransport.new
|
|
24
26
|
@protocol = protocol_factory.get_protocol(@transport)
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
def serialize(base)
|
|
28
30
|
@transport.reset_buffer
|
|
31
|
+
@protocol ||= @protocol_factory.get_protocol(@transport)
|
|
29
32
|
base.write(@protocol)
|
|
33
|
+
@protocol.trans.flush
|
|
30
34
|
@transport.read(@transport.available)
|
|
35
|
+
rescue
|
|
36
|
+
@protocol = nil
|
|
37
|
+
raise
|
|
31
38
|
end
|
|
32
39
|
end
|
|
33
40
|
end
|