ruby-dbus 0.18.0.beta4 → 0.18.0.beta5
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 +17 -0
- data/VERSION +1 -1
- data/lib/dbus/data.rb +84 -104
- data/lib/dbus/marshall.rb +7 -4
- data/lib/dbus/type.rb +120 -14
- data/spec/data_spec.rb +29 -37
- data/spec/property_spec.rb +18 -1
- data/spec/type_spec.rb +105 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8b0c43d3f27f0877e52c0adfb8014374829f97bcd38be6b9fabda1d5da8413c
|
4
|
+
data.tar.gz: 000eadf163b0fab2ef4ab39de81a79714b34392cd81b3be68e12587ddfa93372
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c2206dcd935fed4e3711b88b2c0c265e5a335700f9137d2c3972f419791d9c25198d0acf9ba7aaecdbc6a25e540005c64321e5165c6c644838fb3557355861ac
|
7
|
+
data.tar.gz: 212cb8bdcd75e3f35622843f262cdb80eaa07c1919a7d17ffdf601e05c627556343b7855a014f60a220c8a757c201431d66799a6025a98d084aef6cc12f7d8bb
|
data/NEWS.md
CHANGED
@@ -2,6 +2,23 @@
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
+
## Ruby D-Bus 0.18.0.beta5 - 2022-04-27
|
6
|
+
|
7
|
+
API:
|
8
|
+
* DBus::Type instances are frozen.
|
9
|
+
* Data::Container classes (Array, Struct, DictEntry, but not Variant)
|
10
|
+
constructors (#initialize, .from_items, .from_typed) changed to have
|
11
|
+
a *type* argument instead of *member_type* or *member_types*.
|
12
|
+
* Added type factories
|
13
|
+
* Type::Array[type]
|
14
|
+
* Type::Hash[key_type, value_type]
|
15
|
+
* Type::Struct[type1, type2...]
|
16
|
+
|
17
|
+
Bug fixes:
|
18
|
+
* Properties containing Variants would return them doubly wrapped ([#111][]).
|
19
|
+
|
20
|
+
[#111]: https://github.com/mvidner/ruby-dbus/pull/111
|
21
|
+
|
5
22
|
## Ruby D-Bus 0.18.0.beta4 - 2022-04-21
|
6
23
|
|
7
24
|
Bug fixes:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.18.0.
|
1
|
+
0.18.0.beta5
|
data/lib/dbus/data.rb
CHANGED
@@ -43,7 +43,7 @@ module DBus
|
|
43
43
|
data_class = Data::BY_TYPE_CODE[type.sigtype]
|
44
44
|
# not nil because DBus.type validates
|
45
45
|
|
46
|
-
data_class.from_typed(value,
|
46
|
+
data_class.from_typed(value, type: type)
|
47
47
|
end
|
48
48
|
module_function :make_typed
|
49
49
|
|
@@ -67,6 +67,15 @@ module DBus
|
|
67
67
|
# for the specific see {Variant#member_type}
|
68
68
|
# @return [Type] the exact type of this value
|
69
69
|
|
70
|
+
# @!method self.from_typed(value, type:)
|
71
|
+
# @param value [::Object]
|
72
|
+
# @param type [Type]
|
73
|
+
# @return [Base]
|
74
|
+
# @api private
|
75
|
+
# Use {Data.make_typed} instead.
|
76
|
+
# Construct an instance of the specific subclass, with a type further
|
77
|
+
# specified in the *type* argument.
|
78
|
+
|
70
79
|
# Child classes must validate *value*.
|
71
80
|
def initialize(value)
|
72
81
|
@value = value
|
@@ -83,6 +92,11 @@ module DBus
|
|
83
92
|
# Hash key equality
|
84
93
|
# See https://ruby-doc.org/core-3.0.0/Object.html#method-i-eql-3F
|
85
94
|
alias eql? ==
|
95
|
+
|
96
|
+
# @param type [Type]
|
97
|
+
def self.assert_type_matches_class(type)
|
98
|
+
raise ArgumentError unless type.sigtype == type_code
|
99
|
+
end
|
86
100
|
end
|
87
101
|
|
88
102
|
# A value that is not a {Container}.
|
@@ -103,10 +117,10 @@ module DBus
|
|
103
117
|
end
|
104
118
|
|
105
119
|
# @param value [::Object]
|
106
|
-
# @param
|
120
|
+
# @param type [Type]
|
107
121
|
# @return [Basic]
|
108
|
-
def self.from_typed(value,
|
109
|
-
|
122
|
+
def self.from_typed(value, type:)
|
123
|
+
assert_type_matches_class(type)
|
110
124
|
new(value)
|
111
125
|
end
|
112
126
|
end
|
@@ -132,34 +146,6 @@ module DBus
|
|
132
146
|
end
|
133
147
|
end
|
134
148
|
|
135
|
-
# {DBus::Data::String}, {DBus::Data::ObjectPath}, or {DBus::Data::Signature}.
|
136
|
-
class StringLike < Basic
|
137
|
-
def self.fixed?
|
138
|
-
false
|
139
|
-
end
|
140
|
-
|
141
|
-
def initialize(value)
|
142
|
-
if value.is_a?(self.class)
|
143
|
-
value = value.value
|
144
|
-
else
|
145
|
-
self.class.validate_raw!(value)
|
146
|
-
end
|
147
|
-
|
148
|
-
super(value)
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
# Contains one or more other values.
|
153
|
-
class Container < Base
|
154
|
-
def self.basic?
|
155
|
-
false
|
156
|
-
end
|
157
|
-
|
158
|
-
def self.fixed?
|
159
|
-
false
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
163
149
|
# Format strings for String#unpack, both little- and big-endian.
|
164
150
|
Format = ::Struct.new(:little, :big)
|
165
151
|
|
@@ -398,6 +384,23 @@ module DBus
|
|
398
384
|
end
|
399
385
|
end
|
400
386
|
|
387
|
+
# {DBus::Data::String}, {DBus::Data::ObjectPath}, or {DBus::Data::Signature}.
|
388
|
+
class StringLike < Basic
|
389
|
+
def self.fixed?
|
390
|
+
false
|
391
|
+
end
|
392
|
+
|
393
|
+
def initialize(value)
|
394
|
+
if value.is_a?(self.class)
|
395
|
+
value = value.value
|
396
|
+
else
|
397
|
+
self.class.validate_raw!(value)
|
398
|
+
end
|
399
|
+
|
400
|
+
super(value)
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
401
404
|
# UTF-8 encoded string.
|
402
405
|
class String < StringLike
|
403
406
|
def self.type_code
|
@@ -494,6 +497,21 @@ module DBus
|
|
494
497
|
end
|
495
498
|
end
|
496
499
|
|
500
|
+
# Contains one or more other values.
|
501
|
+
class Container < Base
|
502
|
+
def self.basic?
|
503
|
+
false
|
504
|
+
end
|
505
|
+
|
506
|
+
def self.fixed?
|
507
|
+
false
|
508
|
+
end
|
509
|
+
|
510
|
+
# For containers, the type varies among instances
|
511
|
+
# @see Base#type
|
512
|
+
attr_reader :type
|
513
|
+
end
|
514
|
+
|
497
515
|
# An Array, or a Dictionary (Hash).
|
498
516
|
class Array < Container
|
499
517
|
def self.type_code
|
@@ -504,44 +522,32 @@ module DBus
|
|
504
522
|
4
|
505
523
|
end
|
506
524
|
|
507
|
-
# @return [Type]
|
508
|
-
attr_reader :member_type
|
509
|
-
|
510
|
-
def type
|
511
|
-
return @type if @type
|
512
|
-
|
513
|
-
# TODO: reconstructing the type is cumbersome; have #initialize take *type* instead?
|
514
|
-
# TODO: or rather add Type::Array[t]
|
515
|
-
@type = Type.new("a")
|
516
|
-
@type << member_type
|
517
|
-
@type
|
518
|
-
end
|
519
|
-
|
520
525
|
# TODO: check that Hash keys are basic types
|
521
526
|
# @param mode [:plain,:exact]
|
522
|
-
# @param
|
527
|
+
# @param type [Type]
|
523
528
|
# @param hash [Boolean] are we unmarshalling an ARRAY of DICT_ENTRY
|
524
529
|
# @return [Data::Array]
|
525
|
-
def self.from_items(value, mode:,
|
530
|
+
def self.from_items(value, mode:, type:, hash: false)
|
526
531
|
value = Hash[value] if hash
|
527
532
|
return value if mode == :plain
|
528
533
|
|
529
|
-
new(value,
|
534
|
+
new(value, type: type)
|
530
535
|
end
|
531
536
|
|
532
537
|
# @param value [::Object]
|
533
|
-
# @param
|
538
|
+
# @param type [Type]
|
534
539
|
# @return [Data::Array]
|
535
|
-
def self.from_typed(value,
|
540
|
+
def self.from_typed(value, type:)
|
541
|
+
assert_type_matches_class(type)
|
536
542
|
# TODO: validation
|
537
|
-
member_type =
|
543
|
+
member_type = type.child
|
538
544
|
|
539
545
|
# TODO: Dict??
|
540
546
|
items = value.map do |i|
|
541
547
|
Data.make_typed(member_type, i)
|
542
548
|
end
|
543
549
|
|
544
|
-
new(items,
|
550
|
+
new(items, type: type) # initialize(::Array<Data::Base>)
|
545
551
|
end
|
546
552
|
|
547
553
|
# FIXME: should Data::Array be mutable?
|
@@ -550,12 +556,12 @@ module DBus
|
|
550
556
|
# TODO: specify type or guess type?
|
551
557
|
# Data is the exact type, so its constructor should be exact
|
552
558
|
# and guesswork should be clearly labeled
|
553
|
-
# @param
|
554
|
-
def initialize(value,
|
555
|
-
|
559
|
+
# @param type [SingleCompleteType,Type]
|
560
|
+
def initialize(value, type:)
|
561
|
+
type = DBus.type(type) unless type.is_a?(Type)
|
562
|
+
self.class.assert_type_matches_class(type)
|
563
|
+
@type = type
|
556
564
|
# TODO: copy from another Data::Array
|
557
|
-
@member_type = member_type
|
558
|
-
@type = nil
|
559
565
|
super(value)
|
560
566
|
end
|
561
567
|
end
|
@@ -572,46 +578,32 @@ module DBus
|
|
572
578
|
8
|
573
579
|
end
|
574
580
|
|
575
|
-
# @return [::Array<Type>]
|
576
|
-
attr_reader :member_types
|
577
|
-
|
578
|
-
def type
|
579
|
-
return @type if @type
|
580
|
-
|
581
|
-
# TODO: reconstructing the type is cumbersome; have #initialize take *type* instead?
|
582
|
-
# TODO: or rather add Type::Struct[t1, t2, ...]
|
583
|
-
@type = Type.new(self.class.type_code, abstract: true)
|
584
|
-
@member_types.each do |member_type|
|
585
|
-
@type << member_type
|
586
|
-
end
|
587
|
-
@type
|
588
|
-
end
|
589
|
-
|
590
581
|
# @param value [::Array]
|
591
|
-
def self.from_items(value, mode:,
|
582
|
+
def self.from_items(value, mode:, type:)
|
592
583
|
value.freeze
|
593
584
|
return value if mode == :plain
|
594
585
|
|
595
|
-
new(value,
|
586
|
+
new(value, type: type)
|
596
587
|
end
|
597
588
|
|
598
589
|
# @param value [::Object] (#size, #each)
|
599
|
-
# @param
|
590
|
+
# @param type [Type]
|
600
591
|
# @return [Struct]
|
601
|
-
def self.from_typed(value,
|
592
|
+
def self.from_typed(value, type:)
|
602
593
|
# TODO: validation
|
594
|
+
member_types = type.members
|
603
595
|
raise unless value.size == member_types.size
|
604
596
|
|
605
597
|
items = member_types.zip(value).map do |item_type, item|
|
606
598
|
Data.make_typed(item_type, item)
|
607
599
|
end
|
608
600
|
|
609
|
-
new(items,
|
601
|
+
new(items, type: type) # initialize(::Array<Data::Base>)
|
610
602
|
end
|
611
603
|
|
612
|
-
def initialize(value,
|
613
|
-
|
614
|
-
@type =
|
604
|
+
def initialize(value, type:)
|
605
|
+
self.class.assert_type_matches_class(type)
|
606
|
+
@type = type
|
615
607
|
super(value)
|
616
608
|
end
|
617
609
|
end
|
@@ -634,10 +626,10 @@ module DBus
|
|
634
626
|
end
|
635
627
|
|
636
628
|
# @param value [::Object]
|
637
|
-
# @param
|
629
|
+
# @param type [Type]
|
638
630
|
# @return [Variant]
|
639
|
-
def self.from_typed(value,
|
640
|
-
|
631
|
+
def self.from_typed(value, type:)
|
632
|
+
assert_type_matches_class(type)
|
641
633
|
|
642
634
|
# decide on type of value
|
643
635
|
new(value, member_type: nil)
|
@@ -690,31 +682,19 @@ module DBus
|
|
690
682
|
8
|
691
683
|
end
|
692
684
|
|
693
|
-
# @return [::Array<Type>]
|
694
|
-
attr_reader :member_types
|
695
|
-
|
696
|
-
def type
|
697
|
-
return @type if @type
|
698
|
-
|
699
|
-
# TODO: reconstructing the type is cumbersome; have #initialize take *type* instead?
|
700
|
-
@type = Type.new(self.class.type_code, abstract: true)
|
701
|
-
@member_types.each do |member_type|
|
702
|
-
@type << member_type
|
703
|
-
end
|
704
|
-
@type
|
705
|
-
end
|
706
|
-
|
707
685
|
# @param value [::Array]
|
708
|
-
def self.from_items(value, mode:,
|
686
|
+
def self.from_items(value, mode:, type:) # rubocop:disable Lint/UnusedMethodArgument
|
709
687
|
value.freeze
|
710
688
|
# DictEntry ignores the :exact mode
|
711
689
|
value
|
712
690
|
end
|
713
691
|
|
714
692
|
# @param value [::Object] (#size, #each)
|
715
|
-
# @param
|
693
|
+
# @param type [Type]
|
716
694
|
# @return [DictEntry]
|
717
|
-
def self.from_typed(value,
|
695
|
+
def self.from_typed(value, type:)
|
696
|
+
assert_type_matches_class(type)
|
697
|
+
member_types = type.members
|
718
698
|
# assert member_types.size == 2
|
719
699
|
# TODO: duplicated from Struct. Inherit/delegate?
|
720
700
|
# TODO: validation
|
@@ -724,12 +704,12 @@ module DBus
|
|
724
704
|
Data.make_typed(item_type, item)
|
725
705
|
end
|
726
706
|
|
727
|
-
new(items,
|
707
|
+
new(items, type: type) # initialize(::Array<Data::Base>)
|
728
708
|
end
|
729
709
|
|
730
|
-
def initialize(value,
|
731
|
-
|
732
|
-
@type =
|
710
|
+
def initialize(value, type:)
|
711
|
+
self.class.assert_type_matches_class(type)
|
712
|
+
@type = type
|
733
713
|
super(value)
|
734
714
|
end
|
735
715
|
end
|
data/lib/dbus/marshall.rb
CHANGED
@@ -118,7 +118,7 @@ module DBus
|
|
118
118
|
values = signature.members.map do |child_sig|
|
119
119
|
do_parse(child_sig, mode: mode)
|
120
120
|
end
|
121
|
-
packet = data_class.from_items(values, mode: mode,
|
121
|
+
packet = data_class.from_items(values, mode: mode, type: signature)
|
122
122
|
|
123
123
|
when Type::VARIANT
|
124
124
|
data_sig = do_parse(Data::Signature.type, mode: :exact) # -> Data::Signature
|
@@ -147,7 +147,7 @@ module DBus
|
|
147
147
|
items << item
|
148
148
|
end
|
149
149
|
is_hash = signature.child.sigtype == Type::DICT_ENTRY
|
150
|
-
packet = data_class.from_items(items, mode: mode,
|
150
|
+
packet = data_class.from_items(items, mode: mode, type: signature, hash: is_hash)
|
151
151
|
end
|
152
152
|
end
|
153
153
|
packet
|
@@ -282,8 +282,11 @@ module DBus
|
|
282
282
|
|
283
283
|
def append_variant(val)
|
284
284
|
vartype = nil
|
285
|
-
if val.is_a?(DBus::Data::
|
286
|
-
vartype = val.
|
285
|
+
if val.is_a?(DBus::Data::Variant)
|
286
|
+
vartype = val.member_type
|
287
|
+
vardata = val.value
|
288
|
+
elsif val.is_a?(DBus::Data::Base)
|
289
|
+
vartype = val.type
|
287
290
|
vardata = val.value
|
288
291
|
elsif val.is_a?(Array) && val.size == 2
|
289
292
|
case val[0]
|
data/lib/dbus/type.rb
CHANGED
@@ -29,14 +29,12 @@ module DBus
|
|
29
29
|
# For documentation purposes only.
|
30
30
|
class Prototype < String; end
|
31
31
|
|
32
|
-
#
|
33
|
-
#
|
34
|
-
# This module containts the constants of the types specified in the D-Bus
|
35
|
-
# protocol.
|
32
|
+
# Represents the D-Bus types.
|
36
33
|
#
|
37
34
|
# Corresponds to {SingleCompleteType}.
|
35
|
+
# Instances are immutable/frozen once fully constructed.
|
38
36
|
#
|
39
|
-
# See also {DBus::Data::Signature}
|
37
|
+
# See also {DBus::Data::Signature} which is "type on the wire".
|
40
38
|
class Type
|
41
39
|
# Mapping from type number to name and alignment.
|
42
40
|
TYPE_MAPPING = {
|
@@ -104,8 +102,9 @@ module DBus
|
|
104
102
|
end
|
105
103
|
end
|
106
104
|
|
107
|
-
@sigtype = sigtype
|
108
|
-
@members = []
|
105
|
+
@sigtype = sigtype.freeze
|
106
|
+
@members = [] # not frozen yet, Parser#parse_one or Factory will do it
|
107
|
+
freeze
|
109
108
|
end
|
110
109
|
|
111
110
|
# Return the required alignment for the type.
|
@@ -124,16 +123,15 @@ module DBus
|
|
124
123
|
when DICT_ENTRY
|
125
124
|
"{#{@members.collect(&:to_s).join}}"
|
126
125
|
else
|
127
|
-
if !TYPE_MAPPING.keys.member?(@sigtype)
|
128
|
-
raise NotImplementedError
|
129
|
-
end
|
130
|
-
|
131
126
|
@sigtype.chr
|
132
127
|
end
|
133
128
|
end
|
134
129
|
|
135
130
|
# Add a new member type _item_.
|
131
|
+
# @param item [Type]
|
136
132
|
def <<(item)
|
133
|
+
raise ArgumentError unless item.is_a?(Type)
|
134
|
+
|
137
135
|
if ![STRUCT, ARRAY, DICT_ENTRY].member?(@sigtype)
|
138
136
|
raise SignatureException
|
139
137
|
end
|
@@ -232,6 +230,7 @@ module DBus
|
|
232
230
|
else
|
233
231
|
res = Type.new(char)
|
234
232
|
end
|
233
|
+
res.members.freeze
|
235
234
|
res
|
236
235
|
end
|
237
236
|
|
@@ -243,7 +242,7 @@ module DBus
|
|
243
242
|
while (c = nextchar)
|
244
243
|
ret << parse_one(c)
|
245
244
|
end
|
246
|
-
ret
|
245
|
+
ret.freeze
|
247
246
|
end
|
248
247
|
|
249
248
|
# Parse one {SingleCompleteType}
|
@@ -255,9 +254,116 @@ module DBus
|
|
255
254
|
t = parse_one(c)
|
256
255
|
raise SignatureException, "Has more than a Single Complete Type: #{@signature}" unless nextchar.nil?
|
257
256
|
|
257
|
+
t.freeze
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
class Factory
|
262
|
+
# @param type [Type,SingleCompleteType,Class]
|
263
|
+
# @see from_plain_class
|
264
|
+
# @return [Type] (frozen)
|
265
|
+
def self.make_type(type)
|
266
|
+
case type
|
267
|
+
when Type
|
268
|
+
type
|
269
|
+
when String
|
270
|
+
DBus.type(type)
|
271
|
+
when Class
|
272
|
+
from_plain_class(type)
|
273
|
+
else
|
274
|
+
msg = "Expecting DBus::Type, DBus::SingleCompleteType(aka ::String), or Class, got #{type.inspect}"
|
275
|
+
raise ArgumentError, msg
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
# Make a {Type} corresponding to some plain classes:
|
280
|
+
# - String
|
281
|
+
# - Float
|
282
|
+
# - DBus::ObjectPath
|
283
|
+
# - DBus::Signature, DBus::SingleCompleteType
|
284
|
+
# @param klass [Class]
|
285
|
+
# @return [Type] (frozen)
|
286
|
+
def self.from_plain_class(klass)
|
287
|
+
@signature_type ||= DBus.type(SIGNATURE)
|
288
|
+
@class_to_type ||= {
|
289
|
+
DBus::ObjectPath => DBus.type(OBJECT_PATH),
|
290
|
+
DBus::Signature => @signature_type,
|
291
|
+
DBus::SingleCompleteType => @signature_type,
|
292
|
+
String => DBus.type(STRING),
|
293
|
+
Float => DBus.type(DOUBLE)
|
294
|
+
}
|
295
|
+
t = @class_to_type[klass]
|
296
|
+
raise ArgumentError, "Cannot convert plain class #{klass} to a D-Bus type" if t.nil?
|
297
|
+
|
298
|
+
t
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
# Syntactic helper for constructing an array Type.
|
303
|
+
# You may be looking for {Data::Array} instead.
|
304
|
+
# @example
|
305
|
+
# t = Type::Array[Type::INT16]
|
306
|
+
class ArrayFactory < Factory
|
307
|
+
# @param member_type [Type,SingleCompleteType]
|
308
|
+
# @return [Type] (frozen)
|
309
|
+
def self.[](member_type)
|
310
|
+
t = Type.new(ARRAY)
|
311
|
+
t << make_type(member_type)
|
312
|
+
t.members.freeze
|
313
|
+
t
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
# @example
|
318
|
+
# t = Type::Array[Type::INT16]
|
319
|
+
Array = ArrayFactory
|
320
|
+
|
321
|
+
# Syntactic helper for constructing a hash Type.
|
322
|
+
# You may be looking for {Data::Array} and {Data::DictEntry} instead.
|
323
|
+
# @example
|
324
|
+
# t = Type::Hash[Type::STRING, Type::VARIANT]
|
325
|
+
class HashFactory < Factory
|
326
|
+
# @param key_type [Type,SingleCompleteType]
|
327
|
+
# @param value_type [Type,SingleCompleteType]
|
328
|
+
# @return [Type] (frozen)
|
329
|
+
def self.[](key_type, value_type)
|
330
|
+
t = Type.new(ARRAY)
|
331
|
+
de = Type.new(DICT_ENTRY, abstract: true)
|
332
|
+
de << make_type(key_type)
|
333
|
+
de << make_type(value_type)
|
334
|
+
de.members.freeze
|
335
|
+
t << de
|
336
|
+
t.members.freeze
|
258
337
|
t
|
259
338
|
end
|
260
339
|
end
|
340
|
+
|
341
|
+
# @example
|
342
|
+
# t = Type::Hash[Type::INT16]
|
343
|
+
Hash = HashFactory
|
344
|
+
|
345
|
+
# Syntactic helper for constructing a struct Type.
|
346
|
+
# You may be looking for {Data::Struct} instead.
|
347
|
+
# @example
|
348
|
+
# t = Type::Struct[Type::INT16, Type::STRING]
|
349
|
+
class StructFactory < Factory
|
350
|
+
# @param member_types [::Array<Type,SingleCompleteType>]
|
351
|
+
# @return [Type] (frozen)
|
352
|
+
def self.[](*member_types)
|
353
|
+
raise ArgumentError if member_types.empty?
|
354
|
+
|
355
|
+
t = Type.new(STRUCT, abstract: true)
|
356
|
+
member_types.each do |mt|
|
357
|
+
t << make_type(mt)
|
358
|
+
end
|
359
|
+
t.members.freeze
|
360
|
+
t
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
# @example
|
365
|
+
# t = Type::Struct[Type::INT16, Type::STRING]
|
366
|
+
Struct = StructFactory
|
261
367
|
end
|
262
368
|
|
263
369
|
# shortcuts
|
@@ -266,7 +372,7 @@ module DBus
|
|
266
372
|
# This is prefered to {Type#initialize} which allows
|
267
373
|
# incomplete or invalid types.
|
268
374
|
# @param string_type [SingleCompleteType]
|
269
|
-
# @return [DBus::Type]
|
375
|
+
# @return [DBus::Type] (frozen)
|
270
376
|
# @raise SignatureException
|
271
377
|
def type(string_type)
|
272
378
|
Type::Parser.new(string_type).parse1
|
@@ -275,7 +381,7 @@ module DBus
|
|
275
381
|
|
276
382
|
# Parse a String to zero or more {DBus::Type}s.
|
277
383
|
# @param string_type [Signature]
|
278
|
-
# @return [Array<DBus::Type>]
|
384
|
+
# @return [Array<DBus::Type>] (frozen)
|
279
385
|
# @raise SignatureException
|
280
386
|
def types(string_type)
|
281
387
|
Type::Parser.new(string_type).parse
|
data/spec/data_spec.rb
CHANGED
@@ -85,6 +85,8 @@ end
|
|
85
85
|
# TODO: Look at conversions? to_str, to_int?
|
86
86
|
|
87
87
|
describe DBus::Data do
|
88
|
+
T = DBus::Type unless const_defined? "T"
|
89
|
+
|
88
90
|
# test initialization, from user code, or from packet (from_raw)
|
89
91
|
# remember to unpack if initializing from Data::Base
|
90
92
|
# #value should recurse inside so that the user doesnt have to
|
@@ -245,18 +247,18 @@ describe DBus::Data do
|
|
245
247
|
describe "containers" do
|
246
248
|
describe DBus::Data::Array do
|
247
249
|
good = [
|
248
|
-
# [[1, 2, 3],
|
249
|
-
[[1, 2, 3], {
|
250
|
-
[[1, 2, 3], {
|
251
|
-
[[1, 2, 3], {
|
252
|
-
[[DBus::Data::UInt16.new(1), DBus::Data::UInt16.new(2), DBus::Data::UInt16.new(3)], {
|
250
|
+
# [[1, 2, 3], type: nil],
|
251
|
+
[[1, 2, 3], { type: "aq" }],
|
252
|
+
[[1, 2, 3], { type: T::Array[T::UINT16] }],
|
253
|
+
[[1, 2, 3], { type: T::Array["q"] }],
|
254
|
+
[[DBus::Data::UInt16.new(1), DBus::Data::UInt16.new(2), DBus::Data::UInt16.new(3)], { type: T::Array["q"] }]
|
253
255
|
# TODO: others
|
254
256
|
]
|
255
257
|
|
256
258
|
bad = [
|
257
259
|
# undesirable type guessing
|
258
|
-
## [[1, 2, 3], {
|
259
|
-
## [[1, 2, 3], {
|
260
|
+
## [[1, 2, 3], { type: nil }, DBus::InvalidPacketException, "Unknown type code"],
|
261
|
+
## [[1, 2, 3], { type: "!" }, DBus::InvalidPacketException, "Unknown type code"]
|
260
262
|
# TODO: others
|
261
263
|
]
|
262
264
|
|
@@ -265,8 +267,8 @@ describe DBus::Data do
|
|
265
267
|
|
266
268
|
describe ".from_typed" do
|
267
269
|
it "creates new instance from given object and type" do
|
268
|
-
type =
|
269
|
-
expect(described_class.from_typed(["test", "lest"],
|
270
|
+
type = T::Array[String]
|
271
|
+
expect(described_class.from_typed(["test", "lest"], type: type)).to be_a(described_class)
|
270
272
|
end
|
271
273
|
end
|
272
274
|
end
|
@@ -274,7 +276,7 @@ describe DBus::Data do
|
|
274
276
|
describe DBus::Data::Struct do
|
275
277
|
three_words = ::Struct.new(:a, :b, :c)
|
276
278
|
|
277
|
-
qqq = [
|
279
|
+
qqq = T::Struct[T::UINT16, T::UINT16, T::UINT16]
|
278
280
|
integers = [1, 2, 3]
|
279
281
|
uints = [DBus::Data::UInt16.new(1), DBus::Data::UInt16.new(2), DBus::Data::UInt16.new(3)]
|
280
282
|
|
@@ -291,28 +293,25 @@ describe DBus::Data do
|
|
291
293
|
# TODO: also check data ownership: reasonable to own the data?
|
292
294
|
# can make it explicit?
|
293
295
|
good = [
|
294
|
-
# from plain array; various
|
295
|
-
[integers, {
|
296
|
-
[integers, {
|
297
|
-
[integers, {
|
296
|
+
# from plain array; various *type* styles
|
297
|
+
[integers, { type: DBus.type("(qqq)") }],
|
298
|
+
[integers, { type: T::Struct["q", "q", "q"] }],
|
299
|
+
[integers, { type: T::Struct[T::UINT16, T::UINT16, T::UINT16] }],
|
300
|
+
[integers, { type: T::Struct[*DBus.types("qqq")] }],
|
298
301
|
# plain array of data
|
299
|
-
[uints, {
|
302
|
+
[uints, { type: qqq }],
|
300
303
|
# ::Struct
|
301
|
-
[three_words.new(*integers), {
|
302
|
-
[three_words.new(*uints), {
|
304
|
+
[three_words.new(*integers), { type: qqq }],
|
305
|
+
[three_words.new(*uints), { type: qqq }]
|
303
306
|
# TODO: others
|
304
307
|
]
|
305
308
|
|
309
|
+
# check these only when canonicalizing @value, because that will
|
310
|
+
# type-check the value deeply
|
306
311
|
_bad_but_valid = [
|
307
|
-
# Wrong member_types arg:
|
308
|
-
# hmm this is another reason to pass the type
|
309
|
-
# as the entire struct type, not the members:
|
310
|
-
# empty struct will be caught naturally
|
311
|
-
[integers, { member_types: [] }, ArgumentError, "???"],
|
312
|
-
[integers, { member_types: ["!"] }, DBus::InvalidPacketException, "Unknown type code"],
|
313
312
|
# STRUCT specific: member count mismatch
|
314
|
-
[[1, 2], {
|
315
|
-
[[1, 2, 3, 4], {
|
313
|
+
[[1, 2], { type: qqq }, ArgumentError, "???"],
|
314
|
+
[[1, 2, 3, 4], { type: qqq }, ArgumentError, "???"]
|
316
315
|
# TODO: others
|
317
316
|
]
|
318
317
|
|
@@ -321,8 +320,8 @@ describe DBus::Data do
|
|
321
320
|
|
322
321
|
describe ".from_typed" do
|
323
322
|
it "creates new instance from given object and type" do
|
324
|
-
type =
|
325
|
-
expect(described_class.from_typed(["test", "lest"].freeze,
|
323
|
+
type = T::Struct[T::STRING, T::STRING]
|
324
|
+
expect(described_class.from_typed(["test", "lest"].freeze, type: type))
|
326
325
|
.to be_a(described_class)
|
327
326
|
end
|
328
327
|
end
|
@@ -331,16 +330,9 @@ describe DBus::Data do
|
|
331
330
|
describe DBus::Data::Variant do
|
332
331
|
describe ".from_typed" do
|
333
332
|
it "creates new instance from given object and type" do
|
334
|
-
type = DBus
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
it "ignores the member_types argument" do
|
339
|
-
type = DBus::Type.new("s")
|
340
|
-
# Base.from_typed is a generic interface with a fixed signature;
|
341
|
-
# So it must offer the member_types parameter, which is misleading
|
342
|
-
# for a Variant
|
343
|
-
value = described_class.from_typed("test", member_types: [type])
|
333
|
+
type = DBus.type(T::VARIANT)
|
334
|
+
value = described_class.from_typed("test", type: type)
|
335
|
+
expect(value).to be_a(described_class)
|
344
336
|
expect(value.type.to_s).to eq "v"
|
345
337
|
expect(value.member_type.to_s).to eq "s"
|
346
338
|
end
|
data/spec/property_spec.rb
CHANGED
@@ -163,7 +163,7 @@ describe "PropertyTest" do
|
|
163
163
|
end
|
164
164
|
end
|
165
165
|
|
166
|
-
context "
|
166
|
+
context "a dict-typed property" do
|
167
167
|
it "gets read as a hash" do
|
168
168
|
val = @iface["MyDict"]
|
169
169
|
expect(val).to eq({
|
@@ -172,6 +172,23 @@ describe "PropertyTest" do
|
|
172
172
|
"three" => [3, 3, 3]
|
173
173
|
})
|
174
174
|
end
|
175
|
+
|
176
|
+
it "Get returns the correctly typed value (check with dbus-send)" do
|
177
|
+
cmd = "dbus-send --print-reply " \
|
178
|
+
"--dest=org.ruby.service " \
|
179
|
+
"/org/ruby/MyInstance " \
|
180
|
+
"org.freedesktop.DBus.Properties.Get " \
|
181
|
+
"string:org.ruby.SampleInterface " \
|
182
|
+
"string:MyDict"
|
183
|
+
reply = `#{cmd}`
|
184
|
+
# a bug about variant nesting lead to a "variant variant int32 1" value
|
185
|
+
match_rx = /variant \s+ array \s \[ \s+
|
186
|
+
dict \s entry\( \s+
|
187
|
+
string \s "one" \s+
|
188
|
+
variant \s+ int32 \s 1 \s+
|
189
|
+
\)/x
|
190
|
+
expect(reply).to match(match_rx)
|
191
|
+
end
|
175
192
|
end
|
176
193
|
|
177
194
|
context "a variant-typed property" do
|
data/spec/type_spec.rb
CHANGED
@@ -45,6 +45,7 @@ describe DBus do
|
|
45
45
|
["a{vs}", "DICT_ENTRY key must be basic (non-container)"],
|
46
46
|
["{sv}", "DICT_ENTRY not an immediate child of an ARRAY"],
|
47
47
|
["a({sv})", "DICT_ENTRY not an immediate child of an ARRAY"],
|
48
|
+
["a{s", "DICT_ENTRY not closed"],
|
48
49
|
["a{sv", "DICT_ENTRY not closed"],
|
49
50
|
["}", "DICT_ENTRY unexpectedly closed"],
|
50
51
|
|
@@ -79,4 +80,108 @@ describe DBus do
|
|
79
80
|
end
|
80
81
|
end
|
81
82
|
end
|
83
|
+
|
84
|
+
describe DBus::Type do
|
85
|
+
describe "#<<" do
|
86
|
+
it "raises if the argument is not a Type" do
|
87
|
+
t = DBus::Type.new(DBus::Type::ARRAY)
|
88
|
+
expect { t << "s" }.to raise_error(ArgumentError)
|
89
|
+
end
|
90
|
+
|
91
|
+
# TODO: the following raise checks do not occur in practice, as there are
|
92
|
+
# parallel checks in the parses. The code could be simplified?
|
93
|
+
it "raises if adding too much to an array" do
|
94
|
+
t = DBus::Type.new(DBus::Type::ARRAY)
|
95
|
+
b = DBus::Type.new(DBus::Type::BOOLEAN)
|
96
|
+
t << b
|
97
|
+
expect { t << b }.to raise_error(DBus::Type::SignatureException)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "raises if adding too much to a dict_entry" do
|
101
|
+
t = DBus::Type.new(DBus::Type::DICT_ENTRY, abstract: true)
|
102
|
+
b = DBus::Type.new(DBus::Type::BOOLEAN)
|
103
|
+
t << b
|
104
|
+
t << b
|
105
|
+
expect { t << b }.to raise_error(DBus::Type::SignatureException)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "raises if adding to a non-container" do
|
109
|
+
t = DBus::Type.new(DBus::Type::STRING)
|
110
|
+
b = DBus::Type.new(DBus::Type::BOOLEAN)
|
111
|
+
expect { t << b }.to raise_error(DBus::Type::SignatureException)
|
112
|
+
|
113
|
+
t = DBus::Type.new(DBus::Type::VARIANT)
|
114
|
+
expect { t << b }.to raise_error(DBus::Type::SignatureException)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe DBus::Type::Array do
|
119
|
+
describe ".[]" do
|
120
|
+
it "takes Type argument" do
|
121
|
+
t = DBus::Type::Array[DBus::Type.new("s")]
|
122
|
+
expect(t.to_s).to eq "as"
|
123
|
+
end
|
124
|
+
|
125
|
+
it "takes 's':String argument" do
|
126
|
+
t = DBus::Type::Array["s"]
|
127
|
+
expect(t.to_s).to eq "as"
|
128
|
+
end
|
129
|
+
|
130
|
+
it "takes String:Class argument" do
|
131
|
+
t = DBus::Type::Array[String]
|
132
|
+
expect(t.to_s).to eq "as"
|
133
|
+
end
|
134
|
+
|
135
|
+
it "rejects Integer:Class argument" do
|
136
|
+
expect { DBus::Type::Array[Integer] }.to raise_error(ArgumentError)
|
137
|
+
end
|
138
|
+
|
139
|
+
it "rejects /./:Regexp argument" do
|
140
|
+
expect { DBus::Type::Array[/./] }.to raise_error(ArgumentError)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
describe DBus::Type::Hash do
|
146
|
+
describe ".[]" do
|
147
|
+
it "takes Type arguments" do
|
148
|
+
t = DBus::Type::Hash[DBus::Type.new("s"), DBus::Type.new("v")]
|
149
|
+
expect(t.to_s).to eq "a{sv}"
|
150
|
+
end
|
151
|
+
|
152
|
+
it "takes 's':String arguments" do
|
153
|
+
t = DBus::Type::Hash["s", "v"]
|
154
|
+
expect(t.to_s).to eq "a{sv}"
|
155
|
+
end
|
156
|
+
|
157
|
+
it "takes String:Class argument" do
|
158
|
+
t = DBus::Type::Hash[String, DBus::Type::VARIANT]
|
159
|
+
expect(t.to_s).to eq "a{sv}"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe DBus::Type::Struct do
|
165
|
+
describe ".[]" do
|
166
|
+
it "takes Type arguments" do
|
167
|
+
t = DBus::Type::Struct[DBus::Type.new("s"), DBus::Type.new("v")]
|
168
|
+
expect(t.to_s).to eq "(sv)"
|
169
|
+
end
|
170
|
+
|
171
|
+
it "takes 's':String arguments" do
|
172
|
+
t = DBus::Type::Struct["s", "v"]
|
173
|
+
expect(t.to_s).to eq "(sv)"
|
174
|
+
end
|
175
|
+
|
176
|
+
it "takes String:Class argument" do
|
177
|
+
t = DBus::Type::Struct[String, DBus::Type::VARIANT]
|
178
|
+
expect(t.to_s).to eq "(sv)"
|
179
|
+
end
|
180
|
+
|
181
|
+
it "raises on no arguments" do
|
182
|
+
expect { DBus::Type::Struct[] }.to raise_error(ArgumentError)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
82
187
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-dbus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.18.0.
|
4
|
+
version: 0.18.0.beta5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ruby DBus Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-04-
|
11
|
+
date: 2022-04-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rexml
|