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