ruby-dbus 0.18.0.beta1 → 0.18.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/NEWS.md +15 -0
- data/VERSION +1 -1
- data/doc/Reference.md +1 -1
- data/examples/service/complex-property.rb +21 -0
- data/lib/dbus/data.rb +725 -0
- data/lib/dbus/introspect.rb +1 -0
- data/lib/dbus/marshall.rb +158 -256
- data/lib/dbus/message.rb +4 -10
- data/lib/dbus/object.rb +11 -11
- data/lib/dbus/object_path.rb +2 -1
- data/lib/dbus/raw_message.rb +91 -0
- data/lib/dbus/type.rb +147 -70
- data/lib/dbus.rb +6 -0
- data/spec/data/marshall.yaml +1639 -0
- data/spec/data_spec.rb +298 -0
- data/spec/object_path_spec.rb +1 -0
- data/spec/packet_marshaller_spec.rb +34 -0
- data/spec/packet_unmarshaller_spec.rb +262 -0
- data/spec/property_spec.rb +24 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/type_spec.rb +67 -6
- metadata +9 -2
data/lib/dbus/marshall.rb
CHANGED
@@ -12,6 +12,8 @@
|
|
12
12
|
|
13
13
|
require "socket"
|
14
14
|
|
15
|
+
require_relative "../dbus/type"
|
16
|
+
|
15
17
|
# = D-Bus main module
|
16
18
|
#
|
17
19
|
# Module containing all the D-Bus modules and classes.
|
@@ -23,217 +25,128 @@ module DBus
|
|
23
25
|
# = D-Bus packet unmarshaller class
|
24
26
|
#
|
25
27
|
# Class that handles the conversion (unmarshalling) of payload data
|
26
|
-
# to
|
28
|
+
# to #{::Object}s (in **plain** mode) or to {Data::Base} (in **exact** mode)
|
29
|
+
#
|
30
|
+
# Spelling note: this codebase always uses a double L
|
31
|
+
# in the "marshall" word and its inflections.
|
27
32
|
class PacketUnmarshaller
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
# Used to kown what part of the buffer has been consumed by unmarshalling.
|
32
|
-
# FIXME: Maybe should be accessed with a "consumed_size" method.
|
33
|
-
attr_reader :idx
|
34
|
-
|
35
|
-
# Create a new unmarshaller for the given data _buffer_ and _endianness_.
|
33
|
+
# Create a new unmarshaller for the given data *buffer*.
|
34
|
+
# @param buffer [String]
|
35
|
+
# @param endianness [:little,:big]
|
36
36
|
def initialize(buffer, endianness)
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
@uint32 = "N"
|
42
|
-
@uint16 = "n"
|
43
|
-
@double = "G"
|
44
|
-
when LIL_END
|
45
|
-
@uint32 = "V"
|
46
|
-
@uint16 = "v"
|
47
|
-
@double = "E"
|
48
|
-
else
|
49
|
-
raise InvalidPacketException, "Incorrect endianness #{@endianness}"
|
50
|
-
end
|
51
|
-
@idx = 0
|
37
|
+
# TODO: this dup can be avoided if we can prove
|
38
|
+
# that an IncompleteBufferException leaves the original *buffer* intact
|
39
|
+
buffer = buffer.dup
|
40
|
+
@raw_msg = RawMessage.new(buffer, endianness)
|
52
41
|
end
|
53
42
|
|
54
43
|
# Unmarshall the buffer for a given _signature_ and length _len_.
|
55
|
-
# Return an array of unmarshalled objects
|
44
|
+
# Return an array of unmarshalled objects.
|
56
45
|
# @param signature [Signature]
|
57
46
|
# @param len [Integer,nil] if given, and there is not enough data
|
58
47
|
# in the buffer, raise {IncompleteBufferException}
|
59
|
-
# @
|
48
|
+
# @param mode [:plain,:exact]
|
49
|
+
# @return [Array<::Object,DBus::Data::Base>]
|
50
|
+
# Objects in `:plain` mode, {DBus::Data::Base} in `:exact` mode
|
51
|
+
# The array size corresponds to the number of types in *signature*.
|
60
52
|
# @raise IncompleteBufferException
|
61
|
-
|
62
|
-
|
53
|
+
# @raise InvalidPacketException
|
54
|
+
def unmarshall(signature, len = nil, mode: :plain)
|
55
|
+
@raw_msg.want!(len) if len
|
63
56
|
|
64
57
|
sigtree = Type::Parser.new(signature).parse
|
65
58
|
ret = []
|
66
59
|
sigtree.each do |elem|
|
67
|
-
ret << do_parse(elem)
|
60
|
+
ret << do_parse(elem, mode: mode)
|
68
61
|
end
|
69
62
|
ret
|
70
63
|
end
|
71
64
|
|
72
|
-
#
|
73
|
-
|
74
|
-
|
75
|
-
case alignment
|
76
|
-
when 1
|
77
|
-
nil
|
78
|
-
when 2, 4, 8
|
79
|
-
bits = alignment - 1
|
80
|
-
@idx = @idx + bits & ~bits
|
81
|
-
raise IncompleteBufferException if @idx > @buffy.bytesize
|
82
|
-
else
|
83
|
-
raise ArgumentError, "Unsupported alignment #{alignment}"
|
84
|
-
end
|
65
|
+
# after the headers, the body starts 8-aligned
|
66
|
+
def align_body
|
67
|
+
@raw_msg.align(8)
|
85
68
|
end
|
86
69
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
70
|
+
# @return [Integer]
|
71
|
+
def consumed_size
|
72
|
+
@raw_msg.pos
|
73
|
+
end
|
91
74
|
|
92
|
-
|
93
|
-
def read(nbytes)
|
94
|
-
raise IncompleteBufferException if @idx + nbytes > @buffy.bytesize
|
75
|
+
private
|
95
76
|
|
96
|
-
|
97
|
-
|
98
|
-
|
77
|
+
# @param data_class [Class] a subclass of Data::Base (specific?)
|
78
|
+
# @return [::Integer,::Float]
|
79
|
+
def aligned_read_value(data_class)
|
80
|
+
@raw_msg.align(data_class.alignment)
|
81
|
+
bytes = @raw_msg.read(data_class.alignment)
|
82
|
+
bytes.unpack1(data_class.format[@raw_msg.endianness])
|
99
83
|
end
|
100
84
|
|
101
|
-
#
|
102
|
-
#
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
85
|
+
# Based on the _signature_ type, retrieve a packet from the buffer
|
86
|
+
# and return it.
|
87
|
+
# @param signature [Type]
|
88
|
+
# @param mode [:plain,:exact]
|
89
|
+
# @return [Data::Base]
|
90
|
+
def do_parse(signature, mode: :plain)
|
91
|
+
# FIXME: better naming for packet vs value
|
92
|
+
packet = nil
|
93
|
+
data_class = Data::BY_TYPE_CODE[signature.sigtype]
|
108
94
|
|
109
|
-
|
110
|
-
|
111
|
-
|
95
|
+
if data_class.nil?
|
96
|
+
raise NotImplementedError,
|
97
|
+
"sigtype: #{signature.sigtype} (#{signature.sigtype.chr})"
|
112
98
|
end
|
113
99
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
100
|
+
if data_class.fixed?
|
101
|
+
value = aligned_read_value(data_class)
|
102
|
+
packet = data_class.from_raw(value, mode: mode)
|
103
|
+
elsif data_class.basic?
|
104
|
+
size = aligned_read_value(data_class.size_class)
|
105
|
+
value = @raw_msg.read(size)
|
106
|
+
nul = @raw_msg.read(1)
|
107
|
+
if nul != "\u0000"
|
108
|
+
raise InvalidPacketException, "#{data_class} is not NUL-terminated"
|
109
|
+
end
|
118
110
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
111
|
+
packet = data_class.from_raw(value, mode: mode)
|
112
|
+
else
|
113
|
+
@raw_msg.align(data_class.alignment)
|
114
|
+
case signature.sigtype
|
115
|
+
when Type::STRUCT, Type::DICT_ENTRY
|
116
|
+
values = signature.members.map do |child_sig|
|
117
|
+
do_parse(child_sig, mode: mode)
|
118
|
+
end
|
119
|
+
packet = data_class.from_items(values, mode: mode, member_types: signature.members)
|
125
120
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
121
|
+
when Type::VARIANT
|
122
|
+
data_sig = do_parse(Data::Signature.type, mode: :exact) # -> Data::Signature
|
123
|
+
types = Type::Parser.new(data_sig.value).parse # -> Array<Type>
|
124
|
+
unless types.size == 1
|
125
|
+
raise InvalidPacketException, "VARIANT must contain 1 value, #{types.size} found"
|
126
|
+
end
|
130
127
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
end
|
128
|
+
type = types.first
|
129
|
+
value = do_parse(type, mode: mode)
|
130
|
+
packet = data_class.from_items(value, mode: mode, member_type: type)
|
135
131
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
when Type::BYTE
|
142
|
-
packet = read(1).unpack1("C")
|
143
|
-
when Type::UINT16
|
144
|
-
align(2)
|
145
|
-
packet = read(2).unpack1(@uint16)
|
146
|
-
when Type::INT16
|
147
|
-
align(2)
|
148
|
-
packet = read(2).unpack1(@uint16)
|
149
|
-
if (packet & 0x8000) != 0
|
150
|
-
packet -= 0x10000
|
151
|
-
end
|
152
|
-
when Type::UINT32, Type::UNIX_FD
|
153
|
-
align(4)
|
154
|
-
packet = read(4).unpack1(@uint32)
|
155
|
-
when Type::INT32
|
156
|
-
align(4)
|
157
|
-
packet = read(4).unpack1(@uint32)
|
158
|
-
if (packet & 0x80000000) != 0
|
159
|
-
packet -= 0x100000000
|
160
|
-
end
|
161
|
-
when Type::UINT64
|
162
|
-
align(8)
|
163
|
-
packet_l = read(4).unpack1(@uint32)
|
164
|
-
packet_h = read(4).unpack1(@uint32)
|
165
|
-
packet = if @endianness == LIL_END
|
166
|
-
packet_l + packet_h * 2**32
|
167
|
-
else
|
168
|
-
packet_l * 2**32 + packet_h
|
169
|
-
end
|
170
|
-
when Type::INT64
|
171
|
-
align(8)
|
172
|
-
packet_l = read(4).unpack1(@uint32)
|
173
|
-
packet_h = read(4).unpack1(@uint32)
|
174
|
-
packet = if @endianness == LIL_END
|
175
|
-
packet_l + packet_h * 2**32
|
176
|
-
else
|
177
|
-
packet_l * 2**32 + packet_h
|
178
|
-
end
|
179
|
-
if (packet & 0x8000000000000000) != 0
|
180
|
-
packet -= 0x10000000000000000
|
181
|
-
end
|
182
|
-
when Type::DOUBLE
|
183
|
-
align(8)
|
184
|
-
packet = read(8).unpack1(@double)
|
185
|
-
when Type::BOOLEAN
|
186
|
-
align(4)
|
187
|
-
v = read(4).unpack1(@uint32)
|
188
|
-
raise InvalidPacketException if ![0, 1].member?(v)
|
189
|
-
|
190
|
-
packet = (v == 1)
|
191
|
-
when Type::ARRAY
|
192
|
-
align(4)
|
193
|
-
# checks please
|
194
|
-
array_sz = read(4).unpack1(@uint32)
|
195
|
-
raise InvalidPacketException if array_sz > 67_108_864
|
196
|
-
|
197
|
-
align(signature.child.alignment)
|
198
|
-
raise IncompleteBufferException if @idx + array_sz > @buffy.bytesize
|
199
|
-
|
200
|
-
packet = []
|
201
|
-
start_idx = @idx
|
202
|
-
while @idx - start_idx < array_sz
|
203
|
-
packet << do_parse(signature.child)
|
204
|
-
end
|
132
|
+
when Type::ARRAY
|
133
|
+
array_bytes = aligned_read_value(Data::UInt32)
|
134
|
+
if array_bytes > 67_108_864
|
135
|
+
raise InvalidPacketException, "ARRAY body longer than 64MiB"
|
136
|
+
end
|
205
137
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
138
|
+
# needed here because of empty arrays
|
139
|
+
@raw_msg.align(signature.child.alignment)
|
140
|
+
|
141
|
+
items = []
|
142
|
+
end_pos = @raw_msg.pos + array_bytes
|
143
|
+
while @raw_msg.pos < end_pos
|
144
|
+
item = do_parse(signature.child, mode: mode)
|
145
|
+
items << item
|
146
|
+
end
|
147
|
+
is_hash = signature.child.sigtype == Type::DICT_ENTRY
|
148
|
+
packet = data_class.from_items(items, mode: mode, member_type: signature.child, hash: is_hash)
|
214
149
|
end
|
215
|
-
packet.freeze
|
216
|
-
when Type::VARIANT
|
217
|
-
string = read_signature
|
218
|
-
# error checking please
|
219
|
-
sig = Type::Parser.new(string).parse[0]
|
220
|
-
align(sig.alignment)
|
221
|
-
packet = do_parse(sig)
|
222
|
-
when Type::OBJECT_PATH
|
223
|
-
packet = read_string
|
224
|
-
when Type::STRING
|
225
|
-
packet = read_string
|
226
|
-
packet.force_encoding("UTF-8")
|
227
|
-
when Type::SIGNATURE
|
228
|
-
packet = read_signature
|
229
|
-
when Type::DICT_ENTRY
|
230
|
-
align(8)
|
231
|
-
key = do_parse(signature.members[0])
|
232
|
-
value = do_parse(signature.members[1])
|
233
|
-
packet = [key, value]
|
234
|
-
else
|
235
|
-
raise NotImplementedError,
|
236
|
-
"sigtype: #{signature.sigtype} (#{signature.sigtype.chr})"
|
237
150
|
end
|
238
151
|
packet
|
239
152
|
end
|
@@ -246,11 +159,16 @@ module DBus
|
|
246
159
|
class PacketMarshaller
|
247
160
|
# The current or result packet.
|
248
161
|
# FIXME: allow access only when marshalling is finished
|
162
|
+
# @return [String]
|
249
163
|
attr_reader :packet
|
250
164
|
|
165
|
+
# @return [:little,:big]
|
166
|
+
attr_reader :endianness
|
167
|
+
|
251
168
|
# Create a new marshaller, setting the current packet to the
|
252
169
|
# empty packet.
|
253
|
-
def initialize(offset = 0)
|
170
|
+
def initialize(offset = 0, endianness: HOST_ENDIANNESS)
|
171
|
+
@endianness = endianness
|
254
172
|
@packet = ""
|
255
173
|
@offset = offset # for correct alignment of nested marshallers
|
256
174
|
end
|
@@ -272,17 +190,6 @@ module DBus
|
|
272
190
|
@packet = @packet.ljust(pad_count, 0.chr)
|
273
191
|
end
|
274
192
|
|
275
|
-
# Append the the string _str_ itself to the packet.
|
276
|
-
def append_string(str)
|
277
|
-
align(4)
|
278
|
-
@packet += [str.bytesize].pack("L") + [str].pack("Z*")
|
279
|
-
end
|
280
|
-
|
281
|
-
# Append the the signature _signature_ itself to the packet.
|
282
|
-
def append_signature(str)
|
283
|
-
@packet += "#{str.bytesize.chr}#{str}\u0000"
|
284
|
-
end
|
285
|
-
|
286
193
|
# Append the array type _type_ to the packet and allow for appending
|
287
194
|
# the child elements.
|
288
195
|
def array(type)
|
@@ -296,7 +203,8 @@ module DBus
|
|
296
203
|
sz = @packet.bytesize - contentidx
|
297
204
|
raise InvalidPacketException if sz > 67_108_864
|
298
205
|
|
299
|
-
|
206
|
+
sz_data = Data::UInt32.new(sz)
|
207
|
+
@packet[sizeidx...sizeidx + 4] = sz_data.marshall(endianness)
|
300
208
|
end
|
301
209
|
|
302
210
|
# Align and allow for appending struct fields.
|
@@ -308,84 +216,78 @@ module DBus
|
|
308
216
|
# Append a value _val_ to the packet based on its _type_.
|
309
217
|
#
|
310
218
|
# Host native endianness is used, declared in Message#marshall
|
219
|
+
#
|
220
|
+
# @param type [SingleCompleteType] (or Integer or {Type})
|
221
|
+
# @param val [::Object]
|
311
222
|
def append(type, val)
|
312
223
|
raise TypeException, "Cannot send nil" if val.nil?
|
313
224
|
|
314
225
|
type = type.chr if type.is_a?(Integer)
|
315
226
|
type = Type::Parser.new(type).parse[0] if type.is_a?(String)
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
when Type::UINT64
|
323
|
-
align(8)
|
324
|
-
@packet += [val].pack("Q")
|
325
|
-
when Type::INT64
|
326
|
-
align(8)
|
327
|
-
@packet += [val].pack("q")
|
328
|
-
when Type::INT32
|
329
|
-
align(4)
|
330
|
-
@packet += [val].pack("l")
|
331
|
-
when Type::UINT16
|
332
|
-
align(2)
|
333
|
-
@packet += [val].pack("S")
|
334
|
-
when Type::INT16
|
335
|
-
align(2)
|
336
|
-
@packet += [val].pack("s")
|
337
|
-
when Type::DOUBLE
|
338
|
-
align(8)
|
339
|
-
@packet += [val].pack("d")
|
340
|
-
when Type::BOOLEAN
|
341
|
-
align(4)
|
342
|
-
@packet += if val
|
343
|
-
[1].pack("L")
|
344
|
-
else
|
345
|
-
[0].pack("L")
|
346
|
-
end
|
347
|
-
when Type::OBJECT_PATH
|
348
|
-
append_string(val)
|
349
|
-
when Type::STRING
|
350
|
-
append_string(val)
|
351
|
-
when Type::SIGNATURE
|
352
|
-
append_signature(val)
|
353
|
-
when Type::VARIANT
|
354
|
-
append_variant(val)
|
355
|
-
when Type::ARRAY
|
356
|
-
append_array(type.child, val)
|
357
|
-
when Type::STRUCT, Type::DICT_ENTRY
|
358
|
-
unless val.is_a?(Array) || val.is_a?(Struct)
|
359
|
-
type_name = Type::TYPE_MAPPING[type.sigtype].first
|
360
|
-
raise TypeException, "#{type_name} expects an Array or Struct"
|
361
|
-
end
|
227
|
+
# type is [Type] now
|
228
|
+
data_class = Data::BY_TYPE_CODE[type.sigtype]
|
229
|
+
if data_class.nil?
|
230
|
+
raise NotImplementedError,
|
231
|
+
"sigtype: #{type.sigtype} (#{type.sigtype.chr})"
|
232
|
+
end
|
362
233
|
|
363
|
-
|
364
|
-
|
365
|
-
|
234
|
+
if data_class.fixed?
|
235
|
+
align(data_class.alignment)
|
236
|
+
data = data_class.new(val)
|
237
|
+
@packet += data.marshall(endianness)
|
238
|
+
elsif data_class.basic?
|
239
|
+
val = val.value if val.is_a?(Data::Basic)
|
240
|
+
align(data_class.size_class.alignment)
|
241
|
+
size_data = data_class.size_class.new(val.bytesize)
|
242
|
+
@packet += size_data.marshall(endianness)
|
243
|
+
# Z* makes a binary string, as opposed to interpolation
|
244
|
+
@packet += [val].pack("Z*")
|
245
|
+
else
|
246
|
+
case type.sigtype
|
247
|
+
|
248
|
+
when Type::VARIANT
|
249
|
+
append_variant(val)
|
250
|
+
when Type::ARRAY
|
251
|
+
append_array(type.child, val)
|
252
|
+
when Type::STRUCT, Type::DICT_ENTRY
|
253
|
+
val = val.value if val.is_a?(Data::Struct)
|
254
|
+
unless val.is_a?(Array) || val.is_a?(Struct)
|
255
|
+
type_name = Type::TYPE_MAPPING[type.sigtype].first
|
256
|
+
raise TypeException, "#{type_name} expects an Array or Struct, seen #{val.class}"
|
257
|
+
end
|
366
258
|
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
259
|
+
if type.sigtype == Type::DICT_ENTRY && val.size != 2
|
260
|
+
raise TypeException, "DICT_ENTRY expects a pair"
|
261
|
+
end
|
262
|
+
|
263
|
+
if type.members.size != val.size
|
264
|
+
type_name = Type::TYPE_MAPPING[type.sigtype].first
|
265
|
+
raise TypeException, "#{type_name} has #{val.size} elements but type info for #{type.members.size}"
|
266
|
+
end
|
371
267
|
|
372
|
-
|
373
|
-
|
374
|
-
|
268
|
+
struct do
|
269
|
+
type.members.zip(val).each do |t, v|
|
270
|
+
append(t, v)
|
271
|
+
end
|
375
272
|
end
|
273
|
+
else
|
274
|
+
raise NotImplementedError,
|
275
|
+
"sigtype: #{type.sigtype} (#{type.sigtype.chr})"
|
376
276
|
end
|
377
|
-
else
|
378
|
-
raise NotImplementedError,
|
379
|
-
"sigtype: #{type.sigtype} (#{type.sigtype.chr})"
|
380
277
|
end
|
381
278
|
end
|
382
279
|
|
383
280
|
def append_variant(val)
|
384
281
|
vartype = nil
|
385
|
-
if val.is_a?(
|
282
|
+
if val.is_a?(DBus::Data::Base)
|
283
|
+
vartype = val.type # FIXME: box or unbox another variant?
|
284
|
+
vardata = val.value
|
285
|
+
elsif val.is_a?(Array) && val.size == 2
|
386
286
|
case val[0]
|
387
|
-
when
|
287
|
+
when Type
|
388
288
|
vartype, vardata = val
|
289
|
+
# Ambiguous but easy to use, because Type
|
290
|
+
# cannot construct "as" "a{sv}" easily
|
389
291
|
when String
|
390
292
|
begin
|
391
293
|
parsed = Type::Parser.new(val[0]).parse
|
@@ -401,14 +303,14 @@ module DBus
|
|
401
303
|
vartype = Type::Parser.new(vartype).parse[0]
|
402
304
|
end
|
403
305
|
|
404
|
-
|
306
|
+
append(Data::Signature.type, vartype.to_s)
|
405
307
|
align(vartype.alignment)
|
406
|
-
sub = PacketMarshaller.new(@offset + @packet.bytesize)
|
308
|
+
sub = PacketMarshaller.new(@offset + @packet.bytesize, endianness: endianness)
|
407
309
|
sub.append(vartype, vardata)
|
408
310
|
@packet += sub.packet
|
409
311
|
end
|
410
312
|
|
411
|
-
# @param child_type [
|
313
|
+
# @param child_type [Type]
|
412
314
|
def append_array(child_type, val)
|
413
315
|
if val.is_a?(Hash)
|
414
316
|
raise TypeException, "Expected an Array but got a Hash" if child_type.sigtype != Type::DICT_ENTRY
|
data/lib/dbus/message.rb
CHANGED
@@ -172,7 +172,7 @@ module DBus
|
|
172
172
|
@body_length = params.packet.bytesize
|
173
173
|
|
174
174
|
marshaller = PacketMarshaller.new
|
175
|
-
marshaller.append(Type::BYTE, HOST_END)
|
175
|
+
marshaller.append(Type::BYTE, HOST_END.ord)
|
176
176
|
marshaller.append(Type::BYTE, @message_type)
|
177
177
|
marshaller.append(Type::BYTE, @flags)
|
178
178
|
marshaller.append(Type::BYTE, @protocol)
|
@@ -204,13 +204,7 @@ module DBus
|
|
204
204
|
# the detected message (self) and
|
205
205
|
# the index pointer of the buffer where the message data ended.
|
206
206
|
def unmarshall_buffer(buf)
|
207
|
-
|
208
|
-
endianness = if buf[0] == "l"
|
209
|
-
LIL_END
|
210
|
-
else
|
211
|
-
BIG_END
|
212
|
-
end
|
213
|
-
pu = PacketUnmarshaller.new(buf, endianness)
|
207
|
+
pu = PacketUnmarshaller.new(buf, RawMessage.endianness(buf[0]))
|
214
208
|
mdata = pu.unmarshall(MESSAGE_SIGNATURE)
|
215
209
|
_, @message_type, @flags, @protocol, @body_length, @serial,
|
216
210
|
headers = mdata
|
@@ -235,11 +229,11 @@ module DBus
|
|
235
229
|
@signature = struct[1]
|
236
230
|
end
|
237
231
|
end
|
238
|
-
pu.
|
232
|
+
pu.align_body
|
239
233
|
if @body_length.positive? && @signature
|
240
234
|
@params = pu.unmarshall(@signature, @body_length)
|
241
235
|
end
|
242
|
-
[self, pu.
|
236
|
+
[self, pu.consumed_size]
|
243
237
|
end
|
244
238
|
|
245
239
|
# Make a new exception from ex, mark it as being caused by this message
|
data/lib/dbus/object.rb
CHANGED
@@ -61,15 +61,7 @@ module DBus
|
|
61
61
|
retdata = [*retdata]
|
62
62
|
|
63
63
|
reply = Message.method_return(msg)
|
64
|
-
|
65
|
-
# Use the specific property type instead of the generic variant
|
66
|
-
# returned by Get.
|
67
|
-
# TODO: GetAll and Set still missing
|
68
|
-
property = dbus_lookup_property(msg.params[0], msg.params[1])
|
69
|
-
rsigs = [property.type]
|
70
|
-
else
|
71
|
-
rsigs = meth.rets.map(&:type)
|
72
|
-
end
|
64
|
+
rsigs = meth.rets.map(&:type)
|
73
65
|
rsigs.zip(retdata).each do |rsig, rdata|
|
74
66
|
reply.add_param(rsig, rdata)
|
75
67
|
end
|
@@ -345,7 +337,9 @@ module DBus
|
|
345
337
|
if property.readable?
|
346
338
|
ruby_name = property.ruby_name
|
347
339
|
value = public_send(ruby_name)
|
348
|
-
|
340
|
+
# may raise, DBus.error or https://ruby-doc.com/core-3.1.0/TypeError.html
|
341
|
+
typed_value = Data.make_typed(property.type, value)
|
342
|
+
[typed_value]
|
349
343
|
else
|
350
344
|
raise DBus.error("org.freedesktop.DBus.Error.PropertyWriteOnly"),
|
351
345
|
"Property '#{interface_name}.#{property_name}' (on object '#{@path}') is not readable"
|
@@ -357,6 +351,9 @@ module DBus
|
|
357
351
|
|
358
352
|
if property.writable?
|
359
353
|
ruby_name_eq = "#{property.ruby_name}="
|
354
|
+
# TODO: declare dbus_method :Set to take :exact argument
|
355
|
+
# and type check it here before passing its :plain value
|
356
|
+
# to the implementation
|
360
357
|
public_send(ruby_name_eq, value)
|
361
358
|
else
|
362
359
|
raise DBus.error("org.freedesktop.DBus.Error.PropertyReadOnly"),
|
@@ -385,7 +382,10 @@ module DBus
|
|
385
382
|
# > array.
|
386
383
|
# so we will silently omit properties that fail to read.
|
387
384
|
# Get'ting them individually will send DBus.Error
|
388
|
-
|
385
|
+
value = public_send(ruby_name)
|
386
|
+
# may raise, DBus.error or https://ruby-doc.com/core-3.1.0/TypeError.html
|
387
|
+
typed_value = Data.make_typed(property.type, value)
|
388
|
+
p_hash[p_name.to_s] = typed_value
|
389
389
|
rescue StandardError
|
390
390
|
DBus.logger.debug "Property '#{interface_name}.#{p_name}' (on object '#{@path}')" \
|
391
391
|
" has raised during GetAll, omitting it"
|
data/lib/dbus/object_path.rb
CHANGED
@@ -9,7 +9,8 @@
|
|
9
9
|
# See the file "COPYING" for the exact licensing terms.
|
10
10
|
|
11
11
|
module DBus
|
12
|
-
# A {::String} that validates at initialization time
|
12
|
+
# A {::String} that validates at initialization time.
|
13
|
+
# See also {DBus::Data::ObjectPath}
|
13
14
|
# @see https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-marshaling-object-path
|
14
15
|
class ObjectPath < String
|
15
16
|
# @raise Error if not a valid object path
|