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 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: