Class: Qpid::Proton::Codec::Data

Inherits:
Object
  • Object
show all
Defined in:
lib/codec/data.rb

Overview

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

  • BYTE

  • USHORT

  • SHORT

  • UINT

  • INT

  • CHAR

  • ULONG

  • LONG

  • TIMESTAMP

  • FLOAT

  • DOUBLE

  • DECIMAL32

  • DECIMAL64

  • DECIMAL128

  • UUID

  • BINARY

  • STRING

  • SYMBOL

The following types of compound values are supported:

  • DESCRIBED

  • ARRAY

  • LIST

  • MAP

Instance Method Summary collapse

Constructor Details

#initialize(capacity = 16) ⇒ Data

Creates a new instance with the specified capacity.

Parameters:

  • capacity (Fixnum, Object) (defaults to: 16)

    The initial capacity or content.



87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/codec/data.rb', line 87

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, @free))
end

Instance Method Details

#arrayObject

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


369
370
371
372
373
374
375
# File 'lib/codec/data.rb', line 369

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)
  return nil if array_type == -1
  [count, described, Mapping.for_code(array_type) ]
end

#binaryString

If the current node is binary, returns its value. Otherwise, it returns an empty string (“”).

Returns:

  • (String)

    The binary string.

See Also:



827
828
829
# File 'lib/codec/data.rb', line 827

def binary
  Qpid::Proton::Types::BinaryString.new(Cproton.pn_data_get_binary(@data))
end

#binary=(value) ⇒ Object

Puts a binary value.

A binary string is encoded as an ASCII 8-bit string value. This is in contranst to other strings, which are treated as UTF-8 encoded.

Parameters:

  • value (String)

    An arbitrary string value.

See Also:



816
817
818
# File 'lib/codec/data.rb', line 816

def binary=(value)
  check(Cproton.pn_data_put_binary(@data, value))
end

#boolBoolean

If the current node is a boolean, then it returns the value. Otherwise, it returns false.

Returns:

  • (Boolean)

    The boolean value.



486
487
488
# File 'lib/codec/data.rb', line 486

def bool
  Cproton.pn_data_get_bool(@data)
end

#bool=(value) ⇒ Object

Puts a boolean value.

Parameters:

  • value (Boolean)

    The boolean value.



477
478
479
# File 'lib/codec/data.rb', line 477

def bool=(value)
  check(Cproton.pn_data_put_bool(@data, value))
end

#byteFixnum

If the current node is an byte, returns its value. Otherwise, it returns 0.

Returns:

  • (Fixnum)

    The byte value.



520
521
522
# File 'lib/codec/data.rb', line 520

def byte
  Cproton.pn_data_get_byte(@data)
end

#byte=(value) ⇒ Object

Puts a byte value.

Parameters:

  • value (Fixnum)

    The byte value.



511
512
513
# File 'lib/codec/data.rb', line 511

def byte=(value)
  check(Cproton.pn_data_put_byte(@data, value))
end

#charFixnum

If the current node is a character, returns its value. Otherwise, returns 0.

Returns:

  • (Fixnum)

    The character value.



608
609
610
# File 'lib/codec/data.rb', line 608

def char
  Cproton.pn_data_get_char(@data)
end

#char=(value) ⇒ Object

Puts a character value.

Parameters:

  • value (Fixnum)

    The character value.



599
600
601
# File 'lib/codec/data.rb', line 599

def char=(value)
  check(Cproton.pn_data_put_char(@data, value))
end

#clearObject

Clears the object.



120
121
122
# File 'lib/codec/data.rb', line 120

def clear
  Cproton.pn_data_clear(@data)
end

#decimal128Fixnum

If the current node is a decimal128, returns its value. Otherwise, returns 0.

Returns:

  • (Fixnum)

    The decimal128 value.



749
750
751
752
753
# File 'lib/codec/data.rb', line 749

def decimal128
  value = ""
  Cproton.pn_data_get_decimal128(@data).each{|val| value += ("%02x" % val)}
  value.to_i(16)
end

#decimal128=(value) ⇒ Object

Puts a decimal128 value.

Parameters:

  • value (Fixnum)

    The decimal128 value.

Raises:

  • (TypeError)


736
737
738
739
740
741
742
# File 'lib/codec/data.rb', line 736

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

#decimal32Fixnum

If the current node is a decimal32, returns its value. Otherwise, returns 0.

Returns:

  • (Fixnum)

    The decimal32 value.



711
712
713
# File 'lib/codec/data.rb', line 711

def decimal32
  Cproton.pn_data_get_decimal32(@data)
end

#decimal32=(value) ⇒ Object

Puts a decimal32 value.

Parameters:

  • value (Fixnum)

    The decimal32 value.



702
703
704
# File 'lib/codec/data.rb', line 702

def decimal32=(value)
  check(Cproton.pn_data_put_decimal32(@data, value))
end

#decimal64Fixnum

If the current node is a decimal64, returns its value. Otherwise, it returns 0.

Returns:

  • (Fixnum)

    The decimal64 value.



728
729
730
# File 'lib/codec/data.rb', line 728

def decimal64
  Cproton.pn_data_get_decimal64(@data)
end

#decimal64=(value) ⇒ Object

Puts a decimal64 value.

Parameters:

  • value (Fixnum)

    The decimal64 value.



719
720
721
# File 'lib/codec/data.rb', line 719

def decimal64=(value)
  check(Cproton.pn_data_put_decimal64(@data, value))
end

#decode(encoded) ⇒ Object

Decodes the first value from supplied AMQP data and returns the number of bytes consumed.

Examples:


# SCENARIO: A string of encoded data, @encoded, contains the text
#           of "This is a test." and is passed to an instance of Data
#           for decoding.

@data.decode(@encoded)
@data.string #=> "This is a test."

Parameters:

  • encoded (String)

    The encoded data.



226
227
228
# File 'lib/codec/data.rb', line 226

def decode(encoded)
  check(Cproton.pn_data_decode(@data, encoded, encoded.length))
end

#described?Boolean

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

Returns:

  • (Boolean)


426
427
428
# File 'lib/codec/data.rb', line 426

def described?
  Cproton.pn_data_is_described(@data)
end

#doubleFloat

If the current node is a double, returns its value. Otherwise, returns 0.

Returns:

  • (Float)

    The double precision floating point value.



694
695
696
# File 'lib/codec/data.rb', line 694

def double
  Cproton.pn_data_get_double(@data)
end

#double=(value) ⇒ Object

Puts a double value.

Parameters:

  • value (Float)

    The double precision floating point value.



685
686
687
# File 'lib/codec/data.rb', line 685

def double=(value)
  check(Cproton.pn_data_put_double(@data, value))
end

#encodeString

Returns a representation of the data encoded in AMQP format.

Examples:


@data.string = "This is a test."
@encoded = @data.encode

# @encoded now contains the text "This is a test." encoded for
# AMQP transport.

Returns:

  • (String)

    The context of the Data as an AMQP data string.



198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/codec/data.rb', line 198

def encode
  buffer = "\0"*1024
  loop do
    cd = Cproton.pn_data_encode(@data, buffer, buffer.length)
    if cd == Cproton::PN_OVERFLOW
      buffer *= 2
    elsif cd >= 0
      return buffer[0...cd]
    else
      check(cd)
    end
  end
end

#enterObject

Sets the parent node to the current node and clears the current node.

Clearing the current node sets it before the first child.



155
156
157
# File 'lib/codec/data.rb', line 155

def enter
  Cproton.pn_data_enter(@data)
end

#exitObject

Sets the current node to the parent node and the parent node to its own parent.



162
163
164
# File 'lib/codec/data.rb', line 162

def exit
  Cproton.pn_data_exit(@data)
end

#floatFloat

If the current node is a float, returns its value. Otherwise, returns 0.

Returns:

  • (Float)

    The floating point value.



677
678
679
# File 'lib/codec/data.rb', line 677

def float
  Cproton.pn_data_get_float(@data)
end

#float=(value) ⇒ Object

Puts a float value.

Parameters:

  • value (Float)

    The floating point value.



668
669
670
# File 'lib/codec/data.rb', line 668

def float=(value)
  check(Cproton.pn_data_put_float(@data, value))
end

#getObject

Get the current value as a single object.

Returns:

  • (Object)

    The current node’s object.

See Also:



878
879
880
# File 'lib/codec/data.rb', line 878

def get
  type.get(self);
end

#intFixnum

If the current node is an integer, returns its value. Otherwise, returns 0.

Returns:

  • (Fixnum)

    The integer value.



591
592
593
# File 'lib/codec/data.rb', line 591

def int
  Cproton.pn_data_get_int(@data)
end

#int=(value) ⇒ Object

Puts an integer value.

Options

  • value - the integer value



582
583
584
# File 'lib/codec/data.rb', line 582

def int=(value)
  check(Cproton.pn_data_put_int(@data, value))
end

#listObject

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


263
264
265
# File 'lib/codec/data.rb', line 263

def list
  Cproton.pn_data_get_list(@data)
end

#longFixnum

If the current node is a long, returns its value. Otherwise, returns 0.

Returns:

  • (Fixnum)

    The long value.



642
643
644
# File 'lib/codec/data.rb', line 642

def long
  Cproton.pn_data_get_long(@data)
end

#long=(value) ⇒ Object

Puts a long value.

Parameters:

  • value (Fixnum)

    The long value.



635
636
637
# File 'lib/codec/data.rb', line 635

def long=(value)
  check(Cproton.pn_data_put_long(@data, value))
end

#mapObject

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


303
304
305
# File 'lib/codec/data.rb', line 303

def map
  Cproton.pn_data_get_map(@data)
end

#nextObject

Advances the current node to its next sibling and returns its types.

If there is no next sibling the current node remains unchanged and nil is returned.



138
139
140
# File 'lib/codec/data.rb', line 138

def next
  Cproton.pn_data_next(@data)
end

#nullObject

Puts a null value.



432
433
434
# File 'lib/codec/data.rb', line 432

def null
  check(Cproton.pn_data_put_null(@data))
end

#null?Boolean

Checks if the current node is null.

Returns:

  • (Boolean)

    True if the node is null.



469
470
471
# File 'lib/codec/data.rb', line 469

def null?
  Cproton.pn_data_is_null(@data)
end

#objectObject

Gets the current node, based on how it was encoded.

Returns:

  • (Object)

    The current node.



459
460
461
462
463
# File 'lib/codec/data.rb', line 459

def object
  type = self.type
  return nil if type.nil?
  type.get(data)
end

#object=(object) ⇒ Object

Puts an arbitrary object type.

The Data instance will determine which AMQP type is appropriate and will use that to encode the object.

Parameters:

  • object (Object)

    The value.



451
452
453
# File 'lib/codec/data.rb', line 451

def object=(object)
  Mapping.for_class(object.class).put(self, object)
end

#prevObject

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.



147
148
149
# File 'lib/codec/data.rb', line 147

def prev
  return Cproton.pn_data_prev(@data) ? type : nil
end

#put_array(described, element_type) ⇒ Object

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.

Examples:


# create an array of integer values
data = Qpid::Proton::Codec::Data.new
data.put_array(false, INT)
data.enter
data.int = 1
data.int = 2
data.int = 3
data.exit

# create a described  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

Parameters:

  • described (Boolean)

    True if the array is described.

  • element_type (Fixnum)

    The AMQP type for each element of the array.



344
345
346
# File 'lib/codec/data.rb', line 344

def put_array(described, element_type)
  check(Cproton.pn_data_put_array(@data, described, element_type.code))
end

#put_describedObject

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::Codec::Data.new
data.put_described
data.enter
data.symbol = "value-descriptor"
data.string = "the value"
data.exit


397
398
399
# File 'lib/codec/data.rb', line 397

def put_described
  check(Cproton.pn_data_put_described(@data))
end

#put_listObject

Puts a list value.

Elements may be filled by entering the list node and putting element values.

Examples:


data = Qpid::Proton::Codec::Data.new
data.put_list
data.enter
data.int = 1
data.int = 2
data.int = 3
data.exit


245
246
247
# File 'lib/codec/data.rb', line 245

def put_list
  check(Cproton.pn_data_put_list(@data))
end

#put_mapObject

Puts a map value.

Elements may be filled by entering the map node and putting alternating key/value pairs.

Examples:


data = Qpid::Proton::Codec::Data.new
data.put_map
data.enter
data.string = "key"
data.string = "value"
data.exit


281
282
283
# File 'lib/codec/data.rb', line 281

def put_map
  check(Cproton.pn_data_put_map(@data))
end

#rewindObject

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.



129
130
131
# File 'lib/codec/data.rb', line 129

def rewind
  Cproton.pn_data_rewind(@data)
end

#shortFixnum

If the current node is a short, returns its value. Otherwise, returns a 0.

Returns:

  • (Fixnum)

    The short value.



554
555
556
# File 'lib/codec/data.rb', line 554

def short
  Cproton.pn_data_get_short(@data)
end

#short=(value) ⇒ Object

Puts a short value.

Parameters:

  • value (Fixnum)

    The short value.



545
546
547
# File 'lib/codec/data.rb', line 545

def short=(value)
  check(Cproton.pn_data_put_short(@data, value))
end

#stringString

If the current node is a string, returns its value. Otherwise, it returns an empty string (“”).

Returns:

  • (String)

    The UTF-8 encoded string.

See Also:



850
851
852
# File 'lib/codec/data.rb', line 850

def string
  Qpid::Proton::Types::UTFString.new(Cproton.pn_data_get_string(@data))
end

#string=(value) ⇒ Object

Puts a UTF-8 encoded string value.

NOTE: A nil value is stored as an empty string rather than as a nil.

Parameters:

  • value (String)

    The UTF-8 encoded string value.

See Also:



839
840
841
# File 'lib/codec/data.rb', line 839

def string=(value)
  check(Cproton.pn_data_put_string(@data, value))
end

#symbolString

If the current node is a symbol, returns its value. Otherwise, it returns an empty string (“”).

Returns:

  • (String)

    The symbolic string value.



867
868
869
# File 'lib/codec/data.rb', line 867

def symbol
  Cproton.pn_data_get_symbol(@data)
end

#symbol=(value) ⇒ Object

Puts a symbolic value.

Parameters:

  • value (String)

    The symbolic string value.



858
859
860
# File 'lib/codec/data.rb', line 858

def symbol=(value)
  check(Cproton.pn_data_put_symbol(@data, value))
end

#timestampFixnum

If the current node is a timestamp, returns its value. Otherwise, returns 0.

Returns:

  • (Fixnum)

    The timestamp value.



660
661
662
# File 'lib/codec/data.rb', line 660

def timestamp
  Cproton.pn_data_get_timestamp(@data)
end

#timestamp=(value) ⇒ Object

Puts a timestamp value.

Parameters:

  • value (Fixnum)

    The timestamp value.



650
651
652
653
# File 'lib/codec/data.rb', line 650

def timestamp=(value)
  value = value.to_i if (!value.nil? && value.is_a?(Time))
  check(Cproton.pn_data_put_timestamp(@data, value))
end

#typeObject

Return the type object for the current node

Parameters:

  • The (Fixnum)

    object type.

See Also:



182
183
184
# File 'lib/codec/data.rb', line 182

def type
  Mapping.for_code(type_code)
end

#type_codeFixnum?

Returns the numeric type code of the current node.

Returns:

  • (Fixnum)

    The current node type.

  • (nil)

    If there is no current node.



171
172
173
174
# File 'lib/codec/data.rb', line 171

def type_code
  dtype = Cproton.pn_data_type(@data)
  return (dtype == -1) ? nil : dtype
end

#ubyteFixnum

If the current node is an unsigned byte, returns its value. Otherwise, it returns 0.

Returns:

  • (Fixnum)

    The unsigned byte value.



503
504
505
# File 'lib/codec/data.rb', line 503

def ubyte
  Cproton.pn_data_get_ubyte(@data)
end

#ubyte=(value) ⇒ Object

Puts an unsigned byte value.

Parameters:

  • value (Fixnum)

    The unsigned byte value.



494
495
496
# File 'lib/codec/data.rb', line 494

def ubyte=(value)
  check(Cproton.pn_data_put_ubyte(@data, value))
end

#uintFixnum

If the current node is an unsigned int, returns its value. Otherwise, returns 0.

Returns:

  • (Fixnum)

    The unsigned integer value.



573
574
575
# File 'lib/codec/data.rb', line 573

def uint
  Cproton.pn_data_get_uint(@data)
end

#uint=(value) ⇒ Object

Puts an unsigned integer value.

Parameters:

  • value (Fixnum)

    the unsigned integer value

Raises:

  • (TypeError)


562
563
564
565
566
# File 'lib/codec/data.rb', line 562

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

#ulongFixnum

If the current node is an unsigned long, returns its value. Otherwise, returns 0.

Returns:

  • (Fixnum)

    The unsigned long value.



627
628
629
# File 'lib/codec/data.rb', line 627

def ulong
  Cproton.pn_data_get_ulong(@data)
end

#ulong=(value) ⇒ Object

Puts an unsigned long value.

Parameters:

  • value (Fixnum)

    The unsigned long value.

Raises:

  • (TypeError)


616
617
618
619
620
# File 'lib/codec/data.rb', line 616

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

#ushortFixnum

If the current node is an unsigned short, returns its value. Otherwise, it returns 0.

Returns:

  • (Fixnum)

    The unsigned short value.



537
538
539
# File 'lib/codec/data.rb', line 537

def ushort
  Cproton.pn_data_get_ushort(@data)
end

#ushort=(value) ⇒ Object

Puts an unsigned short value.

Parameters:

  • value (Fixnum)

    The unsigned short value



528
529
530
# File 'lib/codec/data.rb', line 528

def ushort=(value)
  check(Cproton.pn_data_put_ushort(@data, value))
end

#uuidString

If the current value is a UUID, returns its value. Otherwise, it returns nil.

Returns:

  • (String)

    The string representation of the UUID.



801
802
803
804
805
# File 'lib/codec/data.rb', line 801

def uuid
  value = ""
  Cproton.pn_data_get_uuid(@data).each{|val| value += ("%02x" % val)}
  value.insert(8, "-").insert(13, "-").insert(18, "-").insert(23, "-")
end

#uuid=(value) ⇒ Object

Puts a UUID value.

The UUID is expected to be in the format of a string or else a 128-bit integer value.

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

Parameters:

  • value (String, Numeric)

    A string or numeric representation of the UUID.

Raises:

  • (::ArgumentError)


774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
# File 'lib/codec/data.rb', line 774

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