Class: Literal::Flags

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/literal/flags.rb

Direct Known Subclasses

Flags16, Flags32, Flags64, Flags8

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value = 0, **new_flags) ⇒ Flags

Returns a new instance of Flags.



6
7
8
9
10
11
12
13
# File 'lib/literal/flags.rb', line 6

def initialize(value = 0, **new_flags)
  if new_flags.length > 0
    value = self.class.calculate_from_hash(new_flags)
  end

  @value = value
  freeze
end

Instance Attribute Details

#valueObject (readonly)

Returns the value of attribute value.



20
21
22
# File 'lib/literal/flags.rb', line 20

def value
  @value
end

Class Method Details

.calculate_array(value) ⇒ Object

(Integer) -> Array(Boolean)



78
79
80
81
# File 'lib/literal/flags.rb', line 78

def self.calculate_array(value)
  bits = self::BITS
  Array.new(bits) { |i| (value & (2 ** (bits - 1 - i)) > 0) }
end

.calculate_bit_string(value) ⇒ Object

(Integer) -> String



52
53
54
# File 'lib/literal/flags.rb', line 52

def self.calculate_bit_string(value)
  value.to_s(2).rjust(self::BITS, "0")
end

.calculate_from_array(array) ⇒ Object

(Array(Boolean)) -> Integer



57
58
59
60
61
# File 'lib/literal/flags.rb', line 57

def self.calculate_from_array(array)
  array.reverse_each.with_index.reduce(0) do |value, (bit, index)|
    value | (bit ? 1 << index : 0)
  end
end

.calculate_from_hash(hash) ⇒ Object

(Hash(Symbol, Boolean)) -> Integer



64
65
66
67
68
69
# File 'lib/literal/flags.rb', line 64

def self.calculate_from_hash(hash)
  flags = self::FLAGS
  hash.reduce(0) do |value, (key, bit)|
    value | (bit ? 2 ** flags.fetch(key) : 0)
  end
end

.calculate_from_tokens(tokens) ⇒ Object

(Array(Symbol)) -> Integer



84
85
86
87
# File 'lib/literal/flags.rb', line 84

def self.calculate_from_tokens(tokens)
  flags = self::FLAGS
  tokens.reduce(0) { |f, t| f | (2 ** flags.fetch(t)) }
end

.calculate_hash_from_value(value) ⇒ Object

(Integer) -> Hash(Symbol, Boolean)



90
91
92
93
94
# File 'lib/literal/flags.rb', line 90

def self.calculate_hash_from_value(value)
  self::FLAGS.transform_values do |bit|
    (value & (2 ** bit)) > 0
  end
end

.calculate_tokens(value) ⇒ Object

(Integer) -> Array(Symbol)



72
73
74
75
# File 'lib/literal/flags.rb', line 72

def self.calculate_tokens(value)
  flags = self::FLAGS
  flags.keys.select { |t| value & (2 ** flags.fetch(t)) > 0 }
end

.define(**flags) ⇒ Object

Raises:



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/literal/flags.rb', line 22

def self.define(**flags)
  raise ArgumentError if frozen?
  unique_values = flags.values
  unique_values.uniq!

  if unique_values.length != flags.length
    raise Literal::ArgumentError.new("Flags must be unique.")
  end

  const_set(:FLAGS, flags.dup.freeze)

  flags.each do |name, bit|
    class_eval "      # frozen_string_literal: true\n\n      def \#{name}?\n        @value & (2 ** \#{bit}) > 0\n      end\n    RUBY\n  end\n\n  freeze\nend\n", __FILE__, __LINE__ + 1

.from_array(array) ⇒ Object

(Array(Boolean)) -> Literal::Flags



107
108
109
110
111
112
113
# File 'lib/literal/flags.rb', line 107

def self.from_array(array)
  if array.length != self::BITS
    raise Literal::ArgumentError.new("The array must have #{self::BITS} items.")
  end

  from_int(calculate_from_array(array))
end

.from_bit_string(bit_string) ⇒ Object

(String) -> Literal::Flags



102
103
104
# File 'lib/literal/flags.rb', line 102

def self.from_bit_string(bit_string)
  from_int(bit_string.to_i(2))
end

.from_int(value) ⇒ Object

(Integer) -> Literal::Flags



121
122
123
# File 'lib/literal/flags.rb', line 121

def self.from_int(value)
  allocate.__initialize_from_value__(value)
end

.from_tokens(tokens) ⇒ Object

(Array(Symbol)) -> Literal::Flags



116
117
118
# File 'lib/literal/flags.rb', line 116

def self.from_tokens(tokens)
  from_int(calculate_from_tokens(tokens))
end

.keysObject

() -> Array(Symbol)



97
98
99
# File 'lib/literal/flags.rb', line 97

def self.keys
  @flags.keys
end

.to_procObject

() -> (Integer) -> Literal::Flags



47
48
49
# File 'lib/literal/flags.rb', line 47

def self.to_proc
  proc { |value| new(value) }
end

.unpack(value) ⇒ Object

(String) -> Literal::Flags



131
132
133
# File 'lib/literal/flags.rb', line 131

def self.unpack(value)
  new(unpack_int(value))
end

.unpack_int(value) ⇒ Object

(String) -> Integer



126
127
128
# File 'lib/literal/flags.rb', line 126

def self.unpack_int(value)
  value.unpack1(self::PACKER)
end

Instance Method Details

#&(other) ⇒ Object



179
180
181
182
183
184
185
186
# File 'lib/literal/flags.rb', line 179

def &(other)
  case other
  when Literal::Flags
    self.class.new(@value & other.value)
  when Integer
    self.class.new(@value & other)
  end
end

#[](key) ⇒ Object

(Symbol) -> Boolean



166
167
168
# File 'lib/literal/flags.rb', line 166

def [](key)
  @value & (bitmap(key)) > 0
end

#__initialize_from_value__(value) ⇒ Object



15
16
17
18
# File 'lib/literal/flags.rb', line 15

def __initialize_from_value__(value)
  @value = value
  freeze
end

#deconstruct_keys(keys = nil) ⇒ Object



206
207
208
209
210
211
212
213
214
# File 'lib/literal/flags.rb', line 206

def deconstruct_keys(keys = nil)
  if keys
    keys.to_h do |key|
      [key, @value & (bitmap(key)) > 0]
    end
  else
    to_h
  end
end

#eachObject



159
160
161
162
163
# File 'lib/literal/flags.rb', line 159

def each
  self.class::FLAGS.each do |key, bit|
    yield key, @value & (2 ** bit) > 0
  end
end

#inspectObject

() -> String



150
151
152
# File 'lib/literal/flags.rb', line 150

def inspect
  to_h.inspect
end

#packObject

() -> String



136
137
138
# File 'lib/literal/flags.rb', line 136

def pack
  [@value].pack(self.class::PACKER)
end

#to_aObject Also known as: deconstruct



200
201
202
# File 'lib/literal/flags.rb', line 200

def to_a
  self.class.calculate_array(@value)
end

#to_bit_stringObject



192
193
194
# File 'lib/literal/flags.rb', line 192

def to_bit_string
  self.class.calculate_bit_string(@value)
end

#to_hObject

() -> Hash(Symbol, Boolean)



155
156
157
# File 'lib/literal/flags.rb', line 155

def to_h
  self.class.calculate_hash_from_value(@value)
end

#to_iObject



188
189
190
# File 'lib/literal/flags.rb', line 188

def to_i
  @value
end

#to_tokensObject



196
197
198
# File 'lib/literal/flags.rb', line 196

def to_tokens
  self.class.calculate_tokens(@value)
end

#with(**attributes) ⇒ Object



140
141
142
143
144
145
146
147
# File 'lib/literal/flags.rb', line 140

def with(**attributes)
  new_val = attributes.reduce(value) do |value, (k, v)|
    v ? value |= bitmap(k) : value &= ~(bitmap(k))
    value
  end

  self.class.allocate.__initialize_from_value__(new_val)
end

#|(other) ⇒ Object



170
171
172
173
174
175
176
177
# File 'lib/literal/flags.rb', line 170

def |(other)
  case other
  when Literal::Flags
    self.class.new(@value | other.value)
  when Integer
    self.class.new(@value | other)
  end
end