ruby-dbus 0.18.0.beta4 → 0.18.0.beta7
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 +40 -0
- data/VERSION +1 -1
- data/doc/Reference.md +13 -4
- data/lib/dbus/data.rb +229 -152
- data/lib/dbus/introspect.rb +13 -3
- data/lib/dbus/marshall.rb +12 -6
- data/lib/dbus/proxy_object_factory.rb +2 -0
- data/lib/dbus/proxy_object_interface.rb +37 -9
- data/lib/dbus/type.rb +146 -16
- data/lib/dbus/xml.rb +4 -0
- data/spec/data_spec.rb +367 -47
- data/spec/packet_unmarshaller_spec.rb +2 -16
- data/spec/property_spec.rb +50 -3
- data/spec/service_newapi.rb +4 -0
- data/spec/type_spec.rb +145 -0
- metadata +6 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56815cd47f001f19c6d74cc02f0f1017e6e17d8df44e0949f020e4932adbc622
|
4
|
+
data.tar.gz: 4aeda5f0c4972671adf6ae24554aa08ce5e6208846f87f5793562e73b8e7d632
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2432d8ada23410027d00c7995c7514e3e927430844cf037fa8496509c47b10b4f5a431335762206bfc9966724d6d84014f57d9bbe31613bfd253145e25b82b77
|
7
|
+
data.tar.gz: c1b480afebcdaf53b6fbe084f6150b7c9758d1329a207b4941dd8256cbc3786d42341564b3b8220d9e897e7487d281fede15eab8a31d81741582272519e1ac19
|
data/NEWS.md
CHANGED
@@ -2,6 +2,46 @@
|
|
2
2
|
|
3
3
|
## Unreleased
|
4
4
|
|
5
|
+
## Ruby D-Bus 0.18.0.beta7 - 2022-05-29
|
6
|
+
|
7
|
+
API:
|
8
|
+
* DBus.variant(type, value) is deprecated in favor of
|
9
|
+
Data::Variant.new(value, member_type:)
|
10
|
+
|
11
|
+
Bug fixes:
|
12
|
+
* Client-side properties: When calling Properties.Set in
|
13
|
+
ProxyObjectInterface#[]=, use the correct type ([#108][]).
|
14
|
+
|
15
|
+
[#108]: https://github.com/mvidner/ruby-dbus/issues/108
|
16
|
+
|
17
|
+
## Ruby D-Bus 0.18.0.beta6 - 2022-05-25
|
18
|
+
|
19
|
+
API:
|
20
|
+
* Data::Base#value returns plain Ruby types;
|
21
|
+
Data::Container#exact_value contains Data::Base ([#114][]).
|
22
|
+
* Data::Base#initialize and .from_typed allow plain or exact values, validate
|
23
|
+
argument types.
|
24
|
+
* Implement #== (converting) and #eql? (strict) for Data::Base and DBus::Type.
|
25
|
+
|
26
|
+
[#114]: https://github.com/mvidner/ruby-dbus/pull/114
|
27
|
+
|
28
|
+
## Ruby D-Bus 0.18.0.beta5 - 2022-04-27
|
29
|
+
|
30
|
+
API:
|
31
|
+
* DBus::Type instances are frozen.
|
32
|
+
* Data::Container classes (Array, Struct, DictEntry, but not Variant)
|
33
|
+
constructors (#initialize, .from_items, .from_typed) changed to have
|
34
|
+
a *type* argument instead of *member_type* or *member_types*.
|
35
|
+
* Added type factories
|
36
|
+
* Type::Array[type]
|
37
|
+
* Type::Hash[key_type, value_type]
|
38
|
+
* Type::Struct[type1, type2...]
|
39
|
+
|
40
|
+
Bug fixes:
|
41
|
+
* Properties containing Variants would return them doubly wrapped ([#111][]).
|
42
|
+
|
43
|
+
[#111]: https://github.com/mvidner/ruby-dbus/pull/111
|
44
|
+
|
5
45
|
## Ruby D-Bus 0.18.0.beta4 - 2022-04-21
|
6
46
|
|
7
47
|
Bug fixes:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.18.0.
|
1
|
+
0.18.0.beta7
|
data/doc/Reference.md
CHANGED
@@ -166,12 +166,21 @@ D-Bus has stricter typing than Ruby, so the library must decide
|
|
166
166
|
which D-Bus type to choose. Most of the time the choice is dictated
|
167
167
|
by the D-Bus signature.
|
168
168
|
|
169
|
+
For exact representation of D-Bus data types, use subclasses
|
170
|
+
of {DBus::Data::Base}, such as {DBus::Data::Int16} or {DBus::Data::UInt64}.
|
171
|
+
|
169
172
|
##### Variants
|
170
173
|
|
171
174
|
If the signature expects a Variant
|
172
175
|
(which is the case for all Properties!) then an explicit mechanism is needed.
|
173
176
|
|
174
|
-
1.
|
177
|
+
1. Any {DBus::Data::Base}.
|
178
|
+
|
179
|
+
2. A {DBus::Data::Variant} made by {DBus.variant}(signature, value).
|
180
|
+
(Formerly this produced the type+value pair below, now it is just an alias
|
181
|
+
to the Variant constructor.)
|
182
|
+
|
183
|
+
3. A pair [{DBus::Type}, value] specifies to marshall *value* as
|
175
184
|
that specified type.
|
176
185
|
The pair can be produced by {DBus.variant}(signature, value) which
|
177
186
|
gives the same result as [{DBus.type}(signature), value].
|
@@ -181,13 +190,13 @@ If the signature expects a Variant
|
|
181
190
|
|
182
191
|
`foo_i["Bar"] = DBus.variant("au", [0, 1, 1, 2, 3, 5, 8])`
|
183
192
|
|
184
|
-
|
193
|
+
4. Other values are tried to fit one of these:
|
185
194
|
Boolean, Double, Array of Variants, Hash of String keyed Variants,
|
186
195
|
String, Int32, Int64.
|
187
196
|
|
188
|
-
|
197
|
+
5. **Deprecated:** A pair [String, value], where String is a valid
|
189
198
|
signature of a single complete type, marshalls value as that
|
190
|
-
type. This will hit you when you rely on method (
|
199
|
+
type. This will hit you when you rely on method (4) but happen to have
|
191
200
|
a particular string value in an array.
|
192
201
|
|
193
202
|
##### Structs
|
data/lib/dbus/data.rb
CHANGED
@@ -35,7 +35,7 @@ module DBus
|
|
35
35
|
# construct an appropriate {Data::Base} instance.
|
36
36
|
#
|
37
37
|
# @param type [SingleCompleteType,Type]
|
38
|
-
# @param value [::Object]
|
38
|
+
# @param value [::Object,Data::Base] a plain value; exact values also allowed
|
39
39
|
# @return [Data::Base]
|
40
40
|
# @raise TypeError
|
41
41
|
def make_typed(type, value)
|
@@ -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
|
|
@@ -58,15 +58,28 @@ module DBus
|
|
58
58
|
# @!method self.fixed?
|
59
59
|
# @return [Boolean]
|
60
60
|
|
61
|
-
# @return
|
61
|
+
# @return [::Object] a valid value, plain-Ruby typed.
|
62
|
+
# @see Data::Container#exact_value
|
62
63
|
attr_reader :value
|
63
64
|
|
65
|
+
# @!method self.type_code
|
66
|
+
# @return [String] a single-character string, for example "a" for arrays
|
67
|
+
|
64
68
|
# @!method type
|
65
69
|
# @abstract
|
66
70
|
# Note that for Variants type=="v",
|
67
71
|
# for the specific see {Variant#member_type}
|
68
72
|
# @return [Type] the exact type of this value
|
69
73
|
|
74
|
+
# @!method self.from_typed(value, type:)
|
75
|
+
# @param value [::Object]
|
76
|
+
# @param type [Type]
|
77
|
+
# @return [Base]
|
78
|
+
# @api private
|
79
|
+
# Use {Data.make_typed} instead.
|
80
|
+
# Construct an instance of the specific subclass, with a type further
|
81
|
+
# specified in the *type* argument.
|
82
|
+
|
70
83
|
# Child classes must validate *value*.
|
71
84
|
def initialize(value)
|
72
85
|
@value = value
|
@@ -82,7 +95,19 @@ module DBus
|
|
82
95
|
|
83
96
|
# Hash key equality
|
84
97
|
# See https://ruby-doc.org/core-3.0.0/Object.html#method-i-eql-3F
|
85
|
-
|
98
|
+
# Stricter than #== (RSpec: eq), 1==1.0 but 1.eql(1.0)->false
|
99
|
+
def eql?(other)
|
100
|
+
return false unless other.class == self.class
|
101
|
+
|
102
|
+
other.value.eql?(@value)
|
103
|
+
# TODO: this should work, now check derived classes, exact_value
|
104
|
+
end
|
105
|
+
|
106
|
+
# @param type [Type]
|
107
|
+
def self.assert_type_matches_class(type)
|
108
|
+
raise ArgumentError, "Expecting #{type_code.inspect} for class #{self}, got #{type.sigtype.inspect}" \
|
109
|
+
unless type.sigtype == type_code
|
110
|
+
end
|
86
111
|
end
|
87
112
|
|
88
113
|
# A value that is not a {Container}.
|
@@ -103,10 +128,10 @@ module DBus
|
|
103
128
|
end
|
104
129
|
|
105
130
|
# @param value [::Object]
|
106
|
-
# @param
|
131
|
+
# @param type [Type]
|
107
132
|
# @return [Basic]
|
108
|
-
def self.from_typed(value,
|
109
|
-
|
133
|
+
def self.from_typed(value, type:)
|
134
|
+
assert_type_matches_class(type)
|
110
135
|
new(value)
|
111
136
|
end
|
112
137
|
end
|
@@ -132,34 +157,6 @@ module DBus
|
|
132
157
|
end
|
133
158
|
end
|
134
159
|
|
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
160
|
# Format strings for String#unpack, both little- and big-endian.
|
164
161
|
Format = ::Struct.new(:little, :big)
|
165
162
|
|
@@ -398,6 +395,23 @@ module DBus
|
|
398
395
|
end
|
399
396
|
end
|
400
397
|
|
398
|
+
# {DBus::Data::String}, {DBus::Data::ObjectPath}, or {DBus::Data::Signature}.
|
399
|
+
class StringLike < Basic
|
400
|
+
def self.fixed?
|
401
|
+
false
|
402
|
+
end
|
403
|
+
|
404
|
+
def initialize(value)
|
405
|
+
if value.is_a?(self.class)
|
406
|
+
value = value.value
|
407
|
+
else
|
408
|
+
self.class.validate_raw!(value)
|
409
|
+
end
|
410
|
+
|
411
|
+
super(value)
|
412
|
+
end
|
413
|
+
end
|
414
|
+
|
401
415
|
# UTF-8 encoded string.
|
402
416
|
class String < StringLike
|
403
417
|
def self.type_code
|
@@ -477,7 +491,7 @@ module DBus
|
|
477
491
|
Byte
|
478
492
|
end
|
479
493
|
|
480
|
-
# @return [Array<Type>]
|
494
|
+
# @return [::Array<Type>]
|
481
495
|
def self.validate_raw!(value)
|
482
496
|
DBus.types(value)
|
483
497
|
rescue Type::SignatureException => e
|
@@ -494,6 +508,44 @@ module DBus
|
|
494
508
|
end
|
495
509
|
end
|
496
510
|
|
511
|
+
# Contains one or more other values.
|
512
|
+
class Container < Base
|
513
|
+
def self.basic?
|
514
|
+
false
|
515
|
+
end
|
516
|
+
|
517
|
+
def self.fixed?
|
518
|
+
false
|
519
|
+
end
|
520
|
+
|
521
|
+
# For containers, the type varies among instances
|
522
|
+
# @see Base#type
|
523
|
+
attr_reader :type
|
524
|
+
|
525
|
+
# @return something that is, or contains, {Data::Base}.
|
526
|
+
# Er, this docs kinda sucks.
|
527
|
+
def exact_value
|
528
|
+
@value
|
529
|
+
end
|
530
|
+
|
531
|
+
def value
|
532
|
+
@value.map(&:value)
|
533
|
+
end
|
534
|
+
|
535
|
+
# Hash key equality
|
536
|
+
# See https://ruby-doc.org/core-3.0.0/Object.html#method-i-eql-3F
|
537
|
+
# Stricter than #== (RSpec: eq), 1==1.0 but 1.eql(1.0)->false
|
538
|
+
def eql?(other)
|
539
|
+
return false unless other.class == self.class
|
540
|
+
|
541
|
+
other.exact_value.eql?(exact_value)
|
542
|
+
end
|
543
|
+
|
544
|
+
# def ==(other)
|
545
|
+
# eql?(other) || super
|
546
|
+
# end
|
547
|
+
end
|
548
|
+
|
497
549
|
# An Array, or a Dictionary (Hash).
|
498
550
|
class Array < Container
|
499
551
|
def self.type_code
|
@@ -504,44 +556,33 @@ module DBus
|
|
504
556
|
4
|
505
557
|
end
|
506
558
|
|
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
559
|
# TODO: check that Hash keys are basic types
|
521
560
|
# @param mode [:plain,:exact]
|
522
|
-
# @param
|
561
|
+
# @param type [Type]
|
523
562
|
# @param hash [Boolean] are we unmarshalling an ARRAY of DICT_ENTRY
|
524
563
|
# @return [Data::Array]
|
525
|
-
def self.from_items(value, mode:,
|
564
|
+
def self.from_items(value, mode:, type:, hash: false)
|
526
565
|
value = Hash[value] if hash
|
527
566
|
return value if mode == :plain
|
528
567
|
|
529
|
-
new(value,
|
568
|
+
new(value, type: type)
|
530
569
|
end
|
531
570
|
|
532
571
|
# @param value [::Object]
|
533
|
-
# @param
|
572
|
+
# @param type [Type]
|
534
573
|
# @return [Data::Array]
|
535
|
-
def self.from_typed(value,
|
536
|
-
|
537
|
-
|
574
|
+
def self.from_typed(value, type:)
|
575
|
+
new(value, type: type) # initialize(::Array<Data::Base>)
|
576
|
+
end
|
538
577
|
|
539
|
-
|
540
|
-
|
541
|
-
|
578
|
+
def value
|
579
|
+
v = super
|
580
|
+
if type.child.sigtype == Type::DICT_ENTRY
|
581
|
+
# BTW this makes a copy so mutating it is pointless
|
582
|
+
v.to_h
|
583
|
+
else
|
584
|
+
v
|
542
585
|
end
|
543
|
-
|
544
|
-
new(items, member_type: member_type) # initialize(::Array<Data::Base>)
|
545
586
|
end
|
546
587
|
|
547
588
|
# FIXME: should Data::Array be mutable?
|
@@ -550,13 +591,29 @@ module DBus
|
|
550
591
|
# TODO: specify type or guess type?
|
551
592
|
# Data is the exact type, so its constructor should be exact
|
552
593
|
# and guesswork should be clearly labeled
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
594
|
+
|
595
|
+
# @param value [Data::Array,Enumerable]
|
596
|
+
# @param type [SingleCompleteType,Type]
|
597
|
+
def initialize(value, type:)
|
598
|
+
type = Type::Factory.make_type(type)
|
599
|
+
self.class.assert_type_matches_class(type)
|
600
|
+
@type = type
|
601
|
+
|
602
|
+
typed_value = case value
|
603
|
+
when Data::Array
|
604
|
+
unless value.type == type
|
605
|
+
raise ArgumentError,
|
606
|
+
"Specified type is #{type.inspect} but value type is #{value.type.inspect}"
|
607
|
+
end
|
608
|
+
|
609
|
+
value.exact_value
|
610
|
+
else
|
611
|
+
# TODO: Dict??
|
612
|
+
value.map do |i|
|
613
|
+
Data.make_typed(type.child, i)
|
614
|
+
end
|
615
|
+
end
|
616
|
+
super(typed_value)
|
560
617
|
end
|
561
618
|
end
|
562
619
|
|
@@ -572,51 +629,86 @@ module DBus
|
|
572
629
|
8
|
573
630
|
end
|
574
631
|
|
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
632
|
# @param value [::Array]
|
591
|
-
def self.from_items(value, mode:,
|
633
|
+
def self.from_items(value, mode:, type:)
|
592
634
|
value.freeze
|
593
635
|
return value if mode == :plain
|
594
636
|
|
595
|
-
new(value,
|
637
|
+
new(value, type: type)
|
596
638
|
end
|
597
639
|
|
598
640
|
# @param value [::Object] (#size, #each)
|
599
|
-
# @param
|
641
|
+
# @param type [Type]
|
600
642
|
# @return [Struct]
|
601
|
-
def self.from_typed(value,
|
602
|
-
|
603
|
-
|
643
|
+
def self.from_typed(value, type:)
|
644
|
+
new(value, type: type)
|
645
|
+
end
|
646
|
+
|
647
|
+
# @param value [Data::Struct,Enumerable]
|
648
|
+
# @param type [SingleCompleteType,Type]
|
649
|
+
def initialize(value, type:)
|
650
|
+
type = Type::Factory.make_type(type)
|
651
|
+
self.class.assert_type_matches_class(type)
|
652
|
+
@type = type
|
653
|
+
|
654
|
+
typed_value = case value
|
655
|
+
when self.class
|
656
|
+
unless value.type == type
|
657
|
+
raise ArgumentError,
|
658
|
+
"Specified type is #{type.inspect} but value type is #{value.type.inspect}"
|
659
|
+
end
|
660
|
+
|
661
|
+
value.exact_value
|
662
|
+
else
|
663
|
+
member_types = type.members
|
664
|
+
unless value.size == member_types.size
|
665
|
+
raise ArgumentError, "Specified type has #{member_types.size} members " \
|
666
|
+
"but value has #{value.size} members"
|
667
|
+
end
|
668
|
+
|
669
|
+
member_types.zip(value).map do |item_type, item|
|
670
|
+
Data.make_typed(item_type, item)
|
671
|
+
end
|
672
|
+
end
|
673
|
+
super(typed_value)
|
674
|
+
end
|
604
675
|
|
605
|
-
|
606
|
-
|
676
|
+
def ==(other)
|
677
|
+
case other
|
678
|
+
when ::Struct
|
679
|
+
@value.size == other.size &&
|
680
|
+
@value.zip(other.to_a).all? { |i, other_i| i == other_i }
|
681
|
+
else
|
682
|
+
super
|
607
683
|
end
|
684
|
+
end
|
685
|
+
end
|
608
686
|
|
609
|
-
|
687
|
+
# Dictionary/Hash entry.
|
688
|
+
# TODO: shouldn't instantiate?
|
689
|
+
class DictEntry < Struct
|
690
|
+
def self.type_code
|
691
|
+
"e"
|
610
692
|
end
|
611
693
|
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
694
|
+
# @param value [::Array]
|
695
|
+
def self.from_items(value, mode:, type:) # rubocop:disable Lint/UnusedMethodArgument
|
696
|
+
value.freeze
|
697
|
+
# DictEntry ignores the :exact mode
|
698
|
+
value
|
699
|
+
end
|
700
|
+
|
701
|
+
# @param value [::Object] (#size, #each)
|
702
|
+
# @param type [Type]
|
703
|
+
# @return [DictEntry]
|
704
|
+
def self.from_typed(value, type:)
|
705
|
+
new(value, type: type)
|
616
706
|
end
|
617
707
|
end
|
618
708
|
|
619
|
-
# A generic type
|
709
|
+
# A generic type.
|
710
|
+
#
|
711
|
+
# Implementation note: @value is a {Data::Base}.
|
620
712
|
class Variant < Container
|
621
713
|
def self.type_code
|
622
714
|
"v"
|
@@ -626,6 +718,10 @@ module DBus
|
|
626
718
|
1
|
627
719
|
end
|
628
720
|
|
721
|
+
def value
|
722
|
+
@value.value
|
723
|
+
end
|
724
|
+
|
629
725
|
# @param member_type [Type]
|
630
726
|
def self.from_items(value, mode:, member_type:)
|
631
727
|
return value if mode == :plain
|
@@ -634,12 +730,12 @@ module DBus
|
|
634
730
|
end
|
635
731
|
|
636
732
|
# @param value [::Object]
|
637
|
-
# @param
|
733
|
+
# @param type [Type]
|
638
734
|
# @return [Variant]
|
639
|
-
def self.from_typed(value,
|
640
|
-
|
735
|
+
def self.from_typed(value, type:)
|
736
|
+
assert_type_matches_class(type)
|
641
737
|
|
642
|
-
# decide on type of value
|
738
|
+
# nil: decide on type of value
|
643
739
|
new(value, member_type: nil)
|
644
740
|
end
|
645
741
|
|
@@ -659,78 +755,59 @@ module DBus
|
|
659
755
|
# @return [Type]
|
660
756
|
attr_reader :member_type
|
661
757
|
|
758
|
+
# Determine the type of *value*
|
759
|
+
# @param value [::Object]
|
760
|
+
# @return [Type]
|
761
|
+
# @api private
|
762
|
+
# See also {PacketMarshaller.make_variant}
|
662
763
|
def self.guess_type(value)
|
663
764
|
sct, = PacketMarshaller.make_variant(value)
|
664
765
|
DBus.type(sct)
|
665
766
|
end
|
666
767
|
|
667
|
-
# @param member_type [Type,nil]
|
768
|
+
# @param member_type [SingleCompleteType,Type,nil]
|
668
769
|
def initialize(value, member_type:)
|
770
|
+
member_type = Type::Factory.make_type(member_type) if member_type
|
669
771
|
# TODO: validate that the given *member_type* matches *value*
|
670
|
-
|
772
|
+
case value
|
773
|
+
when Data::Variant
|
671
774
|
# Copy the contained value instead of boxing it more
|
672
775
|
# TODO: except perhaps for round-tripping in exact mode?
|
673
776
|
@member_type = value.member_type
|
674
|
-
value = value.
|
777
|
+
value = value.exact_value
|
778
|
+
when Data::Base
|
779
|
+
@member_type = member_type || value.type
|
780
|
+
raise ArgumentError, "Variant type #{@member_type} does not match value type #{value.type}" \
|
781
|
+
unless @member_type == value.type
|
675
782
|
else
|
676
783
|
@member_type = member_type || self.class.guess_type(value)
|
784
|
+
value = Data.make_typed(@member_type, value)
|
677
785
|
end
|
678
786
|
super(value)
|
679
787
|
end
|
680
|
-
end
|
681
788
|
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
def
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
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
|
789
|
+
# Internal helpers to keep the {DBus.variant} method working.
|
790
|
+
# Formerly it returned just a pair of [DBus.type(string_type), value]
|
791
|
+
# so let's provide [0], [1], .first, .last
|
792
|
+
def [](index)
|
793
|
+
case index
|
794
|
+
when 0
|
795
|
+
member_type
|
796
|
+
when 1
|
797
|
+
value
|
798
|
+
else
|
799
|
+
raise ArgumentError, "DBus.variant can only be indexed with 0 or 1, seen #{index.inspect}"
|
703
800
|
end
|
704
|
-
@type
|
705
|
-
end
|
706
|
-
|
707
|
-
# @param value [::Array]
|
708
|
-
def self.from_items(value, mode:, member_types:) # rubocop:disable Lint/UnusedMethodArgument
|
709
|
-
value.freeze
|
710
|
-
# DictEntry ignores the :exact mode
|
711
|
-
value
|
712
801
|
end
|
713
802
|
|
714
|
-
# @
|
715
|
-
|
716
|
-
|
717
|
-
def self.from_typed(value, member_types:)
|
718
|
-
# assert member_types.size == 2
|
719
|
-
# TODO: duplicated from Struct. Inherit/delegate?
|
720
|
-
# TODO: validation
|
721
|
-
raise unless value.size == member_types.size
|
722
|
-
|
723
|
-
items = member_types.zip(value).map do |item_type, item|
|
724
|
-
Data.make_typed(item_type, item)
|
725
|
-
end
|
726
|
-
|
727
|
-
new(items, member_types: member_types) # initialize(::Array<Data::Base>)
|
803
|
+
# @see #[]
|
804
|
+
def first
|
805
|
+
self[0]
|
728
806
|
end
|
729
807
|
|
730
|
-
|
731
|
-
|
732
|
-
|
733
|
-
super(value)
|
808
|
+
# @see #[]
|
809
|
+
def last
|
810
|
+
self[1]
|
734
811
|
end
|
735
812
|
end
|
736
813
|
|
data/lib/dbus/introspect.rb
CHANGED
@@ -238,19 +238,20 @@ module DBus
|
|
238
238
|
# An (exported) property
|
239
239
|
# https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties
|
240
240
|
class Property
|
241
|
-
# @return [
|
241
|
+
# @return [Symbol] The name of the property, for example FooBar.
|
242
242
|
attr_reader :name
|
243
243
|
# @return [SingleCompleteType]
|
244
244
|
attr_reader :type
|
245
245
|
# @return [Symbol] :read :write or :readwrite
|
246
246
|
attr_reader :access
|
247
247
|
|
248
|
-
# @return [Symbol] What to call at Ruby side.
|
248
|
+
# @return [Symbol,nil] What to call at Ruby side.
|
249
249
|
# (Always without the trailing `=`)
|
250
|
+
# It is `nil` IFF representing a client-side proxy.
|
250
251
|
attr_reader :ruby_name
|
251
252
|
|
252
253
|
def initialize(name, type, access, ruby_name:)
|
253
|
-
@name = name
|
254
|
+
@name = name.to_sym
|
254
255
|
@type = type
|
255
256
|
@access = access
|
256
257
|
@ruby_name = ruby_name
|
@@ -270,5 +271,14 @@ module DBus
|
|
270
271
|
def to_xml
|
271
272
|
" <property type=\"#{@type}\" name=\"#{@name}\" access=\"#{@access}\"/>\n"
|
272
273
|
end
|
274
|
+
|
275
|
+
# @param xml_node [AbstractXML::Node]
|
276
|
+
# @return [Property]
|
277
|
+
def self.from_xml(xml_node)
|
278
|
+
name = xml_node["name"].to_sym
|
279
|
+
type = xml_node["type"]
|
280
|
+
access = xml_node["access"].to_sym
|
281
|
+
new(name, type, access, ruby_name: nil)
|
282
|
+
end
|
273
283
|
end
|
274
284
|
end
|