ruby-dbus 0.18.0.beta1 → 0.18.0.beta2
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 +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
|