enums 1.3.0 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 21d675f9ace380c191b6ee58c484ab192dbdb440
4
- data.tar.gz: 42c0d89f1a150c48a432b3c2d1b1fbbe00ac1aa0
3
+ metadata.gz: 65a45b808ac04efdf1cf4b9b299b61882d691605
4
+ data.tar.gz: fc6259850c15fe3f81ee5d8e2bebf4d40f0a754f
5
5
  SHA512:
6
- metadata.gz: f990e4ab5fcc741b1226a3f4eb0d8f9e53f8b2b446d1c8175a4f8bd3464d6fcde42a59cc966735bd2216abc4ec397fd3f043c89254815209c7c61fd0464459ba
7
- data.tar.gz: 22ff3b44aea19efd814a45f3ad46184bfaf9df24bbb3e23bb306b91b9f068ff68381de7404293ecb47d5e8b8e6e8d669d92f184d2adcd36ff372740b2c35ce57
6
+ metadata.gz: f4875a80e70ac8099ce8b79b92ec6385edced9606a4e873c2ffd3709dd2d454d6057c4aab302c5fa6f4a78999dd79bf36a0fc910ee216af1bbdaaccdc764f25a
7
+ data.tar.gz: 38c9a7a44081ecad43ebd9431c3149f48632466499dfea0029532dd036013e8a59add6cd33996cd96cccd61c170e24d3b7ad8803fb41c5c39359d71e20556ba1
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Enums - Safe Enumeration Types
2
2
 
3
- enums library / gem - safe enumeration types - a set of symbolic keys bound to unique integer numbers
3
+ enums library / gem - safe enumeration types - a set of symbolic keys bound to unique integer numbers (incl. bit flags option)
4
4
 
5
5
  * home :: [github.com/s6ruby/enums](https://github.com/s6ruby/enums)
6
6
  * bugs :: [github.com/s6ruby/enums/issues](https://github.com/s6ruby/enums/issues)
@@ -50,7 +50,7 @@ enum :Color, :red, :green, :blue
50
50
  # or
51
51
  enum :Color, [:red, :green, :blue]
52
52
  # or
53
- enum :Color, { red: 0,
53
+ enum :Color, { red: 0,
54
54
  green: 1,
55
55
  blue: 2 }
56
56
 
@@ -149,8 +149,8 @@ enum :State, :fundraising, :expired_refund, :successful
149
149
  # or
150
150
  enum :State, [:fundraising, :expired_refund, :successful]
151
151
  # or
152
- enum :State, { fundraising: 0,
153
- expired_refund: 1,
152
+ enum :State, { fundraising: 0,
153
+ expired_refund: 1,
154
154
  successful: 2 }
155
155
 
156
156
 
@@ -231,21 +231,25 @@ end
231
231
 
232
232
  class FileAttrib < Flag
233
233
 
234
+ NONE = new( :none, 0 )
234
235
  READ_ONLY = new( :read_only, 1<<0 )
235
236
  HIDDEN = new( :hidden, 1<<1 )
236
237
  SYSTEM = new( :system, 1<<2 )
237
238
  ARCHIVE = new( :archive, 1<<3 )
239
+ ALL = new( :all, 1<<0|1<<1|1<<2|1<<3 )
238
240
 
241
+ def self.none() NONE; end
239
242
  def self.read_only() READ_ONLY; end
240
243
  def self.hidden() HIDDEN; end
241
244
  def self.system() SYSTEM; end
242
245
  def self.archive() ARCHIVE; end
246
+ def self.all() ALL; end
243
247
 
244
248
  def self.values() [1<<0,1<<1,1<<2,1<<3]; end
245
249
  def self.keys() [:read_only, :hidden, :system, :archive]; end
246
250
  def self.members() [READ_ONLY, HIDDEN, SYSTEM, ARCHIVE]; end
247
251
 
248
- def self.zero() @zero ||= new(0); end
252
+ def self.zero() NONE; end
249
253
 
250
254
  def self.key( key )
251
255
  @hash_by_key ||= Hash[ keys.zip( members ) ]
@@ -253,10 +257,12 @@ class FileAttrib < Flag
253
257
  end
254
258
  def self.[]( key ) self.key( key ); end
255
259
 
256
- def read_only?() member?( READ_ONLY ); end
257
- def hidden?() member?( HIDDEN ); end
258
- def system?() member?( SYSTEM ); end
259
- def archive?() member?( ARCHIVE ); end
260
+ def none? @value == 0; end
261
+ def read_only?() @value & 1<<0 == 1<<0; end
262
+ def hidden?() @value & 1<<1 == 1<<1; end
263
+ def system?() @value & 1<<2 == 1<<2; end
264
+ def archive?() @value & 1<<3 == 1<<3; end
265
+ def all?() @value == 1<<0|1<<1|1<<2|1<<3; end
260
266
 
261
267
  def member?( other ) @value & other.value == other.value; end
262
268
 
@@ -284,15 +290,11 @@ class FileAttrib < Flag
284
290
  alias_method :toggle, :bitwise_xor
285
291
 
286
292
  # ...
287
-
288
- def initialize( *args )
289
- # ...
290
- end
291
293
  end
292
294
 
293
295
 
294
296
  def FileAttrib( *args )
295
- FileAttrib.new( *args )
297
+ FileAttrib.convert( *args )
296
298
  end
297
299
  ```
298
300
 
@@ -306,20 +308,16 @@ FileAttrib.read_only #=> <FileAttrib @key=:read_only, @valu
306
308
  FileAttrib::READ_ONLY #=> <FileAttrib @key=:read_only, @value=1>
307
309
  FileAttribs[:read_only] #=> <FileAttrib @key=:read_only, @value=1>
308
310
 
309
- FileAttrib(0) #=> <FileAttrib @key=:0000, @value=0>
311
+ FileAttrib(0) #=> <FileAttrib @key=:none, @value=0>
310
312
  FileAttrib.read_only | FileAttrib.hidden #=> <FileAttrib @key=:0011, @value=3>
311
313
  # -or-
312
- FileAttrib.new( FileAttrib.read_only | FileAttrib.hidden )
313
- FileAttrib.new( FileAttrib::READ_ONLY | FileAttrib::HIDDEN )
314
- FileAttrib.new( :read_only, :hidden )
315
- # -or-
316
314
  FileAttrib( FileAttrib.read_only | FileAttrib.hidden )
317
315
  FileAttrib( FileAttrib::READ_ONLY | FileAttrib::HIDDEN )
318
316
  FileAttrib( :read_only, :hidden )
319
317
  #=> <FileAttrib @key=:0011, @value=3>
320
318
 
321
- attrib = FileAttrib.new #=> <FileAttrib @key=:0000, @value=0>
322
- attrib |= FileAttrib.read_only #=> <FileAttrib @key=:0001, @value=1>
319
+ attrib = FileAttrib.none #=> <FileAttrib @key=:none, @value=0>
320
+ attrib |= FileAttrib.read_only #=> <FileAttrib @key=:read_only, @value=1>
323
321
  attrib.read_only? #=> true
324
322
  # -or-
325
323
  attrib.member?( FileAttrib.read_only ) #=> true
@@ -327,12 +325,12 @@ attrib.member?( FileAttrib.READ_ONLY ) #=> true
327
325
  attrib.member?( :read_only ) #=> true
328
326
  attrib & FileAttrib.read_only == FileAttrib.read_only #=> true
329
327
 
330
- attrib ^= FileAttrib.read_only #=> <FileAttrib @key=:0000, @value=0>
328
+ attrib ^= FileAttrib.read_only #=> <FileAttrib @key=:none, @value=0>
331
329
  attrib.read_only? #=> false
332
- attrib ^= FileAttrib.read_only #=> <FileAttrib @key=:0001, @value=1>
330
+ attrib ^= FileAttrib.read_only #=> <FileAttrib @key=:read_ony, @value=1>
333
331
  attrib.read_only? #=> true
334
332
 
335
- attrib &= ~FileAttrib.read_only #=> <FileAttrib @key=:0000, @value=0>
333
+ attrib &= ~FileAttrib.read_only #=> <FileAttrib @key=:none, @value=0>
336
334
  attrib.read_only? #=> false
337
335
 
338
336
  attrib.is_a? Flag #=> true
@@ -340,6 +338,66 @@ attrib.is_a? FileAttrib #=> true
340
338
  # ...
341
339
  ```
342
340
 
341
+
342
+ Let's try another example:
343
+
344
+ ``` ruby
345
+ Flag.new( :TextStyle, :bold, :italic, :underline )
346
+ # -or -
347
+ enum :TextStyle, [:bold, :italic, :underline], flags: true
348
+ # -or -
349
+ enum :TextStyle, :bold, :italic, :underline, flags: true
350
+ # -or -
351
+ enum :TextStyle, { bold: 1<<0,
352
+ italic: 1<<1,
353
+ underline: 1<<2
354
+ },
355
+ flags: true
356
+
357
+
358
+ TextStyle.values #=> [1, 2, 4]
359
+ TextStyle.keys #=> [:bold, :italic, :underline]
360
+
361
+ TextStyle.bold #=> <TextStyle @key=:bold, @value=1>
362
+ TextStyle::BOLD #=> <TextStyle @key=:bold, @value=1>
363
+ TextStyle[:bold] #=> <TextStyle @key=:bold, @value=1>
364
+
365
+ TextStyle(0) #=> <TextStyle @key=:none, @value=0>
366
+ TextStyle.bold | TextStyle.italic #=> <TextStyle @key=:0011, @value=3>
367
+ # -or-
368
+ TextStyle( TextStyle.bold | TextStyle.italic )
369
+ TextStyle( TextStyle::BOLD | TextStyle::ITALIC )
370
+ TextStyle( :bold, :italic )
371
+ #=> <TextStyle @key=:0011, @value=3>
372
+
373
+ style = TextStyle.none #=> <TextStyle @key=:none, @value=0>
374
+ style |= TextStyle.bold #=> <TextStyle @key=:bold, @value=1>
375
+ style.bold? #=> true
376
+ # -or-
377
+ style.member?( TextStyle.bold ) #=> true
378
+ style.member?( TextStyle.BOLD ) #=> true
379
+ style.member?( :bold ) #=> true
380
+ style & TextStyle.bold == TextStyle.bold #=> true
381
+
382
+ style ^= TextStyle.bold #=> <TextStyle @key=:none, @value=0>
383
+ style.bold? #=> false
384
+ style ^= TextStyle.bold #=> <TextStyle @key=:bold, @value=1>
385
+ style.bold? #=> true
386
+
387
+ style &= ~TextStyle.bold #=> <TextStyle @key=:none, @value=0>
388
+ style.bold? #=> false
389
+
390
+ style = TextStyle.bold | TextStyle.italic | TextStyle.underline
391
+ #=> <TextStyle @key=:all, @value=7>
392
+ style & TextStyle.all == TextStyle.all #=> true
393
+ style & TextStyle.all != 0 #=> true
394
+ style.all? #=> true
395
+
396
+ style.is_a? Flag #=> true
397
+ style.is_a? TextStyle #=> true
398
+ # ...
399
+ ```
400
+
343
401
  and so on.
344
402
 
345
403
 
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ Hoe.spec 'enums' do
5
5
 
6
6
  self.version = Enums::VERSION
7
7
 
8
- self.summary = "enums - safe enumeration types - a set of symbolic keys bound to unique integer numbers"
8
+ self.summary = "enums - safe enumeration types - a set of symbolic keys bound to unique integer numbers (incl. bit flags option)"
9
9
  self.description = summary
10
10
 
11
11
  self.urls = ['https://github.com/s6ruby/enums']
@@ -10,47 +10,32 @@ class Flag
10
10
  attr_reader :key
11
11
  attr_reader :value
12
12
 
13
- def initialize( *args )
14
- fmt = "%08b"
15
-
16
- if args.size == 0
17
- @value = 0 ## same as new(0)
18
- @key = :"#{fmt % @value}" ## use :none for 0 key - why? why not?
19
- elsif args.size == 1 && args[0].is_a?(Integer)
20
- @value = args[0]
21
- @key = :"#{fmt % @value}" ## todo: lookup if value is a known flag (with key) - why? why not?
22
- elsif args.size == 2 && args[0].is_a?(Symbol) && args[1].is_a?(Integer)
23
- @key = args[0]
24
- @value = args[1]
25
- else
26
- ## assume flag object or symbols
27
- @value = 0
28
- args.each do |arg|
29
- flag = _typecast_flag!( arg )
30
- @value |= flag.value
31
- end
32
- @key = :"#{fmt % @value}" ## todo: lookup if value is a known flag (with key) - why? why not?
33
- end
34
- self.freeze ## make "immutable" - should be a value object like an integer number!!!
35
- self # return self for chaining
13
+ def initialize( key, value )
14
+ @key = key
15
+ @value = value
16
+ self.freeze
17
+ self
36
18
  end
37
19
 
38
-
39
- def _typecheck_flag!( o )
40
- if self.class == o.class
20
+ def self._typecheck_flag!( o )
21
+ if self == o.class
41
22
  o
42
23
  else
43
- raise TypeError.new( "[Flag] flag >#{self.class.name}< type expected; got >#{o.class.inspect}<" )
24
+ raise TypeError.new( "[Flag] flag >#{name}< type expected; got >#{o.class.inspect}<" )
44
25
  end
45
26
  end
46
27
 
47
- def _typecast_flag!( o )
28
+ def self._typecast_flag!( o )
48
29
  if o.is_a? Symbol ## auto-convert symbol to flag
49
- o = self.class.key( o ) ## lookup symbol in "parent" flags class
30
+ o = key( o ) ## lookup symbol in "parent" flags class
50
31
  end
51
32
  _typecheck_flag!( o )
52
33
  end
53
34
 
35
+ def _typecheck_flag!( o ) self.class._typecheck_flag!( o ); end
36
+ def _typecast_flag!( o ) self.class._typecast_flag!( o ); end
37
+
38
+
54
39
 
55
40
  def ==( other )
56
41
  if self.class == other.class
@@ -64,56 +49,58 @@ class Flag
64
49
  alias_method :eql?, :==
65
50
 
66
51
 
67
- def member?( other ) _member?(_typecast_flag!( other )); end
68
- def _member?( other ) @value & other.value == other.value; end
52
+ def member?( other )
53
+ other = _typecast_flag!( other )
54
+ @value & other.value == other.value
55
+ end
69
56
 
70
57
 
71
58
  def bitwise_or( other )
72
- self.class.new( @value | _typecheck_flag!( other ).value )
59
+ self.class.build( @value | _typecheck_flag!( other ).value )
73
60
  end
74
- alias_method :|, :bitwise_or
61
+ alias_method :|, :bitwise_or
75
62
 
76
63
  def bitwise_and( other )
77
- self.class.new( @value & _typecheck_flag!( other ).value )
64
+ self.class.build( @value & _typecheck_flag!( other ).value )
78
65
  end
79
66
  alias_method :&, :bitwise_and
80
67
 
81
68
  def bitwise_xor( other )
82
- self.class.new( @value ^ _typecheck_flag!( other ).value )
69
+ self.class.build( @value ^ _typecheck_flag!( other ).value )
83
70
  end
84
- alias_method :^, :bitwise_xor
71
+ alias_method :^, :bitwise_xor
85
72
 
86
73
  def bitwise_inverse
87
- self.class.new( ~@value )
74
+ self.class.build( ~@value )
88
75
  end
89
76
  alias_method :~, :bitwise_inverse
90
77
 
91
78
 
92
79
  def set( other ) ## note: typecast also allows symbol e.g (:read_only, etc.)
93
- self.class.new( @value | _typecast_flag!( other ).value )
80
+ self.class.build( @value | _typecast_flag!( other ).value )
94
81
  end
95
82
  alias_method :flag, :set
96
83
 
97
84
  def unset( other )
98
- self.class.new( @value & ~_typecast_flag!( other ).value )
85
+ self.class.build( @value & ~_typecast_flag!( other ).value )
99
86
  end
100
87
  alias_method :unflag, :unset
101
88
 
102
89
  def toggle( other )
103
- self.class.new( @value ^ _typecast_flag!( other ).value )
90
+ self.class.build( @value ^ _typecast_flag!( other ).value )
104
91
  end
105
92
 
106
93
 
107
94
 
108
-
109
95
  def self.keys()
110
- # note: does NOT include none - why? why not?
96
+ # note: does NOT include :none (and :all)
111
97
  @keys ||= members.map { |member| member.key }.freeze
112
98
  end
113
99
 
114
100
  def self.key( key )
115
- @hash ||= Hash[ keys.zip( members ) ].freeze
116
- @hash[key]
101
+ # note: does NOT include :none (and :all)
102
+ @hash_by_key ||= Hash[ keys.zip( members ) ].freeze
103
+ @hash_by_key[key]
117
104
  end
118
105
 
119
106
  def self.[]( key ) ## convenience alias for key
@@ -122,23 +109,50 @@ class Flag
122
109
 
123
110
 
124
111
  def self.values()
125
- # note: does NOT include none - why? why not?
112
+ # note: does NOT include :none (and :all)
126
113
  @values ||= members.map { |member| member.value }.freeze
127
114
  end
128
115
 
116
+ def self.value( value )
117
+ ## note: adds :none and :all for value lookup
118
+ @hash_by_value ||= Hash[ values.zip( members ) ].merge( self::NONE.value => self::NONE,
119
+ self::ALL.value => self::ALL ).freeze
120
+ @hash_by_value[value]
121
+ end
122
+
123
+ def self.build( value )
124
+ o = self.value( value ) # lookup if value is a known flag (with key)
125
+ o = new( :"#{'%08b' % value}", value ) if o.nil?
126
+ o
127
+ end
128
+
129
129
 
130
- def self.zero() @zero ||= new(0); end
130
+ def self.zero() @zero ||= self::NONE; end
131
131
  def zero?() @value == 0; end
132
132
 
133
+ def self.none() self::NONE; end
134
+ def none?() @value == 0; end
135
+ def self.all() self::ALL; end
136
+ def all?() @value & self.class::ALL.value == self.class::ALL.value; end
137
+
133
138
 
134
139
  def self.convert( *args )
135
- new( *args )
140
+ if args.size == 0
141
+ self::NONE
142
+ elsif args.size == 1 && args[0].is_a?(Integer)
143
+ build( args[0] )
144
+ else
145
+ ## assume flag object or symbols
146
+ value = 0
147
+ args.each do |arg|
148
+ flag = _typecast_flag!( arg )
149
+ value |= flag.value
150
+ end
151
+ build( value )
152
+ end
136
153
  end
137
154
 
138
-
139
155
  ## add size|length too why? why not?
140
- ## add value() lookup?
141
- ## not for now - why? combined values are undefined!! what to return??
142
156
 
143
157
  ## add to_i, to_int - why? why not?
144
158
  ## def to_i() @value; end
@@ -44,12 +44,15 @@ def self.build_class( class_name, *args, **kwargs )
44
44
  end
45
45
 
46
46
  def #{key}?
47
- _member?( #{key.upcase} )
47
+ @value & #{value} == #{value}
48
48
  end
49
49
  RUBY
50
50
  end
51
51
 
52
52
  klass.class_eval( <<RUBY )
53
+ NONE = new( :none, 0 )
54
+ ALL = new( :all, #{f.values.reduce( 0 ) { |sum, value| sum|value }} )
55
+
53
56
  def self.members
54
57
  @members ||= [#{f.keys.map {|key|key.upcase}.join(',')}].freeze
55
58
  end
@@ -6,7 +6,7 @@ module Enums
6
6
 
7
7
  MAJOR = 1
8
8
  MINOR = 3
9
- PATCH = 0
9
+ PATCH = 1
10
10
  VERSION = [MAJOR,MINOR,PATCH].join('.')
11
11
 
12
12
  def self.version
@@ -60,6 +60,19 @@ def test_attrib
60
60
  assert_equal :read_only, FileAttrib.read_only.key
61
61
  assert_equal 1<<0, FileAttrib::READ_ONLY.value
62
62
  assert_equal :read_only, FileAttrib::READ_ONLY.key
63
+
64
+ attrib = FileAttrib.read_only | FileAttrib.hidden
65
+ assert_equal false, attrib.none?
66
+ assert_equal false, attrib & FileAttrib.all == FileAttrib.all
67
+ assert_equal false, attrib.all?
68
+ assert_equal true, attrib.read_only?
69
+ assert_equal true, attrib.hidden?
70
+
71
+ attrib |= FileAttrib.system
72
+ attrib |= FileAttrib.archive
73
+ assert_equal true, attrib & FileAttrib.all == FileAttrib.all
74
+ assert_equal true, attrib.all?
75
+ assert_equal false, attrib.none?
63
76
  end
64
77
 
65
78
  def test_text_style
@@ -70,6 +83,9 @@ def test_text_style
70
83
 
71
84
  style = TextStyle(0)
72
85
  assert_equal true, style == 0
86
+ assert_equal true, style.zero?
87
+ assert_equal true, style.none?
88
+
73
89
  style |= TextStyle.bold
74
90
  assert_equal true, style.member?( :bold )
75
91
  assert_equal true, style.member?( TextStyle.bold )
@@ -83,6 +99,11 @@ def test_text_style
83
99
  assert_equal true, style.member?( TextStyle.italic )
84
100
  assert_equal true, style & TextStyle.italic == TextStyle.italic
85
101
  assert_equal true, style & TextStyle.italic != 0
102
+
103
+ style = TextStyle.bold | TextStyle.italic | TextStyle.underline
104
+ assert_equal true, style & TextStyle.all == TextStyle.all
105
+ assert_equal true, style & TextStyle.all != 0
106
+ assert_equal true, style.all?
86
107
  end
87
108
 
88
109
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: enums
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-28 00:00:00.000000000 Z
11
+ date: 2019-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdoc
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '3.16'
41
41
  description: enums - safe enumeration types - a set of symbolic keys bound to unique
42
- integer numbers
42
+ integer numbers (incl. bit flags option)
43
43
  email: wwwmake@googlegroups.com
44
44
  executables: []
45
45
  extensions: []
@@ -89,5 +89,5 @@ rubygems_version: 2.5.2
89
89
  signing_key:
90
90
  specification_version: 4
91
91
  summary: enums - safe enumeration types - a set of symbolic keys bound to unique integer
92
- numbers
92
+ numbers (incl. bit flags option)
93
93
  test_files: []