File: type.rb

package info (click to toggle)
ruby-dbus 0.16.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 520 kB
  • sloc: ruby: 3,786; sh: 53; makefile: 8
file content (191 lines) | stat: -rw-r--r-- 5,267 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# 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