thrift 0.24.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.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +107 -4
  3. data/ext/binary_protocol_accelerated.c +52 -17
  4. data/ext/compact_protocol.c +135 -70
  5. data/ext/constants.h +3 -0
  6. data/ext/extconf.rb +4 -4
  7. data/ext/macros.h +11 -0
  8. data/ext/memory_buffer.c +35 -17
  9. data/ext/struct.c +185 -64
  10. data/ext/thrift_native.c +6 -0
  11. data/lib/thrift/bytes.rb +2 -2
  12. data/lib/thrift/client.rb +31 -22
  13. data/lib/thrift/exceptions.rb +10 -8
  14. data/lib/thrift/multiplexed_processor.rb +5 -6
  15. data/lib/thrift/processor.rb +24 -3
  16. data/lib/thrift/protocol/base_protocol.rb +53 -27
  17. data/lib/thrift/protocol/binary_protocol.rb +54 -40
  18. data/lib/thrift/protocol/binary_protocol_accelerated.rb +6 -2
  19. data/lib/thrift/protocol/compact_protocol.rb +193 -88
  20. data/lib/thrift/protocol/header_protocol.rb +14 -3
  21. data/lib/thrift/protocol/json_protocol.rb +146 -104
  22. data/lib/thrift/protocol/multiplexed_protocol.rb +2 -3
  23. data/lib/thrift/protocol/protocol_decorator.rb +5 -2
  24. data/lib/thrift/serializer/serializer.rb +6 -0
  25. data/lib/thrift/server/base_server.rb +10 -2
  26. data/lib/thrift/server/nonblocking_server.rb +49 -26
  27. data/lib/thrift/server/rack_application.rb +69 -0
  28. data/lib/thrift/server/simple_server.rb +27 -23
  29. data/lib/thrift/server/thin_http_server.rb +20 -44
  30. data/lib/thrift/server/thread_pool_server.rb +20 -17
  31. data/lib/thrift/server/threaded_server.rb +22 -26
  32. data/lib/thrift/struct.rb +33 -18
  33. data/lib/thrift/struct_union.rb +36 -30
  34. data/lib/thrift/transport/base_transport.rb +23 -5
  35. data/lib/thrift/transport/buffered_transport.rb +4 -4
  36. data/lib/thrift/transport/framed_transport.rb +32 -7
  37. data/lib/thrift/transport/header_transport.rb +130 -50
  38. data/lib/thrift/transport/http_client_transport.rb +27 -14
  39. data/lib/thrift/transport/io_stream_transport.rb +2 -1
  40. data/lib/thrift/transport/memory_buffer_transport.rb +8 -10
  41. data/lib/thrift/transport/server_socket.rb +4 -5
  42. data/lib/thrift/transport/socket.rb +20 -22
  43. data/lib/thrift/transport/ssl_server_socket.rb +64 -4
  44. data/lib/thrift/transport/ssl_socket.rb +32 -5
  45. data/lib/thrift/transport/unix_server_socket.rb +1 -1
  46. data/lib/thrift/transport/unix_socket.rb +4 -6
  47. data/lib/thrift/types.rb +22 -22
  48. data/lib/thrift/union.rb +20 -11
  49. data/lib/thrift/uuid.rb +8 -8
  50. data/lib/thrift.rb +39 -39
  51. metadata +5 -230
  52. data/benchmark/Benchmark.thrift +0 -24
  53. data/benchmark/benchmark.rb +0 -286
  54. data/benchmark/client.rb +0 -118
  55. data/benchmark/server.rb +0 -121
  56. data/benchmark/thin_server.rb +0 -46
  57. data/lib/thrift/server/mongrel_http_server.rb +0 -61
  58. data/spec/BaseService.thrift +0 -27
  59. data/spec/ExtendedService.thrift +0 -25
  60. data/spec/Referenced.thrift +0 -44
  61. data/spec/ThriftNamespacedSpec.thrift +0 -53
  62. data/spec/ThriftSpec.thrift +0 -203
  63. data/spec/base_protocol_spec.rb +0 -244
  64. data/spec/base_transport_spec.rb +0 -428
  65. data/spec/binary_protocol_accelerated_spec.rb +0 -47
  66. data/spec/binary_protocol_spec.rb +0 -73
  67. data/spec/binary_protocol_spec_shared.rb +0 -509
  68. data/spec/bytes_spec.rb +0 -117
  69. data/spec/client_spec.rb +0 -167
  70. data/spec/compact_protocol_spec.rb +0 -295
  71. data/spec/constants_demo_spec.rb +0 -102
  72. data/spec/exception_spec.rb +0 -141
  73. data/spec/flat_spec.rb +0 -63
  74. data/spec/header_protocol_spec.rb +0 -476
  75. data/spec/header_transport_spec.rb +0 -431
  76. data/spec/http_client_spec.rb +0 -160
  77. data/spec/json_protocol_spec.rb +0 -574
  78. data/spec/multiplexed_processor_spec.rb +0 -75
  79. data/spec/namespaced_spec.rb +0 -67
  80. data/spec/nonblocking_server_spec.rb +0 -429
  81. data/spec/processor_spec.rb +0 -80
  82. data/spec/recursion_depth_spec.rb +0 -223
  83. data/spec/serializer_spec.rb +0 -67
  84. data/spec/server_socket_spec.rb +0 -121
  85. data/spec/server_spec.rb +0 -238
  86. data/spec/socket_spec.rb +0 -174
  87. data/spec/socket_spec_shared.rb +0 -168
  88. data/spec/spec_helper.rb +0 -70
  89. data/spec/ssl_server_socket_spec.rb +0 -85
  90. data/spec/ssl_socket_spec.rb +0 -248
  91. data/spec/struct_nested_containers_spec.rb +0 -191
  92. data/spec/struct_spec.rb +0 -398
  93. data/spec/support/header_protocol_helper.rb +0 -55
  94. data/spec/thin_http_server_spec.rb +0 -127
  95. data/spec/types_spec.rb +0 -118
  96. data/spec/union_spec.rb +0 -273
  97. data/spec/unix_socket_spec.rb +0 -131
  98. data/spec/uuid_validation_spec.rb +0 -239
  99. data/test/fuzz/Makefile +0 -779
  100. data/test/fuzz/Makefile.am +0 -173
  101. data/test/fuzz/Makefile.in +0 -775
  102. data/test/fuzz/README.md +0 -149
  103. data/test/fuzz/fuzz_common.rb +0 -96
  104. data/test/fuzz/fuzz_parse_binary_protocol.rb +0 -23
  105. data/test/fuzz/fuzz_parse_binary_protocol_accelerated.rb +0 -23
  106. data/test/fuzz/fuzz_parse_binary_protocol_accelerated_harness.rb +0 -23
  107. data/test/fuzz/fuzz_parse_binary_protocol_harness.rb +0 -23
  108. data/test/fuzz/fuzz_parse_compact_protocol.rb +0 -23
  109. data/test/fuzz/fuzz_parse_compact_protocol_harness.rb +0 -23
  110. data/test/fuzz/fuzz_parse_json_protocol.rb +0 -23
  111. data/test/fuzz/fuzz_parse_json_protocol_harness.rb +0 -23
  112. data/test/fuzz/fuzz_roundtrip_binary_protocol.rb +0 -23
  113. data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated.rb +0 -23
  114. data/test/fuzz/fuzz_roundtrip_binary_protocol_accelerated_harness.rb +0 -23
  115. data/test/fuzz/fuzz_roundtrip_binary_protocol_harness.rb +0 -23
  116. data/test/fuzz/fuzz_roundtrip_compact_protocol.rb +0 -23
  117. data/test/fuzz/fuzz_roundtrip_compact_protocol_harness.rb +0 -23
  118. data/test/fuzz/fuzz_roundtrip_json_protocol.rb +0 -23
  119. data/test/fuzz/fuzz_roundtrip_json_protocol_harness.rb +0 -23
  120. data/test/fuzz/fuzz_tracer.rb +0 -29
data/ext/thrift_native.c CHANGED
@@ -92,6 +92,7 @@ ID skip_method_id;
92
92
  ID write_method_id;
93
93
  ID read_all_method_id;
94
94
  ID read_into_buffer_method_id;
95
+ ID reset_message_size_method_id;
95
96
  ID force_binary_encoding_id;
96
97
  ID convert_to_utf8_byte_buffer_id;
97
98
  ID convert_to_string_id;
@@ -99,8 +100,10 @@ ID convert_to_string_id;
99
100
  // constant ids
100
101
  ID fields_const_id;
101
102
  ID transport_ivar_id;
103
+ ID reset_message_size_ivar_id;
102
104
  ID strict_read_ivar_id;
103
105
  ID strict_write_ivar_id;
106
+ ID max_string_size_ivar_id;
104
107
 
105
108
  // cached symbols
106
109
  VALUE type_sym;
@@ -200,6 +203,7 @@ RUBY_FUNC_EXPORTED void Init_thrift_native(void) {
200
203
  write_method_id = rb_intern("write");
201
204
  read_all_method_id = rb_intern("read_all");
202
205
  read_into_buffer_method_id = rb_intern("read_into_buffer");
206
+ reset_message_size_method_id = rb_intern("reset_message_size");
203
207
  force_binary_encoding_id = rb_intern("force_binary_encoding");
204
208
  convert_to_utf8_byte_buffer_id = rb_intern("convert_to_utf8_byte_buffer");
205
209
  convert_to_string_id = rb_intern("convert_to_string");
@@ -207,8 +211,10 @@ RUBY_FUNC_EXPORTED void Init_thrift_native(void) {
207
211
  // constant ids
208
212
  fields_const_id = rb_intern("FIELDS");
209
213
  transport_ivar_id = rb_intern("@trans");
214
+ reset_message_size_ivar_id = rb_intern("@reset_message_size");
210
215
  strict_read_ivar_id = rb_intern("@strict_read");
211
216
  strict_write_ivar_id = rb_intern("@strict_write");
217
+ max_string_size_ivar_id = rb_intern("@max_string_size");
212
218
 
213
219
  // cached symbols
214
220
  type_sym = ID2SYM(rb_intern("type"));
data/lib/thrift/bytes.rb CHANGED
@@ -29,10 +29,10 @@ module Thrift
29
29
  # Returns a String with BINARY encoding, filled with null characters
30
30
  # if size is greater than zero
31
31
  def self.empty_byte_buffer(size = nil)
32
- if (size && size > 0)
32
+ if size && size > 0
33
33
  "\0".b * size
34
34
  else
35
- ''.b
35
+ "".b
36
36
  end
37
37
  end
38
38
 
data/lib/thrift/client.rb CHANGED
@@ -31,33 +31,18 @@ module Thrift
31
31
  end
32
32
 
33
33
  def send_message(name, args_class, args = {})
34
- seqid = next_seqid!
35
- @oprot.write_message_begin(name, MessageTypes::CALL, seqid)
36
- send_message_args(args_class, args)
37
- @pending_seqids << seqid
34
+ write_message(name, MessageTypes::CALL, args_class, args)
38
35
  end
39
36
 
40
37
  def send_oneway_message(name, args_class, args = {})
41
- @oprot.write_message_begin(name, MessageTypes::ONEWAY, next_seqid!)
42
- send_message_args(args_class, args)
38
+ write_message(name, MessageTypes::ONEWAY, args_class, args)
43
39
  end
44
40
 
45
41
  def send_message_args(args_class, args)
46
- data = args_class.new
47
- args.each do |k, v|
48
- data.send("#{k.to_s}=", v)
49
- end
50
- begin
51
- data.write(@oprot)
52
- rescue StandardError => e
53
- @oprot.trans.close
54
- raise e
55
- end
56
- @oprot.write_message_end
57
- @oprot.trans.flush
42
+ write_message(nil, nil, args_class, args)
58
43
  end
59
44
 
60
- def receive_message_begin()
45
+ def receive_message_begin
61
46
  fname, mtype, rseqid = @iprot.read_message_begin
62
47
  [fname, mtype, rseqid]
63
48
  end
@@ -72,14 +57,14 @@ module Thrift
72
57
  if mtype != MessageTypes::REPLY
73
58
  raise ApplicationException.new(
74
59
  ApplicationException::INVALID_MESSAGE_TYPE,
75
- "#{expected_name} failed: invalid message type"
60
+ "#{expected_name} failed: invalid message type",
76
61
  )
77
62
  end
78
63
 
79
64
  if fname != expected_name
80
65
  raise ApplicationException.new(
81
66
  ApplicationException::WRONG_METHOD_NAME,
82
- "#{expected_name} failed: wrong method name"
67
+ "#{expected_name} failed: wrong method name",
83
68
  )
84
69
  end
85
70
 
@@ -87,7 +72,7 @@ module Thrift
87
72
 
88
73
  raise ApplicationException.new(
89
74
  ApplicationException::BAD_SEQUENCE_ID,
90
- "#{expected_name} failed: out of sequence response"
75
+ "#{expected_name} failed: out of sequence response",
91
76
  )
92
77
  end
93
78
 
@@ -100,6 +85,30 @@ module Thrift
100
85
 
101
86
  private
102
87
 
88
+ def write_message(name, type, args_class, args)
89
+ data = args_class.new
90
+ args.each do |k, v|
91
+ data.send("#{k}=", v)
92
+ end
93
+ seqid = next_seqid! unless name.nil?
94
+
95
+ flush_result = begin
96
+ @oprot.write_message_begin(name, type, seqid) unless name.nil?
97
+ data.write(@oprot)
98
+ @oprot.write_message_end
99
+ @oprot.trans.flush
100
+ rescue StandardError
101
+ begin
102
+ @oprot.trans.close
103
+ rescue StandardError
104
+ # Preserve the original send error.
105
+ end
106
+ raise
107
+ end
108
+
109
+ type == MessageTypes::CALL ? @pending_seqids << seqid : flush_result
110
+ end
111
+
103
112
  def next_seqid!
104
113
  seqid = @seqid
105
114
  @seqid = (seqid == MAX_SEQUENCE_ID) ? MIN_SEQUENCE_ID : seqid + 1
@@ -19,6 +19,8 @@
19
19
  #
20
20
 
21
21
  module Thrift
22
+ DEFAULT_RECURSION_DEPTH = 64
23
+
22
24
  class Exception < StandardError
23
25
  def initialize(message)
24
26
  super
@@ -29,7 +31,6 @@ module Thrift
29
31
  end
30
32
 
31
33
  class ApplicationException < Exception
32
-
33
34
  UNKNOWN = 0
34
35
  UNKNOWN_METHOD = 1
35
36
  INVALID_MESSAGE_TYPE = 2
@@ -49,10 +50,11 @@ module Thrift
49
50
  @type = type
50
51
  end
51
52
 
52
- def read(iprot)
53
+ def read(iprot, remaining_depth = DEFAULT_RECURSION_DEPTH)
54
+ raise ProtocolException.new(ProtocolException::DEPTH_LIMIT, "Maximum recursion depth exceeded") if remaining_depth <= 0
53
55
  iprot.read_struct_begin
54
56
  while true
55
- fname, ftype, fid = iprot.read_field_begin
57
+ _, ftype, fid = iprot.read_field_begin
56
58
  if ftype == Types::STOP
57
59
  break
58
60
  end
@@ -68,21 +70,21 @@ module Thrift
68
70
  iprot.read_struct_end
69
71
  end
70
72
 
71
- def write(oprot)
72
- oprot.write_struct_begin('Thrift::ApplicationException')
73
+ def write(oprot, remaining_depth = DEFAULT_RECURSION_DEPTH)
74
+ raise ProtocolException.new(ProtocolException::DEPTH_LIMIT, "Maximum recursion depth exceeded") if remaining_depth <= 0
75
+ oprot.write_struct_begin("Thrift::ApplicationException")
73
76
  unless @message.nil?
74
- oprot.write_field_begin('message', Types::STRING, 1)
77
+ oprot.write_field_begin("message", Types::STRING, 1)
75
78
  oprot.write_string(@message)
76
79
  oprot.write_field_end
77
80
  end
78
81
  unless @type.nil?
79
- oprot.write_field_begin('type', Types::I32, 2)
82
+ oprot.write_field_begin("type", Types::I32, 2)
80
83
  oprot.write_i32(@type)
81
84
  oprot.write_field_end
82
85
  end
83
86
  oprot.write_field_stop
84
87
  oprot.write_struct_end
85
88
  end
86
-
87
89
  end
88
90
  end
@@ -17,8 +17,8 @@
17
17
  # specific language governing permissions and limitations
18
18
  # under the License.
19
19
 
20
- require 'thrift/protocol/protocol_decorator'
21
- require 'thrift/protocol/base_protocol'
20
+ require "thrift/protocol/protocol_decorator"
21
+ require "thrift/protocol/base_protocol"
22
22
 
23
23
  module Thrift
24
24
  class MultiplexedProcessor
@@ -38,12 +38,12 @@ module Thrift
38
38
  def process(iprot, oprot)
39
39
  name, type, seqid = iprot.read_message_begin
40
40
  check_type(type)
41
- if name.count(':') < 1
41
+ if name.count(":") < 1
42
42
  check_default_processor(name)
43
43
  return @default_processor.process(StoredMessageProtocol.new(iprot, [name, type, seqid]), oprot)
44
44
  end
45
45
 
46
- service_name, method = name.split(':', 2)
46
+ service_name, method = name.split(":", 2)
47
47
  processor(service_name).process(StoredMessageProtocol.new(iprot, [method, type, seqid]), oprot)
48
48
  end
49
49
 
@@ -59,7 +59,7 @@ module Thrift
59
59
 
60
60
  def check_type(type)
61
61
  unless [MessageTypes::CALL, MessageTypes::ONEWAY].include?(type)
62
- raise Thrift::Exception.new('This should not have happened!?')
62
+ raise Thrift::Exception.new("This should not have happened!?")
63
63
  end
64
64
  end
65
65
 
@@ -71,7 +71,6 @@ module Thrift
71
71
  end
72
72
 
73
73
  class StoredMessageProtocol < BaseProtocol
74
-
75
74
  include ProtocolDecorator
76
75
 
77
76
  def initialize(protocol, message_begin)
@@ -18,10 +18,15 @@
18
18
  # under the License.
19
19
  #
20
20
 
21
- require 'logger'
21
+ require "logger"
22
+ require "thrift/protocol/base_protocol"
22
23
 
23
24
  module Thrift
24
25
  module Processor
26
+ class ArgumentProtocolException < ProtocolException
27
+ end
28
+ private_constant :ArgumentProtocolException
29
+
25
30
  def initialize(handler, logger = nil)
26
31
  @handler = handler
27
32
  if logger.nil?
@@ -34,11 +39,25 @@ module Thrift
34
39
 
35
40
  def process(iprot, oprot)
36
41
  name, type, seqid = iprot.read_message_begin
42
+ unless type == MessageTypes::CALL || type == MessageTypes::ONEWAY
43
+ iprot.skip(Types::STRUCT)
44
+ iprot.read_message_end
45
+ x = ApplicationException.new(
46
+ ApplicationException::INVALID_MESSAGE_TYPE,
47
+ "Invalid message type #{type} for function #{name}",
48
+ )
49
+ write_error(x, oprot, name, seqid)
50
+ return false
51
+ end
52
+
37
53
  if respond_to?("process_#{name}")
38
54
  begin
39
55
  send("process_#{name}", seqid, iprot, oprot)
56
+ rescue ArgumentProtocolException => e
57
+ x = ApplicationException.new(ApplicationException::PROTOCOL_ERROR, e.message)
58
+ write_error(x, oprot, name, seqid)
40
59
  rescue => e
41
- x = ApplicationException.new(ApplicationException::INTERNAL_ERROR, 'Internal error')
60
+ x = ApplicationException.new(ApplicationException::INTERNAL_ERROR, "Internal error")
42
61
  @logger.debug "Internal error : #{e.message}\n#{e.backtrace.join("\n")}"
43
62
  write_error(x, oprot, name, seqid)
44
63
  end
@@ -46,7 +65,7 @@ module Thrift
46
65
  else
47
66
  iprot.skip(Types::STRUCT)
48
67
  iprot.read_message_end
49
- x = ApplicationException.new(ApplicationException::UNKNOWN_METHOD, 'Unknown function '+name)
68
+ x = ApplicationException.new(ApplicationException::UNKNOWN_METHOD, "Unknown function " + name)
50
69
  write_error(x, oprot, name, seqid)
51
70
  false
52
71
  end
@@ -57,6 +76,8 @@ module Thrift
57
76
  args.read(iprot)
58
77
  iprot.read_message_end
59
78
  args
79
+ rescue ProtocolException => e
80
+ raise ArgumentProtocolException.new(e.type, e.message)
60
81
  end
61
82
 
62
83
  def write_result(result, oprot, name, seqid)
@@ -19,11 +19,11 @@
19
19
  #
20
20
 
21
21
  # this require is to make generated struct definitions happy
22
- require 'set'
22
+ require "set"
23
+ require "thrift/exceptions"
23
24
 
24
25
  module Thrift
25
26
  class ProtocolException < Exception
26
-
27
27
  UNKNOWN = 0
28
28
  INVALID_DATA = 1
29
29
  NEGATIVE_SIZE = 2
@@ -41,6 +41,14 @@ module Thrift
41
41
  end
42
42
 
43
43
  class BaseProtocol
44
+ MAX_CONTAINER_SIZE = (1 << 31) - 1
45
+
46
+ # The longest string or binary field BinaryProtocol and CompactProtocol read
47
+ # by default: the frame size limit the framed transports apply. A string's
48
+ # length is the read size handed to the transport, and an unframed transport
49
+ # has no frame to bound it. Pass max_string_size: nil to read strings of any
50
+ # length.
51
+ DEFAULT_MAX_STRING_SIZE = 16_384_000
44
52
 
45
53
  attr_reader :trans
46
54
 
@@ -49,10 +57,24 @@ module Thrift
49
57
  end
50
58
 
51
59
  def native?
52
- puts "wrong method is being called!"
53
60
  false
54
61
  end
55
62
 
63
+ # Raises a SIZE_LIMIT ProtocolException when a declared string length is over
64
+ # the protocol's max_string_size.
65
+ def check_string_size(size)
66
+ max = @max_string_size
67
+ return if max.nil? || size <= max
68
+
69
+ raise ProtocolException.new(ProtocolException::SIZE_LIMIT, "String size #{size} larger than the maximum #{max}")
70
+ end
71
+
72
+ def self.validate_max_string_size(max_string_size)
73
+ return if max_string_size.nil? || (max_string_size.is_a?(Integer) && max_string_size > 0)
74
+
75
+ raise ArgumentError, "max_string_size must be nil or a positive Integer"
76
+ end
77
+
56
78
  def write_message_begin(name, type, seqid)
57
79
  raise NotImplementedError
58
80
  end
@@ -229,6 +251,10 @@ module Thrift
229
251
  raise NotImplementedError
230
252
  end
231
253
 
254
+ def skip_string
255
+ read_string
256
+ end
257
+
232
258
  # Writes a field based on the field information, field ID and value.
233
259
  #
234
260
  # field_info - A Hash containing the definition of the field:
@@ -237,25 +263,19 @@ module Thrift
237
263
  # :binary - A Boolean flag that indicates if Thrift::Types::STRING is a binary string (string without encoding).
238
264
  # fid - The ID of the field.
239
265
  # value - The field's value to write; object type varies based on :type.
266
+ # remaining_depth - The optional recursion budget of the enclosing struct.
240
267
  #
241
268
  # Returns nothing.
242
- def write_field(*args)
243
- if args.size == 3
244
- # handles the documented method signature - write_field(field_info, fid, value)
245
- field_info = args[0]
246
- fid = args[1]
247
- value = args[2]
248
- elsif args.size == 4
249
- # handles the deprecated method signature - write_field(name, type, fid, value)
250
- field_info = {:name => args[0], :type => args[1]}
251
- fid = args[2]
252
- value = args[3]
253
- else
254
- raise ArgumentError, "wrong number of arguments (#{args.size} for 3)"
269
+ def write_field(field_info, fid, value, remaining_depth = nil)
270
+ unless field_info.is_a?(Hash)
271
+ field_info = {name: field_info, type: fid}
272
+ fid = value
273
+ value = remaining_depth
274
+ remaining_depth = nil
255
275
  end
256
276
 
257
277
  write_field_begin(field_info[:name], field_info[:type], fid)
258
- write_type(field_info, value)
278
+ write_type(field_info, value, remaining_depth)
259
279
  write_field_end
260
280
  end
261
281
 
@@ -265,13 +285,14 @@ module Thrift
265
285
  # :type - The Thrift::Types constant that determines how the value is written.
266
286
  # :binary - A Boolean flag that indicates if Thrift::Types::STRING is a binary string (string without encoding).
267
287
  # value - The field's value to write; object type varies based on field_info[:type].
288
+ # remaining_depth - The optional recursion budget of the enclosing struct.
268
289
  #
269
290
  # Returns nothing.
270
- def write_type(field_info, value)
291
+ def write_type(field_info, value, remaining_depth = nil)
271
292
  # if field_info is a Integer, assume it is a Thrift::Types constant
272
293
  # convert it into a field_info Hash for backwards compatibility
273
294
  if field_info.is_a? Integer
274
- field_info = {:type => field_info}
295
+ field_info = {type: field_info}
275
296
  end
276
297
 
277
298
  case field_info[:type]
@@ -296,7 +317,11 @@ module Thrift
296
317
  when Types::UUID
297
318
  write_uuid(value)
298
319
  when Types::STRUCT
299
- value.write(self)
320
+ if remaining_depth
321
+ value.write(self, remaining_depth - 1)
322
+ else
323
+ value.write(self)
324
+ end
300
325
  else
301
326
  raise NotImplementedError
302
327
  end
@@ -313,7 +338,7 @@ module Thrift
313
338
  # if field_info is a Integer, assume it is a Thrift::Types constant
314
339
  # convert it into a field_info Hash for backwards compatibility
315
340
  if field_info.is_a? Integer
316
- field_info = {:type => field_info}
341
+ field_info = {type: field_info}
317
342
  end
318
343
 
319
344
  case field_info[:type]
@@ -343,7 +368,7 @@ module Thrift
343
368
  end
344
369
 
345
370
  def skip(type, max_depth = 64)
346
- raise ProtocolException.new(ProtocolException::DEPTH_LIMIT, 'Maximum skip depth exceeded') if max_depth <= 0
371
+ raise ProtocolException.new(ProtocolException::DEPTH_LIMIT, "Maximum skip depth exceeded") if max_depth <= 0
347
372
  case type
348
373
  when Types::BOOL
349
374
  read_bool
@@ -358,13 +383,13 @@ module Thrift
358
383
  when Types::DOUBLE
359
384
  read_double
360
385
  when Types::STRING
361
- read_string
386
+ skip_string
362
387
  when Types::UUID
363
388
  read_uuid
364
389
  when Types::STRUCT
365
390
  read_struct_begin
366
391
  while true
367
- name, type, id = read_field_begin
392
+ _, type, _ = read_field_begin
368
393
  break if type == Types::STOP
369
394
  skip(type, max_depth - 1)
370
395
  read_field_end
@@ -393,16 +418,17 @@ module Thrift
393
418
  end
394
419
  read_list_end
395
420
  else
396
- raise ProtocolException.new(ProtocolException::INVALID_DATA, 'Invalid data')
421
+ raise ProtocolException.new(ProtocolException::INVALID_DATA, "Invalid data")
397
422
  end
398
423
  end
399
424
 
400
425
  def validate_container_size(size)
401
- raise ProtocolException.new(ProtocolException::NEGATIVE_SIZE, 'Negative size') unless size >= 0
426
+ raise ProtocolException.new(ProtocolException::NEGATIVE_SIZE, "Negative size") unless size >= 0
427
+ raise ProtocolException.new(ProtocolException::SIZE_LIMIT, "Container size limit exceeded") if size > MAX_CONTAINER_SIZE
402
428
  end
403
429
 
404
430
  def to_s
405
- "#{trans.to_s}"
431
+ trans.to_s
406
432
  end
407
433
  end
408
434