ruby-dbus 0.18.0.beta3 → 0.18.0.beta6

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.
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
- # = D-Bus type module
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,32 @@ 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
108
+ end
109
+
110
+ # A Type is equal to
111
+ # - another Type with the same string representation
112
+ # - a String ({SingleCompleteType}) describing the type
113
+ def ==(other)
114
+ case other
115
+ when ::String
116
+ to_s == other
117
+ else
118
+ eql?(other)
119
+ end
120
+ end
121
+
122
+ # A Type is eql? to
123
+ # - another Type with the same string representation
124
+ #
125
+ # Hash key equality
126
+ # See https://ruby-doc.org/core-3.0.0/Object.html#method-i-eql-3F
127
+ def eql?(other)
128
+ return false unless other.is_a?(Type)
129
+
130
+ @sigtype == other.sigtype && @members == other.members
109
131
  end
110
132
 
111
133
  # Return the required alignment for the type.
@@ -124,16 +146,15 @@ module DBus
124
146
  when DICT_ENTRY
125
147
  "{#{@members.collect(&:to_s).join}}"
126
148
  else
127
- if !TYPE_MAPPING.keys.member?(@sigtype)
128
- raise NotImplementedError
129
- end
130
-
131
149
  @sigtype.chr
132
150
  end
133
151
  end
134
152
 
135
153
  # Add a new member type _item_.
154
+ # @param item [Type]
136
155
  def <<(item)
156
+ raise ArgumentError unless item.is_a?(Type)
157
+
137
158
  if ![STRUCT, ARRAY, DICT_ENTRY].member?(@sigtype)
138
159
  raise SignatureException
139
160
  end
@@ -159,7 +180,7 @@ module DBus
159
180
 
160
181
  def inspect
161
182
  s = TYPE_MAPPING[@sigtype].first
162
- if [STRUCT, ARRAY].member?(@sigtype)
183
+ if [STRUCT, ARRAY, DICT_ENTRY].member?(@sigtype)
163
184
  s += ": #{@members.inspect}"
164
185
  end
165
186
  s
@@ -232,6 +253,7 @@ module DBus
232
253
  else
233
254
  res = Type.new(char)
234
255
  end
256
+ res.members.freeze
235
257
  res
236
258
  end
237
259
 
@@ -243,7 +265,7 @@ module DBus
243
265
  while (c = nextchar)
244
266
  ret << parse_one(c)
245
267
  end
246
- ret
268
+ ret.freeze
247
269
  end
248
270
 
249
271
  # Parse one {SingleCompleteType}
@@ -255,9 +277,116 @@ module DBus
255
277
  t = parse_one(c)
256
278
  raise SignatureException, "Has more than a Single Complete Type: #{@signature}" unless nextchar.nil?
257
279
 
280
+ t.freeze
281
+ end
282
+ end
283
+
284
+ class Factory
285
+ # @param type [Type,SingleCompleteType,Class]
286
+ # @see from_plain_class
287
+ # @return [Type] (frozen)
288
+ def self.make_type(type)
289
+ case type
290
+ when Type
291
+ type
292
+ when String
293
+ DBus.type(type)
294
+ when Class
295
+ from_plain_class(type)
296
+ else
297
+ msg = "Expecting DBus::Type, DBus::SingleCompleteType(aka ::String), or Class, got #{type.inspect}"
298
+ raise ArgumentError, msg
299
+ end
300
+ end
301
+
302
+ # Make a {Type} corresponding to some plain classes:
303
+ # - String
304
+ # - Float
305
+ # - DBus::ObjectPath
306
+ # - DBus::Signature, DBus::SingleCompleteType
307
+ # @param klass [Class]
308
+ # @return [Type] (frozen)
309
+ def self.from_plain_class(klass)
310
+ @signature_type ||= DBus.type(SIGNATURE)
311
+ @class_to_type ||= {
312
+ DBus::ObjectPath => DBus.type(OBJECT_PATH),
313
+ DBus::Signature => @signature_type,
314
+ DBus::SingleCompleteType => @signature_type,
315
+ String => DBus.type(STRING),
316
+ Float => DBus.type(DOUBLE)
317
+ }
318
+ t = @class_to_type[klass]
319
+ raise ArgumentError, "Cannot convert plain class #{klass} to a D-Bus type" if t.nil?
320
+
258
321
  t
259
322
  end
260
323
  end
324
+
325
+ # Syntactic helper for constructing an array Type.
326
+ # You may be looking for {Data::Array} instead.
327
+ # @example
328
+ # t = Type::Array[Type::INT16]
329
+ class ArrayFactory < Factory
330
+ # @param member_type [Type,SingleCompleteType]
331
+ # @return [Type] (frozen)
332
+ def self.[](member_type)
333
+ t = Type.new(ARRAY)
334
+ t << make_type(member_type)
335
+ t.members.freeze
336
+ t
337
+ end
338
+ end
339
+
340
+ # @example
341
+ # t = Type::Array[Type::INT16]
342
+ Array = ArrayFactory
343
+
344
+ # Syntactic helper for constructing a hash Type.
345
+ # You may be looking for {Data::Array} and {Data::DictEntry} instead.
346
+ # @example
347
+ # t = Type::Hash[Type::STRING, Type::VARIANT]
348
+ class HashFactory < Factory
349
+ # @param key_type [Type,SingleCompleteType]
350
+ # @param value_type [Type,SingleCompleteType]
351
+ # @return [Type] (frozen)
352
+ def self.[](key_type, value_type)
353
+ t = Type.new(ARRAY)
354
+ de = Type.new(DICT_ENTRY, abstract: true)
355
+ de << make_type(key_type)
356
+ de << make_type(value_type)
357
+ de.members.freeze
358
+ t << de
359
+ t.members.freeze
360
+ t
361
+ end
362
+ end
363
+
364
+ # @example
365
+ # t = Type::Hash[Type::INT16]
366
+ Hash = HashFactory
367
+
368
+ # Syntactic helper for constructing a struct Type.
369
+ # You may be looking for {Data::Struct} instead.
370
+ # @example
371
+ # t = Type::Struct[Type::INT16, Type::STRING]
372
+ class StructFactory < Factory
373
+ # @param member_types [::Array<Type,SingleCompleteType>]
374
+ # @return [Type] (frozen)
375
+ def self.[](*member_types)
376
+ raise ArgumentError if member_types.empty?
377
+
378
+ t = Type.new(STRUCT, abstract: true)
379
+ member_types.each do |mt|
380
+ t << make_type(mt)
381
+ end
382
+ t.members.freeze
383
+ t
384
+ end
385
+ end
386
+
387
+ # @example
388
+ # t = Type::Struct[Type::INT16, Type::STRING]
389
+ Struct = StructFactory
261
390
  end
262
391
 
263
392
  # shortcuts
@@ -266,7 +395,7 @@ module DBus
266
395
  # This is prefered to {Type#initialize} which allows
267
396
  # incomplete or invalid types.
268
397
  # @param string_type [SingleCompleteType]
269
- # @return [DBus::Type]
398
+ # @return [DBus::Type] (frozen)
270
399
  # @raise SignatureException
271
400
  def type(string_type)
272
401
  Type::Parser.new(string_type).parse1
@@ -275,7 +404,7 @@ module DBus
275
404
 
276
405
  # Parse a String to zero or more {DBus::Type}s.
277
406
  # @param string_type [Signature]
278
- # @return [Array<DBus::Type>]
407
+ # @return [Array<DBus::Type>] (frozen)
279
408
  # @raise SignatureException
280
409
  def types(string_type)
281
410
  Type::Parser.new(string_type).parse
@@ -1534,6 +1534,34 @@
1534
1534
  - [0xDE, 0xAD, 0xBE, 0xEF]
1535
1535
  exc: DBus::InvalidPacketException
1536
1536
  msg: ''
1537
+ - sig: a{oq}
1538
+ end: little
1539
+ buf:
1540
+ # body size
1541
+ - [0, 0, 0, 0]
1542
+ # padding
1543
+ - [0, 0, 0, 0]
1544
+ val: {}
1545
+ - sig: a{oq}
1546
+ end: little
1547
+ buf:
1548
+ # body size
1549
+ - [26, 0, 0, 0]
1550
+ # dict_entry padding
1551
+ - [0, 0, 0, 0]
1552
+ # key, padding, value
1553
+ - [2, 0, 0, 0, "/7", 0]
1554
+ - 0
1555
+ - [7, 0]
1556
+ # dict_entry padding
1557
+ - [0, 0, 0, 0, 0, 0]
1558
+ # key, padding, value
1559
+ - [2, 0, 0, 0, "/9", 0]
1560
+ - 0
1561
+ - [9, 0]
1562
+ val:
1563
+ /7: 7
1564
+ /9: 9
1537
1565
  - sig: "(qq)"
1538
1566
  end: little
1539
1567
  buf: