ruby-dbus 0.16.0 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/NEWS.md +160 -0
  3. data/README.md +3 -5
  4. data/Rakefile +18 -8
  5. data/VERSION +1 -1
  6. data/doc/Reference.md +106 -7
  7. data/examples/doc/_extract_examples +7 -0
  8. data/examples/gdbus/gdbus +31 -24
  9. data/examples/no-introspect/nm-test.rb +2 -0
  10. data/examples/no-introspect/tracker-test.rb +3 -1
  11. data/examples/rhythmbox/playpause.rb +2 -1
  12. data/examples/service/call_service.rb +2 -1
  13. data/examples/service/complex-property.rb +21 -0
  14. data/examples/service/service_newapi.rb +1 -1
  15. data/examples/simple/call_introspect.rb +1 -0
  16. data/examples/simple/get_id.rb +2 -1
  17. data/examples/simple/properties.rb +2 -0
  18. data/examples/utils/listnames.rb +1 -0
  19. data/examples/utils/notify.rb +1 -0
  20. data/lib/dbus/api_options.rb +9 -0
  21. data/lib/dbus/auth.rb +20 -15
  22. data/lib/dbus/bus.rb +123 -75
  23. data/lib/dbus/bus_name.rb +12 -8
  24. data/lib/dbus/core_ext/class/attribute.rb +1 -1
  25. data/lib/dbus/data.rb +821 -0
  26. data/lib/dbus/emits_changed_signal.rb +83 -0
  27. data/lib/dbus/error.rb +4 -2
  28. data/lib/dbus/introspect.rb +132 -31
  29. data/lib/dbus/logger.rb +3 -1
  30. data/lib/dbus/marshall.rb +247 -296
  31. data/lib/dbus/matchrule.rb +16 -16
  32. data/lib/dbus/message.rb +44 -37
  33. data/lib/dbus/message_queue.rb +16 -10
  34. data/lib/dbus/object.rb +358 -24
  35. data/lib/dbus/object_path.rb +11 -6
  36. data/lib/dbus/proxy_object.rb +22 -1
  37. data/lib/dbus/proxy_object_factory.rb +13 -7
  38. data/lib/dbus/proxy_object_interface.rb +63 -30
  39. data/lib/dbus/raw_message.rb +91 -0
  40. data/lib/dbus/type.rb +318 -86
  41. data/lib/dbus/xml.rb +32 -17
  42. data/lib/dbus.rb +14 -7
  43. data/ruby-dbus.gemspec +7 -3
  44. data/spec/async_spec.rb +2 -0
  45. data/spec/binding_spec.rb +2 -0
  46. data/spec/bus_and_xml_backend_spec.rb +2 -0
  47. data/spec/bus_driver_spec.rb +2 -0
  48. data/spec/bus_name_spec.rb +3 -1
  49. data/spec/bus_spec.rb +2 -0
  50. data/spec/byte_array_spec.rb +2 -0
  51. data/spec/client_robustness_spec.rb +4 -2
  52. data/spec/data/marshall.yaml +1667 -0
  53. data/spec/data_spec.rb +673 -0
  54. data/spec/emits_changed_signal_spec.rb +58 -0
  55. data/spec/err_msg_spec.rb +2 -0
  56. data/spec/introspect_xml_parser_spec.rb +2 -0
  57. data/spec/introspection_spec.rb +2 -0
  58. data/spec/main_loop_spec.rb +3 -1
  59. data/spec/node_spec.rb +23 -0
  60. data/spec/object_path_spec.rb +3 -0
  61. data/spec/object_spec.rb +138 -0
  62. data/spec/packet_marshaller_spec.rb +41 -0
  63. data/spec/packet_unmarshaller_spec.rb +248 -0
  64. data/spec/property_spec.rb +192 -5
  65. data/spec/proxy_object_spec.rb +2 -0
  66. data/spec/server_robustness_spec.rb +2 -0
  67. data/spec/server_spec.rb +2 -0
  68. data/spec/service_newapi.rb +70 -70
  69. data/spec/session_bus_spec.rb +3 -1
  70. data/spec/session_bus_spec_manual.rb +2 -0
  71. data/spec/signal_spec.rb +5 -3
  72. data/spec/spec_helper.rb +37 -9
  73. data/spec/thread_safety_spec.rb +2 -0
  74. data/spec/tools/dbus-limited-session.conf +4 -0
  75. data/spec/type_spec.rb +214 -6
  76. data/spec/value_spec.rb +16 -1
  77. data/spec/variant_spec.rb +4 -2
  78. data/spec/zzz_quit_spec.rb +16 -0
  79. metadata +34 -8
data/lib/dbus/type.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # dbus/type.rb - module containing low-level D-Bus data type information
2
4
  #
3
5
  # This file is part of the ruby-dbus project
@@ -9,13 +11,33 @@
9
11
  # See the file "COPYING" for the exact licensing terms.
10
12
 
11
13
  module DBus
12
- # = D-Bus type module
14
+ # Like a {Signature} but containing only a single complete type.
15
+ #
16
+ # For documentation purposes only.
17
+ class SingleCompleteType < String; end
18
+
19
+ # Zero or more {SingleCompleteType}s; its own type code is "g".
20
+ # For example "ssv" for a method taking two Strings and a Variant/
21
+ #
22
+ # For documentation purposes only.
23
+ class Signature < String; end
24
+
25
+ # Similar to {Signature} but for {DBus::Object.define_method},
26
+ # contains names and direction of the parameters.
27
+ # For example "in query:s, in case_sensitive:b, out results:ao".
13
28
  #
14
- # This module containts the constants of the types specified in the D-Bus
15
- # protocol.
16
- module Type
29
+ # For documentation purposes only.
30
+ class Prototype < String; end
31
+
32
+ # Represents the D-Bus types.
33
+ #
34
+ # Corresponds to {SingleCompleteType}.
35
+ # Instances are immutable/frozen once fully constructed.
36
+ #
37
+ # See also {DBus::Data::Signature} which is "type on the wire".
38
+ class Type
17
39
  # Mapping from type number to name and alignment.
18
- TypeMapping = {
40
+ TYPE_MAPPING = {
19
41
  0 => ["INVALID", nil],
20
42
  "y" => ["BYTE", 1],
21
43
  "b" => ["BOOLEAN", 4],
@@ -36,7 +58,7 @@ module DBus
36
58
  "h" => ["UNIX_FD", 4]
37
59
  }.freeze
38
60
  # Defines the set of constants
39
- TypeMapping.each_pair do |key, value|
61
+ TYPE_MAPPING.each_pair do |key, value|
40
62
  Type.const_set(value.first, key)
41
63
  end
42
64
 
@@ -44,87 +66,140 @@ module DBus
44
66
  class SignatureException < Exception
45
67
  end
46
68
 
47
- # = D-Bus type conversion class
69
+ # Formerly this was a Module and there was a DBus::Type::Type class
70
+ # but the class got too prominent to keep its double double name.
71
+ # This is for backward compatibility.
72
+ Type = self # rubocop:disable Naming/ConstantName
73
+
74
+ # @return [String] the signature type character, eg "s" or "e".
75
+ attr_reader :sigtype
76
+ # @return [Array<Type>] contained member types.
77
+ attr_reader :members
78
+
79
+ # Use {DBus.type} instead, because this allows constructing
80
+ # incomplete or invalid types, for backward compatibility.
48
81
  #
49
- # Helper class for representing a D-Bus type.
50
- class Type
51
- # Returns the signature type number.
52
- attr_reader :sigtype
53
- # Return contained member types.
54
- attr_reader :members
55
-
56
- # Create a new type instance for type number _sigtype_.
57
- def initialize(sigtype)
58
- if !TypeMapping.keys.member?(sigtype)
59
- raise SignatureException, "Unknown key in signature: #{sigtype.chr}"
82
+ # @param abstract [Boolean] allow abstract types "r" and "e"
83
+ # (Enabled for internal usage by {Parser}.)
84
+ def initialize(sigtype, abstract: false)
85
+ if !TYPE_MAPPING.keys.member?(sigtype)
86
+ case sigtype
87
+ when ")"
88
+ raise SignatureException, "STRUCT unexpectedly closed: )"
89
+ when "}"
90
+ raise SignatureException, "DICT_ENTRY unexpectedly closed: }"
91
+ else
92
+ raise SignatureException, "Unknown type code #{sigtype.inspect}"
60
93
  end
61
- @sigtype = sigtype
62
- @members = []
63
- end
64
-
65
- # Return the required alignment for the type.
66
- def alignment
67
- TypeMapping[@sigtype].last
68
94
  end
69
95
 
70
- # Return a string representation of the type according to the
71
- # D-Bus specification.
72
- def to_s
73
- case @sigtype
96
+ unless abstract
97
+ case sigtype
74
98
  when STRUCT
75
- "(" + @members.collect(&:to_s).join + ")"
76
- when ARRAY
77
- "a" + child.to_s
99
+ raise SignatureException, "Abstract STRUCT, use \"(...)\" instead of \"#{STRUCT}\""
78
100
  when DICT_ENTRY
79
- "{" + @members.collect(&:to_s).join + "}"
80
- else
81
- if !TypeMapping.keys.member?(@sigtype)
82
- raise NotImplementedError
83
- end
84
- @sigtype.chr
101
+ raise SignatureException, "Abstract DICT_ENTRY, use \"{..}\" instead of \"#{DICT_ENTRY}\""
85
102
  end
86
103
  end
87
104
 
88
- # Add a new member type _a_.
89
- def <<(a)
90
- if ![STRUCT, ARRAY, DICT_ENTRY].member?(@sigtype)
91
- raise SignatureException
92
- end
93
- raise SignatureException if @sigtype == ARRAY && !@members.empty?
94
- if @sigtype == DICT_ENTRY
95
- if @members.size == 2
96
- raise SignatureException, "Dict entries have exactly two members"
97
- end
98
- if @members.empty?
99
- if [STRUCT, ARRAY, DICT_ENTRY].member?(a.sigtype)
100
- raise SignatureException, "Dict entry keys must be basic types"
101
- end
102
- end
103
- end
104
- @members << a
105
+ @sigtype = sigtype.freeze
106
+ @members = [] # not frozen yet, Parser#parse_one or Factory will do it
107
+ freeze
108
+ end
109
+
110
+ # A Type is equal to
111
+ # - another Type with the same string representation
112
+ # - a String ({SingleCompleteType}) describing the type
113
+ def ==(other)
114
+ case other
115
+ when ::String
116
+ to_s == other
117
+ else
118
+ eql?(other)
105
119
  end
120
+ end
121
+
122
+ # A Type is eql? to
123
+ # - another Type with the same string representation
124
+ #
125
+ # Hash key equality
126
+ # See https://ruby-doc.org/core-3.0.0/Object.html#method-i-eql-3F
127
+ def eql?(other)
128
+ return false unless other.is_a?(Type)
129
+
130
+ @sigtype == other.sigtype && @members == other.members
131
+ end
132
+
133
+ # Return the required alignment for the type.
134
+ def alignment
135
+ TYPE_MAPPING[@sigtype].last
136
+ end
106
137
 
107
- # Return the first contained member type.
108
- def child
109
- @members[0]
138
+ # Return a string representation of the type according to the
139
+ # D-Bus specification.
140
+ def to_s
141
+ case @sigtype
142
+ when STRUCT
143
+ "(#{@members.collect(&:to_s).join})"
144
+ when ARRAY
145
+ "a#{child}"
146
+ when DICT_ENTRY
147
+ "{#{@members.collect(&:to_s).join}}"
148
+ else
149
+ @sigtype.chr
110
150
  end
151
+ end
152
+
153
+ # Add a new member type _item_.
154
+ # @param item [Type]
155
+ def <<(item)
156
+ raise ArgumentError unless item.is_a?(Type)
111
157
 
112
- def inspect
113
- s = TypeMapping[@sigtype].first
114
- if [STRUCT, ARRAY].member?(@sigtype)
115
- s += ": " + @members.inspect
158
+ if ![STRUCT, ARRAY, DICT_ENTRY].member?(@sigtype)
159
+ raise SignatureException
160
+ end
161
+ raise SignatureException if @sigtype == ARRAY && !@members.empty?
162
+
163
+ if @sigtype == DICT_ENTRY
164
+ case @members.size
165
+ when 2
166
+ raise SignatureException, "DICT_ENTRY must have 2 subtypes, found 3 or more in #{@signature}"
167
+ when 0
168
+ if [STRUCT, ARRAY, DICT_ENTRY, VARIANT].member?(item.sigtype)
169
+ raise SignatureException, "DICT_ENTRY key must be basic (non-container)"
170
+ end
116
171
  end
117
- s
118
172
  end
119
- end # class Type
173
+ @members << item
174
+ end
175
+
176
+ # Return the first contained member type.
177
+ def child
178
+ @members[0]
179
+ end
180
+
181
+ def inspect
182
+ s = TYPE_MAPPING[@sigtype].first
183
+ if [STRUCT, ARRAY, DICT_ENTRY].member?(@sigtype)
184
+ s += ": #{@members.inspect}"
185
+ end
186
+ s
187
+ end
120
188
 
121
189
  # = D-Bus type parser class
122
190
  #
123
191
  # Helper class to parse a type signature in the protocol.
192
+ # @api private
124
193
  class Parser
125
194
  # Create a new parser for the given _signature_.
195
+ # @param signature [Signature]
126
196
  def initialize(signature)
127
197
  @signature = signature
198
+ if signature.size > 255
199
+ msg = "Potential signature is longer than 255 characters (#{@signature.size}): #{@signature}"
200
+ raise SignatureException, msg
201
+ end
202
+
128
203
  @idx = 0
129
204
  end
130
205
 
@@ -135,57 +210,214 @@ module DBus
135
210
  c
136
211
  end
137
212
 
138
- # Parse one character _c_ of the signature.
139
- def parse_one(c)
213
+ # Parse one character _char_ of the signature.
214
+ # @param for_array [Boolean] are we parsing an immediate child of an ARRAY
215
+ # @return [Type]
216
+ def parse_one(char, for_array: false)
140
217
  res = nil
141
- case c
218
+ case char
142
219
  when "a"
143
220
  res = Type.new(ARRAY)
144
- c = nextchar
145
- raise SignatureException, "Parse error in #{@signature}" if c.nil?
146
- child = parse_one(c)
221
+ char = nextchar
222
+ raise SignatureException, "Empty ARRAY in #{@signature}" if char.nil?
223
+
224
+ child = parse_one(char, for_array: true)
147
225
  res << child
148
226
  when "("
149
- res = Type.new(STRUCT)
150
- while (c = nextchar) && c != ")"
151
- res << parse_one(c)
227
+ res = Type.new(STRUCT, abstract: true)
228
+ while (char = nextchar) && char != ")"
229
+ res << parse_one(char)
152
230
  end
153
- raise SignatureException, "Parse error in #{@signature}" if c.nil?
231
+ raise SignatureException, "STRUCT not closed in #{@signature}" if char.nil?
232
+ raise SignatureException, "Empty STRUCT in #{@signature}" if res.members.empty?
154
233
  when "{"
155
- res = Type.new(DICT_ENTRY)
156
- while (c = nextchar) && c != "}"
157
- res << parse_one(c)
234
+ raise SignatureException, "DICT_ENTRY not an immediate child of an ARRAY" unless for_array
235
+
236
+ res = Type.new(DICT_ENTRY, abstract: true)
237
+
238
+ # key type, value type
239
+ 2.times do |i|
240
+ char = nextchar
241
+ raise SignatureException, "DICT_ENTRY not closed in #{@signature}" if char.nil?
242
+
243
+ raise SignatureException, "DICT_ENTRY must have 2 subtypes, found #{i} in #{@signature}" if char == "}"
244
+
245
+ res << parse_one(char)
158
246
  end
159
- raise SignatureException, "Parse error in #{@signature}" if c.nil?
247
+
248
+ # closing "}"
249
+ char = nextchar
250
+ raise SignatureException, "DICT_ENTRY not closed in #{@signature}" if char.nil?
251
+
252
+ raise SignatureException, "DICT_ENTRY must have 2 subtypes, found 3 or more in #{@signature}" if char != "}"
160
253
  else
161
- res = Type.new(c)
254
+ res = Type.new(char)
162
255
  end
256
+ res.members.freeze
163
257
  res
164
258
  end
165
259
 
166
260
  # Parse the entire signature, return a DBus::Type object.
261
+ # @return [Array<Type>]
167
262
  def parse
168
263
  @idx = 0
169
264
  ret = []
170
265
  while (c = nextchar)
171
266
  ret << parse_one(c)
172
267
  end
173
- ret
268
+ ret.freeze
269
+ end
270
+
271
+ # Parse one {SingleCompleteType}
272
+ # @return [Type]
273
+ def parse1
274
+ c = nextchar
275
+ raise SignatureException, "Empty signature, expecting a Single Complete Type" if c.nil?
276
+
277
+ t = parse_one(c)
278
+ raise SignatureException, "Has more than a Single Complete Type: #{@signature}" unless nextchar.nil?
279
+
280
+ t.freeze
281
+ end
282
+ end
283
+
284
+ class Factory
285
+ # @param type [Type,SingleCompleteType,Class]
286
+ # @see from_plain_class
287
+ # @return [Type] (frozen)
288
+ def self.make_type(type)
289
+ case type
290
+ when Type
291
+ type
292
+ when String
293
+ DBus.type(type)
294
+ when Class
295
+ from_plain_class(type)
296
+ else
297
+ msg = "Expecting DBus::Type, DBus::SingleCompleteType(aka ::String), or Class, got #{type.inspect}"
298
+ raise ArgumentError, msg
299
+ end
174
300
  end
175
- end # class Parser
176
- end # module Type
301
+
302
+ # Make a {Type} corresponding to some plain classes:
303
+ # - String
304
+ # - Float
305
+ # - DBus::ObjectPath
306
+ # - DBus::Signature, DBus::SingleCompleteType
307
+ # @param klass [Class]
308
+ # @return [Type] (frozen)
309
+ def self.from_plain_class(klass)
310
+ @signature_type ||= DBus.type(SIGNATURE)
311
+ @class_to_type ||= {
312
+ DBus::ObjectPath => DBus.type(OBJECT_PATH),
313
+ DBus::Signature => @signature_type,
314
+ DBus::SingleCompleteType => @signature_type,
315
+ String => DBus.type(STRING),
316
+ Float => DBus.type(DOUBLE)
317
+ }
318
+ t = @class_to_type[klass]
319
+ raise ArgumentError, "Cannot convert plain class #{klass} to a D-Bus type" if t.nil?
320
+
321
+ t
322
+ end
323
+ end
324
+
325
+ # Syntactic helper for constructing an array Type.
326
+ # You may be looking for {Data::Array} instead.
327
+ # @example
328
+ # t = Type::Array[Type::INT16]
329
+ class ArrayFactory < Factory
330
+ # @param member_type [Type,SingleCompleteType]
331
+ # @return [Type] (frozen)
332
+ def self.[](member_type)
333
+ t = Type.new(ARRAY)
334
+ t << make_type(member_type)
335
+ t.members.freeze
336
+ t
337
+ end
338
+ end
339
+
340
+ # @example
341
+ # t = Type::Array[Type::INT16]
342
+ Array = ArrayFactory
343
+
344
+ # Syntactic helper for constructing a hash Type.
345
+ # You may be looking for {Data::Array} and {Data::DictEntry} instead.
346
+ # @example
347
+ # t = Type::Hash[Type::STRING, Type::VARIANT]
348
+ class HashFactory < Factory
349
+ # @param key_type [Type,SingleCompleteType]
350
+ # @param value_type [Type,SingleCompleteType]
351
+ # @return [Type] (frozen)
352
+ def self.[](key_type, value_type)
353
+ t = Type.new(ARRAY)
354
+ de = Type.new(DICT_ENTRY, abstract: true)
355
+ de << make_type(key_type)
356
+ de << make_type(value_type)
357
+ de.members.freeze
358
+ t << de
359
+ t.members.freeze
360
+ t
361
+ end
362
+ end
363
+
364
+ # @example
365
+ # t = Type::Hash[Type::INT16]
366
+ Hash = HashFactory
367
+
368
+ # Syntactic helper for constructing a struct Type.
369
+ # You may be looking for {Data::Struct} instead.
370
+ # @example
371
+ # t = Type::Struct[Type::INT16, Type::STRING]
372
+ class StructFactory < Factory
373
+ # @param member_types [::Array<Type,SingleCompleteType>]
374
+ # @return [Type] (frozen)
375
+ def self.[](*member_types)
376
+ raise ArgumentError if member_types.empty?
377
+
378
+ t = Type.new(STRUCT, abstract: true)
379
+ member_types.each do |mt|
380
+ t << make_type(mt)
381
+ end
382
+ t.members.freeze
383
+ t
384
+ end
385
+ end
386
+
387
+ # @example
388
+ # t = Type::Struct[Type::INT16, Type::STRING]
389
+ Struct = StructFactory
390
+ end
177
391
 
178
392
  # shortcuts
179
393
 
180
- # Parse a String to a DBus::Type::Type
394
+ # Parse a String to a valid {DBus::Type}.
395
+ # This is prefered to {Type#initialize} which allows
396
+ # incomplete or invalid types.
397
+ # @param string_type [SingleCompleteType]
398
+ # @return [DBus::Type] (frozen)
399
+ # @raise SignatureException
181
400
  def type(string_type)
182
- Type::Parser.new(string_type).parse[0]
401
+ Type::Parser.new(string_type).parse1
183
402
  end
184
403
  module_function :type
185
404
 
405
+ # Parse a String to zero or more {DBus::Type}s.
406
+ # @param string_type [Signature]
407
+ # @return [Array<DBus::Type>] (frozen)
408
+ # @raise SignatureException
409
+ def types(string_type)
410
+ Type::Parser.new(string_type).parse
411
+ end
412
+ module_function :types
413
+
186
414
  # Make an explicit [Type, value] pair
415
+ # @param string_type [SingleCompleteType]
416
+ # @param value [::Object]
417
+ # @return [Array(DBus::Type::Type,::Object)]
418
+ # @deprecated Use {Data::Variant#initialize} instead
187
419
  def variant(string_type, value)
188
- [type(string_type), value]
420
+ Data::Variant.new(value, member_type: string_type)
189
421
  end
190
422
  module_function :variant
191
- end # module DBus
423
+ end
data/lib/dbus/xml.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # dbus/xml.rb - introspection parser, rexml/nokogiri abstraction
2
4
  #
3
5
  # This file is part of the ruby-dbus project
@@ -26,14 +28,23 @@ module DBus
26
28
  attr_accessor :backend
27
29
  end
28
30
  # Creates a new parser for XML data in string _xml_.
31
+ # @param xml [String]
29
32
  def initialize(xml)
30
33
  @xml = xml
31
34
  end
32
35
 
33
36
  class AbstractXML
37
+ # @!method initialize(xml)
38
+ # @abstract
39
+
40
+ # @!method each(xpath)
41
+ # @abstract
42
+ # yields nodes which match xpath of type AbstractXML::Node
43
+
34
44
  def self.have_nokogiri?
35
45
  Object.const_defined?("Nokogiri")
36
46
  end
47
+
37
48
  class Node
38
49
  def initialize(node)
39
50
  @node = node
@@ -46,12 +57,6 @@ module DBus
46
57
  # yields child nodes which match xpath of type AbstractXML::Node
47
58
  def each(xpath); end
48
59
  end
49
- # required methods
50
- # initialize parser with xml string
51
- def initialize(xml); end
52
-
53
- # yields nodes which match xpath of type AbstractXML::Node
54
- def each(xpath); end
55
60
  end
56
61
 
57
62
  class NokogiriParser < AbstractXML
@@ -64,7 +69,9 @@ module DBus
64
69
  @node.search(path).each { |node| block.call NokogiriNode.new(node) }
65
70
  end
66
71
  end
72
+
67
73
  def initialize(xml)
74
+ super()
68
75
  @doc = Nokogiri.XML(xml)
69
76
  end
70
77
 
@@ -83,7 +90,9 @@ module DBus
83
90
  @node.elements.each(path) { |node| block.call REXMLNode.new(node) }
84
91
  end
85
92
  end
93
+
86
94
  def initialize(xml)
95
+ super()
87
96
  @doc = REXML::Document.new(xml)
88
97
  end
89
98
 
@@ -125,6 +134,10 @@ module DBus
125
134
  parse_methsig(se, s)
126
135
  i << s
127
136
  end
137
+ e.each("property") do |pe|
138
+ p = Property.from_xml(pe)
139
+ i << p
140
+ end
128
141
  end
129
142
  d = Time.now - t
130
143
  if d > 2
@@ -136,28 +149,30 @@ module DBus
136
149
  ######################################################################
137
150
  private
138
151
 
139
- # Parses a method signature XML element _e_ and initialises
140
- # method/signal _m_.
141
- def parse_methsig(e, m)
142
- e.each("arg") do |ae|
152
+ # Parses a method signature XML element *elem* and initialises
153
+ # method/signal *methsig*.
154
+ # @param elem [AbstractXML::Node]
155
+ def parse_methsig(elem, methsig)
156
+ elem.each("arg") do |ae|
143
157
  name = ae["name"]
144
158
  dir = ae["direction"]
145
159
  sig = ae["type"]
146
- if m.is_a?(DBus::Signal)
160
+ case methsig
161
+ when DBus::Signal
147
162
  # Direction can only be "out", ignore it
148
- m.add_fparam(name, sig)
149
- elsif m.is_a?(DBus::Method)
163
+ methsig.add_fparam(name, sig)
164
+ when DBus::Method
150
165
  case dir
151
166
  # This is a method, so dir defaults to "in"
152
167
  when "in", nil
153
- m.add_fparam(name, sig)
168
+ methsig.add_fparam(name, sig)
154
169
  when "out"
155
- m.add_return(name, sig)
170
+ methsig.add_return(name, sig)
156
171
  end
157
172
  else
158
173
  raise NotImplementedError, dir
159
174
  end
160
175
  end
161
176
  end
162
- end # class IntrospectXMLParser
163
- end # module DBus
177
+ end
178
+ end
data/lib/dbus.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # dbus.rb - Module containing the low-level D-Bus implementation
2
4
  #
3
5
  # This file is part of the ruby-dbus project
@@ -12,6 +14,8 @@ require_relative "dbus/api_options"
12
14
  require_relative "dbus/auth"
13
15
  require_relative "dbus/bus"
14
16
  require_relative "dbus/bus_name"
17
+ require_relative "dbus/data"
18
+ require_relative "dbus/emits_changed_signal"
15
19
  require_relative "dbus/error"
16
20
  require_relative "dbus/introspect"
17
21
  require_relative "dbus/logger"
@@ -24,31 +28,34 @@ require_relative "dbus/object_path"
24
28
  require_relative "dbus/proxy_object"
25
29
  require_relative "dbus/proxy_object_factory"
26
30
  require_relative "dbus/proxy_object_interface"
31
+ require_relative "dbus/raw_message"
27
32
  require_relative "dbus/type"
28
33
  require_relative "dbus/xml"
29
34
 
30
35
  require "socket"
31
- require "thread"
32
-
33
36
  # = D-Bus main module
34
37
  #
35
38
  # Module containing all the D-Bus modules and classes.
36
39
  module DBus
37
40
  # Default socket name for the system bus.
38
- SystemSocketName = "unix:path=/var/run/dbus/system_bus_socket".freeze
41
+ SYSTEM_BUS_ADDRESS = "unix:path=/var/run/dbus/system_bus_socket"
39
42
 
40
43
  # Byte signifying big endianness.
41
- BIG_END = "B".freeze
44
+ BIG_END = "B"
42
45
  # Byte signifying little endianness.
43
- LIL_END = "l".freeze
46
+ LIL_END = "l"
44
47
 
45
48
  # Byte signifying the host's endianness.
46
- HOST_END = if [0x01020304].pack("L").unpack("V")[0] == 0x01020304
49
+ HOST_END = if [0x01020304].pack("L").unpack1("V") == 0x01020304
47
50
  LIL_END
48
51
  else
49
52
  BIG_END
50
53
  end
51
54
 
55
+ # Comparing symbols is faster than strings
56
+ # @return [:little,:big]
57
+ HOST_ENDIANNESS = RawMessage.endianness(HOST_END)
58
+
52
59
  # General exceptions.
53
60
 
54
61
  # Exception raised when there is a problem with a type (may be unknown or
@@ -69,4 +76,4 @@ module DBus
69
76
  # Exception raised when invalid introspection data is parsed/used.
70
77
  class InvalidIntrospectionData < Exception
71
78
  end
72
- end # module DBus
79
+ end
data/ruby-dbus.gemspec CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # -*- ruby -*-
2
4
  require "rubygems"
3
5
 
@@ -18,15 +20,17 @@ GEMSPEC = Gem::Specification.new do |s|
18
20
  ]
19
21
  s.require_path = "lib"
20
22
 
21
- s.required_ruby_version = ">= 2.0.0"
23
+ s.required_ruby_version = ">= 2.4.0"
24
+
25
+ s.add_dependency "rexml"
22
26
 
23
27
  # This is optional
24
28
  # s.add_runtime_dependency "nokogiri"
25
29
 
26
- s.add_development_dependency "coveralls"
27
30
  s.add_development_dependency "packaging_rake_tasks"
28
31
  s.add_development_dependency "rake"
29
32
  s.add_development_dependency "rspec", "~> 3"
30
- s.add_development_dependency "rubocop", "= 0.41.2"
33
+ s.add_development_dependency "rubocop", "= 1.0"
31
34
  s.add_development_dependency "simplecov"
35
+ s.add_development_dependency "simplecov-lcov"
32
36
  end