qpid_proton 0.4 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/ChangeLog +18 -0
- data/ext/cproton/cproton.c +4868 -1733
- data/lib/qpid_proton.rb +5 -0
- data/lib/qpid_proton/array.rb +173 -0
- data/lib/qpid_proton/data.rb +87 -99
- data/lib/qpid_proton/described.rb +66 -0
- data/lib/qpid_proton/exception_handling.rb +3 -0
- data/lib/qpid_proton/exceptions.rb +1 -0
- data/lib/qpid_proton/hash.rb +86 -0
- data/lib/qpid_proton/mapping.rb +142 -0
- data/lib/qpid_proton/message.rb +180 -1
- data/lib/qpid_proton/messenger.rb +60 -51
- metadata +18 -21
data/lib/qpid_proton.rb
CHANGED
@@ -18,7 +18,12 @@
|
|
18
18
|
#
|
19
19
|
|
20
20
|
require "cproton"
|
21
|
+
require "date"
|
21
22
|
|
23
|
+
require "qpid_proton/described"
|
24
|
+
require "qpid_proton/mapping"
|
25
|
+
require "qpid_proton/array"
|
26
|
+
require "qpid_proton/hash"
|
22
27
|
require "qpid_proton/exceptions"
|
23
28
|
require "qpid_proton/exception_handling"
|
24
29
|
require "qpid_proton/message_format"
|
@@ -0,0 +1,173 @@
|
|
1
|
+
#
|
2
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
3
|
+
# or more contributor license agreements. See the NOTICE file
|
4
|
+
# distributed with this work for additional information
|
5
|
+
# regarding copyright ownership. The ASF licenses this file
|
6
|
+
# to you under the Apache License, Version 2.0 (the
|
7
|
+
# "License"); you may not use this file except in compliance
|
8
|
+
# with the License. You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing,
|
13
|
+
# software distributed under the License is distributed on an
|
14
|
+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
15
|
+
# KIND, either express or implied. See the License for the
|
16
|
+
# specific language governing permissions and limitations
|
17
|
+
# under the License.
|
18
|
+
#
|
19
|
+
|
20
|
+
#--
|
21
|
+
# Patch the Array class to provide methods for adding its contents
|
22
|
+
# to a Qpid::Proton::Data instance.
|
23
|
+
#++
|
24
|
+
|
25
|
+
module Qpid
|
26
|
+
|
27
|
+
module Proton
|
28
|
+
|
29
|
+
# Holds the information for an AMQP Array compound type.
|
30
|
+
#
|
31
|
+
# It holds the type for the array and the descriptor if the
|
32
|
+
# array is described.
|
33
|
+
#
|
34
|
+
class ArrayHeader
|
35
|
+
attr_reader :type
|
36
|
+
attr_reader :descriptor
|
37
|
+
|
38
|
+
def initialize(type, descriptor = nil)
|
39
|
+
@type = type
|
40
|
+
@descriptor = descriptor
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns true if the array is described.
|
44
|
+
def described?
|
45
|
+
!@descriptor.nil?
|
46
|
+
end
|
47
|
+
|
48
|
+
def ==(that)
|
49
|
+
((@type == that.type) && (@descriptor == that.descriptor))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
class Array
|
58
|
+
|
59
|
+
# Used to declare an array as an AMQP array.
|
60
|
+
#
|
61
|
+
# The value, if defined, is an instance of Qpid::Proton::ArrayHeader
|
62
|
+
attr_accessor :proton_array_header
|
63
|
+
|
64
|
+
# Returns true if the array is the a Proton described type.
|
65
|
+
def proton_described?
|
66
|
+
!@proton_array_header.nil? && @proton_array_header.described?
|
67
|
+
end
|
68
|
+
|
69
|
+
# Puts the elements of the array into the specified Qpid::Proton::Data object.
|
70
|
+
def proton_put(data)
|
71
|
+
raise TypeError, "data object cannot be nil" if data.nil?
|
72
|
+
|
73
|
+
if @proton_array_header.nil?
|
74
|
+
proton_put_list(data)
|
75
|
+
else
|
76
|
+
proton_put_array(data)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def proton_put_list(data)
|
83
|
+
# create a list, then enter it and add each element
|
84
|
+
data.put_list
|
85
|
+
data.enter
|
86
|
+
each do |element|
|
87
|
+
# get the proton type for the element
|
88
|
+
mapping = Qpid::Proton::Mapping.for_class(element.class)
|
89
|
+
# add the element
|
90
|
+
mapping.put(data, element)
|
91
|
+
end
|
92
|
+
# exit the list
|
93
|
+
data.exit
|
94
|
+
end
|
95
|
+
|
96
|
+
def proton_put_array(data)
|
97
|
+
data.put_array(@proton_array_header.described?, @proton_array_header.type)
|
98
|
+
data.enter
|
99
|
+
if @proton_array_header.described?
|
100
|
+
data.symbol = @proton_array_header.descriptor
|
101
|
+
end
|
102
|
+
|
103
|
+
each do |element|
|
104
|
+
@proton_array_header.type.put(data, element)
|
105
|
+
end
|
106
|
+
|
107
|
+
data.exit
|
108
|
+
end
|
109
|
+
|
110
|
+
class << self
|
111
|
+
|
112
|
+
# Gets the elements of an array or list out of the specified
|
113
|
+
# Qpid::Proton::Data object.
|
114
|
+
def proton_get(data)
|
115
|
+
raise TypeError, "can't convert nil into Qpid::Proton::Data" if data.nil?
|
116
|
+
|
117
|
+
type = data.type
|
118
|
+
|
119
|
+
if type == Qpid::Proton::LIST
|
120
|
+
result = proton_get_list(data)
|
121
|
+
elsif type == Qpid::Proton::ARRAY
|
122
|
+
result = proton_get_array(data)
|
123
|
+
else
|
124
|
+
raise TypeError, "element is not a list and not an array"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def proton_get_list(data)
|
131
|
+
size = data.list
|
132
|
+
raise TypeError, "not a list" unless data.enter
|
133
|
+
elements = []
|
134
|
+
(0...size).each do
|
135
|
+
data.next
|
136
|
+
type = data.type
|
137
|
+
raise TypeError, "missing next element in list" unless type
|
138
|
+
elements << type.get(data)
|
139
|
+
end
|
140
|
+
data.exit
|
141
|
+
return elements
|
142
|
+
end
|
143
|
+
|
144
|
+
def proton_get_array(data)
|
145
|
+
count, described, type = data.array
|
146
|
+
|
147
|
+
raise TypeError, "not an array" unless data.enter
|
148
|
+
elements = []
|
149
|
+
|
150
|
+
descriptor = nil
|
151
|
+
|
152
|
+
if described
|
153
|
+
data.next
|
154
|
+
descriptor = data.symbol
|
155
|
+
end
|
156
|
+
|
157
|
+
elements.proton_array_header = Qpid::Proton::ArrayHeader.new(type, descriptor)
|
158
|
+
(0...count).each do |which|
|
159
|
+
if data.next
|
160
|
+
etype = data.type
|
161
|
+
raise TypeError, "missing next element in array" unless etype
|
162
|
+
raise TypeError, "invalid array element: #{etype}" unless etype == type
|
163
|
+
elements << type.get(data)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
data.exit
|
167
|
+
return elements
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
data/lib/qpid_proton/data.rb
CHANGED
@@ -17,6 +17,8 @@
|
|
17
17
|
# under the License.
|
18
18
|
#
|
19
19
|
|
20
|
+
require 'cproton'
|
21
|
+
|
20
22
|
module Qpid
|
21
23
|
|
22
24
|
module Proton
|
@@ -51,27 +53,34 @@ module Qpid
|
|
51
53
|
#
|
52
54
|
# The following types of scalar values are supported:
|
53
55
|
#
|
54
|
-
# *
|
55
|
-
# *
|
56
|
-
# *
|
57
|
-
# *
|
58
|
-
# *
|
59
|
-
# *
|
60
|
-
# *
|
61
|
-
# *
|
62
|
-
# *
|
63
|
-
# *
|
64
|
-
# *
|
65
|
-
# *
|
66
|
-
# *
|
67
|
-
# *
|
56
|
+
# * *NULL*
|
57
|
+
# * *BOOL*
|
58
|
+
# * *UBYTE*
|
59
|
+
# * *BYTE*
|
60
|
+
# * *USHORT*
|
61
|
+
# * *SHORT*
|
62
|
+
# * *UINT*
|
63
|
+
# * *INT*
|
64
|
+
# * *CHAR*
|
65
|
+
# * *ULONG*
|
66
|
+
# * *LONG*
|
67
|
+
# * *TIMESTAMP*
|
68
|
+
# * *FLOAT*
|
69
|
+
# * *DOUBLE*
|
70
|
+
# * *DECIMAL32*
|
71
|
+
# * *DECIMAL64*
|
72
|
+
# * *DECIMAL128*
|
73
|
+
# * *UUID*
|
74
|
+
# * *BINARY*
|
75
|
+
# * *STRING*
|
76
|
+
# * *SYMBOL*
|
68
77
|
#
|
69
78
|
# The following types of compound values are supported:
|
70
79
|
#
|
71
|
-
# *
|
72
|
-
# *
|
73
|
-
# *
|
74
|
-
# *
|
80
|
+
# * *DESCRIBED*
|
81
|
+
# * *ARRAY*
|
82
|
+
# * *LIST*
|
83
|
+
# * *MAP*
|
75
84
|
#
|
76
85
|
class Data
|
77
86
|
|
@@ -115,13 +124,12 @@ module Qpid
|
|
115
124
|
Cproton.pn_data_rewind(@data)
|
116
125
|
end
|
117
126
|
|
118
|
-
# Advances the current node to
|
127
|
+
# Advances the current node to its next sibling and returns its types.
|
119
128
|
#
|
120
129
|
# If there is no next sibling the current node remains unchanged
|
121
130
|
# and nil is returned.
|
122
|
-
def next
|
123
|
-
|
124
|
-
return found ? found : nil
|
131
|
+
def next(print = false)
|
132
|
+
Cproton.pn_data_next(@data)
|
125
133
|
end
|
126
134
|
|
127
135
|
# Advances the current node to its previous sibling and returns its type.
|
@@ -129,8 +137,7 @@ module Qpid
|
|
129
137
|
# If there is no previous sibling then the current node remains unchanged
|
130
138
|
# and nil is return.
|
131
139
|
def prev
|
132
|
-
|
133
|
-
return found ? found : nil
|
140
|
+
return Cproton.pn_data_prev(@data) ? type : nil
|
134
141
|
end
|
135
142
|
|
136
143
|
# Sets the parent node to the current node and clears the current node.
|
@@ -146,21 +153,26 @@ module Qpid
|
|
146
153
|
Cproton.pn_data_exit(@data)
|
147
154
|
end
|
148
155
|
|
149
|
-
# Returns the type of the current node.
|
150
|
-
def
|
156
|
+
# Returns the numeric type code of the current node.
|
157
|
+
def type_code
|
151
158
|
dtype = Cproton.pn_data_type(@data)
|
152
159
|
return (dtype == -1) ? nil : dtype
|
153
160
|
end
|
154
161
|
|
155
|
-
#
|
162
|
+
# Return the Type object for the current node
|
163
|
+
def type
|
164
|
+
Mapping.for_code(type_code)
|
165
|
+
end
|
166
|
+
|
167
|
+
# Returns a representation of the data encoded in AMQP format.
|
156
168
|
def encode
|
157
|
-
|
169
|
+
buffer = "\0"*1024
|
158
170
|
loop do
|
159
|
-
|
171
|
+
cd = Cproton.pn_data_encode(@data, buffer, buffer.length)
|
160
172
|
if cd == Cproton::PN_OVERFLOW
|
161
|
-
|
173
|
+
buffer *= 2
|
162
174
|
elsif cd >= 0
|
163
|
-
return
|
175
|
+
return buffer[0...cd]
|
164
176
|
else
|
165
177
|
check(cd)
|
166
178
|
end
|
@@ -175,7 +187,7 @@ module Qpid
|
|
175
187
|
# * encoded - the encoded data
|
176
188
|
#
|
177
189
|
def decode(encoded)
|
178
|
-
check(Cproton.pn_data_decode(@data, encoded))
|
190
|
+
check(Cproton.pn_data_decode(@data, encoded, encoded.length))
|
179
191
|
end
|
180
192
|
|
181
193
|
# Puts a list value.
|
@@ -208,7 +220,7 @@ module Qpid
|
|
208
220
|
# @data.enter
|
209
221
|
# (0...count).each
|
210
222
|
# type = @data.next
|
211
|
-
# puts "Value: #{@data.string}" if type ==
|
223
|
+
# puts "Value: #{@data.string}" if type == STRING
|
212
224
|
# # ... process other node types
|
213
225
|
# end
|
214
226
|
def list
|
@@ -244,10 +256,10 @@ module Qpid
|
|
244
256
|
# @data.enter
|
245
257
|
# (0...count).each do
|
246
258
|
# type = @data.next
|
247
|
-
# puts "Key=#{@data.string}" if type ==
|
259
|
+
# puts "Key=#{@data.string}" if type == STRING
|
248
260
|
# # ... process other key types
|
249
261
|
# type = @data.next
|
250
|
-
# puts "Value=#{@data.string}" if type ==
|
262
|
+
# puts "Value=#{@data.string}" if type == STRING
|
251
263
|
# # ... process other value types
|
252
264
|
# end
|
253
265
|
# @data.exit
|
@@ -255,6 +267,10 @@ module Qpid
|
|
255
267
|
Cproton.pn_data_get_map(@data)
|
256
268
|
end
|
257
269
|
|
270
|
+
def get_map # :nodoc:
|
271
|
+
::Hash.proton_data_get(self)
|
272
|
+
end
|
273
|
+
|
258
274
|
# Puts an array value.
|
259
275
|
#
|
260
276
|
# Elements may be filled by entering the array node and putting the
|
@@ -273,7 +289,7 @@ module Qpid
|
|
273
289
|
#
|
274
290
|
# # create an array of integer values
|
275
291
|
# data = Qpid::Proton::Data.new
|
276
|
-
# data.put_array(false,
|
292
|
+
# data.put_array(false, INT)
|
277
293
|
# data.enter
|
278
294
|
# data.int = 1
|
279
295
|
# data.int = 2
|
@@ -281,7 +297,7 @@ module Qpid
|
|
281
297
|
# data.exit
|
282
298
|
#
|
283
299
|
# # create an array of double values
|
284
|
-
# data.put_array(true,
|
300
|
+
# data.put_array(true, DOUBLE)
|
285
301
|
# data.enter
|
286
302
|
# data.symbol = "array-descriptor"
|
287
303
|
# data.double = 1.1
|
@@ -290,8 +306,7 @@ module Qpid
|
|
290
306
|
# data.exit
|
291
307
|
#
|
292
308
|
def put_array(described, element_type)
|
293
|
-
check(Cproton.pn_data_put_array(@data, described,
|
294
|
-
Data.type_value(element_type)))
|
309
|
+
check(Cproton.pn_data_put_array(@data, described, element_type.code))
|
295
310
|
end
|
296
311
|
|
297
312
|
# If the current node is an array, returns a tuple of the element count, a
|
@@ -319,12 +334,12 @@ module Qpid
|
|
319
334
|
count = Cproton.pn_data_get_array(@data)
|
320
335
|
described = Cproton.pn_data_is_array_described(@data)
|
321
336
|
array_type = Cproton.pn_data_get_array_type(@data)
|
322
|
-
if array_type == -1
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
337
|
+
return nil if array_type == -1
|
338
|
+
[count, described, Mapping.for_code(array_type) ]
|
339
|
+
end
|
340
|
+
|
341
|
+
def get_array # :nodoc:
|
342
|
+
::Array.proton_get(self)
|
328
343
|
end
|
329
344
|
|
330
345
|
# Puts a described value.
|
@@ -346,6 +361,19 @@ module Qpid
|
|
346
361
|
check(Cproton.pn_data_put_described(@data))
|
347
362
|
end
|
348
363
|
|
364
|
+
def get_described # :nodoc:
|
365
|
+
raise TypeError, "not a described type" unless self.described?
|
366
|
+
self.enter
|
367
|
+
self.next
|
368
|
+
type = self.type
|
369
|
+
descriptor = type.get(self)
|
370
|
+
self.next
|
371
|
+
type = self.type
|
372
|
+
value = type.get(self)
|
373
|
+
self.exit
|
374
|
+
Described.new(descriptor, value)
|
375
|
+
end
|
376
|
+
|
349
377
|
# Checks if the current node is a described value.
|
350
378
|
#
|
351
379
|
# The described and value may be accessed by entering the described value.
|
@@ -366,6 +394,11 @@ module Qpid
|
|
366
394
|
check(Cproton.pn_data_put_null(@data))
|
367
395
|
end
|
368
396
|
|
397
|
+
# Utility method for Qpid::Proton::Mapping
|
398
|
+
def null=(value) # :nodoc:
|
399
|
+
null
|
400
|
+
end
|
401
|
+
|
369
402
|
# Checks if the current node is null.
|
370
403
|
def null?
|
371
404
|
Cproton.pn_data_is_null(@data)
|
@@ -719,38 +752,22 @@ module Qpid
|
|
719
752
|
Cproton.pn_data_get_symbol(@data)
|
720
753
|
end
|
721
754
|
|
722
|
-
|
723
|
-
|
724
|
-
|
725
|
-
|
726
|
-
@@type_name ||= {}
|
727
|
-
@@type_name[value] = key
|
728
|
-
end
|
729
|
-
|
730
|
-
# Returns the typename for the specified type.
|
731
|
-
#
|
732
|
-
# ==== Examples
|
733
|
-
# # returns "null"
|
734
|
-
# name = Qpid::Proton::Data.type_name(:NULL)
|
735
|
-
#
|
736
|
-
def self.type_name(key)
|
737
|
-
@@type_name[key]
|
755
|
+
# Get the current value as a single object.
|
756
|
+
def get
|
757
|
+
type.get(self);
|
738
758
|
end
|
739
759
|
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
|
744
|
-
def self.const_missing(key) # :nodoc:
|
745
|
-
@@type_value[key]
|
760
|
+
# Put value as an object of type type_
|
761
|
+
def put(value, type_);
|
762
|
+
type_.put(self, value);
|
746
763
|
end
|
747
764
|
|
748
765
|
private
|
749
766
|
|
750
767
|
def valid_uuid?(value)
|
751
|
-
|
752
|
-
|
753
|
-
|
768
|
+
# ensure that the UUID is in the right format
|
769
|
+
# xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
|
770
|
+
value =~ /[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/
|
754
771
|
end
|
755
772
|
|
756
773
|
def check(err) # :nodoc:
|
@@ -760,35 +777,6 @@ module Qpid
|
|
760
777
|
return err
|
761
778
|
end
|
762
779
|
end
|
763
|
-
|
764
|
-
self.add_item(:NULL, Cproton::PN_NULL, "null")
|
765
|
-
self.add_item(:BOOL, Cproton::PN_BOOL, "bool")
|
766
|
-
self.add_item(:UBYTE, Cproton::PN_UBYTE, "ubyte")
|
767
|
-
self.add_item(:BYTE, Cproton::PN_BYTE, "byte")
|
768
|
-
self.add_item(:USHORT, Cproton::PN_USHORT, "ushort")
|
769
|
-
self.add_item(:SHORT, Cproton::PN_SHORT, "short")
|
770
|
-
self.add_item(:UINT, Cproton::PN_UINT, "uint")
|
771
|
-
self.add_item(:INT, Cproton::PN_INT, "int")
|
772
|
-
self.add_item(:CHAR, Cproton::PN_CHAR, "char")
|
773
|
-
self.add_item(:ULONG, Cproton::PN_ULONG, "ulong")
|
774
|
-
self.add_item(:LONG, Cproton::PN_LONG, "long")
|
775
|
-
self.add_item(:TIMESTAMP, Cproton::PN_TIMESTAMP, "timestamp")
|
776
|
-
self.add_item(:FLOAT, Cproton::PN_FLOAT, "float")
|
777
|
-
self.add_item(:DOUBLE, Cproton::PN_DOUBLE, "double")
|
778
|
-
self.add_item(:DECIMAL32, Cproton::PN_DECIMAL32, "decimal32")
|
779
|
-
self.add_item(:DECIMAL64, Cproton::PN_DECIMAL64, "decimal64")
|
780
|
-
self.add_item(:DECIMAL128, Cproton::PN_DECIMAL128, "decimal128")
|
781
|
-
self.add_item(:UUID, Cproton::PN_UUID, "uuid")
|
782
|
-
self.add_item(:BINARY, Cproton::PN_BINARY, "binary")
|
783
|
-
self.add_item(:STRING, Cproton::PN_STRING, "string")
|
784
|
-
self.add_item(:SYMBOL, Cproton::PN_SYMBOL, "symbol")
|
785
|
-
self.add_item(:DESCRIBED, Cproton::PN_DESCRIBED, "described")
|
786
|
-
self.add_item(:ARRAY, Cproton::PN_ARRAY, "array")
|
787
|
-
self.add_item(:LIST, Cproton::PN_LIST, "list")
|
788
|
-
self.add_item(:MAP, Cproton::PN_MAP, "map")
|
789
|
-
|
790
780
|
end
|
791
|
-
|
792
781
|
end
|
793
|
-
|
794
782
|
end
|