qpid_proton 0.4 → 0.5
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.
- 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
|