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.
- checksums.yaml +4 -4
- data/NEWS.md +160 -0
- data/README.md +3 -5
- data/Rakefile +18 -8
- data/VERSION +1 -1
- data/doc/Reference.md +106 -7
- data/examples/doc/_extract_examples +7 -0
- data/examples/gdbus/gdbus +31 -24
- data/examples/no-introspect/nm-test.rb +2 -0
- data/examples/no-introspect/tracker-test.rb +3 -1
- data/examples/rhythmbox/playpause.rb +2 -1
- data/examples/service/call_service.rb +2 -1
- data/examples/service/complex-property.rb +21 -0
- data/examples/service/service_newapi.rb +1 -1
- data/examples/simple/call_introspect.rb +1 -0
- data/examples/simple/get_id.rb +2 -1
- data/examples/simple/properties.rb +2 -0
- data/examples/utils/listnames.rb +1 -0
- data/examples/utils/notify.rb +1 -0
- data/lib/dbus/api_options.rb +9 -0
- data/lib/dbus/auth.rb +20 -15
- data/lib/dbus/bus.rb +123 -75
- data/lib/dbus/bus_name.rb +12 -8
- data/lib/dbus/core_ext/class/attribute.rb +1 -1
- data/lib/dbus/data.rb +821 -0
- data/lib/dbus/emits_changed_signal.rb +83 -0
- data/lib/dbus/error.rb +4 -2
- data/lib/dbus/introspect.rb +132 -31
- data/lib/dbus/logger.rb +3 -1
- data/lib/dbus/marshall.rb +247 -296
- data/lib/dbus/matchrule.rb +16 -16
- data/lib/dbus/message.rb +44 -37
- data/lib/dbus/message_queue.rb +16 -10
- data/lib/dbus/object.rb +358 -24
- data/lib/dbus/object_path.rb +11 -6
- data/lib/dbus/proxy_object.rb +22 -1
- data/lib/dbus/proxy_object_factory.rb +13 -7
- data/lib/dbus/proxy_object_interface.rb +63 -30
- data/lib/dbus/raw_message.rb +91 -0
- data/lib/dbus/type.rb +318 -86
- data/lib/dbus/xml.rb +32 -17
- data/lib/dbus.rb +14 -7
- data/ruby-dbus.gemspec +7 -3
- data/spec/async_spec.rb +2 -0
- data/spec/binding_spec.rb +2 -0
- data/spec/bus_and_xml_backend_spec.rb +2 -0
- data/spec/bus_driver_spec.rb +2 -0
- data/spec/bus_name_spec.rb +3 -1
- data/spec/bus_spec.rb +2 -0
- data/spec/byte_array_spec.rb +2 -0
- data/spec/client_robustness_spec.rb +4 -2
- data/spec/data/marshall.yaml +1667 -0
- data/spec/data_spec.rb +673 -0
- data/spec/emits_changed_signal_spec.rb +58 -0
- data/spec/err_msg_spec.rb +2 -0
- data/spec/introspect_xml_parser_spec.rb +2 -0
- data/spec/introspection_spec.rb +2 -0
- data/spec/main_loop_spec.rb +3 -1
- data/spec/node_spec.rb +23 -0
- data/spec/object_path_spec.rb +3 -0
- data/spec/object_spec.rb +138 -0
- data/spec/packet_marshaller_spec.rb +41 -0
- data/spec/packet_unmarshaller_spec.rb +248 -0
- data/spec/property_spec.rb +192 -5
- data/spec/proxy_object_spec.rb +2 -0
- data/spec/server_robustness_spec.rb +2 -0
- data/spec/server_spec.rb +2 -0
- data/spec/service_newapi.rb +70 -70
- data/spec/session_bus_spec.rb +3 -1
- data/spec/session_bus_spec_manual.rb +2 -0
- data/spec/signal_spec.rb +5 -3
- data/spec/spec_helper.rb +37 -9
- data/spec/thread_safety_spec.rb +2 -0
- data/spec/tools/dbus-limited-session.conf +4 -0
- data/spec/type_spec.rb +214 -6
- data/spec/value_spec.rb +16 -1
- data/spec/variant_spec.rb +4 -2
- data/spec/zzz_quit_spec.rb +16 -0
- 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
|
-
#
|
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
|
-
#
|
15
|
-
|
16
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#
|
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
|
-
#
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
raise SignatureException, "Unknown
|
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
|
-
|
71
|
-
|
72
|
-
def to_s
|
73
|
-
case @sigtype
|
96
|
+
unless abstract
|
97
|
+
case sigtype
|
74
98
|
when STRUCT
|
75
|
-
"
|
76
|
-
when ARRAY
|
77
|
-
"a" + child.to_s
|
99
|
+
raise SignatureException, "Abstract STRUCT, use \"(...)\" instead of \"#{STRUCT}\""
|
78
100
|
when DICT_ENTRY
|
79
|
-
"{"
|
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
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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
|
-
|
108
|
-
|
109
|
-
|
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
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
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
|
-
|
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
|
139
|
-
|
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
|
218
|
+
case char
|
142
219
|
when "a"
|
143
220
|
res = Type.new(ARRAY)
|
144
|
-
|
145
|
-
raise SignatureException, "
|
146
|
-
|
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 (
|
151
|
-
res << parse_one(
|
227
|
+
res = Type.new(STRUCT, abstract: true)
|
228
|
+
while (char = nextchar) && char != ")"
|
229
|
+
res << parse_one(char)
|
152
230
|
end
|
153
|
-
raise SignatureException, "
|
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
|
-
|
156
|
-
|
157
|
-
|
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
|
-
|
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(
|
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
|
-
|
176
|
-
|
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
|
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).
|
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
|
-
|
420
|
+
Data::Variant.new(value, member_type: string_type)
|
189
421
|
end
|
190
422
|
module_function :variant
|
191
|
-
end
|
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
|
140
|
-
# method/signal
|
141
|
-
|
142
|
-
|
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
|
-
|
160
|
+
case methsig
|
161
|
+
when DBus::Signal
|
147
162
|
# Direction can only be "out", ignore it
|
148
|
-
|
149
|
-
|
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
|
-
|
168
|
+
methsig.add_fparam(name, sig)
|
154
169
|
when "out"
|
155
|
-
|
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
|
163
|
-
end
|
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
|
-
|
41
|
+
SYSTEM_BUS_ADDRESS = "unix:path=/var/run/dbus/system_bus_socket"
|
39
42
|
|
40
43
|
# Byte signifying big endianness.
|
41
|
-
BIG_END = "B"
|
44
|
+
BIG_END = "B"
|
42
45
|
# Byte signifying little endianness.
|
43
|
-
LIL_END = "l"
|
46
|
+
LIL_END = "l"
|
44
47
|
|
45
48
|
# Byte signifying the host's endianness.
|
46
|
-
HOST_END = if [0x01020304].pack("L").
|
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
|
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.
|
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
|
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
|