banditmask 0.1.0 → 0.2.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 +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
|
+
# [![Gem Version](https://badge.fury.io/rb/banditmask.svg)](http://badge.fury.io/rb/banditmask) [![Build Status](https://travis-ci.org/jparker/banditmask.svg?branch=master)](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:
|