Parent

Files

DBus::PacketMarshaller

D-Bus packet marshaller class

Class that handles the conversion (marshalling) of Ruby objects to (binary) payload data.

Attributes

packet[R]

The current or result packet. FIXME: allow access only when marshalling is finished

Public Class Methods

make_variant(value) click to toggle source

Make a [signature, value] pair for a variant

# File lib/dbus/marshall.rb, line 414
def self.make_variant(value)
  # TODO: mix in _make_variant to String, Integer...
  if value == true
    ["b", true]
  elsif value == false
    ["b", false]
  elsif value.nil?
    ["b", nil]
  elsif value.is_a? Float
    ["d", value]
  elsif value.is_a? Symbol
    ["s", value.to_s]
  elsif value.is_a? Array
    ["av", value.map {|i| make_variant(i) }]
  elsif value.is_a? Hash
    h = {}
    value.each_key {|k| h[k] = make_variant(value[k]) }
    ["a{sv}", h]
  elsif value.respond_to? :to_str
    ["s", value.to_str]
  elsif value.respond_to? :to_int
    i = value.to_int
    if -2_147_483_648 <= i && i < 2_147_483_648
      ["i", i]
    else
      ["x", i]
    end
  end
end
new(offset = 0) click to toggle source

Create a new marshaller, setting the current packet to the empty packet.

# File lib/dbus/marshall.rb, line 251
def initialize(offset = 0)
  @packet = ""
  @offset = offset          # for correct alignment of nested marshallers
end

Public Instance Methods

align(a) click to toggle source

Align the buffer with NULL (0) bytes on a byte length of a.

# File lib/dbus/marshall.rb, line 268
def align(a)
  @packet = @packet.ljust(num_align(@offset + @packet.bytesize, a) - @offset, 0.chr)
end
append(type, val) click to toggle source

Append a value val to the packet based on its type.

Host native endianness is used, declared in Message#marshall

# File lib/dbus/marshall.rb, line 312
def append(type, val)
  raise TypeException, "Cannot send nil" if val.nil?

  type = type.chr if type.kind_of?(Fixnum)
  type = Type::Parser.new(type).parse[0] if type.kind_of?(String)
  case type.sigtype
  when Type::BYTE
    @packet += val.chr
  when Type::UINT32
    align(4)
    @packet += [val].pack("L")
  when Type::UINT64
    align(8)
    @packet += [val].pack("Q")
  when Type::INT64
    align(8)
    @packet += [val].pack("q")
  when Type::INT32
    align(4)
    @packet += [val].pack("l")
  when Type::UINT16
    align(2)
    @packet += [val].pack("S")
  when Type::INT16
    align(2)
    @packet += [val].pack("s")
  when Type::DOUBLE
    align(8)
    @packet += [val].pack("d")
  when Type::BOOLEAN
    align(4)
    if val
      @packet += [1].pack("L")
    else
      @packet += [0].pack("L")
    end
  when Type::OBJECT_PATH
    append_string(val)
  when Type::STRING
    append_string(val)
  when Type::SIGNATURE
    append_signature(val)
  when Type::VARIANT
    vartype = nil
    if val.is_a?(Array) and val.size == 2
      if val[0].is_a?(DBus::Type::Type)
        vartype, vardata = val
      elsif val[0].is_a?(String)
        begin
          parsed = Type::Parser.new(val[0]).parse
          vartype = parsed[0] if parsed.size == 1
          vardata = val[1]
        rescue Type::SignatureException
          # no assignment
        end
      end
    end
    if vartype.nil?
      vartype, vardata = PacketMarshaller.make_variant(val)
      vartype = Type::Parser.new(vartype).parse[0]
    end

    append_signature(vartype.to_s)
    align(vartype.alignment)
    sub = PacketMarshaller.new(@offset + @packet.bytesize)
    sub.append(vartype, vardata)
    @packet += sub.packet
  when Type::ARRAY
    if val.kind_of?(Hash)
      raise TypeException, "Expected an Array but got a Hash" if type.child.sigtype != Type::DICT_ENTRY
      # Damn ruby rocks here
      val = val.to_a
    end
    if not val.kind_of?(Array)
      raise TypeException, "Expected an Array but got a #{val.class}"
    end
    array(type.child) do
      val.each do |elem|
        append(type.child, elem)
      end
    end
  when Type::STRUCT, Type::DICT_ENTRY
    # TODO use duck typing, val.respond_to?
    raise TypeException, "Struct/DE expects an Array" if not val.kind_of?(Array)
    if type.sigtype == Type::DICT_ENTRY and val.size != 2
      raise TypeException, "Dict entry expects a pair"
    end
    if type.members.size != val.size
      raise TypeException, "Struct/DE has #{val.size} elements but type info for #{type.members.size}"
    end
    struct do
      type.members.zip(val).each do |t, v|
        append(t, v)
      end
    end
  else
    raise NotImplementedError,
      "sigtype: #{type.sigtype} (#{type.sigtype.chr})"     
  end
end
append_signature(str) click to toggle source

Append the the signature signature itself to the packet.

# File lib/dbus/marshall.rb, line 279
def append_signature(str)
  @packet += str.bytesize.chr + str + "\00""
end
append_simple_string(s) click to toggle source

Append a string of bytes without type.

# File lib/dbus/marshall.rb, line 305
def append_simple_string(s)
  @packet += s + "\00""
end
append_string(str) click to toggle source

Append the the string str itself to the packet.

# File lib/dbus/marshall.rb, line 273
def append_string(str)
  align(4)
  @packet += [str.bytesize].pack("L") + [str].pack("Z*")
end
array(type) click to toggle source

Append the array type type to the packet and allow for appending the child elements.

# File lib/dbus/marshall.rb, line 285
def array(type)
  # Thanks to Peter Rullmann for this line
  align(4)
  sizeidx = @packet.bytesize
  @packet += "ABCD"
  align(type.alignment)
  contentidx = @packet.bytesize
  yield
  sz = @packet.bytesize - contentidx
  raise InvalidPacketException if sz > 67108864
  @packet[sizeidx...sizeidx + 4] = [sz].pack("L")
end
num_align(n, a) click to toggle source

Round n up to the specified power of two, a

# File lib/dbus/marshall.rb, line 257
def num_align(n, a)
  case a
  when 1, 2, 4, 8
    bits = a - 1
    n + bits & ~bits
  else
    raise "Unsupported alignment"
  end
end
struct() click to toggle source

Align and allow for appending struct fields.

# File lib/dbus/marshall.rb, line 299
def struct
  align(8)
  yield
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.