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,268 @@ else
9
11
  end
10
12
 
11
13
  module Qrack
12
- module Transport #: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 Transport #: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
+ end
127
+ end
128
+
129
+ t
130
+ when :bit
131
+ if (@bits ||= []).empty?
132
+ val = read(:octet)
133
+ @bits = (0..7).map{|i| (val & (1 << i)) != 0 }
134
+ end
135
+
136
+ @bits.shift
137
+ else
138
+ raise Qrack::InvalidTypeError, "Cannot read data of type #{type}"
139
+ end
140
+ end
141
+
142
+ types.size == 1 ? values.first : values
143
+ end
144
+
145
+ def write type, data
146
+ case type
147
+ when :octet
148
+ _write(data, 'C')
149
+ when :short
150
+ _write(data, 'n')
151
+ when :long
152
+ _write(data, 'N')
153
+ when :longlong
154
+ lower = data & 0xffffffff
155
+ upper = (data & ~0xffffffff) >> 32
156
+ _write([upper, lower], 'NN')
157
+ when :shortstr
158
+ data = (data || '').to_s
159
+ _write([data.bytesize, data], 'Ca*')
160
+ when :longstr
161
+ if data.is_a? Hash
162
+ write(:table, data)
163
+ else
164
+ data = (data || '').to_s
165
+ _write([data.bytesize, data], 'Na*')
166
+ end
167
+ when :timestamp
168
+ write(:longlong, data.to_i)
169
+ when :table
170
+ data ||= {}
171
+ write :longstr, (data.inject(Buffer.new) do |table, (key, value)|
172
+ table.write(:shortstr, key.to_s)
173
+
174
+ case value
175
+ when String
176
+ table.write(:octet, 83) # 'S'
177
+ table.write(:longstr, value.to_s)
178
+ when Fixnum
179
+ table.write(:octet, 73) # 'I'
180
+ table.write(:long, value)
181
+ when Float
182
+ table.write(:octet, 68) # 'D'
183
+ # XXX there's gotta be a better way to do this..
184
+ exp = value.to_s.split('.').last.bytesize
185
+ num = value * 10**exp
186
+ table.write(:octet, exp)
187
+ table.write(:long, num)
188
+ when Time
189
+ table.write(:octet, 84) # 'T'
190
+ table.write(:timestamp, value)
191
+ when Hash
192
+ table.write(:octet, 70) # 'F'
193
+ table.write(:table, value)
194
+ end
195
+
196
+ table
197
+ end)
198
+ when :bit
199
+ [*data].to_enum(:each_slice, 8).each{|bits|
200
+ write(:octet, bits.enum_with_index.inject(0){ |byte, (bit, i)|
201
+ byte |= (1 << i) if bit
202
+ byte
203
+ })
204
+ }
205
+ when :properties
206
+ values = []
207
+ data.enum_with_index.inject(0) do |short, ((type, value), i)|
208
+ n = i % 15
209
+ last = i+1 == data.size
210
+
211
+ if (n == 0 and i != 0) or last
212
+ if data.size > i+1
213
+ short |= (1 << 0)
214
+ elsif last and value
215
+ values << [type,value]
216
+ short |= 1<<(15-n)
217
+ end
218
+
219
+ write(:short, short)
220
+ short = 0
221
+ end
222
+
223
+ if value and !last
224
+ values << [type,value]
225
+ short |= 1<<(15-n)
226
+ end
227
+
228
+ short
229
+ end
230
+
231
+ values.each do |type, value|
232
+ write(type, value) unless type == :bit
233
+ end
234
+ else
235
+ raise Qrack::InvalidTypeError, "Cannot write data of type #{type}"
236
+ end
237
+
238
+ self
239
+ end
240
+
241
+ def extract
242
+ begin
243
+ cur_data, cur_pos = @data.clone, @pos
244
+ yield self
245
+ rescue Qrack::BufferOverflowError
246
+ @data, @pos = cur_data, cur_pos
247
+ nil
248
+ end
249
+ end
250
+
251
+ def _read(size, pack = nil)
252
+ if @data.is_a?(Qrack::Client)
253
+ raw = @data.read(size)
254
+ return raw if raw.nil? or pack.nil?
255
+ return raw.unpack(pack).first
256
+ end
257
+
258
+ if @pos + size > length
259
+ raise Qrack::BufferOverflowError
260
+ else
261
+ data = @data[@pos,size]
262
+ @data[@pos,size] = ''
263
+ if pack
264
+ data = data.unpack(pack)
265
+ data = data.pop if data.size == 1
266
+ end
267
+ data
268
+ end
269
+ end
270
+
271
+ def _write data, pack = nil
272
+ data = [*data].pack(pack) if pack
273
+ @data[@pos,0] = data
274
+ @pos += data.bytesize
275
+ end
276
+ end
277
+ end
276
278
  end