celldee-bunny 0.1.1 → 0.2.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.
@@ -0,0 +1,156 @@
1
+ module Protocol
2
+ #:stopdoc:
3
+ class Class::Method
4
+ def initialize *args
5
+ opts = args.pop if args.last.is_a? Hash
6
+ opts ||= {}
7
+
8
+ @debug = 1 # XXX hack, p(obj) == '' if no instance vars are set
9
+
10
+ if args.size == 1 and args.first.is_a? Transport::Buffer
11
+ buf = args.shift
12
+ else
13
+ buf = nil
14
+ end
15
+
16
+ self.class.arguments.each do |type, name|
17
+ val = buf ? buf.read(type) :
18
+ args.shift || opts[name] || opts[name.to_s]
19
+ instance_variable_set("@#{name}", val)
20
+ end
21
+ end
22
+
23
+ def arguments
24
+ self.class.arguments.inject({}) do |hash, (type, name)|
25
+ hash.update name => instance_variable_get("@#{name}")
26
+ end
27
+ end
28
+
29
+ def to_binary
30
+ buf = Transport::Buffer.new
31
+ buf.write :short, self.class.parent.id
32
+ buf.write :short, self.class.id
33
+
34
+ bits = []
35
+
36
+ self.class.arguments.each do |type, name|
37
+ val = instance_variable_get("@#{name}")
38
+ if type == :bit
39
+ bits << (val || false)
40
+ else
41
+ unless bits.empty?
42
+ buf.write :bit, bits
43
+ bits = []
44
+ end
45
+ buf.write type, val
46
+ end
47
+ end
48
+
49
+ buf.write :bit, bits unless bits.empty?
50
+ buf.rewind
51
+
52
+ buf
53
+ end
54
+
55
+ def to_s
56
+ to_binary.to_s
57
+ end
58
+
59
+ def to_frame channel = 0
60
+ Transport::Frame::Method.new(self, channel)
61
+ end
62
+ end
63
+
64
+ #:startdoc:
65
+ #
66
+ # Contains a properties hash that holds some potentially interesting
67
+ # information.
68
+ # * :delivery_mode
69
+ # 1 equals transient.
70
+ # 2 equals persistent. Unconsumed persistent messages will survive
71
+ # a server restart when they are stored in a durable queue.
72
+ # * :redelivered
73
+ # True or False
74
+ # * :routing_key
75
+ # The routing string used for matching this message to this queue.
76
+ # * :priority
77
+ # An integer in the range of 0 to 9 inclusive.
78
+ # * :content_type
79
+ # Always "application/octet-stream" (byte stream)
80
+ # * :exchange
81
+ # The source exchange which published this message.
82
+ # * :message_count
83
+ # The number of unconsumed messages contained in the queue.
84
+ # * :delivery_tag
85
+ # A monotonically increasing integer. This number should not be trusted
86
+ # as a sequence number. There is no guarantee it won't get reset.
87
+ class Header
88
+ def initialize *args
89
+ opts = args.pop if args.last.is_a? Hash
90
+ opts ||= {}
91
+
92
+ first = args.shift
93
+
94
+ if first.is_a? ::Class and first.ancestors.include? Protocol::Class
95
+ @klass = first
96
+ @size = args.shift || 0
97
+ @weight = args.shift || 0
98
+ @properties = opts
99
+
100
+ elsif first.is_a? Transport::Buffer or first.is_a? String
101
+ buf = first
102
+ buf = Transport::Buffer.new(buf) unless buf.is_a? Transport::Buffer
103
+
104
+ @klass = Protocol.classes[buf.read(:short)]
105
+ @weight = buf.read(:short)
106
+ @size = buf.read(:longlong)
107
+
108
+ props = buf.read(:properties, *klass.properties.map{|type,_| type })
109
+ @properties = Hash[*klass.properties.map{|_,name| name }.zip(props).reject{|k,v| v.nil? }.flatten]
110
+
111
+ else
112
+ raise ArgumentError, 'Invalid argument'
113
+ end
114
+
115
+ end
116
+ attr_accessor :klass, :size, :weight, :properties
117
+
118
+ def to_binary
119
+ buf = Transport::Buffer.new
120
+ buf.write :short, klass.id
121
+ buf.write :short, weight # XXX rabbitmq only supports weight == 0
122
+ buf.write :longlong, size
123
+ buf.write :properties, (klass.properties.map do |type, name|
124
+ [ type, properties[name] || properties[name.to_s] ]
125
+ end)
126
+ buf.rewind
127
+ buf
128
+ end
129
+
130
+ def to_s
131
+ to_binary.to_s
132
+ end
133
+
134
+ def to_frame channel = 0
135
+ Transport::Frame::Header.new(self, channel)
136
+ end
137
+
138
+ def == header
139
+ [ :klass, :size, :weight, :properties ].inject(true) do |eql, field|
140
+ eql and __send__(field) == header.__send__(field)
141
+ end
142
+ end
143
+
144
+ def method_missing meth, *args, &blk
145
+ @properties.has_key?(meth) || @klass.properties.find{|_,name| name == meth } ? @properties[meth] :
146
+ super
147
+ end
148
+ end
149
+
150
+ def self.parse buf
151
+ buf = Transport::Buffer.new(buf) unless buf.is_a? Transport::Buffer
152
+ class_id, method_id = buf.read(:short, :short)
153
+ classes[class_id].methods[method_id].new(buf)
154
+ end
155
+ #:stopdoc:
156
+ end