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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b0ba2ce5f3058aca2b5b0aea9b05215a6b76026f
4
- data.tar.gz: 5b41de6797071fc9e82a73da1bd341855a5e5594
3
+ metadata.gz: 1274b0e400a4133553877fbe39fdf8e7a5a4d66c
4
+ data.tar.gz: 919cceb675c02361a28b6c8d6e0c252f72a391e2
5
5
  SHA512:
6
- metadata.gz: 6fbe95e064c17ddf564ef77d757df53c5fab34f648974d412e29e2e8fddf42abc945e17bc74f053419d7d04529b662c173113e35ae64329810c71e4e9c658829
7
- data.tar.gz: 60c69509a022d36d2a1d33fa72e94ea41e503ea37b5198a126cf9f2be04ec8ff7dce4addcc33d2d1d2e576ba9672f1ad94cc394724278a0daf3c94725df4b5c4
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
- To instantiate a new mask class:
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 `bin/console` for an interactive prompt that will allow you to experiment.
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 release a new version, update the version number in `version.rb`, and then run `bundle exec rake release` to create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
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
@@ -1,3 +1,3 @@
1
1
  class BanditMask
2
- VERSION = "0.1.0"
2
+ VERSION = '0.2.0'
3
3
  end
data/lib/banditmask.rb CHANGED
@@ -1,21 +1,22 @@
1
- require "banditmask/version"
1
+ require 'banditmask/version'
2
+ require 'banditmask/banditry'
2
3
 
3
4
  class BanditMask
4
- attr_reader :mask
5
+ attr_reader :bitmask
5
6
 
6
- def initialize(mask = 0b0) # :nodoc:
7
- @mask = mask
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
- # BanditMask.bits # => { :read => 1, :write => 2 }
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
- mask
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.names # => [:read]
57
- def names
58
- self.class.bits.select { |name, _| include? name }.keys
51
+ # mask.bits # => [:read]
52
+ def bits
53
+ self.class.bits.select { |bit, _| include? bit }.keys
59
54
  end
60
- alias_method :to_a, :names
55
+ alias_method :to_a, :bits
61
56
 
62
57
  ##
63
- # Enables the bit named +name+. Returns +self+, so calles to #<< can be
64
- # chained (think Array#<<). Raises +ArgumentError+ if +name+ does not
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 <<(name)
75
- @mask |= name_to_bit(name)
69
+ def <<(bit)
70
+ @bitmask |= bit_value(bit)
76
71
  self
77
72
  end
78
73
 
79
74
  ##
80
- # Returns true if +name+ is among the currently enabled bits. Returns false
81
- # otherwise. Raises +ArgumentError+ if +name+ does not correspond to a bit
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?(name)
93
- @mask & name_to_bit(name) != 0
87
+ def include?(bit)
88
+ bitmask & bit_value(bit) != 0
94
89
  end
95
90
 
96
91
  private
97
92
 
98
- def name_to_bit(name)
99
- self.class.bits.fetch(name) do
100
- raise ArgumentError, "undefined bit: #{name.inspect}"
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.1.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: