# dbus/type.rb - module containing low-level D-Bus data type information # # This file is part of the ruby-dbus project # Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License, version 2.1 as published by the Free Software Foundation. # See the file "COPYING" for the exact licensing terms. module DBus # = D-Bus type module # # This module containts the constants of the types specified in the D-Bus # protocol. module Type # Mapping from type number to name and alignment. TypeMapping = { 0 => ["INVALID", nil], "y" => ["BYTE", 1], "b" => ["BOOLEAN", 4], "n" => ["INT16", 2], "q" => ["UINT16", 2], "i" => ["INT32", 4], "u" => ["UINT32", 4], "x" => ["INT64", 8], "t" => ["UINT64", 8], "d" => ["DOUBLE", 8], "r" => ["STRUCT", 8], "a" => ["ARRAY", 4], "v" => ["VARIANT", 1], "o" => ["OBJECT_PATH", 4], "s" => ["STRING", 4], "g" => ["SIGNATURE", 1], "e" => ["DICT_ENTRY", 8], "h" => ["UNIX_FD", 4] }.freeze # Defines the set of constants TypeMapping.each_pair do |key, value| Type.const_set(value.first, key) end # Exception raised when an unknown/incorrect type is encountered. class SignatureException < Exception end # = D-Bus type conversion class # # Helper class for representing a D-Bus type. class Type # Returns the signature type number. attr_reader :sigtype # Return contained member types. attr_reader :members # Create a new type instance for type number _sigtype_. def initialize(sigtype) if !TypeMapping.keys.member?(sigtype) raise SignatureException, "Unknown key in signature: #{sigtype.chr}" end @sigtype = sigtype @members = [] end # Return the required alignment for the type. def alignment TypeMapping[@sigtype].last end # Return a string representation of the type according to the # D-Bus specification. def to_s case @sigtype when STRUCT "(" + @members.collect(&:to_s).join + ")" when ARRAY "a" + child.to_s when DICT_ENTRY "{" + @members.collect(&:to_s).join + "}" else if !TypeMapping.keys.member?(@sigtype) raise NotImplementedError end @sigtype.chr end end # Add a new member type _a_. def <<(a) if ![STRUCT, ARRAY, DICT_ENTRY].member?(@sigtype) raise SignatureException end raise SignatureException if @sigtype == ARRAY && !@members.empty? if @sigtype == DICT_ENTRY if @members.size == 2 raise SignatureException, "Dict entries have exactly two members" end if @members.empty? if [STRUCT, ARRAY, DICT_ENTRY].member?(a.sigtype) raise SignatureException, "Dict entry keys must be basic types" end end end @members << a end # Return the first contained member type. def child @members[0] end def inspect s = TypeMapping[@sigtype].first if [STRUCT, ARRAY].member?(@sigtype) s += ": " + @members.inspect end s end end # class Type # = D-Bus type parser class # # Helper class to parse a type signature in the protocol. class Parser # Create a new parser for the given _signature_. def initialize(signature) @signature = signature @idx = 0 end # Returns the next character from the signature. def nextchar c = @signature[@idx] @idx += 1 c end # Parse one character _c_ of the signature. def parse_one(c) res = nil case c when "a" res = Type.new(ARRAY) c = nextchar raise SignatureException, "Parse error in #{@signature}" if c.nil? child = parse_one(c) res << child when "(" res = Type.new(STRUCT) while (c = nextchar) && c != ")" res << parse_one(c) end raise SignatureException, "Parse error in #{@signature}" if c.nil? when "{" res = Type.new(DICT_ENTRY) while (c = nextchar) && c != "}" res << parse_one(c) end raise SignatureException, "Parse error in #{@signature}" if c.nil? else res = Type.new(c) end res end # Parse the entire signature, return a DBus::Type object. def parse @idx = 0 ret = [] while (c = nextchar) ret << parse_one(c) end ret end end # class Parser end # module Type # shortcuts # Parse a String to a DBus::Type::Type def type(string_type) Type::Parser.new(string_type).parse[0] end module_function :type # Make an explicit [Type, value] pair def variant(string_type, value) [type(string_type), value] end module_function :variant end # module DBus