banditmask 0.1.0 → 0.2.0
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/README.md +48 -4
- data/lib/banditmask/banditry.rb +59 -0
- data/lib/banditmask/version.rb +1 -1
- data/lib/banditmask.rb +24 -29
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1274b0e400a4133553877fbe39fdf8e7a5a4d66c
|
4
|
+
data.tar.gz: 919cceb675c02361a28b6c8d6e0c252f72a391e2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1fc4ee2ae4d36e5fa5d5618565c771b239cf80aa51ef5c0ed5da76b8a9342a20fd1683e88fa0e2ef2e2a4f48210b0577cef5f07923224175a6bbdb7fec030a6
|
7
|
+
data.tar.gz: acb861486cb0f63f3a3209ed005e97e9526a8ed9dc4389eed2fa7cae6deb28f36f2455dd0c2e49d8c17c19698d6f57d5b71df7a8c6cab366bc68ac202fde58b2
|
data/README.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# [](http://badge.fury.io/rb/banditmask) [](https://travis-ci.org/jparker/banditmask)
|
2
|
+
|
1
3
|
# BanditMask
|
2
4
|
|
3
5
|
BanditMask provides a generic wrapper for working with bitmasks.
|
@@ -20,7 +22,7 @@ Or install it yourself as:
|
|
20
22
|
|
21
23
|
## Usage
|
22
24
|
|
23
|
-
Create a class which inherits from BanditMask and declare the available bit
|
25
|
+
Create a class which inherits from `BanditMask`, and declare the available bit
|
24
26
|
names and their corresponding values.
|
25
27
|
|
26
28
|
```ruby
|
@@ -33,7 +35,7 @@ end
|
|
33
35
|
ChmodMask.bits # => { :read => 1, :write => 2, :execute => 4 }
|
34
36
|
```
|
35
37
|
|
36
|
-
|
38
|
+
Instantiate a new mask class:
|
37
39
|
|
38
40
|
```ruby
|
39
41
|
mask = ChmodMask.new
|
@@ -62,11 +64,53 @@ Retrieve a list of all currently enabled bits.
|
|
62
64
|
mask.names # => [:read, :write]
|
63
65
|
```
|
64
66
|
|
67
|
+
In an class with a bitmask attribute, extend `BanditMask::Banditry` and call
|
68
|
+
`BanditMask::Banditry.bandit_mask` to add accessor methods for working with the
|
69
|
+
bitmask attribute.
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
class ObjectWithBitmaskAttribute
|
73
|
+
attr_accessor :bitmask
|
74
|
+
|
75
|
+
extend BanditMask::Banditry
|
76
|
+
bandit_mask :bitmask, as: :bits, with: ChmodMask
|
77
|
+
end
|
78
|
+
|
79
|
+
obj = ObjectWithBitmaskAttribute.new
|
80
|
+
obj.bitmask = 0b011
|
81
|
+
```
|
82
|
+
|
83
|
+
This gives you a reader method which delegates to `BanditMask#names`.
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
obj.bits # => [:read, :write]
|
87
|
+
```
|
88
|
+
|
89
|
+
It also gives you a writer method which lets you overwrite the bitmask.
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
obj.bits = [:read, :execute]
|
93
|
+
obj.bitmask # => 5
|
94
|
+
```
|
95
|
+
|
96
|
+
Finally, it gives you a query method for checking whether a particular bit is
|
97
|
+
set on the bitmask.
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
obj.has? :read # => true
|
101
|
+
obj.has? :write # => false
|
102
|
+
```
|
103
|
+
|
65
104
|
## Development
|
66
105
|
|
67
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
106
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
107
|
+
`bin/console` for an interactive prompt that will allow you to experiment.
|
68
108
|
|
69
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To
|
109
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
110
|
+
release a new version, update the version number in `version.rb`, and then run
|
111
|
+
`bundle exec rake release` to create a git tag for the version, push git
|
112
|
+
commits and tags, and push the `.gem` file to
|
113
|
+
[rubygems.org](https://rubygems.org).
|
70
114
|
|
71
115
|
## Contributing
|
72
116
|
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
class BanditMask
|
4
|
+
module Banditry
|
5
|
+
def self.extended(cls) # :nodoc:
|
6
|
+
cls.extend Forwardable
|
7
|
+
end
|
8
|
+
|
9
|
+
##
|
10
|
+
# Creates wrapper methods for reading and writing the bitmask stored in
|
11
|
+
# +attribute+ using the class +with+. +with+ defaults to BanditMask, but
|
12
|
+
# you can (and probably) should define your own class descending from
|
13
|
+
# +BanditMask+ to fill this role. The name of the accessor methods will be
|
14
|
+
# derived from +as+, e.g., if +as+ is +:foo+, the reader method will be
|
15
|
+
# +:foo+ and the writer will be +:foo=+.
|
16
|
+
#
|
17
|
+
# The reader method will call BanditMask#bits to get an array of the
|
18
|
+
# enabled bit names represented by +attribute+.
|
19
|
+
#
|
20
|
+
# The writer method will replace the current bitmask with an Integer
|
21
|
+
# representation of a new BanditMask built up using BanditMask#<<.
|
22
|
+
#
|
23
|
+
# In addition to the accessor methods, a method named +has?+ will be added
|
24
|
+
# which delegates to the BanditMask#include?.
|
25
|
+
#
|
26
|
+
# class ThingMask < BanditMask
|
27
|
+
# # ...
|
28
|
+
# # bit :foo, 0b1
|
29
|
+
# # ...
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# class Thing
|
33
|
+
# attr_accessor :bitmask
|
34
|
+
#
|
35
|
+
# extend BanditMask::Banditry
|
36
|
+
# bandit_mask :bitmask, as: :bits, with: ThingMask
|
37
|
+
# end
|
38
|
+
def bandit_mask(attribute, as:, with: BanditMask)
|
39
|
+
cls = with
|
40
|
+
wrapper = as
|
41
|
+
|
42
|
+
class_eval do
|
43
|
+
##
|
44
|
+
# A reader method which instances a new BanditMask object and calls
|
45
|
+
# BanditMask#bits.
|
46
|
+
define_method wrapper do
|
47
|
+
cls.new(send(attribute)).bits
|
48
|
+
end
|
49
|
+
|
50
|
+
define_method :"#{wrapper}=" do |bits|
|
51
|
+
mask = bits.reduce(cls.new) { |mask, bit| mask << bit }
|
52
|
+
send :"#{attribute}=", Integer(mask)
|
53
|
+
end
|
54
|
+
|
55
|
+
def_delegator wrapper, :include?, :has?
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/banditmask/version.rb
CHANGED
data/lib/banditmask.rb
CHANGED
@@ -1,21 +1,22 @@
|
|
1
|
-
require
|
1
|
+
require 'banditmask/version'
|
2
|
+
require 'banditmask/banditry'
|
2
3
|
|
3
4
|
class BanditMask
|
4
|
-
attr_reader :
|
5
|
+
attr_reader :bitmask
|
5
6
|
|
6
|
-
def initialize(
|
7
|
-
@
|
7
|
+
def initialize(bitmask = 0b0) # :nodoc:
|
8
|
+
@bitmask = bitmask
|
8
9
|
end
|
9
10
|
|
10
11
|
##
|
11
12
|
# Returns a Hash mapping all defined names to their respective bits.
|
12
13
|
#
|
13
|
-
# class BanditMask
|
14
|
+
# class MyMask < BanditMask
|
14
15
|
# bit :read, 0b01
|
15
16
|
# bit :write, 0b10
|
16
17
|
# end
|
17
18
|
#
|
18
|
-
#
|
19
|
+
# MyMask.bits # => { :read => 1, :write => 2 }
|
19
20
|
def self.bits
|
20
21
|
@bits ||= {}
|
21
22
|
end
|
@@ -23,7 +24,7 @@ class BanditMask
|
|
23
24
|
##
|
24
25
|
# Maps +name+ to +value+ in the global list of defined bits.
|
25
26
|
#
|
26
|
-
# class BanditMask
|
27
|
+
# class MyMask < BanditMask
|
27
28
|
# bit :read, 0b001
|
28
29
|
# bit :write, 0b010
|
29
30
|
# bit :execute, 0b100
|
@@ -32,16 +33,10 @@ class BanditMask
|
|
32
33
|
bits.update name => value
|
33
34
|
end
|
34
35
|
|
35
|
-
##
|
36
|
-
# Clears all defined bits.
|
37
|
-
def self.reset_bits!
|
38
|
-
@bits = {}
|
39
|
-
end
|
40
|
-
|
41
36
|
##
|
42
37
|
# Returns integer value of current bitmask.
|
43
38
|
def to_i
|
44
|
-
|
39
|
+
bitmask
|
45
40
|
end
|
46
41
|
|
47
42
|
##
|
@@ -53,15 +48,15 @@ class BanditMask
|
|
53
48
|
# end
|
54
49
|
#
|
55
50
|
# mask = BanditMask.new 0b01
|
56
|
-
# mask.
|
57
|
-
def
|
58
|
-
self.class.bits.select { |
|
51
|
+
# mask.bits # => [:read]
|
52
|
+
def bits
|
53
|
+
self.class.bits.select { |bit, _| include? bit }.keys
|
59
54
|
end
|
60
|
-
alias_method :to_a, :
|
55
|
+
alias_method :to_a, :bits
|
61
56
|
|
62
57
|
##
|
63
|
-
# Enables the bit named +
|
64
|
-
# chained (
|
58
|
+
# Enables the bit named +bit+. Returns +self+, so calls to #<< can be
|
59
|
+
# chained. (Think Array#<<.) Raises +ArgumentError+ if +bit+ does not
|
65
60
|
# correspond to a bit that was previously declared with BanditMask.bit.
|
66
61
|
#
|
67
62
|
# class BanditMask
|
@@ -71,14 +66,14 @@ class BanditMask
|
|
71
66
|
#
|
72
67
|
# mask = BanditMask.new
|
73
68
|
# mask << :read << :write
|
74
|
-
def <<(
|
75
|
-
@
|
69
|
+
def <<(bit)
|
70
|
+
@bitmask |= bit_value(bit)
|
76
71
|
self
|
77
72
|
end
|
78
73
|
|
79
74
|
##
|
80
|
-
# Returns true if +
|
81
|
-
# otherwise. Raises +ArgumentError+ if +
|
75
|
+
# Returns true if +bit+ is among the currently enabled bits. Returns false
|
76
|
+
# otherwise. Raises +ArgumentError+ if +bit+ does not correspond to a bit
|
82
77
|
# that was previously declared with BanditMask.bit.
|
83
78
|
#
|
84
79
|
# class BanditMask
|
@@ -89,15 +84,15 @@ class BanditMask
|
|
89
84
|
# mask = BanditMask.new 0b01
|
90
85
|
# mask.include? :read # => true
|
91
86
|
# mask.include? :write # => false
|
92
|
-
def include?(
|
93
|
-
|
87
|
+
def include?(bit)
|
88
|
+
bitmask & bit_value(bit) != 0
|
94
89
|
end
|
95
90
|
|
96
91
|
private
|
97
92
|
|
98
|
-
def
|
99
|
-
self.class.bits.fetch(
|
100
|
-
raise ArgumentError, "undefined bit: #{
|
93
|
+
def bit_value(bit)
|
94
|
+
self.class.bits.fetch(bit) do
|
95
|
+
raise ArgumentError, "undefined bit: #{bit.inspect}"
|
101
96
|
end
|
102
97
|
end
|
103
98
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: banditmask
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Parker
|
@@ -69,6 +69,7 @@ files:
|
|
69
69
|
- bin/console
|
70
70
|
- bin/setup
|
71
71
|
- lib/banditmask.rb
|
72
|
+
- lib/banditmask/banditry.rb
|
72
73
|
- lib/banditmask/version.rb
|
73
74
|
homepage: https://github.com/jparker/banditmask
|
74
75
|
licenses:
|