enums 1.3.1 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +38 -20
- data/lib/enums.rb +8 -0
- data/lib/enums/enum.rb +38 -5
- data/lib/enums/flag.rb +13 -10
- data/lib/enums/version.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3fd8c533a33e8a97a70892813fe984a95e9a296f
|
4
|
+
data.tar.gz: f8fc99c3b73a0473b3fe2717d86fd538bf85bdb0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 30521b0da15ad85a970ef1fbfae486a4f987501dbd5b729fb370df89e8f0cb179fed63951274374c63322ba93c76ebdd16c6e9a646084f7f2ea960fc81eac30c
|
7
|
+
data.tar.gz: a8d14b650496db549103d58c19d028186a4451887fb46115ac09afcd4177a7f8612cbefdf33ca0c4b804e6c87ff39c1b65a43f88848687d87c8d8fff2ed909ac
|
data/README.md
CHANGED
@@ -32,8 +32,8 @@ module Color
|
|
32
32
|
BLUE = 1
|
33
33
|
GREEN = 2
|
34
34
|
end
|
35
|
-
Color::RED
|
36
|
-
Color::BLUE
|
35
|
+
Color::RED #=> 0
|
36
|
+
Color::BLUE #=> 1
|
37
37
|
Color.constants #=> [:RED, :BLUE, :GREEN]
|
38
38
|
# ...
|
39
39
|
```
|
@@ -210,14 +210,30 @@ enum :FileAttrib, [:read_only, :hidden, :system, :archive], flags: true
|
|
210
210
|
# -or -
|
211
211
|
enum :FileAttrib, :read_only, :hidden, :system, :archive, flags: true
|
212
212
|
# -or -
|
213
|
-
enum :FileAttrib, { read_only:
|
214
|
-
hidden: 1
|
215
|
-
system:
|
216
|
-
archive:
|
213
|
+
enum :FileAttrib, { read_only: Bit(0),
|
214
|
+
hidden: Bit(1),
|
215
|
+
system: Bit(2),
|
216
|
+
archive: Bit(5),
|
217
217
|
},
|
218
218
|
flags: true
|
219
219
|
```
|
220
220
|
|
221
|
+
Aside: What's `Bit()`?
|
222
|
+
|
223
|
+
`Bit()` is a bit conversion helper defined as `def Bit(n) 1 << n; end`. Example:
|
224
|
+
|
225
|
+
| | Bit Shift | Binary | Decimal | Hex |
|
226
|
+
|-----------|------------|---------------|-------------|---------|
|
227
|
+
| `Bit(0)` | `1<<0` | `0b00000001` | `2^0 = 1` | `0x01` |
|
228
|
+
| `Bit(1)` | `1<<1` | `0b00000010` | `2^1 = 2` | `0x02` |
|
229
|
+
| `Bit(2)` | `1<<2` | `0b00000100` | `2^2 = 4` | `0x04` |
|
230
|
+
| `Bit(3)` | `1<<3` | `0b00001000` | `2^3 = 8` | `0x08` |
|
231
|
+
| `Bit(4)` | `1<<4` | `0b00010000` | `2^4 = 16` | `0x10` |
|
232
|
+
| `Bit(5)` | `1<<5` | `0b00100000` | `2^5 = 32` | `0x20` |
|
233
|
+
| ... |
|
234
|
+
|
235
|
+
|
236
|
+
|
221
237
|
(Auto-)builds a class and code like:
|
222
238
|
|
223
239
|
``` ruby
|
@@ -232,11 +248,11 @@ end
|
|
232
248
|
class FileAttrib < Flag
|
233
249
|
|
234
250
|
NONE = new( :none, 0 )
|
235
|
-
READ_ONLY = new( :read_only,
|
236
|
-
HIDDEN = new( :hidden, 1
|
237
|
-
SYSTEM = new( :system,
|
238
|
-
ARCHIVE = new( :archive,
|
239
|
-
ALL = new( :all,
|
251
|
+
READ_ONLY = new( :read_only, Bit(0) )
|
252
|
+
HIDDEN = new( :hidden, Bit(1) )
|
253
|
+
SYSTEM = new( :system, Bit(2) )
|
254
|
+
ARCHIVE = new( :archive, Bit(3) )
|
255
|
+
ALL = new( :all, Bit(0)|Bit(1)|Bit(2)|Bit(3) )
|
240
256
|
|
241
257
|
def self.none() NONE; end
|
242
258
|
def self.read_only() READ_ONLY; end
|
@@ -245,7 +261,7 @@ class FileAttrib < Flag
|
|
245
261
|
def self.archive() ARCHIVE; end
|
246
262
|
def self.all() ALL; end
|
247
263
|
|
248
|
-
def self.values() [
|
264
|
+
def self.values() [Bit(0),Bit(1),Bit(2),Bit(3)]; end
|
249
265
|
def self.keys() [:read_only, :hidden, :system, :archive]; end
|
250
266
|
def self.members() [READ_ONLY, HIDDEN, SYSTEM, ARCHIVE]; end
|
251
267
|
|
@@ -258,11 +274,11 @@ class FileAttrib < Flag
|
|
258
274
|
def self.[]( key ) self.key( key ); end
|
259
275
|
|
260
276
|
def none? @value == 0; end
|
261
|
-
def read_only?() @value &
|
262
|
-
def hidden?() @value & 1
|
263
|
-
def system?() @value &
|
264
|
-
def archive?() @value &
|
265
|
-
def all?() @value ==
|
277
|
+
def read_only?() @value & Bit(0) == Bit(0); end
|
278
|
+
def hidden?() @value & Bit(1) == Bit(1); end
|
279
|
+
def system?() @value & Bit(2) == Bit(2); end
|
280
|
+
def archive?() @value & Bit(3) == Bit(3); end
|
281
|
+
def all?() @value == Bit(0)|Bit(1)|Bit(2)|Bit(3); end
|
266
282
|
|
267
283
|
def member?( other ) @value & other.value == other.value; end
|
268
284
|
|
@@ -348,9 +364,9 @@ enum :TextStyle, [:bold, :italic, :underline], flags: true
|
|
348
364
|
# -or -
|
349
365
|
enum :TextStyle, :bold, :italic, :underline, flags: true
|
350
366
|
# -or -
|
351
|
-
enum :TextStyle, { bold:
|
352
|
-
italic: 1
|
353
|
-
underline:
|
367
|
+
enum :TextStyle, { bold: Bit(0),
|
368
|
+
italic: Bit(1),
|
369
|
+
underline: Bit(2)
|
354
370
|
},
|
355
371
|
flags: true
|
356
372
|
|
@@ -401,6 +417,8 @@ style.is_a? TextStyle #=> true
|
|
401
417
|
and so on.
|
402
418
|
|
403
419
|
|
420
|
+
|
421
|
+
|
404
422
|
### What about enums for (algebraic) union data types with variants?
|
405
423
|
|
406
424
|
Yes, yes, yes. Use the `Union` class or the `data` helper from the safedata library.
|
data/lib/enums.rb
CHANGED
@@ -10,6 +10,9 @@ require 'enums/version' # note: let version always go first
|
|
10
10
|
|
11
11
|
## forward declarations
|
12
12
|
module Safe
|
13
|
+
|
14
|
+
## todo/check/discuss: auto-include SafeHelper - why? why not?
|
15
|
+
|
13
16
|
## note: use ClassMethods pattern for auto-including class methods
|
14
17
|
## note ClassMethods module is called SafeHelper
|
15
18
|
def self.included( klass )
|
@@ -26,6 +29,11 @@ module Safe
|
|
26
29
|
end # module Safe
|
27
30
|
|
28
31
|
|
32
|
+
module Kernel
|
33
|
+
def Bit( n ) 1 << n; end ## add "global" bit conversion helper
|
34
|
+
end
|
35
|
+
|
36
|
+
|
29
37
|
|
30
38
|
require 'enums/enum'
|
31
39
|
require 'enums/enum_builder'
|
data/lib/enums/enum.rb
CHANGED
@@ -16,6 +16,28 @@ class Enum
|
|
16
16
|
self
|
17
17
|
end
|
18
18
|
|
19
|
+
def self._typecheck_enum!( o )
|
20
|
+
if o.instance_of?( self )
|
21
|
+
o
|
22
|
+
else
|
23
|
+
raise TypeError.new( "[Enum] enum >#{name}< type expected; got >#{o.class.inspect}<" )
|
24
|
+
end
|
25
|
+
end
|
26
|
+
def _typecheck_enum!( o ) self.class._typecheck_enum!( o ); end
|
27
|
+
|
28
|
+
|
29
|
+
def ==( other )
|
30
|
+
if other.is_a?( Integer ) && other == 0 ## note: only allow compare by zero (0) integer - why? why not?
|
31
|
+
@value == 0
|
32
|
+
else
|
33
|
+
@value == _typecheck_enum!( other ).value
|
34
|
+
end
|
35
|
+
end
|
36
|
+
alias_method :eql?, :==
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
|
19
41
|
|
20
42
|
def self.keys
|
21
43
|
@keys ||= members.map {|member| member.key}.freeze
|
@@ -29,11 +51,12 @@ class Enum
|
|
29
51
|
@hash_by_key[key]
|
30
52
|
end
|
31
53
|
|
32
|
-
|
33
|
-
|
54
|
+
class << self
|
55
|
+
alias_method :[], :key ## convenience alias for key
|
34
56
|
end
|
35
57
|
|
36
58
|
|
59
|
+
|
37
60
|
def self.values
|
38
61
|
@values ||= members.map {|member| member.value}.freeze
|
39
62
|
@values
|
@@ -48,12 +71,13 @@ class Enum
|
|
48
71
|
|
49
72
|
|
50
73
|
def self.zero() members[0]; end
|
51
|
-
def zero?() self == self.class.zero; end
|
74
|
+
def zero?() self == self.class.zero; end ## note: use compare by identity (object_id) and NOT value e.g. 0
|
52
75
|
|
53
76
|
|
54
77
|
def self.size() keys.size; end
|
55
|
-
|
56
|
-
|
78
|
+
class << self
|
79
|
+
alias_method :length, :size ## alias (as is the ruby tradition)
|
80
|
+
end
|
57
81
|
|
58
82
|
def self.convert( arg )
|
59
83
|
## todo/check: support keys too - why? why not?
|
@@ -62,5 +86,14 @@ class Enum
|
|
62
86
|
## note: will ALWAYS look-up by (member) index and NOT by value (integer number value might be different!!)
|
63
87
|
members[ arg ]
|
64
88
|
end
|
89
|
+
|
90
|
+
|
91
|
+
## add to_i, to_int - why? why not?
|
92
|
+
def to_i() @value; end
|
93
|
+
def to_int() @value; end ## allows Integer( .. )
|
94
|
+
|
95
|
+
def to_b() parse_bool(); end
|
96
|
+
def parse_bool() @value != 0; end ## nonzero == true, zero == false like numbers
|
97
|
+
alias_method :to_bool, :parse_bool
|
65
98
|
end # class Enum
|
66
99
|
end # module Safe
|
data/lib/enums/flag.rb
CHANGED
@@ -18,7 +18,7 @@ class Flag
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def self._typecheck_flag!( o )
|
21
|
-
if self
|
21
|
+
if o.instance_of?( self )
|
22
22
|
o
|
23
23
|
else
|
24
24
|
raise TypeError.new( "[Flag] flag >#{name}< type expected; got >#{o.class.inspect}<" )
|
@@ -38,12 +38,10 @@ class Flag
|
|
38
38
|
|
39
39
|
|
40
40
|
def ==( other )
|
41
|
-
if
|
42
|
-
@value ==
|
43
|
-
elsif other.is_a?( Integer ) ## note: also allow compare by "plain" integer
|
44
|
-
@value == other
|
41
|
+
if other.is_a?( Integer ) && other == 0 ## note: only allow compare by zero (0) integer - why? why not?
|
42
|
+
@value == 0
|
45
43
|
else
|
46
|
-
|
44
|
+
@value == _typecheck_flag!( other ).value
|
47
45
|
end
|
48
46
|
end
|
49
47
|
alias_method :eql?, :==
|
@@ -103,8 +101,8 @@ class Flag
|
|
103
101
|
@hash_by_key[key]
|
104
102
|
end
|
105
103
|
|
106
|
-
|
107
|
-
|
104
|
+
class << self
|
105
|
+
alias_method :[], :key ## convenience alias for key
|
108
106
|
end
|
109
107
|
|
110
108
|
|
@@ -154,8 +152,13 @@ class Flag
|
|
154
152
|
|
155
153
|
## add size|length too why? why not?
|
156
154
|
|
155
|
+
|
157
156
|
## add to_i, to_int - why? why not?
|
158
|
-
|
159
|
-
|
157
|
+
def to_i() @value; end
|
158
|
+
def to_int() @value; end ## allows Integer( .. )
|
159
|
+
|
160
|
+
def to_b() parse_bool(); end
|
161
|
+
def parse_bool() @value != 0; end ## nonzero == true, zero == false like numbers
|
162
|
+
alias_method :to_bool, :parse_bool
|
160
163
|
end # class Flag
|
161
164
|
end # module Safe
|
data/lib/enums/version.rb
CHANGED
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.
|
4
|
+
version: 1.4.0
|
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-
|
11
|
+
date: 2019-03-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rdoc
|