amq-protocol 1.5.0 → 1.6.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.
data/.gitignore CHANGED
@@ -12,3 +12,4 @@ Gemfile.lock
12
12
  .bundle/*
13
13
  bin/*
14
14
  *.bundle
15
+ Makefile
data/Gemfile CHANGED
@@ -4,7 +4,9 @@ source "https://rubygems.org"
4
4
 
5
5
  group :development do
6
6
  # excludes Windows, Rubinius and JRuby
7
- gem "perftools.rb", :platform => :mri_18
7
+ gem "ruby-prof", :platform => :mri
8
+
9
+ gem "rake"
8
10
  end
9
11
 
10
12
  group :test do
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ require "bundler"
2
+ Bundler.setup
3
+
4
+ require "rake"
5
+ require "rspec/core/rake_task"
6
+
7
+ $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
8
+ require "amq/protocol/version"
9
+
10
+ task :gem => :build
11
+ task :build do
12
+ system "gem build amq-protocol.gemspec"
13
+ end
14
+
15
+ task :install => :build do
16
+ system "gem install amq-protocol-#{AMQ::Protocol::VERSION}.gem"
17
+ end
18
+
19
+ def extension
20
+ RUBY_PLATFORM =~ /darwin/ ? "bundle" : "so"
21
+ end
22
+
23
+ def compile!
24
+ puts "Compiling native extensions..."
25
+ Dir.chdir(Pathname(__FILE__).dirname + "ext/") do
26
+ `bundle exec ruby extconf.rb`
27
+ `make`
28
+ `cp client.#{extension} ../lib/amq/protocol/native/`
29
+ end
30
+ end
31
+
32
+ RSpec::Core::RakeTask.new("spec") do |spec|
33
+ spec.pattern = "spec/**/*_spec.rb"
34
+ end
35
+
36
+ RSpec::Core::RakeTask.new("clean_spec") do |spec|
37
+ spec.pattern = "spec/**/*_spec.rb"
38
+ end
39
+
40
+ task :compile do
41
+ compile!
42
+ end
43
+
44
+ task :clean do
45
+ puts "Cleaning out native extensions..."
46
+ begin
47
+ Dir.chdir(Pathname(__FILE__).dirname + "lib/amq-protocol/native") do
48
+ `rm client.#{extension}`
49
+ end
50
+ rescue Exception => e
51
+ puts e.message
52
+ end
53
+ end
54
+
55
+ task :default => [:compile, :spec, :clean, :clean_spec]
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "lib"))
5
+
6
+ require "amq/protocol/client"
7
+ require "benchmark"
8
+
9
+ FRAME_SIZE = 128 * 1024
10
+
11
+ puts
12
+ puts "-" * 80
13
+ puts "Benchmarking on #{RUBY_DESCRIPTION}"
14
+
15
+ n = 250_000
16
+
17
+ # warm up the JIT, etc
18
+ puts "Doing a warmup run..."
19
+ 15_000.times { AMQ::Protocol::Method.encode_body("a" * 256 * 1024, 1, FRAME_SIZE) }
20
+
21
+ t = Benchmark.realtime do
22
+ n.times { AMQ::Protocol::Method.encode_body("a" * 256 * 1024, 1, FRAME_SIZE) }
23
+ end
24
+ r = (n.to_f/t.to_f)
25
+
26
+ puts "AMQ::Protocol::Method.encode_body rate: #{(r / 1000).round(2)} KGHz"
27
+ puts
28
+ puts "-" * 80
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: utf-8
3
+
4
+ $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "lib"))
5
+
6
+ require "amq/protocol/client"
7
+ require "benchmark"
8
+
9
+ FRAME_SIZE = 128 * 1024
10
+
11
+ puts
12
+ puts "-" * 80
13
+ puts "Benchmarking on #{RUBY_DESCRIPTION}"
14
+
15
+ n = 250_000
16
+
17
+ # warm up the JIT, etc
18
+ puts "Doing a warmup run..."
19
+ 15_000.times { AMQ::Protocol::Method.encode_body("ab" * 1024, 1, FRAME_SIZE) }
20
+
21
+ t = Benchmark.realtime do
22
+ n.times { AMQ::Protocol::Method.encode_body("ab" * 1024, 1, FRAME_SIZE) }
23
+ end
24
+ r = (n.to_f/t.to_f)
25
+
26
+ puts "AMQ::Protocol::Method.encode_body rate: #{(r / 1000).round(2)} KGHz"
27
+ puts
28
+ puts "-" * 80
@@ -16,9 +16,9 @@ def genSingleEncode(spec, cValue, unresolved_domain):
16
16
  elif type == 'long':
17
17
  buffer.append("buffer << [%s].pack(PACK_UINT32)" % (cValue,))
18
18
  elif type == 'longlong':
19
- buffer.append("buffer << AMQ::Hacks.pack_uint64_big_endian(%s)" % (cValue,))
19
+ buffer.append("buffer << AMQ::Pack.pack_uint64_big_endian(%s)" % (cValue,))
20
20
  elif type == 'timestamp':
21
- buffer.append("buffer << AMQ::Hacks.pack_uint64_big_endian(%s)" % (cValue,))
21
+ buffer.append("buffer << AMQ::Pack.pack_uint64_big_endian(%s)" % (cValue,))
22
22
  elif type == 'bit':
23
23
  raise "Can't encode bit in genSingleEncode"
24
24
  elif type == 'table':
@@ -58,7 +58,7 @@ def genSingleDecode(spec, field):
58
58
  buffer.append("%s = data[offset, 4].unpack(PACK_UINT32).first" % (cLvalue,))
59
59
  buffer.append("offset += 4")
60
60
  elif type == 'longlong':
61
- buffer.append("%s = AMQ::Hacks.unpack_uint64_big_endian(data[offset, 8]).first" % (cLvalue,))
61
+ buffer.append("%s = AMQ::Pack.unpack_uint64_big_endian(data[offset, 8]).first" % (cLvalue,))
62
62
  buffer.append("offset += 8")
63
63
  elif type == 'timestamp':
64
64
  buffer.append("%s = data[offset, 8].unpack(PACK_UINT32_X2).first" % (cLvalue,))
@@ -97,7 +97,7 @@ def genSingleSimpleDecode(spec, field):
97
97
  elif type == 'long':
98
98
  buffer.append("data.unpack(PACK_UINT32).first")
99
99
  elif type == 'longlong':
100
- buffer.append("AMQ::Hacks.unpack_uint64_big_endian(data).first")
100
+ buffer.append("AMQ::Pack.unpack_uint64_big_endian(data).first")
101
101
  elif type == 'timestamp':
102
102
  buffer.append("Time.at(data.unpack(PACK_UINT32_X2).last)")
103
103
  elif type == 'bit':
@@ -5,35 +5,19 @@
5
5
  # IT DIRECTLY ! FOR CHANGES, PLEASE UPDATE FILES
6
6
  # IN THE ./codegen DIRECTORY OF THE AMQ-PROTOCOL REPOSITORY.<% import codegen_helpers as helpers %><% import re, os, codegen %>
7
7
 
8
+ require "amq/pack"
9
+
8
10
  require "amq/protocol/table"
9
11
  require "amq/protocol/frame"
10
- require "amq/hacks"
12
+
13
+ require "amq/protocol/constants"
14
+ require "amq/protocol/exceptions"
11
15
 
12
16
  module AMQ
13
17
  module Protocol
14
18
  PROTOCOL_VERSION = "${spec.major}.${spec.minor}.${spec.revision}".freeze
15
19
  PREAMBLE = "${'AMQP\\x00\\x%02x\\x%02x\\x%02x' % (spec.major, spec.minor, spec.revision)}".freeze
16
20
  DEFAULT_PORT = ${spec.port}
17
- TLS_PORT = 5671
18
- SSL_PORT = 5671
19
-
20
- # caching
21
- EMPTY_STRING = "".freeze
22
-
23
- PACK_INT8 = 'c'.freeze
24
- PACK_CHAR = 'C'.freeze
25
- PACK_UINT16 = 'n'.freeze
26
- PACK_UINT16_X2 = 'n2'.freeze
27
- PACK_UINT32 = 'N'.freeze
28
- PACK_UINT32_X2 = 'N2'.freeze
29
- PACK_INT64 = 'q'.freeze
30
- PACK_UCHAR_UINT32 = 'CN'.freeze
31
- PACK_CHAR_UINT16_UINT32 = 'cnN'.freeze
32
-
33
- PACK_32BIT_FLOAT = 'f'.freeze
34
- PACK_64BIT_FLOAT = 'G'.freeze
35
-
36
-
37
21
 
38
22
  # @return [Array] Collection of subclasses of AMQ::Protocol::Class.
39
23
  def self.classes
@@ -45,63 +29,6 @@ module AMQ
45
29
  Protocol::Method.methods
46
30
  end
47
31
 
48
- class Error < StandardError
49
- DEFAULT_MESSAGE = "AMQP error".freeze
50
-
51
- def self.inherited(subclass)
52
- @_subclasses ||= []
53
- @_subclasses << subclass
54
- end # self.inherited(subclazz)
55
-
56
- def self.subclasses_with_values
57
- @_subclasses.select{ |k| defined?(k::VALUE) }
58
- end # self.subclasses_with_values
59
-
60
- def self.[](code)
61
- if result = subclasses_with_values.detect { |klass| klass::VALUE == code }
62
- result
63
- else
64
- raise "No such exception class for code #{code}" unless result
65
- end # if
66
- end # self.[]
67
-
68
- def initialize(message = self.class::DEFAULT_MESSAGE)
69
- super(message)
70
- end
71
- end
72
-
73
- class FrameTypeError < Protocol::Error
74
- def initialize(types)
75
- super("Must be one of #{types.inspect}")
76
- end
77
- end
78
-
79
- class EmptyResponseError < Protocol::Error
80
- DEFAULT_MESSAGE = "Empty response received from the server."
81
-
82
- def initialize(message = self.class::DEFAULT_MESSAGE)
83
- super(message)
84
- end
85
- end
86
-
87
- class BadResponseError < Protocol::Error
88
- def initialize(argument, expected, actual)
89
- super("Argument #{argument} has to be #{expected.inspect}, was #{data.inspect}")
90
- end
91
- end
92
-
93
- class SoftError < Protocol::Error
94
- def self.inherited(subclass)
95
- Error.inherited(subclass)
96
- end # self.inherited(subclass)
97
- end
98
-
99
- class HardError < Protocol::Error
100
- def self.inherited(subclass)
101
- Error.inherited(subclass)
102
- end # self.inherited(subclass)
103
- end
104
-
105
32
  % for tuple in spec.constants:
106
33
  % if tuple[2] == "soft-error" or tuple[2] == "hard-error":
107
34
  class ${codegen.to_ruby_class_name(tuple[0])} < ${codegen.to_ruby_class_name(tuple[2])}
@@ -111,21 +38,6 @@ module AMQ
111
38
  % endif
112
39
  % endfor
113
40
 
114
- # We don't instantiate the following classes,
115
- # as we don't actually need any per-instance state.
116
- # Also, this is pretty low-level functionality,
117
- # hence it should have a reasonable performance.
118
- # As everyone knows, garbage collector in MRI performs
119
- # really badly, which is another good reason for
120
- # not creating any objects, but only use class as
121
- # a struct. Creating classes is quite expensive though,
122
- # but here the inheritance comes handy and mainly
123
- # as we can't simply make a reference to a function,
124
- # we can't use a hash or an object. I've been also
125
- # considering to have just a bunch of methods, but
126
- # here's the problem, that after we'd require this file,
127
- # all these methods would become global which would
128
- # be a bad, bad thing to do.
129
41
  class Class
130
42
  @classes = Array.new
131
43
 
@@ -195,6 +107,7 @@ module AMQ
195
107
  # 4 bytes of frame payload length
196
108
  # 1 byte of payload trailer FRAME_END byte
197
109
  limit = frame_size - 8
110
+ return [BodyFrame.new(body, channel)] if body.bytesize < limit
198
111
 
199
112
  # Otherwise String#slice on 1.9 will operate with code points,
200
113
  # and we need bytes. MK.
@@ -203,24 +116,14 @@ module AMQ
203
116
  array = Array.new
204
117
  while body
205
118
  payload, body = body[0, limit], body[limit, body.length - limit]
206
- # array << [0x03, payload]
207
119
  array << BodyFrame.new(payload, channel)
208
120
  end
209
121
 
210
122
  array
211
123
  end
212
124
 
213
- # We can return different:
214
- # - instantiate given subclass of Method
215
- # - create an OpenStruct object
216
- # - create a hash
217
- # - yield params into the block rather than just return
218
- # @api plugin
219
125
  def self.instantiate(*args, &block)
220
126
  self.new(*args, &block)
221
- # or OpenStruct.new(args.first)
222
- # or args.first
223
- # or block.call(*args)
224
127
  end
225
128
  end
226
129
 
@@ -250,7 +153,6 @@ module AMQ
250
153
 
251
154
  % endif
252
155
 
253
- ## TODO: not only basic, resp. in fact it's only this class, but not necessarily in the future, rather check if properties are empty #}
254
156
  % if klass.name == "basic" :
255
157
  def self.encode_properties(body_size, properties)
256
158
  pieces, flags = [], 0
@@ -263,7 +165,7 @@ module AMQ
263
165
 
264
166
  # result = [${klass.index}, 0, body_size, flags].pack('n2Qn')
265
167
  result = [${klass.index}, 0].pack(PACK_UINT16_X2)
266
- result += AMQ::Hacks.pack_uint64_big_endian(body_size)
168
+ result += AMQ::Pack.pack_uint64_big_endian(body_size)
267
169
  result += [flags].pack(PACK_UINT16)
268
170
  result + pieces.join(EMPTY_STRING)
269
171
  end
@@ -376,8 +278,7 @@ module AMQ
376
278
  % if klass.name == "connection":
377
279
  channel = 0
378
280
  % endif
379
- buffer = ''
380
- buffer << @packed_indexes
281
+ buffer = @packed_indexes.dup
381
282
  % for line in helpers.genEncodeMethodDefinition(spec, method):
382
283
  ${line}
383
284
  % endfor
@@ -385,9 +286,8 @@ module AMQ
385
286
  frames = [MethodFrame.new(buffer, channel)]
386
287
  % if "user_headers" in method.args():
387
288
  properties, headers = self.split_headers(user_headers)
388
- # TODO: what shall I do with the headers?
389
289
  if properties.nil? or properties.empty?
390
- raise RuntimeError.new("Properties can not be empty!") # TODO: or can they?
290
+ raise RuntimeError.new("Properties can not be empty!")
391
291
  end
392
292
  properties_payload = Basic.encode_properties(payload.bytesize, properties)
393
293
  frames << HeaderFrame.new(properties_payload, channel)
@@ -2,10 +2,10 @@
2
2
 
3
3
  require 'amq/endianness'
4
4
 
5
- # Ruby doesn't support pack to/unpack from
6
- # 64bit string in network byte order.
7
5
  module AMQ
8
- module Hacks
6
+ # Implements pack to/unpack from 64bit string in network byte order
7
+ # compatible with Ruby 1.8+.
8
+ module Pack
9
9
  UINT64 = "Q".freeze
10
10
  INT16 = "c".freeze
11
11
 
@@ -47,7 +47,7 @@ module AMQ
47
47
  end
48
48
  end
49
49
  end
50
- end
51
50
 
52
- # AMQ::Hacks.pack_uint64_big_endian(17)
53
- # AMQ::Hacks.unpack_uint64_big_endian("\x00\x00\x00\x00\x00\x00\x00\x11")
51
+ # Backwards compatibility
52
+ Hacks = Pack
53
+ end
@@ -4,35 +4,19 @@
4
4
  # IT DIRECTLY ! FOR CHANGES, PLEASE UPDATE FILES
5
5
  # IN THE ./codegen DIRECTORY OF THE AMQ-PROTOCOL REPOSITORY.
6
6
 
7
+ require "amq/pack"
8
+
7
9
  require "amq/protocol/table"
8
10
  require "amq/protocol/frame"
9
- require "amq/hacks"
11
+
12
+ require "amq/protocol/constants"
13
+ require "amq/protocol/exceptions"
10
14
 
11
15
  module AMQ
12
16
  module Protocol
13
17
  PROTOCOL_VERSION = "0.9.1".freeze
14
18
  PREAMBLE = "AMQP\x00\x00\x09\x01".freeze
15
19
  DEFAULT_PORT = 5672
16
- TLS_PORT = 5671
17
- SSL_PORT = 5671
18
-
19
- # caching
20
- EMPTY_STRING = "".freeze
21
-
22
- PACK_INT8 = 'c'.freeze
23
- PACK_CHAR = 'C'.freeze
24
- PACK_UINT16 = 'n'.freeze
25
- PACK_UINT16_X2 = 'n2'.freeze
26
- PACK_UINT32 = 'N'.freeze
27
- PACK_UINT32_X2 = 'N2'.freeze
28
- PACK_INT64 = 'q'.freeze
29
- PACK_UCHAR_UINT32 = 'CN'.freeze
30
- PACK_CHAR_UINT16_UINT32 = 'cnN'.freeze
31
-
32
- PACK_32BIT_FLOAT = 'f'.freeze
33
- PACK_64BIT_FLOAT = 'G'.freeze
34
-
35
-
36
20
 
37
21
  # @return [Array] Collection of subclasses of AMQ::Protocol::Class.
38
22
  def self.classes
@@ -44,63 +28,6 @@ module AMQ
44
28
  Protocol::Method.methods
45
29
  end
46
30
 
47
- class Error < StandardError
48
- DEFAULT_MESSAGE = "AMQP error".freeze
49
-
50
- def self.inherited(subclass)
51
- @_subclasses ||= []
52
- @_subclasses << subclass
53
- end # self.inherited(subclazz)
54
-
55
- def self.subclasses_with_values
56
- @_subclasses.select{ |k| defined?(k::VALUE) }
57
- end # self.subclasses_with_values
58
-
59
- def self.[](code)
60
- if result = subclasses_with_values.detect { |klass| klass::VALUE == code }
61
- result
62
- else
63
- raise "No such exception class for code #{code}" unless result
64
- end # if
65
- end # self.[]
66
-
67
- def initialize(message = self.class::DEFAULT_MESSAGE)
68
- super(message)
69
- end
70
- end
71
-
72
- class FrameTypeError < Protocol::Error
73
- def initialize(types)
74
- super("Must be one of #{types.inspect}")
75
- end
76
- end
77
-
78
- class EmptyResponseError < Protocol::Error
79
- DEFAULT_MESSAGE = "Empty response received from the server."
80
-
81
- def initialize(message = self.class::DEFAULT_MESSAGE)
82
- super(message)
83
- end
84
- end
85
-
86
- class BadResponseError < Protocol::Error
87
- def initialize(argument, expected, actual)
88
- super("Argument #{argument} has to be #{expected.inspect}, was #{data.inspect}")
89
- end
90
- end
91
-
92
- class SoftError < Protocol::Error
93
- def self.inherited(subclass)
94
- Error.inherited(subclass)
95
- end # self.inherited(subclass)
96
- end
97
-
98
- class HardError < Protocol::Error
99
- def self.inherited(subclass)
100
- Error.inherited(subclass)
101
- end # self.inherited(subclass)
102
- end
103
-
104
31
  class ContentTooLarge < SoftError
105
32
  VALUE = 311
106
33
  end
@@ -174,21 +101,6 @@ module AMQ
174
101
  end
175
102
 
176
103
 
177
- # We don't instantiate the following classes,
178
- # as we don't actually need any per-instance state.
179
- # Also, this is pretty low-level functionality,
180
- # hence it should have a reasonable performance.
181
- # As everyone knows, garbage collector in MRI performs
182
- # really badly, which is another good reason for
183
- # not creating any objects, but only use class as
184
- # a struct. Creating classes is quite expensive though,
185
- # but here the inheritance comes handy and mainly
186
- # as we can't simply make a reference to a function,
187
- # we can't use a hash or an object. I've been also
188
- # considering to have just a bunch of methods, but
189
- # here's the problem, that after we'd require this file,
190
- # all these methods would become global which would
191
- # be a bad, bad thing to do.
192
104
  class Class
193
105
  @classes = Array.new
194
106
 
@@ -258,6 +170,7 @@ module AMQ
258
170
  # 4 bytes of frame payload length
259
171
  # 1 byte of payload trailer FRAME_END byte
260
172
  limit = frame_size - 8
173
+ return [BodyFrame.new(body, channel)] if body.bytesize < limit
261
174
 
262
175
  # Otherwise String#slice on 1.9 will operate with code points,
263
176
  # and we need bytes. MK.
@@ -266,24 +179,14 @@ module AMQ
266
179
  array = Array.new
267
180
  while body
268
181
  payload, body = body[0, limit], body[limit, body.length - limit]
269
- # array << [0x03, payload]
270
182
  array << BodyFrame.new(payload, channel)
271
183
  end
272
184
 
273
185
  array
274
186
  end
275
187
 
276
- # We can return different:
277
- # - instantiate given subclass of Method
278
- # - create an OpenStruct object
279
- # - create a hash
280
- # - yield params into the block rather than just return
281
- # @api plugin
282
188
  def self.instantiate(*args, &block)
283
189
  self.new(*args, &block)
284
- # or OpenStruct.new(args.first)
285
- # or args.first
286
- # or block.call(*args)
287
190
  end
288
191
  end
289
192
 
@@ -351,8 +254,7 @@ module AMQ
351
254
  # [u'client_properties = nil', u"mechanism = u'PLAIN'", u'response = nil', u"locale = u'en_US'"]
352
255
  def self.encode(client_properties, mechanism, response, locale)
353
256
  channel = 0
354
- buffer = ''
355
- buffer << @packed_indexes
257
+ buffer = @packed_indexes.dup
356
258
  buffer << AMQ::Protocol::Table.encode(client_properties)
357
259
  buffer << mechanism.to_s.bytesize.chr
358
260
  buffer << mechanism.to_s
@@ -408,8 +310,7 @@ module AMQ
408
310
  # [u'response = nil']
409
311
  def self.encode(response)
410
312
  channel = 0
411
- buffer = ''
412
- buffer << @packed_indexes
313
+ buffer = @packed_indexes.dup
413
314
  buffer << [response.to_s.bytesize].pack(PACK_UINT32)
414
315
  buffer << response.to_s
415
316
  MethodFrame.new(buffer, channel)
@@ -464,8 +365,7 @@ module AMQ
464
365
  # [u'channel_max = false', u'frame_max = false', u'heartbeat = false']
465
366
  def self.encode(channel_max, frame_max, heartbeat)
466
367
  channel = 0
467
- buffer = ''
468
- buffer << @packed_indexes
368
+ buffer = @packed_indexes.dup
469
369
  buffer << [channel_max].pack(PACK_UINT16)
470
370
  buffer << [frame_max].pack(PACK_UINT32)
471
371
  buffer << [heartbeat].pack(PACK_UINT16)
@@ -491,8 +391,7 @@ module AMQ
491
391
  capabilities = EMPTY_STRING
492
392
  insist = false
493
393
  channel = 0
494
- buffer = ''
495
- buffer << @packed_indexes
394
+ buffer = @packed_indexes.dup
496
395
  buffer << virtual_host.to_s.bytesize.chr
497
396
  buffer << virtual_host.to_s
498
397
  buffer << capabilities.to_s.bytesize.chr
@@ -571,8 +470,7 @@ module AMQ
571
470
  # [u'reply_code = nil', u'reply_text = EMPTY_STRING', u'class_id = nil', u'method_id = nil']
572
471
  def self.encode(reply_code, reply_text, class_id, method_id)
573
472
  channel = 0
574
- buffer = ''
575
- buffer << @packed_indexes
473
+ buffer = @packed_indexes.dup
576
474
  buffer << [reply_code].pack(PACK_UINT16)
577
475
  buffer << reply_text.to_s.bytesize.chr
578
476
  buffer << reply_text.to_s
@@ -606,8 +504,7 @@ module AMQ
606
504
  # []
607
505
  def self.encode()
608
506
  channel = 0
609
- buffer = ''
610
- buffer << @packed_indexes
507
+ buffer = @packed_indexes.dup
611
508
  MethodFrame.new(buffer, channel)
612
509
  end
613
510
 
@@ -635,8 +532,7 @@ module AMQ
635
532
  # @return
636
533
  # [u'out_of_band = EMPTY_STRING']
637
534
  def self.encode(channel, out_of_band)
638
- buffer = ''
639
- buffer << @packed_indexes
535
+ buffer = @packed_indexes.dup
640
536
  buffer << out_of_band.to_s.bytesize.chr
641
537
  buffer << out_of_band.to_s
642
538
  MethodFrame.new(buffer, channel)
@@ -699,8 +595,7 @@ module AMQ
699
595
  # @return
700
596
  # [u'active = nil']
701
597
  def self.encode(channel, active)
702
- buffer = ''
703
- buffer << @packed_indexes
598
+ buffer = @packed_indexes.dup
704
599
  bit_buffer = 0
705
600
  bit_buffer = bit_buffer | (1 << 0) if active
706
601
  buffer << [bit_buffer].pack(PACK_CHAR)
@@ -736,8 +631,7 @@ module AMQ
736
631
  # @return
737
632
  # [u'active = nil']
738
633
  def self.encode(channel, active)
739
- buffer = ''
740
- buffer << @packed_indexes
634
+ buffer = @packed_indexes.dup
741
635
  bit_buffer = 0
742
636
  bit_buffer = bit_buffer | (1 << 0) if active
743
637
  buffer << [bit_buffer].pack(PACK_CHAR)
@@ -783,8 +677,7 @@ module AMQ
783
677
  # @return
784
678
  # [u'reply_code = nil', u'reply_text = EMPTY_STRING', u'class_id = nil', u'method_id = nil']
785
679
  def self.encode(channel, reply_code, reply_text, class_id, method_id)
786
- buffer = ''
787
- buffer << @packed_indexes
680
+ buffer = @packed_indexes.dup
788
681
  buffer << [reply_code].pack(PACK_UINT16)
789
682
  buffer << reply_text.to_s.bytesize.chr
790
683
  buffer << reply_text.to_s
@@ -817,8 +710,7 @@ module AMQ
817
710
  # @return
818
711
  # []
819
712
  def self.encode(channel)
820
- buffer = ''
821
- buffer << @packed_indexes
713
+ buffer = @packed_indexes.dup
822
714
  MethodFrame.new(buffer, channel)
823
715
  end
824
716
 
@@ -847,8 +739,7 @@ module AMQ
847
739
  # [u'ticket = 0', u'exchange = nil', u"type = u'direct'", u'passive = false', u'durable = false', u'auto_delete = false', u'internal = false', u'nowait = false', u'arguments = {}']
848
740
  def self.encode(channel, exchange, type, passive, durable, auto_delete, internal, nowait, arguments)
849
741
  ticket = 0
850
- buffer = ''
851
- buffer << @packed_indexes
742
+ buffer = @packed_indexes.dup
852
743
  buffer << [ticket].pack(PACK_UINT16)
853
744
  buffer << exchange.to_s.bytesize.chr
854
745
  buffer << exchange.to_s
@@ -904,8 +795,7 @@ module AMQ
904
795
  # [u'ticket = 0', u'exchange = nil', u'if_unused = false', u'nowait = false']
905
796
  def self.encode(channel, exchange, if_unused, nowait)
906
797
  ticket = 0
907
- buffer = ''
908
- buffer << @packed_indexes
798
+ buffer = @packed_indexes.dup
909
799
  buffer << [ticket].pack(PACK_UINT16)
910
800
  buffer << exchange.to_s.bytesize.chr
911
801
  buffer << exchange.to_s
@@ -955,8 +845,7 @@ module AMQ
955
845
  # [u'ticket = 0', u'destination = nil', u'source = nil', u'routing_key = EMPTY_STRING', u'nowait = false', u'arguments = {}']
956
846
  def self.encode(channel, destination, source, routing_key, nowait, arguments)
957
847
  ticket = 0
958
- buffer = ''
959
- buffer << @packed_indexes
848
+ buffer = @packed_indexes.dup
960
849
  buffer << [ticket].pack(PACK_UINT16)
961
850
  buffer << destination.to_s.bytesize.chr
962
851
  buffer << destination.to_s
@@ -1010,8 +899,7 @@ module AMQ
1010
899
  # [u'ticket = 0', u'destination = nil', u'source = nil', u'routing_key = EMPTY_STRING', u'nowait = false', u'arguments = {}']
1011
900
  def self.encode(channel, destination, source, routing_key, nowait, arguments)
1012
901
  ticket = 0
1013
- buffer = ''
1014
- buffer << @packed_indexes
902
+ buffer = @packed_indexes.dup
1015
903
  buffer << [ticket].pack(PACK_UINT16)
1016
904
  buffer << destination.to_s.bytesize.chr
1017
905
  buffer << destination.to_s
@@ -1073,8 +961,7 @@ module AMQ
1073
961
  # [u'ticket = 0', u'queue = EMPTY_STRING', u'passive = false', u'durable = false', u'exclusive = false', u'auto_delete = false', u'nowait = false', u'arguments = {}']
1074
962
  def self.encode(channel, queue, passive, durable, exclusive, auto_delete, nowait, arguments)
1075
963
  ticket = 0
1076
- buffer = ''
1077
- buffer << @packed_indexes
964
+ buffer = @packed_indexes.dup
1078
965
  buffer << [ticket].pack(PACK_UINT16)
1079
966
  buffer << queue.to_s.bytesize.chr
1080
967
  buffer << queue.to_s
@@ -1140,8 +1027,7 @@ module AMQ
1140
1027
  # [u'ticket = 0', u'queue = EMPTY_STRING', u'exchange = nil', u'routing_key = EMPTY_STRING', u'nowait = false', u'arguments = {}']
1141
1028
  def self.encode(channel, queue, exchange, routing_key, nowait, arguments)
1142
1029
  ticket = 0
1143
- buffer = ''
1144
- buffer << @packed_indexes
1030
+ buffer = @packed_indexes.dup
1145
1031
  buffer << [ticket].pack(PACK_UINT16)
1146
1032
  buffer << queue.to_s.bytesize.chr
1147
1033
  buffer << queue.to_s
@@ -1195,8 +1081,7 @@ module AMQ
1195
1081
  # [u'ticket = 0', u'queue = EMPTY_STRING', u'nowait = false']
1196
1082
  def self.encode(channel, queue, nowait)
1197
1083
  ticket = 0
1198
- buffer = ''
1199
- buffer << @packed_indexes
1084
+ buffer = @packed_indexes.dup
1200
1085
  buffer << [ticket].pack(PACK_UINT16)
1201
1086
  buffer << queue.to_s.bytesize.chr
1202
1087
  buffer << queue.to_s
@@ -1249,8 +1134,7 @@ module AMQ
1249
1134
  # [u'ticket = 0', u'queue = EMPTY_STRING', u'if_unused = false', u'if_empty = false', u'nowait = false']
1250
1135
  def self.encode(channel, queue, if_unused, if_empty, nowait)
1251
1136
  ticket = 0
1252
- buffer = ''
1253
- buffer << @packed_indexes
1137
+ buffer = @packed_indexes.dup
1254
1138
  buffer << [ticket].pack(PACK_UINT16)
1255
1139
  buffer << queue.to_s.bytesize.chr
1256
1140
  buffer << queue.to_s
@@ -1305,8 +1189,7 @@ module AMQ
1305
1189
  # [u'ticket = 0', u'queue = EMPTY_STRING', u'exchange = nil', u'routing_key = EMPTY_STRING', u'arguments = {}']
1306
1190
  def self.encode(channel, queue, exchange, routing_key, arguments)
1307
1191
  ticket = 0
1308
- buffer = ''
1309
- buffer << @packed_indexes
1192
+ buffer = @packed_indexes.dup
1310
1193
  buffer << [ticket].pack(PACK_UINT16)
1311
1194
  buffer << queue.to_s.bytesize.chr
1312
1195
  buffer << queue.to_s
@@ -1437,7 +1320,7 @@ module AMQ
1437
1320
  # 1 << 6
1438
1321
  def self.encode_timestamp(value)
1439
1322
  buffer = ''
1440
- buffer << AMQ::Hacks.pack_uint64_big_endian(value)
1323
+ buffer << AMQ::Pack.pack_uint64_big_endian(value)
1441
1324
  [9, 0x0040, buffer]
1442
1325
  end
1443
1326
 
@@ -1486,7 +1369,7 @@ module AMQ
1486
1369
 
1487
1370
  # result = [60, 0, body_size, flags].pack('n2Qn')
1488
1371
  result = [60, 0].pack(PACK_UINT16_X2)
1489
- result += AMQ::Hacks.pack_uint64_big_endian(body_size)
1372
+ result += AMQ::Pack.pack_uint64_big_endian(body_size)
1490
1373
  result += [flags].pack(PACK_UINT16)
1491
1374
  result + pieces.join(EMPTY_STRING)
1492
1375
  end
@@ -1592,8 +1475,7 @@ module AMQ
1592
1475
  # @return
1593
1476
  # [u'prefetch_size = false', u'prefetch_count = false', u'global = false']
1594
1477
  def self.encode(channel, prefetch_size, prefetch_count, global)
1595
- buffer = ''
1596
- buffer << @packed_indexes
1478
+ buffer = @packed_indexes.dup
1597
1479
  buffer << [prefetch_size].pack(PACK_UINT32)
1598
1480
  buffer << [prefetch_count].pack(PACK_UINT16)
1599
1481
  bit_buffer = 0
@@ -1641,8 +1523,7 @@ module AMQ
1641
1523
  # [u'ticket = 0', u'queue = EMPTY_STRING', u'consumer_tag = EMPTY_STRING', u'no_local = false', u'no_ack = false', u'exclusive = false', u'nowait = false', u'arguments = {}']
1642
1524
  def self.encode(channel, queue, consumer_tag, no_local, no_ack, exclusive, nowait, arguments)
1643
1525
  ticket = 0
1644
- buffer = ''
1645
- buffer << @packed_indexes
1526
+ buffer = @packed_indexes.dup
1646
1527
  buffer << [ticket].pack(PACK_UINT16)
1647
1528
  buffer << queue.to_s.bytesize.chr
1648
1529
  buffer << queue.to_s
@@ -1720,8 +1601,7 @@ module AMQ
1720
1601
  # @return
1721
1602
  # [u'consumer_tag = nil', u'nowait = false']
1722
1603
  def self.encode(channel, consumer_tag, nowait)
1723
- buffer = ''
1724
- buffer << @packed_indexes
1604
+ buffer = @packed_indexes.dup
1725
1605
  buffer << consumer_tag.to_s.bytesize.chr
1726
1606
  buffer << consumer_tag.to_s
1727
1607
  bit_buffer = 0
@@ -1775,8 +1655,7 @@ module AMQ
1775
1655
  # [u'ticket = 0', u'exchange = EMPTY_STRING', u'routing_key = EMPTY_STRING', u'mandatory = false', u'immediate = false', 'user_headers = nil', 'payload = ""', 'frame_size = nil']
1776
1656
  def self.encode(channel, payload, user_headers, exchange, routing_key, mandatory, immediate, frame_size)
1777
1657
  ticket = 0
1778
- buffer = ''
1779
- buffer << @packed_indexes
1658
+ buffer = @packed_indexes.dup
1780
1659
  buffer << [ticket].pack(PACK_UINT16)
1781
1660
  buffer << exchange.to_s.bytesize.chr
1782
1661
  buffer << exchange.to_s
@@ -1788,9 +1667,8 @@ module AMQ
1788
1667
  buffer << [bit_buffer].pack(PACK_CHAR)
1789
1668
  frames = [MethodFrame.new(buffer, channel)]
1790
1669
  properties, headers = self.split_headers(user_headers)
1791
- # TODO: what shall I do with the headers?
1792
1670
  if properties.nil? or properties.empty?
1793
- raise RuntimeError.new("Properties can not be empty!") # TODO: or can they?
1671
+ raise RuntimeError.new("Properties can not be empty!")
1794
1672
  end
1795
1673
  properties_payload = Basic.encode_properties(payload.bytesize, properties)
1796
1674
  frames << HeaderFrame.new(properties_payload, channel)
@@ -1854,7 +1732,7 @@ module AMQ
1854
1732
  offset += 1
1855
1733
  consumer_tag = data[offset, length]
1856
1734
  offset += length
1857
- delivery_tag = AMQ::Hacks.unpack_uint64_big_endian(data[offset, 8]).first
1735
+ delivery_tag = AMQ::Pack.unpack_uint64_big_endian(data[offset, 8]).first
1858
1736
  offset += 8
1859
1737
  bit_buffer = data[offset, 1].unpack(PACK_CHAR).first
1860
1738
  offset += 1
@@ -1901,8 +1779,7 @@ module AMQ
1901
1779
  # [u'ticket = 0', u'queue = EMPTY_STRING', u'no_ack = false']
1902
1780
  def self.encode(channel, queue, no_ack)
1903
1781
  ticket = 0
1904
- buffer = ''
1905
- buffer << @packed_indexes
1782
+ buffer = @packed_indexes.dup
1906
1783
  buffer << [ticket].pack(PACK_UINT16)
1907
1784
  buffer << queue.to_s.bytesize.chr
1908
1785
  buffer << queue.to_s
@@ -1923,7 +1800,7 @@ module AMQ
1923
1800
  # @return
1924
1801
  def self.decode(data)
1925
1802
  offset = 0
1926
- delivery_tag = AMQ::Hacks.unpack_uint64_big_endian(data[offset, 8]).first
1803
+ delivery_tag = AMQ::Pack.unpack_uint64_big_endian(data[offset, 8]).first
1927
1804
  offset += 8
1928
1805
  bit_buffer = data[offset, 1].unpack(PACK_CHAR).first
1929
1806
  offset += 1
@@ -1994,7 +1871,7 @@ module AMQ
1994
1871
  # @return
1995
1872
  def self.decode(data)
1996
1873
  offset = 0
1997
- delivery_tag = AMQ::Hacks.unpack_uint64_big_endian(data[offset, 8]).first
1874
+ delivery_tag = AMQ::Pack.unpack_uint64_big_endian(data[offset, 8]).first
1998
1875
  offset += 8
1999
1876
  bit_buffer = data[offset, 1].unpack(PACK_CHAR).first
2000
1877
  offset += 1
@@ -2015,9 +1892,8 @@ module AMQ
2015
1892
  # @return
2016
1893
  # [u'delivery_tag = false', u'multiple = false']
2017
1894
  def self.encode(channel, delivery_tag, multiple)
2018
- buffer = ''
2019
- buffer << @packed_indexes
2020
- buffer << AMQ::Hacks.pack_uint64_big_endian(delivery_tag)
1895
+ buffer = @packed_indexes.dup
1896
+ buffer << AMQ::Pack.pack_uint64_big_endian(delivery_tag)
2021
1897
  bit_buffer = 0
2022
1898
  bit_buffer = bit_buffer | (1 << 0) if multiple
2023
1899
  buffer << [bit_buffer].pack(PACK_CHAR)
@@ -2040,9 +1916,8 @@ module AMQ
2040
1916
  # @return
2041
1917
  # [u'delivery_tag = nil', u'requeue = true']
2042
1918
  def self.encode(channel, delivery_tag, requeue)
2043
- buffer = ''
2044
- buffer << @packed_indexes
2045
- buffer << AMQ::Hacks.pack_uint64_big_endian(delivery_tag)
1919
+ buffer = @packed_indexes.dup
1920
+ buffer << AMQ::Pack.pack_uint64_big_endian(delivery_tag)
2046
1921
  bit_buffer = 0
2047
1922
  bit_buffer = bit_buffer | (1 << 0) if requeue
2048
1923
  buffer << [bit_buffer].pack(PACK_CHAR)
@@ -2065,8 +1940,7 @@ module AMQ
2065
1940
  # @return
2066
1941
  # [u'requeue = false']
2067
1942
  def self.encode(channel, requeue)
2068
- buffer = ''
2069
- buffer << @packed_indexes
1943
+ buffer = @packed_indexes.dup
2070
1944
  bit_buffer = 0
2071
1945
  bit_buffer = bit_buffer | (1 << 0) if requeue
2072
1946
  buffer << [bit_buffer].pack(PACK_CHAR)
@@ -2089,8 +1963,7 @@ module AMQ
2089
1963
  # @return
2090
1964
  # [u'requeue = false']
2091
1965
  def self.encode(channel, requeue)
2092
- buffer = ''
2093
- buffer << @packed_indexes
1966
+ buffer = @packed_indexes.dup
2094
1967
  bit_buffer = 0
2095
1968
  bit_buffer = bit_buffer | (1 << 0) if requeue
2096
1969
  buffer << [bit_buffer].pack(PACK_CHAR)
@@ -2130,7 +2003,7 @@ module AMQ
2130
2003
  # @return
2131
2004
  def self.decode(data)
2132
2005
  offset = 0
2133
- delivery_tag = AMQ::Hacks.unpack_uint64_big_endian(data[offset, 8]).first
2006
+ delivery_tag = AMQ::Pack.unpack_uint64_big_endian(data[offset, 8]).first
2134
2007
  offset += 8
2135
2008
  bit_buffer = data[offset, 1].unpack(PACK_CHAR).first
2136
2009
  offset += 1
@@ -2153,9 +2026,8 @@ module AMQ
2153
2026
  # @return
2154
2027
  # [u'delivery_tag = false', u'multiple = false', u'requeue = true']
2155
2028
  def self.encode(channel, delivery_tag, multiple, requeue)
2156
- buffer = ''
2157
- buffer << @packed_indexes
2158
- buffer << AMQ::Hacks.pack_uint64_big_endian(delivery_tag)
2029
+ buffer = @packed_indexes.dup
2030
+ buffer << AMQ::Pack.pack_uint64_big_endian(delivery_tag)
2159
2031
  bit_buffer = 0
2160
2032
  bit_buffer = bit_buffer | (1 << 0) if multiple
2161
2033
  bit_buffer = bit_buffer | (1 << 1) if requeue
@@ -2200,8 +2072,7 @@ module AMQ
2200
2072
  # @return
2201
2073
  # [u'consumer_tag = EMPTY_STRING', u'credit = nil', u'drain = nil']
2202
2074
  def self.encode(channel, consumer_tag, credit, drain)
2203
- buffer = ''
2204
- buffer << @packed_indexes
2075
+ buffer = @packed_indexes.dup
2205
2076
  buffer << consumer_tag.to_s.bytesize.chr
2206
2077
  buffer << consumer_tag.to_s
2207
2078
  buffer << [credit].pack(PACK_UINT32)
@@ -2239,8 +2110,7 @@ module AMQ
2239
2110
  # @return
2240
2111
  # [u'available = nil']
2241
2112
  def self.encode(channel, available)
2242
- buffer = ''
2243
- buffer << @packed_indexes
2113
+ buffer = @packed_indexes.dup
2244
2114
  buffer << [available].pack(PACK_UINT32)
2245
2115
  MethodFrame.new(buffer, channel)
2246
2116
  end
@@ -2278,8 +2148,7 @@ module AMQ
2278
2148
  # @return
2279
2149
  # [u'consumer_tag = EMPTY_STRING', u'credit_drained = nil']
2280
2150
  def self.encode(channel, consumer_tag, credit_drained)
2281
- buffer = ''
2282
- buffer << @packed_indexes
2151
+ buffer = @packed_indexes.dup
2283
2152
  buffer << consumer_tag.to_s.bytesize.chr
2284
2153
  buffer << consumer_tag.to_s
2285
2154
  buffer << [credit_drained].pack(PACK_UINT32)
@@ -2310,8 +2179,7 @@ module AMQ
2310
2179
  # @return
2311
2180
  # []
2312
2181
  def self.encode(channel)
2313
- buffer = ''
2314
- buffer << @packed_indexes
2182
+ buffer = @packed_indexes.dup
2315
2183
  MethodFrame.new(buffer, channel)
2316
2184
  end
2317
2185
 
@@ -2353,8 +2221,7 @@ module AMQ
2353
2221
  # @return
2354
2222
  # []
2355
2223
  def self.encode(channel)
2356
- buffer = ''
2357
- buffer << @packed_indexes
2224
+ buffer = @packed_indexes.dup
2358
2225
  MethodFrame.new(buffer, channel)
2359
2226
  end
2360
2227
 
@@ -2396,8 +2263,7 @@ module AMQ
2396
2263
  # @return
2397
2264
  # []
2398
2265
  def self.encode(channel)
2399
- buffer = ''
2400
- buffer << @packed_indexes
2266
+ buffer = @packed_indexes.dup
2401
2267
  MethodFrame.new(buffer, channel)
2402
2268
  end
2403
2269
 
@@ -2460,8 +2326,7 @@ module AMQ
2460
2326
  # @return
2461
2327
  # [u'nowait = false']
2462
2328
  def self.encode(channel, nowait)
2463
- buffer = ''
2464
- buffer << @packed_indexes
2329
+ buffer = @packed_indexes.dup
2465
2330
  bit_buffer = 0
2466
2331
  bit_buffer = bit_buffer | (1 << 0) if nowait
2467
2332
  buffer << [bit_buffer].pack(PACK_CHAR)
@@ -2492,8 +2357,7 @@ module AMQ
2492
2357
  # @return
2493
2358
  # []
2494
2359
  def self.encode(channel)
2495
- buffer = ''
2496
- buffer << @packed_indexes
2360
+ buffer = @packed_indexes.dup
2497
2361
  MethodFrame.new(buffer, channel)
2498
2362
  end
2499
2363