bunny 0.6.3.rc2 → 0.7

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 (68) hide show
  1. data/.gitignore +8 -0
  2. data/.rspec +3 -0
  3. data/.travis.yml +15 -0
  4. data/.yardopts +9 -0
  5. data/CHANGELOG +3 -0
  6. data/Gemfile +39 -0
  7. data/Gemfile.lock +34 -0
  8. data/LICENSE +5 -4
  9. data/README.textile +54 -0
  10. data/Rakefile +15 -13
  11. data/bunny.gemspec +42 -61
  12. data/examples/simple_08.rb +4 -2
  13. data/examples/simple_09.rb +4 -2
  14. data/examples/simple_ack_08.rb +3 -1
  15. data/examples/simple_ack_09.rb +3 -1
  16. data/examples/simple_consumer_08.rb +4 -2
  17. data/examples/simple_consumer_09.rb +4 -2
  18. data/examples/simple_fanout_08.rb +3 -1
  19. data/examples/simple_fanout_09.rb +3 -1
  20. data/examples/simple_headers_08.rb +5 -3
  21. data/examples/simple_headers_09.rb +5 -3
  22. data/examples/simple_publisher_08.rb +3 -1
  23. data/examples/simple_publisher_09.rb +3 -1
  24. data/examples/simple_topic_08.rb +5 -3
  25. data/examples/simple_topic_09.rb +5 -3
  26. data/ext/amqp-0.8.json +616 -0
  27. data/ext/amqp-0.9.1.json +388 -0
  28. data/ext/config.yml +4 -0
  29. data/ext/qparser.rb +463 -0
  30. data/lib/bunny.rb +88 -66
  31. data/lib/bunny/channel08.rb +38 -38
  32. data/lib/bunny/channel09.rb +37 -37
  33. data/lib/bunny/client08.rb +184 -206
  34. data/lib/bunny/client09.rb +277 -363
  35. data/lib/bunny/consumer.rb +35 -0
  36. data/lib/bunny/exchange08.rb +37 -41
  37. data/lib/bunny/exchange09.rb +106 -124
  38. data/lib/bunny/queue08.rb +216 -202
  39. data/lib/bunny/queue09.rb +256 -326
  40. data/lib/bunny/subscription08.rb +30 -29
  41. data/lib/bunny/subscription09.rb +84 -83
  42. data/lib/bunny/version.rb +5 -0
  43. data/lib/qrack/amq-client-url.rb +165 -0
  44. data/lib/qrack/channel.rb +19 -17
  45. data/lib/qrack/client.rb +152 -151
  46. data/lib/qrack/errors.rb +5 -0
  47. data/lib/qrack/protocol/protocol08.rb +132 -130
  48. data/lib/qrack/protocol/protocol09.rb +133 -131
  49. data/lib/qrack/protocol/spec08.rb +2 -0
  50. data/lib/qrack/protocol/spec09.rb +2 -0
  51. data/lib/qrack/qrack08.rb +7 -10
  52. data/lib/qrack/qrack09.rb +7 -10
  53. data/lib/qrack/queue.rb +27 -40
  54. data/lib/qrack/subscription.rb +102 -101
  55. data/lib/qrack/transport/buffer08.rb +266 -264
  56. data/lib/qrack/transport/buffer09.rb +268 -264
  57. data/lib/qrack/transport/frame08.rb +13 -11
  58. data/lib/qrack/transport/frame09.rb +9 -7
  59. data/spec/spec_08/bunny_spec.rb +48 -45
  60. data/spec/spec_08/connection_spec.rb +10 -7
  61. data/spec/spec_08/exchange_spec.rb +145 -143
  62. data/spec/spec_08/queue_spec.rb +161 -161
  63. data/spec/spec_09/bunny_spec.rb +46 -44
  64. data/spec/spec_09/connection_spec.rb +15 -8
  65. data/spec/spec_09/exchange_spec.rb +147 -145
  66. data/spec/spec_09/queue_spec.rb +182 -184
  67. metadata +60 -41
  68. data/README.rdoc +0 -66
@@ -1,3 +1,5 @@
1
+ # encoding: utf-8
2
+
1
3
  if [].map.respond_to? :with_index
2
4
  class Array #:nodoc:
3
5
  def enum_with_index
@@ -9,268 +11,270 @@ else
9
11
  end
10
12
 
11
13
  module Qrack
12
- module Transport09 #:nodoc: all
13
- class Buffer
14
-
15
- def initialize data = ''
16
- @data = data
17
- @pos = 0
18
- end
19
-
20
- attr_reader :pos
21
-
22
- def data
23
- @data.clone
24
- end
25
- alias :contents :data
26
- alias :to_s :data
27
-
28
- def << data
29
- @data << data.to_s
30
- self
31
- end
32
-
33
- def length
34
- @data.bytesize
35
- end
36
-
37
- def empty?
38
- pos == length
39
- end
40
-
41
- def rewind
42
- @pos = 0
43
- end
44
-
45
- def read_properties *types
46
- types.shift if types.first == :properties
47
-
48
- i = 0
49
- values = []
50
-
51
- while props = read(:short)
52
- (0..14).each do |n|
53
- # no more property types
54
- break unless types[i]
55
-
56
- # if flag is set
57
- if props & (1<<(15-n)) != 0
58
- if types[i] == :bit
59
- # bit values exist in flags only
60
- values << true
61
- else
62
- # save type name for later reading
63
- values << types[i]
64
- end
65
- else
66
- # property not set or is false bit
67
- values << (types[i] == :bit ? false : nil)
68
- end
69
-
70
- i+=1
71
- end
72
-
73
- # bit(0) == 0 means no more property flags
74
- break unless props & 1 == 1
75
- end
76
-
77
- values.map do |value|
78
- value.is_a?(Symbol) ? read(value) : value
79
- end
80
- end
81
-
82
- def read *types
83
- if types.first == :properties
84
- return read_properties(*types)
85
- end
86
-
87
- values = types.map do |type|
88
- case type
89
- when :octet
90
- _read(1, 'C')
91
- when :short
92
- _read(2, 'n')
93
- when :long
94
- _read(4, 'N')
95
- when :longlong
96
- upper, lower = _read(8, 'NN')
97
- upper << 32 | lower
98
- when :shortstr
99
- _read read(:octet)
100
- when :longstr
101
- _read read(:long)
102
- when :timestamp
103
- Time.at read(:longlong)
104
- when :table
105
- t = Hash.new
106
-
107
- table = Buffer.new(read(:longstr))
108
- until table.empty?
109
- key, type = table.read(:shortstr, :octet)
110
- key = key.intern
111
- t[key] ||= case type
112
- when 83 # 'S'
113
- table.read(:longstr)
114
- when 73 # 'I'
115
- table.read(:long)
116
- when 68 # 'D'
117
- exp = table.read(:octet)
118
- num = table.read(:long)
119
- num / 10.0**exp
120
- when 84 # 'T'
121
- table.read(:timestamp)
122
- when 70 # 'F'
123
- table.read(:table)
124
- end
125
- end
126
-
127
- t
128
- when :bit
129
- if (@bits ||= []).empty?
130
- val = read(:octet)
131
- @bits = (0..7).map{|i| (val & 1<<i) != 0 }
132
- end
133
-
134
- @bits.shift
135
- else
136
- raise Qrack::InvalidTypeError, "Cannot read data of type #{type}"
137
- end
138
- end
139
-
140
- types.size == 1 ? values.first : values
141
- end
142
-
143
- def write type, data
144
- case type
145
- when :octet
146
- _write(data, 'C')
147
- when :short
148
- _write(data, 'n')
149
- when :long
150
- _write(data, 'N')
151
- when :longlong
152
- lower = data & 0xffffffff
153
- upper = (data & ~0xffffffff) >> 32
154
- _write([upper, lower], 'NN')
155
- when :shortstr
156
- data = (data || '').to_s
157
- _write([data.bytesize, data], 'Ca*')
158
- when :longstr
159
- if data.is_a? Hash
160
- write(:table, data)
161
- else
162
- data = (data || '').to_s
163
- _write([data.bytesize, data], 'Na*')
164
- end
165
- when :timestamp
166
- write(:longlong, data.to_i)
167
- when :table
168
- data ||= {}
169
- write :longstr, (data.inject(Buffer.new) do |table, (key, value)|
170
- table.write(:shortstr, key.to_s)
171
-
172
- case value
173
- when String
174
- table.write(:octet, 83) # 'S'
175
- table.write(:longstr, value.to_s)
176
- when Fixnum
177
- table.write(:octet, 73) # 'I'
178
- table.write(:long, value)
179
- when Float
180
- table.write(:octet, 68) # 'D'
181
- # XXX there's gotta be a better way to do this..
182
- exp = value.to_s.split('.').last.bytesize
183
- num = value * 10**exp
184
- table.write(:octet, exp)
185
- table.write(:long, num)
186
- when Time
187
- table.write(:octet, 84) # 'T'
188
- table.write(:timestamp, value)
189
- when Hash
190
- table.write(:octet, 70) # 'F'
191
- table.write(:table, value)
192
- end
193
-
194
- table
195
- end)
196
- when :bit
197
- [*data].to_enum(:each_slice, 8).each{|bits|
198
- write(:octet, bits.enum_with_index.inject(0){ |byte, (bit, i)|
199
- byte |= 1<<i if bit
200
- byte
201
- })
202
- }
203
- when :properties
204
- values = []
205
- data.enum_with_index.inject(0) do |short, ((type, value), i)|
206
- n = i % 15
207
- last = i+1 == data.size
208
-
209
- if (n == 0 and i != 0) or last
210
- if data.size > i+1
211
- short |= 1<<0
212
- elsif last and value
213
- values << [type,value]
214
- short |= 1<<(15-n)
215
- end
216
-
217
- write(:short, short)
218
- short = 0
219
- end
220
-
221
- if value and !last
222
- values << [type,value]
223
- short |= 1<<(15-n)
224
- end
225
-
226
- short
227
- end
228
-
229
- values.each do |type, value|
230
- write(type, value) unless type == :bit
231
- end
232
- else
233
- raise Qrack::InvalidTypeError, "Cannot write data of type #{type}"
234
- end
235
-
236
- self
237
- end
238
-
239
- def extract
240
- begin
241
- cur_data, cur_pos = @data.clone, @pos
242
- yield self
243
- rescue Qrack::BufferOverflowError
244
- @data, @pos = cur_data, cur_pos
245
- nil
246
- end
247
- end
248
-
249
- def _read(size, pack = nil)
250
- if @data.is_a?(Qrack::Client)
251
- raw = @data.read(size)
252
- return raw if raw.nil? or pack.nil?
253
- return raw.unpack(pack).first
254
- end
255
-
256
- if @pos + size > length
257
- raise Qrack::BufferOverflowError
258
- else
259
- data = @data[@pos,size]
260
- @data[@pos,size] = ''
261
- if pack
262
- data = data.unpack(pack)
263
- data = data.pop if data.size == 1
264
- end
265
- data
266
- end
267
- end
268
-
269
- def _write data, pack = nil
270
- data = [*data].pack(pack) if pack
271
- @data[@pos,0] = data
272
- @pos += data.bytesize
273
- end
274
- end
275
- end
14
+ module Transport09 #:nodoc: all
15
+ class Buffer
16
+
17
+ def initialize data = ''
18
+ @data = data
19
+ @pos = 0
20
+ end
21
+
22
+ attr_reader :pos
23
+
24
+ def data
25
+ @data.clone
26
+ end
27
+ alias :contents :data
28
+ alias :to_s :data
29
+
30
+ def << data
31
+ @data << data.to_s
32
+ self
33
+ end
34
+
35
+ def length
36
+ @data.bytesize
37
+ end
38
+
39
+ def empty?
40
+ pos == length
41
+ end
42
+
43
+ def rewind
44
+ @pos = 0
45
+ end
46
+
47
+ def read_properties *types
48
+ types.shift if types.first == :properties
49
+
50
+ i = 0
51
+ values = []
52
+
53
+ while props = read(:short)
54
+ (0..14).each do |n|
55
+ # no more property types
56
+ break unless types[i]
57
+
58
+ # if flag is set
59
+ if props & (1<<(15-n)) != 0
60
+ if types[i] == :bit
61
+ # bit values exist in flags only
62
+ values << true
63
+ else
64
+ # save type name for later reading
65
+ values << types[i]
66
+ end
67
+ else
68
+ # property not set or is false bit
69
+ values << (types[i] == :bit ? false : nil)
70
+ end
71
+
72
+ i+=1
73
+ end
74
+
75
+ # bit(0) == 0 means no more property flags
76
+ break unless props & 1 == 1
77
+ end
78
+
79
+ values.map do |value|
80
+ value.is_a?(Symbol) ? read(value) : value
81
+ end
82
+ end
83
+
84
+ def read *types
85
+ if types.first == :properties
86
+ return read_properties(*types)
87
+ end
88
+
89
+ values = types.map do |type|
90
+ case type
91
+ when :octet
92
+ _read(1, 'C')
93
+ when :short
94
+ _read(2, 'n')
95
+ when :long
96
+ _read(4, 'N')
97
+ when :longlong
98
+ upper, lower = _read(8, 'NN')
99
+ upper << 32 | lower
100
+ when :shortstr
101
+ _read read(:octet)
102
+ when :longstr
103
+ _read read(:long)
104
+ when :timestamp
105
+ Time.at read(:longlong)
106
+ when :table
107
+ t = Hash.new
108
+
109
+ table = Buffer.new(read(:longstr))
110
+ until table.empty?
111
+ key, type = table.read(:shortstr, :octet)
112
+ key = key.intern
113
+ t[key] ||= case type
114
+ when 83 # 'S'
115
+ table.read(:longstr)
116
+ when 73 # 'I'
117
+ table.read(:long)
118
+ when 68 # 'D'
119
+ exp = table.read(:octet)
120
+ num = table.read(:long)
121
+ num / 10.0**exp
122
+ when 84 # 'T'
123
+ table.read(:timestamp)
124
+ when 70 # 'F'
125
+ table.read(:table)
126
+ when 116 # 't'
127
+ table.read(:octet)
128
+ end
129
+ end
130
+
131
+ t
132
+ when :bit
133
+ if (@bits ||= []).empty?
134
+ val = read(:octet)
135
+ @bits = (0..7).map{|i| (val & (1 << i)) != 0 }
136
+ end
137
+
138
+ @bits.shift
139
+ else
140
+ raise Qrack::InvalidTypeError, "Cannot read data of type #{type}"
141
+ end
142
+ end
143
+
144
+ types.size == 1 ? values.first : values
145
+ end
146
+
147
+ def write type, data
148
+ case type
149
+ when :octet
150
+ _write(data, 'C')
151
+ when :short
152
+ _write(data, 'n')
153
+ when :long
154
+ _write(data, 'N')
155
+ when :longlong
156
+ lower = data & 0xffffffff
157
+ upper = (data & ~0xffffffff) >> 32
158
+ _write([upper, lower], 'NN')
159
+ when :shortstr
160
+ data = (data || '').to_s
161
+ _write([data.bytesize, data], 'Ca*')
162
+ when :longstr
163
+ if data.is_a? Hash
164
+ write(:table, data)
165
+ else
166
+ data = (data || '').to_s
167
+ _write([data.bytesize, data], 'Na*')
168
+ end
169
+ when :timestamp
170
+ write(:longlong, data.to_i)
171
+ when :table
172
+ data ||= {}
173
+ write :longstr, (data.inject(Buffer.new) do |table, (key, value)|
174
+ table.write(:shortstr, key.to_s)
175
+
176
+ case value
177
+ when String
178
+ table.write(:octet, 83) # 'S'
179
+ table.write(:longstr, value.to_s)
180
+ when Fixnum
181
+ table.write(:octet, 73) # 'I'
182
+ table.write(:long, value)
183
+ when Float
184
+ table.write(:octet, 68) # 'D'
185
+ # XXX there's gotta be a better way to do this..
186
+ exp = value.to_s.split('.').last.bytesize
187
+ num = value * 10**exp
188
+ table.write(:octet, exp)
189
+ table.write(:long, num)
190
+ when Time
191
+ table.write(:octet, 84) # 'T'
192
+ table.write(:timestamp, value)
193
+ when Hash
194
+ table.write(:octet, 70) # 'F'
195
+ table.write(:table, value)
196
+ end
197
+
198
+ table
199
+ end)
200
+ when :bit
201
+ [*data].to_enum(:each_slice, 8).each{|bits|
202
+ write(:octet, bits.enum_with_index.inject(0){ |byte, (bit, i)|
203
+ byte |= (1 << i) if bit
204
+ byte
205
+ })
206
+ }
207
+ when :properties
208
+ values = []
209
+ data.enum_with_index.inject(0) do |short, ((type, value), i)|
210
+ n = i % 15
211
+ last = i+1 == data.size
212
+
213
+ if (n == 0 and i != 0) or last
214
+ if data.size > i+1
215
+ short |= (1 << 0)
216
+ elsif last and value
217
+ values << [type,value]
218
+ short |= 1<<(15-n)
219
+ end
220
+
221
+ write(:short, short)
222
+ short = 0
223
+ end
224
+
225
+ if value and !last
226
+ values << [type,value]
227
+ short |= 1<<(15-n)
228
+ end
229
+
230
+ short
231
+ end
232
+
233
+ values.each do |type, value|
234
+ write(type, value) unless type == :bit
235
+ end
236
+ else
237
+ raise Qrack::InvalidTypeError, "Cannot write data of type #{type}"
238
+ end
239
+
240
+ self
241
+ end
242
+
243
+ def extract
244
+ begin
245
+ cur_data, cur_pos = @data.clone, @pos
246
+ yield self
247
+ rescue Qrack::BufferOverflowError
248
+ @data, @pos = cur_data, cur_pos
249
+ nil
250
+ end
251
+ end
252
+
253
+ def _read(size, pack = nil)
254
+ if @data.is_a?(Qrack::Client)
255
+ raw = @data.read(size)
256
+ return raw if raw.nil? or pack.nil?
257
+ return raw.unpack(pack).first
258
+ end
259
+
260
+ if @pos + size > length
261
+ raise Qrack::BufferOverflowError
262
+ else
263
+ data = @data[@pos,size]
264
+ @data[@pos,size] = ''
265
+ if pack
266
+ data = data.unpack(pack)
267
+ data = data.pop if data.size == 1
268
+ end
269
+ data
270
+ end
271
+ end
272
+
273
+ def _write data, pack = nil
274
+ data = [*data].pack(pack) if pack
275
+ @data[@pos,0] = data
276
+ @pos += data.bytesize
277
+ end
278
+ end
279
+ end
276
280
  end