lib/banditmask.rb in banditmask-0.2.1 vs lib/banditmask.rb in banditmask-0.3.0
- old
+ new
@@ -2,12 +2,12 @@
require 'banditmask/banditry'
class BanditMask
attr_reader :bitmask
- def initialize(bitmask = 0b0) # :nodoc:
- @bitmask = bitmask
+ def initialize(bitmask = nil) # :nodoc:
+ @bitmask = bitmask || 0b0
end
##
# Returns a Hash mapping all defined names to their respective bits.
#
@@ -40,51 +40,102 @@
end
##
# Returns an array of names of the currently enabled bits.
#
- # class BanditMask
+ # class MyMask < BanditMask
# bit :read, 0b01
# bit :write, 0b10
# end
#
- # mask = BanditMask.new 0b01
+ # mask = MyMask.new 0b01
# mask.bits # => [:read]
def bits
self.class.bits.select { |bit, _| include? bit }.keys
end
alias_method :to_a, :bits
##
# Enables the bit named +bit+. Returns +self+, so calls to #<< can be
# chained. (Think Array#<<.) Raises +ArgumentError+ if +bit+ does not
- # correspond to a bit that was previously declared with BanditMask.bit.
+ # correspond to a bit that was previously defined with BanditMask.bit.
#
- # class BanditMask
+ # class MyMask < BanditMask
# bit :read, 0b01
# bit :write, 0b10
# end
#
- # mask = BanditMask.new
- # mask << :read << :write
+ # mask = MyMask.new # => #<MyMask:0x007f9ebd44ae40 @bitmask=0>
+ # mask << :read << :write # => #<MyMask:0x007f9ebd44ae40 @bitmask=3>
def <<(bit)
@bitmask |= bit_value(bit)
self
end
##
- # Returns false if any bit in +bits+ is not enabled. Returns true otherwise.
- # Raises +ArgumentError+ if +bits+ is empty or if any element in +bits+ does
- # not correspond to bit that was previously declared with BanditMask.bit.
+ # Returns a new instance with the current bitmask plus +bit+. Raises
+ # +ArgumentError+ if +bit+ does not correspond to a bit that was previously
+ # defined by BanditMask.bit.
#
- # class BanditMask
+ # class MyMask < BanditMask
+ # bit :read, 0b01
+ # bit :write, 0b10
+ # end
+ #
+ # mask = MyMask.new 0b01
+ # mask | :write # => #<MyMask:0x007f9e0bcf5d90 @bitmask=3>
+ def |(bit)
+ self.class.new bitmask | bit_value(bit)
+ end
+
+ ##
+ # Returns +true+ if +other+ is an instance of the same class as +self+ and
+ # they have the same bitmask.
+ #
+ # class MyMask < BanditMask
+ # bit :read, 0b01
+ # bit :write, 0b10
+ # end
+ #
+ # class MyOtherMask < BanditMask
+ # bit :chocolate, 0b01
+ # bit :vanilla, 0b10
+ # end
+ #
+ # a = MyMask.new 0b1
+ # b = MyMask.new 0b1
+ # c = MyMask.new 0b0
+ # d = MyOtherMask.new 0b1
+ #
+ # a == b # => true
+ # a == c # => false
+ # a == d # => false
+ def ==(other)
+ other.class == self.class && other.bitmask == bitmask
+ end
+
+ alias_method :eql?, :==
+
+ ##
+ # Returns an object hash. Two BanditMask objects have identical hashes if
+ # they have identical bitmasks and are instances of the same class.
+ def hash
+ [bitmask, self.class].hash
+ end
+
+ ##
+ # Returns true if every bit in +bits+ is enabled and false otherwise. Raises
+ # +ArgumentError+ if +bits+ is empty or if any element in +bits+ does not
+ # correspond to a bit that was previously defined with BanditMask.bit.
+ #
+ # class MyMask < BanditMask
# bit :read, 0b001
# bit :write, 0b010
# bit :execute, 0b100
# end
#
- # mask = BanditMask.new 0b101
+ # mask = MyMask.new 0b101
#
# mask.include? :read # => true
# mask.include? :write # => false
# mask.include? :execute # => true
#
@@ -95,9 +146,12 @@
bits.all? { |bit| bitmask & bit_value(bit) != 0 }
end
private
+ ##
+ # Returns the integer value for the bit named +bit+. Raises +ArgumentError+
+ # if +bit+ has not been previously defined with BanditMask.bit.
def bit_value(bit)
self.class.bits.fetch(bit) do
raise ArgumentError, "undefined bit: #{bit.inspect}"
end
end