You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by mc...@apache.org on 2013/02/26 16:34:04 UTC
svn commit: r1450219 - in /qpid/proton/trunk: ./ proton-c/bindings/ruby/
proton-c/bindings/ruby/lib/ proton-c/bindings/ruby/lib/qpid_proton/
proton-c/bindings/ruby/spec/ proton-c/bindings/ruby/spec/qpid/proton/
Author: mcpierce
Date: Tue Feb 26 15:34:04 2013
New Revision: 1450219
URL: http://svn.apache.org/r1450219
Log:
PROTON-227: Created the Data class for the Ruby bindings.
The APIs are more Ruby-esque, replacing most of the put_type methods
with type=, and get_type with type.
Added:
qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/data.rb
qpid/proton/trunk/proton-c/bindings/ruby/spec/qpid/proton/data_spec.rb
Modified:
qpid/proton/trunk/config.sh
qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton.rb
qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
qpid/proton/trunk/proton-c/bindings/ruby/spec/spec_helper.rb
Modified: qpid/proton/trunk/config.sh
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/config.sh?rev=1450219&r1=1450218&r2=1450219&view=diff
==============================================================================
--- qpid/proton/trunk/config.sh (original)
+++ qpid/proton/trunk/config.sh Tue Feb 26 15:34:04 2013
@@ -49,7 +49,7 @@ fi
# Ruby
export RUBY_BINDINGS=$PROTON_BINDINGS/ruby
-export RUBYLIB=$RUBY_BINDINGS
+export RUBYLIB=$RUBY_BINDINGS:$PROTON_HOME/proton-c-bindings/ruby/lib
# Perl
export PERL_BINDINGS=$PROTON_BINDINGS/perl
Modified: qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton.rb
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton.rb?rev=1450219&r1=1450218&r2=1450219&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton.rb (original)
+++ qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton.rb Tue Feb 26 15:34:04 2013
@@ -22,8 +22,10 @@ require "cproton"
require "qpid_proton/exceptions"
require "qpid_proton/exception_handling"
require "qpid_proton/message_format"
+require "qpid_proton/data"
require "qpid_proton/message"
require "qpid_proton/subscription"
require "qpid_proton/tracker_status"
require "qpid_proton/tracker"
require "qpid_proton/messenger"
+
Added: qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/data.rb
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/data.rb?rev=1450219&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/data.rb (added)
+++ qpid/proton/trunk/proton-c/bindings/ruby/lib/qpid_proton/data.rb Tue Feb 26 15:34:04 2013
@@ -0,0 +1,794 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+module Qpid
+
+ module Proton
+
+ # +DataError+ is raised when an error occurs while encoding
+ # or decoding data.
+ class DataError < Exception; end
+
+ # The +Data+ class provides an interface for decoding, extracting,
+ # creating, and encoding arbitrary AMQP data. A +Data+ object
+ # contains a tree of AMQP values. Leaf nodes in this tree correspond
+ # to scalars in the AMQP type system such as INT or STRING. Interior
+ # nodes in this tree correspond to compound values in the AMQP type
+ # system such as *LIST*,*MAP*, *ARRAY*, or *DESCRIBED*. The root node
+ # of the tree is the +Data+ object itself and can have an arbitrary
+ # number of children.
+ #
+ # A +Data+ object maintains the notion of the current sibling node
+ # and a current parent node. Siblings are ordered within their parent.
+ # Values are accessed and/or added by using the #next, #prev,
+ # #enter, and #exit methods to navigate to the desired location in
+ # the tree and using the supplied variety of mutator and accessor
+ # methods to access or add a value of the desired type.
+ #
+ # The mutator methods will always add a value _after_ the current node
+ # in the tree. If the current node has a next sibling the mutator method
+ # will overwrite the value on this node. If there is no current node
+ # or the current node has no next sibling then one will be added. The
+ # accessor methods always set the added/modified node to the current
+ # node. The accessor methods read the value of the current node and do
+ # not change which node is current.
+ #
+ # The following types of scalar values are supported:
+ #
+ # * *:NULL*
+ # * *:BOOL*
+ # * *:UBYTE*
+ # * *:USHORT*
+ # * *:SHORT*
+ # * *:UINT*
+ # * *:INT*
+ # * *:ULONG*
+ # * *:LONG*
+ # * *:FLOAT*
+ # * *:DOUBLE*
+ # * *:BINARY*
+ # * *:STRING*
+ # * *:SYMBOL*
+ #
+ # The following types of compound values are supported:
+ #
+ # * *:DESCRIBED*
+ # * *:ARRAY*
+ # * *:LIST*
+ # * *:MAP*
+ #
+ class Data
+
+ # Creates a new instance with the specified capacity.
+ #
+ # ==== Options
+ #
+ # * capacity - the capacity
+ #
+ def initialize(capacity = 16)
+ if (!capacity.nil?) &&
+ (capacity.is_a?(Fixnum) ||
+ capacity.is_a?(Bignum))
+ @data = Cproton.pn_data(capacity)
+ @free = true
+ else
+ @data = capacity
+ @free = false
+ end
+
+ # destructor
+ ObjectSpace.define_finalizer(self, self.class.finalize!(@data))
+ end
+
+ def self.finalize!(data) # :nodoc:
+ proc {
+ Cproton.pn_data_free(data) if @free
+ }
+ end
+
+ # Clears the object.
+ def clear
+ Cproton.pn_data_clear(@data)
+ end
+
+ # Clears the current node and sets the parent to the root node.
+ #
+ # Clearing the current node sets it _before_ the first node, calling
+ # #next will advance to the first node.
+ def rewind
+ Cproton.pn_data_rewind(@data)
+ end
+
+ # Advances the current node to tits next sibling and returns its types.
+ #
+ # If there is no next sibling the current node remains unchanged
+ # and nil is returned.
+ def next
+ found = Cproton.pn_data_next(@data)
+ return found ? found : nil
+ end
+
+ # Advances the current node to its previous sibling and returns its type.
+ #
+ # If there is no previous sibling then the current node remains unchanged
+ # and nil is return.
+ def prev
+ found = Cproton.pn_data_prev(@data)
+ return found ? found : nil
+ end
+
+ # Sets the parent node to the current node and clears the current node.
+ #
+ # Clearing the current node sets it _before_ the first child.
+ def enter
+ Cproton.pn_data_enter(@data)
+ end
+
+ # Sets the current node to the parent node and the parent node to its own
+ # parent.
+ def exit
+ Cproton.pn_data_exit(@data)
+ end
+
+ # Returns the type of the current node.
+ def node_type
+ dtype = Cproton.pn_data_type(@data)
+ return (dtype == -1) ? nil : dtype
+ end
+
+ # Returns a representation of the data encoded. in AMQP format.
+ def encode
+ size = 1024
+ loop do
+ (cd, enc) = Cproton.pn_data_encode(@data, size)
+ if cd == Cproton::PN_OVERFLOW
+ size *= 2
+ elsif cd >= 0
+ return enc
+ else
+ check(cd)
+ end
+ end
+ end
+
+ # Decodes the first value from supplied AMQP data and returns the number
+ # of bytes consumed.
+ #
+ # ==== Options
+ #
+ # * encoded - the encoded data
+ #
+ def decode(encoded)
+ check(Cproton.pn_data_decode(@data, encoded))
+ end
+
+ # Puts a list value.
+ #
+ # Elements may be filled by entering the list node and putting element
+ # values.
+ #
+ # ==== Examples
+ #
+ # data = Qpid::Proton::Data.new
+ # data.put_list
+ # data.enter
+ # data.int = 1
+ # data.int = 2
+ # data.int = 3
+ # data.exit
+ #
+ def put_list
+ check(Cproton.pn_data_put_list(@data))
+ end
+
+ # If the current node is a list, this returns the number of elements.
+ # Otherwise, it returns zero.
+ #
+ # List elements can be accessed by entering the list.
+ #
+ # ==== Examples
+ #
+ # count = @data.list
+ # @data.enter
+ # (0...count).each
+ # type = @data.next
+ # puts "Value: #{@data.string}" if type == :STRING
+ # # ... process other node types
+ # end
+ def list
+ Cproton.pn_data_get_list(@data)
+ end
+
+ # Puts a map value.
+ #
+ # Elements may be filled by entering the map node and putting alternating
+ # key/value pairs.
+ #
+ # ==== Examples
+ #
+ # data = Qpid::Proton::Data.new
+ # data.put_map
+ # data.enter
+ # data.string = "key"
+ # data.string = "value"
+ # data.exit
+ #
+ def put_map
+ check(Cproton.pn_data_put_map(@data))
+ end
+
+ # If the current node is a map, this returns the number of child
+ # elements. Otherwise, it returns zero.
+ #
+ # Key/value pairs can be accessed by entering the map.
+ #
+ # ==== Examples
+ #
+ # count = @data.map
+ # @data.enter
+ # (0...count).each do
+ # type = @data.next
+ # puts "Key=#{@data.string}" if type == :STRING
+ # # ... process other key types
+ # type = @data.next
+ # puts "Value=#{@data.string}" if type == :STRING
+ # # ... process other value types
+ # end
+ # @data.exit
+ def map
+ Cproton.pn_data_get_map(@data)
+ end
+
+ # Puts an array value.
+ #
+ # Elements may be filled by entering the array node and putting the
+ # element values. The values must all be of the specified array element
+ # type.
+ #
+ # If an array is *described* then the first child value of the array
+ # is the descriptor and may be of any type.
+ #
+ # ==== Options
+ #
+ # * described - specifies whether the array is described
+ # * element_type - the type of the array elements
+ #
+ # ==== Examples
+ #
+ # # create an array of integer values
+ # data = Qpid::Proton::Data.new
+ # data.put_array(false, :INT)
+ # data.enter
+ # data.int = 1
+ # data.int = 2
+ # data.int = 3
+ # data.exit
+ #
+ # # create an array of double values
+ # data.put_array(true, :DOUBLE)
+ # data.enter
+ # data.symbol = "array-descriptor"
+ # data.double = 1.1
+ # data.double = 1.2
+ # data.double = 1.3
+ # data.exit
+ #
+ def put_array(described, element_type)
+ check(Cproton.pn_data_put_array(@data, described,
+ Data.type_value(element_type)))
+ end
+
+ # If the current node is an array, returns a tuple of the element count, a
+ # boolean indicating whether the array is described, and the type of each
+ # element. Otherwise it returns +(0, false, nil).
+ #
+ # Array data can be accessed by entering the array.
+ #
+ # ==== Examples
+ #
+ # # get the details of thecurrent array
+ # count, described, array_type = @data.array
+ #
+ # # enter the node
+ # data.enter
+ #
+ # # get the next node
+ # data.next
+ # puts "Descriptor: #{data.symbol}" if described
+ # (0...count).each do
+ # @data.next
+ # puts "Element: #{@data.string}"
+ # end
+ def array
+ count = Cproton.pn_data_get_array(@data)
+ described = Cproton.pn_data_is_array_described(@data)
+ array_type = Cproton.pn_data_get_array_type(@data)
+ if array_type == -1
+ array_type = nil
+ else
+ array_type = Data.type_name(array_type)
+ end
+ [count, described, array_type]
+ end
+
+ # Puts a described value.
+ #
+ # A described node has two children, the descriptor and the value.
+ # These are specified by entering the node and putting the
+ # desired values.
+ #
+ # ==== Examples
+ #
+ # data = Qpid::Proton::Data.new
+ # data.put_described
+ # data.enter
+ # data.symbol = "value-descriptor"
+ # data.string = "the value"
+ # data.exit
+ #
+ def put_described
+ check(Cproton.pn_data_put_described(@data))
+ end
+
+ # Checks if the current node is a described value.
+ #
+ # The described and value may be accessed by entering the described value.
+ #
+ # ==== Examples
+ #
+ # if @data.described?
+ # @data.enter
+ # puts "The symbol is #{@data.symbol}"
+ # puts "The value is #{@data.string}"
+ # end
+ def described?
+ Cproton.pn_data_is_described(@data)
+ end
+
+ # Puts a null value.
+ def null
+ check(Cproton.pn_data_put_null(@data))
+ end
+
+ # Checks if the current node is null.
+ def null?
+ Cproton.pn_data_is_null(@data)
+ end
+
+ # Puts a boolean value.
+ #
+ # ==== Options
+ #
+ # * value - the boolean value
+ def bool=(value)
+ check(Cproton.pn_data_put_bool(@data, value))
+ end
+
+ # If the current node is a boolean, then it returns the value. Otherwise,
+ # it returns false.
+ def bool
+ Cproton.pn_data_get_bool(@data)
+ end
+
+ # Puts an unsigned byte value.
+ #
+ # ==== Options
+ #
+ # * value - the unsigned byte value
+ def ubyte=(value)
+ check(Cproton.pn_data_put_ubyte(@data, value))
+ end
+
+ # If the current node is an unsigned byte, returns its value. Otherwise,
+ # it reutrns 0.
+ def ubyte
+ Cproton.pn_data_get_ubyte(@data)
+ end
+
+ # Puts a byte value.
+ #
+ # ==== Options
+ #
+ # * value - the byte value
+ def byte=(value)
+ check(Cproton.pn_data_put_byte(@data, value))
+ end
+
+ # If the current node is an byte, returns its value. Otherwise,
+ # it returns 0.
+ def byte
+ Cproton.pn_data_get_byte(@data)
+ end
+
+ # Puts an unsigned short value.
+ #
+ # ==== Options
+ #
+ # * value - the unsigned short value
+ def ushort=(value)
+ check(Cproton.pn_data_put_ushort(@data, value))
+ end
+
+ # If the current node is an unsigned short, returns its value. Otherwise,
+ # it returns 0.
+ def ushort
+ Cproton.pn_data_get_ushort(@data)
+ end
+
+ # Puts a short value.
+ #
+ # ==== Options
+ #
+ # * value - the short value
+ def short=(value)
+ check(Cproton.pn_data_put_short(@data, value))
+ end
+
+ # If the current node is a short, returns its value. Otherwise,
+ # returns a 0.
+ def short
+ Cproton.pn_data_get_short(@data)
+ end
+
+ # Puts an unsigned integer value.
+ #
+ # ==== Options
+ #
+ # * value - the unsigned integer value
+ def uint=(value)
+ raise TypeError if value.nil?
+ raise RangeError, "invalid uint: #{value}" if value < 0
+ check(Cproton.pn_data_put_uint(@data, value))
+ end
+
+ # If the current node is an unsigned int, returns its value. Otherwise,
+ # returns 0.
+ def uint
+ Cproton.pn_data_get_uint(@data)
+ end
+
+ # Puts an integer value.
+ #
+ # ==== Options
+ #
+ # * value - the integer value
+ def int=(value)
+ check(Cproton.pn_data_put_int(@data, value))
+ end
+
+ # If the current node is an integer, returns its value. Otherwise,
+ # returns 0.
+ def int
+ Cproton.pn_data_get_int(@data)
+ end
+
+ # Puts a character value.
+ #
+ # ==== Options
+ #
+ # * value - the character value
+ def char=(value)
+ check(Cproton.pn_data_put_char(@data, value))
+ end
+
+ # If the current node is a character, returns its value. Otherwise,
+ # returns 0.
+ def char
+ Cproton.pn_data_get_char(@data)
+ end
+
+ # Puts an unsigned long value.
+ #
+ # ==== Options
+ #
+ # * value - the unsigned long value
+ def ulong=(value)
+ raise TypeError if value.nil?
+ raise RangeError, "invalid ulong: #{value}" if value < 0
+ check(Cproton.pn_data_put_ulong(@data, value))
+ end
+
+ # If the current node is an unsigned long, returns its value. Otherwise,
+ # returns 0.
+ def ulong
+ Cproton.pn_data_get_ulong(@data)
+ end
+
+ # Puts a long value.
+ #
+ # ==== Options
+ #
+ # * value - the long value
+ def long=(value)
+ check(Cproton.pn_data_put_long(@data, value))
+ end
+
+ # If the current node is a long, returns its value. Otherwise, returns 0.
+ def long
+ Cproton.pn_data_get_long(@data)
+ end
+
+ # Puts a timestamp value.
+ #
+ # ==== Options
+ #
+ # * value - the timestamp value
+ def timestamp=(value)
+ value = value.to_i if (!value.nil? && value.is_a?(Time))
+ check(Cproton.pn_data_put_timestamp(@data, value))
+ end
+
+ # If the current node is a timestamp, returns its value. Otherwise,
+ # returns 0.
+ def timestamp
+ Cproton.pn_data_get_timestamp(@data)
+ end
+
+ # Puts a float value.
+ #
+ # ==== Options
+ #
+ # * value - the float value
+ def float=(value)
+ check(Cproton.pn_data_put_float(@data, value))
+ end
+
+ # If the current node is a float, returns its value. Otherwise,
+ # returns 0.
+ def float
+ Cproton.pn_data_get_float(@data)
+ end
+
+ # Puts a double value.
+ #
+ # ==== Options
+ #
+ # * value - the double value
+ def double=(value)
+ check(Cproton.pn_data_put_double(@data, value))
+ end
+
+ # If the current node is a double, returns its value. Otherwise,
+ # returns 0.
+ def double
+ Cproton.pn_data_get_double(@data)
+ end
+
+ # Puts a decimal32 value.
+ #
+ # ==== Options
+ #
+ # * value - the decimal32 value
+ def decimal32=(value)
+ check(Cproton.pn_data_put_decimal32(@data, value))
+ end
+
+ # If the current node is a decimal32, returns its value. Otherwise,
+ # returns 0.
+ def decimal32
+ Cproton.pn_data_get_decimal32(@data)
+ end
+
+ # Puts a decimal64 value.
+ #
+ # ==== Options
+ #
+ # * value - the decimal64 value
+ def decimal64=(value)
+ check(Cproton.pn_data_put_decimal64(@data, value))
+ end
+
+ # If the current node is a decimal64, returns its value. Otherwise,
+ # it returns 0.
+ def decimal64
+ Cproton.pn_data_get_decimal64(@data)
+ end
+
+ # Puts a decimal128 value.
+ #
+ # ==== Options
+ #
+ # * value - the decimal128 value
+ def decimal128=(value)
+ raise TypeError, "invalid decimal128 value: #{value}" if value.nil?
+ value = value.to_s(16).rjust(32, "0")
+ bytes = []
+ value.scan(/(..)/) {|v| bytes << v[0].to_i(16)}
+ check(Cproton.pn_data_put_decimal128(@data, bytes))
+ end
+
+ # If the current node is a decimal128, returns its value. Otherwise,
+ # returns 0.
+ def decimal128
+ value = ""
+ Cproton.pn_data_get_decimal128(@data).each{|val| value += ("%02x" % val)}
+ value.to_i(16)
+ end
+
+ # Puts a +UUID+ value.
+ #
+ # The UUID is expected to be in the format of a string or else a 128-bit
+ # integer value.
+ #
+ # ==== Options
+ #
+ # * value - the +UUID+
+ #
+ # ==== Examples
+ #
+ # # set a uuid value from a string value
+ # require 'securerandom'
+ # @data.uuid = SecureRandom.uuid
+ #
+ # # or
+ # @data.uuid = "fd0289a5-8eec-4a08-9283-81d02c9d2fff"
+ #
+ # # set a uuid value from a 128-bit value
+ # @data.uuid = 0 # sets to 00000000-0000-0000-0000-000000000000
+ #
+ def uuid=(value)
+ raise ArgumentError, "invalid uuid: #{value}" if value.nil?
+
+ # if the uuid that was submitted was numeric value, then translated
+ # it into a hex string, otherwise assume it was a string represtation
+ # and attempt to decode it
+ if value.is_a? Numeric
+ value = "%032x" % value
+ else
+ raise ArgumentError, "invalid uuid: #{value}" if !valid_uuid?(value)
+
+ value = (value[0, 8] +
+ value[9, 4] +
+ value[14, 4] +
+ value[19, 4] +
+ value[24, 12])
+ end
+ bytes = []
+ value.scan(/(..)/) {|v| bytes << v[0].to_i(16)}
+ check(Cproton.pn_data_put_uuid(@data, bytes))
+ end
+
+ # If the current value is a +UUID+, returns its value. Otherwise,
+ # it returns nil.
+ def uuid
+ value = ""
+ Cproton.pn_data_get_uuid(@data).each{|val| value += ("%02x" % val)}
+ value.insert(8, "-").insert(13, "-").insert(18, "-").insert(23, "-")
+ end
+
+ # Puts a binary value.
+ #
+ # ==== Options
+ #
+ # * value - the binary value
+ def binary=(value)
+ check(Cproton.pn_data_put_binary(@data, value))
+ end
+
+ # If the current node is binary, returns its value. Otherwise, it returns
+ # an empty string ("").
+ def binary
+ Cproton.pn_data_get_binary(@data)
+ end
+
+ # Puts a unicode string value.
+ #
+ # *NOTE:* A nil value is stored as an empty string rather than as a nil.
+ #
+ # ==== Options
+ #
+ # * value - the unicode string value
+ def string=(value)
+ check(Cproton.pn_data_put_string(@data, value))
+ end
+
+ # If the current node is a string, returns its value. Otherwise, it
+ # returns an empty string ("").
+ def string
+ Cproton.pn_data_get_string(@data)
+ end
+
+ # Puts a symbolic value.
+ #
+ # ==== Options
+ #
+ # * value - the symbol name
+ def symbol=(value)
+ check(Cproton.pn_data_put_symbol(@data, value))
+ end
+
+ # If the current node is a symbol, returns its value. Otherwise, it
+ # returns an empty string ("").
+ def symbol
+ Cproton.pn_data_get_symbol(@data)
+ end
+
+ def self.add_item(key, value, name) # :nodoc:
+ @@type_value ||= {}
+ @@type_value[key] = value
+
+ @@type_name ||= {}
+ @@type_name[value] = key
+ end
+
+ # Returns the typename for the specified type.
+ #
+ # ==== Examples
+ # # returns "null"
+ # name = Qpid::Proton::Data.type_name(:NULL)
+ #
+ def self.type_name(key)
+ @@type_name[key]
+ end
+
+ def self.type_value(key) # :nodoc:
+ @@type_value[key]
+ end
+
+ def self.const_missing(key) # :nodoc:
+ @@type_value[key]
+ end
+
+ private
+
+ def valid_uuid?(value)
+ # ensure that the UUID is in the right format
+ # xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx
+ 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}/
+ end
+
+ def check(err) # :nodoc:
+ if err < 0
+ raise DataError, "[#{err}]: #{Cproton.pn_data_error(@data)}"
+ else
+ return err
+ end
+ end
+
+ self.add_item(:NULL, Cproton::PN_NULL, "null")
+ self.add_item(:BOOL, Cproton::PN_BOOL, "bool")
+ self.add_item(:UBYTE, Cproton::PN_UBYTE, "ubyte")
+ self.add_item(:BYTE, Cproton::PN_BYTE, "byte")
+ self.add_item(:USHORT, Cproton::PN_USHORT, "ushort")
+ self.add_item(:SHORT, Cproton::PN_SHORT, "short")
+ self.add_item(:UINT, Cproton::PN_UINT, "uint")
+ self.add_item(:INT, Cproton::PN_INT, "int")
+ self.add_item(:CHAR, Cproton::PN_CHAR, "char")
+ self.add_item(:ULONG, Cproton::PN_ULONG, "ulong")
+ self.add_item(:LONG, Cproton::PN_LONG, "long")
+ self.add_item(:TIMESTAMP, Cproton::PN_TIMESTAMP, "timestamp")
+ self.add_item(:FLOAT, Cproton::PN_FLOAT, "float")
+ self.add_item(:DOUBLE, Cproton::PN_DOUBLE, "double")
+ self.add_item(:DECIMAL32, Cproton::PN_DECIMAL32, "decimal32")
+ self.add_item(:DECIMAL64, Cproton::PN_DECIMAL64, "decimal64")
+ self.add_item(:DECIMAL128, Cproton::PN_DECIMAL128, "decimal128")
+ self.add_item(:UUID, Cproton::PN_UUID, "uuid")
+ self.add_item(:BINARY, Cproton::PN_BINARY, "binary")
+ self.add_item(:STRING, Cproton::PN_STRING, "string")
+ self.add_item(:SYMBOL, Cproton::PN_SYMBOL, "symbol")
+ self.add_item(:DESCRIBED, Cproton::PN_DESCRIBED, "described")
+ self.add_item(:ARRAY, Cproton::PN_ARRAY, "array")
+ self.add_item(:LIST, Cproton::PN_LIST, "list")
+ self.add_item(:MAP, Cproton::PN_MAP, "map")
+
+ end
+
+ end
+
+end
Modified: qpid/proton/trunk/proton-c/bindings/ruby/ruby.i
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/ruby.i?rev=1450219&r1=1450218&r2=1450219&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/ruby/ruby.i (original)
+++ qpid/proton/trunk/proton-c/bindings/ruby/ruby.i Tue Feb 26 15:34:04 2013
@@ -26,14 +26,11 @@
#include <proton/messenger.h>
#include <proton/ssl.h>
#include <proton/driver_extras.h>
-%}
-typedef unsigned int size_t;
-typedef signed int ssize_t;
-typedef unsigned char uint8_t;
-typedef unsigned int uint32_t;
-typedef unsigned long int uint64_t;
-typedef int int32_t;
+#include <proton/types.h>
+
+#include <uuid/uuid.h>
+%}
%include <cstring.i>
@@ -55,7 +52,7 @@ typedef int int32_t;
} else {
$1.start = RSTRING_PTR($input);
if (!$1.start) {
- return NULL;
+ $1.size = 0;
}
$1.size = RSTRING_LEN($input);
}
@@ -175,6 +172,70 @@ typedef int int32_t;
}
}
+%typemap (in) pn_decimal32_t
+{
+ $1 = FIX2UINT($input);
+}
+
+%typemap (out) pn_decimal32_t
+{
+ $result = ULL2NUM($1);
+}
+
+%typemap (in) pn_decimal64_t
+{
+ $1 = NUM2ULONG($input);
+}
+
+%typemap (out) pn_decimal64_t
+{
+ $result = ULL2NUM($1);
+}
+
+%typemap (in) pn_decimal128_t
+{
+ int index;
+
+ for(index = 0; index < 16; index++)
+ {
+ VALUE element = rb_ary_entry($input, index);
+ $1.bytes[16 - (index + 1)] = FIX2INT(element);
+ }
+}
+
+%typemap (out) pn_decimal128_t
+{
+ int index;
+
+ $result = rb_ary_new2(16);
+ for(index = 0; index < 16; index++)
+ {
+ rb_ary_store($result, 16 - (index + 1), CHR2FIX($1.bytes[index]));
+ }
+}
+
+%typemap (in) pn_uuid_t
+{
+ int index;
+
+ for(index = 0; index < 16; index++)
+ {
+ VALUE element = rb_ary_entry($input, index);
+ $1.bytes[16 - (index + 1)] = FIX2INT(element);
+ }
+}
+
+%typemap (out) pn_uuid_t
+{
+ int index;
+
+ $result = rb_ary_new2(16);
+ for(index = 0; index < 16; index++)
+ {
+ rb_ary_store($result, 16 - (index + 1), CHR2FIX($1.bytes[index]));
+ }
+}
+
%typemap (in) void *
{
$1 = (void *) $input;
Added: qpid/proton/trunk/proton-c/bindings/ruby/spec/qpid/proton/data_spec.rb
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/spec/qpid/proton/data_spec.rb?rev=1450219&view=auto
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/ruby/spec/qpid/proton/data_spec.rb (added)
+++ qpid/proton/trunk/proton-c/bindings/ruby/spec/qpid/proton/data_spec.rb Tue Feb 26 15:34:04 2013
@@ -0,0 +1,491 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+require "spec_helper"
+
+module Qpid
+
+ module Proton
+
+ describe "A data object" do
+
+ before :each do
+ @data = Qpid::Proton::Data.new
+ end
+
+ it "can be initialized" do
+ @data.should_not be_nil
+ end
+
+ it "can hold a null" do
+ @data.null
+ @data.null?.should be_true
+ end
+
+ it "can hold a true boolean" do
+ @data.bool = true
+ @data.bool.should be_true
+ end
+
+ it "can hold a false boolean" do
+ @data.bool = false
+ @data.bool.should_not be_true
+ end
+
+ it "raises an error on a negative ubyte" do
+ expect {
+ @data.ubyte = (0 - (rand(127) + 1))
+ }.to raise_error(RangeError)
+ end
+
+ it "raises an error on a null ubyte" do
+ expect {
+ @data.ubyte = nil
+ }.to raise_error(TypeError)
+ end
+
+ it "can hold an unsigned byte" do
+ value = rand(255)
+ @data.ubyte = value
+ @data.ubyte.should == value
+ end
+
+ it "can hold a byte" do
+ value = rand(128)
+ @data.byte = value
+ @data.byte.should == value
+ end
+
+ it "can hold a negative byte" do
+ value = 0 - (rand(126) + 1)
+ @data.byte = value
+ @data.byte.should == value
+ end
+
+ it "raises an error on a negative ushort" do
+ expect {
+ @data.ushort = (0 - (rand(65535) + 1))
+ }.to raise_error(RangeError)
+ end
+
+ it "raises an error on a nil ushort" do
+ expect {
+ @data.ushort = nil
+ }.to raise_error(TypeError)
+ end
+
+ it "can hold a zero unsigned short" do
+ @data.ushort = 0
+ @data.ushort.should == 0
+ end
+
+ it "can hold an unsigned short" do
+ value = rand(2**15) + 1
+ @data.ushort = value
+ @data.ushort.should == value
+ end
+
+ it "raises an error on a nil short" do
+ expect {
+ @data.short = nil
+ }.to raise_error(TypeError)
+ end
+
+ it "can hold a short" do
+ value = rand(2**15) + 1
+ @data.short = value
+ @data.short.should == value
+ end
+
+ it "can hold a zero short" do
+ @data.short = 0
+ @data.short.should == 0
+ end
+
+ it "can hold a negative short" do
+ value = (0 - (rand(2**15) + 1))
+ @data.short = value
+ @data.short.should == value
+ end
+
+ it "raises an error on a nil uint" do
+ expect {
+ @data.uint = nil
+ }.to raise_error(TypeError)
+ end
+
+ it "raises an error on a negative uint" do
+ expect {
+ @data.uint = (0 - (rand(2**32) + 1))
+ }.to raise_error(RangeError)
+ end
+
+ it "can hold an unsigned integer" do
+ value = rand(2**32) + 1
+ @data.uint = value
+ @data.uint.should == value
+ end
+
+ it "can hold a zero unsigned integer" do
+ @data.uint = 0
+ @data.uint.should == 0
+ end
+
+ it "raise an error on a null integer" do
+ expect {
+ @data.int = nil
+ }.to raise_error(TypeError)
+ end
+
+ it "can hold an integer" do
+ value = rand(2**31) + 1
+ @data.int = value
+ @data.int.should == value
+ end
+
+ it "can hold zero as an integer" do
+ @data.int = 0
+ @data.int.should == 0
+ end
+
+ it "raises an error on a null character" do
+ expect {
+ @data.char = nil
+ }.to raise_error(TypeError)
+ end
+
+ it "can hold a character" do
+ value = rand(256).chr.ord
+ @data.char = value
+ @data.char.should == value
+ end
+
+ it "raises an error on a null ulong" do
+ expect {
+ @data.ulong = nil
+ }.to raise_error(TypeError)
+ end
+
+ it "raises an error on a negative ulong" do
+ expect {
+ @data.ulong = (0 - (rand(2**63) + 1))
+ }.to raise_error(RangeError)
+ end
+
+ it "can have a zero unsigned long" do
+ @data.ulong = 0
+ @data.ulong.should == 0
+ end
+
+ it "can hold an unsigned long" do
+ value = rand(2**63) + 1
+ @data.ulong = value
+ @data.ulong.should == value
+ end
+
+ it "raises an error on a null long" do
+ expect {
+ @data.long = nil
+ }.to raise_error(TypeError)
+ end
+
+ it "can have a zero long" do
+ @data.long = 0
+ @data.long.should == 0
+ end
+
+ it "can hold a long" do
+ value = rand(2**63) + 1
+ @data.long = value
+ @data.long.should == value
+ end
+
+ it "raise an error on a null timestamp" do
+ expect {
+ @data.timestamp = nil
+ }.to raise_error(TypeError)
+ end
+
+ it "can handle a negative timestamp" do
+ last_year = Time.now - (60*60*24*365)
+ @data.timestamp = last_year
+ @data.timestamp.should == last_year.to_i
+ end
+
+ it "can handle a zero timestamp" do
+ @data.timestamp = 0
+ @data.timestamp.should == 0
+ end
+
+ it "can hold a timestamp" do
+ next_year = Time.now + (60*60*24*365)
+ @data.timestamp = next_year
+ @data.timestamp.should == next_year.to_i
+ end
+
+ it "raises an error on a null float" do
+ expect {
+ @data.float = nil
+ }.to raise_error(TypeError)
+ end
+
+ it "can hold a negative float" do
+ value = 0.0 - (1.0 + rand(2.0**15)).to_f
+ @data.float = value
+ @data.float.should == value
+ end
+
+ it "can hold a zero float" do
+ @data.float = 0.0
+ @data.float.should == 0.0
+ end
+
+ it "can hold a float" do
+ value = (1.0 + rand(2.0**15)).to_f
+ @data.float = value
+ @data.float.should == value
+ end
+
+ it "raise an error on a null double" do
+ expect {
+ @data.double = nil
+ }.to raise_error(TypeError)
+ end
+
+ it "can hold a negative double" do
+ value = 0.0 - (1.0 + rand(2.0**31)).to_f
+ @data.double = value
+ @data.double.should == value
+ end
+
+ it "can hold a zero double" do
+ @data.double = 0.0
+ @data.double.should == 0.0
+ end
+
+ it "can hold a double" do
+ value = (1.0 + rand(2.0**31)).to_f
+ @data.double = value
+ @data.double.should == value
+ end
+
+ it "raises an error on a null decimal32" do
+ expect {
+ @data.decimal32 = nil
+ }.to raise_error(TypeError)
+ end
+
+ it "can hold a zero decimal32" do
+ @data.decimal32 = 0
+ @data.decimal32.should == 0
+ end
+
+ it "can hold a decimal32" do
+ value = 1 + rand(2**31)
+ @data.decimal32 = value
+ @data.decimal32.should == value
+ end
+
+ it "raises an error on a null decimal64" do
+ expect {
+ @data.decimal64 = nil
+ }.to raise_error(TypeError)
+ end
+
+ it "can hold a zero decimal64" do
+ @data.decimal64 = 0
+ @data.decimal64.should == 0
+ end
+
+ it "can hold a decimal64" do
+ value = 1 + rand(2**63)
+ @data.decimal64 = value
+ @data.decimal64.should == value
+ end
+
+ it "raises an error on a null decimal128" do
+ expect {
+ @data.decimal128 = nil
+ }.to raise_error(TypeError)
+ end
+
+ it "can hold a zero decimal128" do
+ @data.decimal128 = 0
+ @data.decimal128.should == 0
+ end
+
+ it "can hold a decimal128" do
+ value = 1 + rand(2**127)
+ @data.decimal128 = value
+ @data.decimal128.should == value
+ end
+
+ it "raises an error on a null UUID" do
+ expect {
+ @data.uuid = nil
+ }.to raise_error(ArgumentError)
+ end
+
+ it "raises an error on a malformed UUID" do
+ expect {
+ @data.uuid = random_string(36)
+ }.to raise_error(ArgumentError)
+ end
+
+ it "can set a UUID from an integer value" do
+ @data.uuid = 336307859334295828133695192821923655679
+ @data.uuid.should == "fd0289a5-8eec-4a08-9283-81d02c9d2fff"
+ end
+
+ it "can hold a UUID" do
+ value = "fd0289a5-8eec-4a08-9283-81d02c9d2fff"
+ @data.uuid = value
+ @data.uuid.should == value
+ end
+
+ it "can hold a null binary" do
+ @data.binary = nil
+ @data.binary.should == ""
+ end
+
+ it "can hold a binary" do
+ value = random_string(128)
+ @data.binary = value
+ @data.binary.should == value
+ end
+
+ it "can hold a null string" do
+ @data.string = nil
+ @data.string.should == ""
+ end
+
+ it "can hold a string" do
+ value = random_string(128)
+ @data.string = value
+ @data.string.should == value
+ end
+
+ it "can hold a null symbol" do
+ @data.symbol = nil
+ @data.symbol.should == ""
+ end
+
+ it "can hold a symbol" do
+ value = random_string(128)
+ @data.symbol = value
+ @data.symbol.should == value
+ end
+
+ it "can hold a described value" do
+ name = random_string(16)
+ value = random_string(16)
+ @data.put_described
+ @data.enter
+ @data.symbol = name
+ @data.string = value
+ @data.exit
+
+ @data.described?.should be_true
+ @data.enter
+ @data.next
+ @data.symbol.should == name
+ @data.next
+ @data.string.should == value
+ end
+
+ it "raises an error when setting the wrong type in an array"
+
+ it "can hold an array" do
+ values = []
+ (1..(rand(100) + 5)).each { values << rand(2**16) }
+ @data.put_array false, :INT
+ @data.enter
+ values.each { |value| @data.int = value }
+ @data.exit
+
+ @data.enter
+ values.each do |value|
+ @data.next
+ @data.int. should == value
+ end
+ end
+
+ it "can hold a described array" do
+ values = []
+ (1..(rand(100) + 5)).each { values << random_string(64) }
+ descriptor = random_string(32)
+ @data.put_array true, :STRING
+ @data.enter
+ @data.symbol = descriptor
+ values.each { |value| @data.string = value }
+ @data.exit
+
+ @data.array.should == [values.size, true, :STRING]
+ @data.enter
+ @data.next
+ @data.symbol.should == descriptor
+ values.each do |value|
+ @data.next
+ @data.string.should == value
+ end
+ end
+
+ it "can hold a list" do
+ values = []
+ (1..(rand(100) + 5)).each { values << random_string(128) }
+ @data.put_list
+ @data.enter
+ values.each {|value| @data.string = value}
+ @data.exit
+
+ @data.enter
+ values.each do |value|
+ @data.next
+ @data.string.should == value
+ end
+ end
+
+ it "can hold a map" do
+ keys = []
+ (1..(rand(100) + 5)).each {keys << random_string(128)}
+ values = {}
+ keys.each {|key| values[key] = random_string(128)}
+
+ @data.put_map
+ @data.enter
+ keys.each do |key|
+ @data.string = key
+ @data.string = values[key]
+ end
+ @data.exit
+
+ @data.enter
+ keys.each do |key|
+ @data.next
+ @data.string.should == key
+ @data.next
+ @data.string.should == values[key]
+ end
+ end
+
+ end
+
+ end
+
+end
Modified: qpid/proton/trunk/proton-c/bindings/ruby/spec/spec_helper.rb
URL: http://svn.apache.org/viewvc/qpid/proton/trunk/proton-c/bindings/ruby/spec/spec_helper.rb?rev=1450219&r1=1450218&r2=1450219&view=diff
==============================================================================
--- qpid/proton/trunk/proton-c/bindings/ruby/spec/spec_helper.rb (original)
+++ qpid/proton/trunk/proton-c/bindings/ruby/spec/spec_helper.rb Tue Feb 26 15:34:04 2013
@@ -37,3 +37,4 @@ def random_string(length = 8)
(0...length).map{65.+(rand(25)).chr}.join
end
+require "securerandom"
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org