sparqcode_bunny 0.0.1

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 +10 -0
  2. data/.rspec +3 -0
  3. data/.travis.yml +15 -0
  4. data/.yardopts +9 -0
  5. data/CHANGELOG +27 -0
  6. data/Gemfile +39 -0
  7. data/LICENSE +21 -0
  8. data/README.textile +82 -0
  9. data/Rakefile +14 -0
  10. data/bunny.gemspec +43 -0
  11. data/examples/simple_08.rb +32 -0
  12. data/examples/simple_09.rb +32 -0
  13. data/examples/simple_ack_08.rb +35 -0
  14. data/examples/simple_ack_09.rb +35 -0
  15. data/examples/simple_consumer_08.rb +55 -0
  16. data/examples/simple_consumer_09.rb +55 -0
  17. data/examples/simple_fanout_08.rb +41 -0
  18. data/examples/simple_fanout_09.rb +41 -0
  19. data/examples/simple_headers_08.rb +42 -0
  20. data/examples/simple_headers_09.rb +42 -0
  21. data/examples/simple_publisher_08.rb +29 -0
  22. data/examples/simple_publisher_09.rb +29 -0
  23. data/examples/simple_topic_08.rb +61 -0
  24. data/examples/simple_topic_09.rb +61 -0
  25. data/ext/amqp-0.8.json +616 -0
  26. data/ext/amqp-0.9.1.json +388 -0
  27. data/ext/config.yml +4 -0
  28. data/ext/qparser.rb +469 -0
  29. data/lib/bunny/channel08.rb +39 -0
  30. data/lib/bunny/channel09.rb +39 -0
  31. data/lib/bunny/client08.rb +472 -0
  32. data/lib/bunny/client09.rb +374 -0
  33. data/lib/bunny/consumer.rb +35 -0
  34. data/lib/bunny/exchange08.rb +171 -0
  35. data/lib/bunny/exchange09.rb +159 -0
  36. data/lib/bunny/queue08.rb +403 -0
  37. data/lib/bunny/queue09.rb +325 -0
  38. data/lib/bunny/subscription08.rb +87 -0
  39. data/lib/bunny/subscription09.rb +87 -0
  40. data/lib/bunny/system_timer.rb +14 -0
  41. data/lib/bunny/version.rb +5 -0
  42. data/lib/bunny.rb +109 -0
  43. data/lib/qrack/amq-client-url.rb +165 -0
  44. data/lib/qrack/channel.rb +20 -0
  45. data/lib/qrack/client.rb +235 -0
  46. data/lib/qrack/errors.rb +5 -0
  47. data/lib/qrack/protocol/protocol08.rb +134 -0
  48. data/lib/qrack/protocol/protocol09.rb +135 -0
  49. data/lib/qrack/protocol/spec08.rb +828 -0
  50. data/lib/qrack/protocol/spec09.rb +524 -0
  51. data/lib/qrack/qrack08.rb +20 -0
  52. data/lib/qrack/qrack09.rb +20 -0
  53. data/lib/qrack/queue.rb +40 -0
  54. data/lib/qrack/subscription.rb +112 -0
  55. data/lib/qrack/transport/buffer08.rb +278 -0
  56. data/lib/qrack/transport/buffer09.rb +280 -0
  57. data/lib/qrack/transport/frame08.rb +117 -0
  58. data/lib/qrack/transport/frame09.rb +97 -0
  59. data/spec/spec_08/bunny_spec.rb +77 -0
  60. data/spec/spec_08/connection_spec.rb +25 -0
  61. data/spec/spec_08/exchange_spec.rb +173 -0
  62. data/spec/spec_08/queue_spec.rb +235 -0
  63. data/spec/spec_09/amqp_url_spec.rb +19 -0
  64. data/spec/spec_09/bunny_spec.rb +76 -0
  65. data/spec/spec_09/connection_spec.rb +29 -0
  66. data/spec/spec_09/exchange_spec.rb +173 -0
  67. data/spec/spec_09/queue_spec.rb +248 -0
  68. metadata +151 -0
@@ -0,0 +1,278 @@
1
+ # encoding: utf-8
2
+
3
+ if [].map.respond_to? :with_index
4
+ class Array #:nodoc:
5
+ def enum_with_index
6
+ each.with_index
7
+ end
8
+ end
9
+ else
10
+ require 'enumerator'
11
+ end
12
+
13
+ module Qrack
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
278
+ end
@@ -0,0 +1,280 @@
1
+ # encoding: utf-8
2
+
3
+ if [].map.respond_to? :with_index
4
+ class Array #:nodoc:
5
+ def enum_with_index
6
+ each.with_index
7
+ end
8
+ end
9
+ else
10
+ require 'enumerator'
11
+ end
12
+
13
+ module Qrack
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
280
+ end
@@ -0,0 +1,117 @@
1
+
2
+ # encoding: utf-8
3
+
4
+
5
+ #:stopdoc:
6
+ # this file was autogenerated on 2011-07-21 07:15:33 +0100
7
+ #
8
+ # DO NOT EDIT! (edit ext/qparser.rb and config.yml instead, and run 'ruby qparser.rb')
9
+
10
+ module Qrack
11
+ module Transport
12
+ class Frame
13
+
14
+ FOOTER = 206
15
+ ID = 0
16
+
17
+ @types = {
18
+ 1 => 'Method',
19
+ 2 => 'Header',
20
+ 3 => 'Body',
21
+ 4 => 'OobMethod',
22
+ 5 => 'OobHeader',
23
+ 6 => 'OobBody',
24
+ 7 => 'Trace',
25
+ 8 => 'Heartbeat',
26
+ }
27
+
28
+ attr_accessor :channel, :payload
29
+
30
+ def initialize payload = nil, channel = 0
31
+ @channel, @payload = channel, payload
32
+ end
33
+
34
+ def id
35
+ self.class::ID
36
+ end
37
+
38
+ def to_binary
39
+ buf = Transport::Buffer.new
40
+ buf.write :octet, id
41
+ buf.write :short, channel
42
+ buf.write :longstr, payload
43
+ buf.write :octet, FOOTER
44
+ buf.rewind
45
+ buf
46
+ end
47
+
48
+ def to_s
49
+ to_binary.to_s
50
+ end
51
+
52
+ def == frame
53
+ [ :id, :channel, :payload ].inject(true) do |eql, field|
54
+ eql and __send__(field) == frame.__send__(field)
55
+ end
56
+ end
57
+
58
+ def self.parse buf
59
+ buf = Transport::Buffer.new(buf) unless buf.is_a? Transport::Buffer
60
+ buf.extract do
61
+ id, channel, payload, footer = buf.read(:octet, :short, :longstr, :octet)
62
+ Qrack::Transport.const_get(@types[id]).new(payload, channel) if footer == FOOTER
63
+ end
64
+ end
65
+
66
+ end
67
+
68
+ class Method < Frame
69
+
70
+ ID = 1
71
+
72
+ def initialize payload = nil, channel = 0
73
+ super
74
+ unless @payload.is_a? Protocol::Class::Method or @payload.nil?
75
+ @payload = Protocol.parse(@payload)
76
+ end
77
+ end
78
+ end
79
+
80
+ class Header < Frame
81
+
82
+ ID = 2
83
+
84
+ def initialize payload = nil, channel = 0
85
+ super
86
+ unless @payload.is_a? Protocol::Header or @payload.nil?
87
+ @payload = Protocol::Header.new(@payload)
88
+ end
89
+ end
90
+ end
91
+
92
+ class Body < Frame
93
+ ID = 3
94
+ end
95
+
96
+ class OobMethod < Frame
97
+ ID = 4
98
+ end
99
+
100
+ class OobHeader < Frame
101
+ ID = 5
102
+ end
103
+
104
+ class OobBody < Frame
105
+ ID = 6
106
+ end
107
+
108
+ class Trace < Frame
109
+ ID = 7
110
+ end
111
+
112
+ class Heartbeat < Frame
113
+ ID = 8
114
+ end
115
+
116
+ end
117
+ end