bunny 0.6.3.rc2 → 0.7

Sign up to get free protection for your applications and to get access to all the features.
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