Class: BinStruct::BitAttr Abstract

Inherits:
Object
  • Object
show all
Includes:
Structable
Defined in:
lib/bin_struct/bit_attr.rb

Overview

This class is abstract.

Subclasses must de derived using BitAttr.create.

Define a bitfield attribute to embed in a Struct. Use it through Struct.define_bit_attr

Examples:

class MyStruct < BinStruct::Struct
  # Create a 32-bit bitfield attribute, with fields a (16 bits), b and c (4 bits each) and d (8 bits).
  # a is the leftmost field in bitfield, and d the rightmost one.
  define_bit_attr :int32, width: 32, a: 16, b: 4, c: 4, d:8
end

s1 = MyStruct.new(int32: 0x12345678)
s1.a #=> 0x1234
s1.b #=> 5
s1.c #=> 6
s1.d #=> 0x78

s2 = MyStruct.new(a: 0x1234, d: 0x42)
s2.to_s #=> "\x12\x34\x00\x42".b

Since:

  • 0.3.0

Defined Under Namespace

Classes: Parameters

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Structable

#sz

Constructor Details

#initialize(values = {}) ⇒ self

Initialize bit attribute

Raises:

Since:

  • 0.3.0

Parameters:

  • (defaults to: {})

    initialization values for fields, where keys are field names and values are initialization values



131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/bin_struct/bit_attr.rb', line 131

def initialize(values = {})
  parameters = self.class.parameters
  raise NotImplementedError, "#initialize may only be called on subclass of #{self.class}" if parameters.nil?

  @width = parameters.width
  @fields = parameters.fields
  @int = parameters.int.dup
  @data = {}

  parameters.fields.each_key do |name|
    @data[name] = values[name] || 0
  end
  @int.value = compute_integer
end

Class Attribute Details

.bit_methods::Array<Symbol> (readonly)

Since:

  • 0.3.0

Returns:



49
50
51
# File 'lib/bin_struct/bit_attr.rb', line 49

def bit_methods
  @bit_methods
end

.parametersParameters (readonly)

Since:

  • 0.3.0

Returns:



45
46
47
# File 'lib/bin_struct/bit_attr.rb', line 45

def parameters
  @parameters
end

Instance Attribute Details

#widthInteger (readonly)

Returns width in bits of bit attribute.

Since:

  • 0.3.0

Returns:

  • width in bits of bit attribute



34
35
36
# File 'lib/bin_struct/bit_attr.rb', line 34

def width
  @width
end

Class Method Details

.create(width:, endian: :big, **fields) ⇒ Class

Create a new BinStruct::BitAttr subclass with specified parameters

Raises:

  • raise if:

    • width is not a size of one of Int subclasses,

    • sum of bitfield sizes is not equal to width

Since:

  • 0.3.0

Parameters:

  • size of bitfields in bits. Must be a size of an Int (8, 16, 24, 32 or 64 bits).

  • (defaults to: :big)

    endianess of bit attribute as an integer (:big, :little or :native)

  • hash associating field names with their size. Total size MUST be equal to width.

Returns:



60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/bin_struct/bit_attr.rb', line 60

def create(width:, endian: :big, **fields)
  raise ArgumentError, 'with must be 8, 16, 24, 32 or 64' unless [8, 16, 24, 32, 64].include?(width)

  hsh = compute_hash(width, endian, fields)
  cached = cache[hsh]
  return cached if cached

  total_size = fields.reduce(0) { |acc, ary| acc + ary.last }
  raise ArgumentError, "sum of bitfield sizes is not equal to #{width}" unless total_size == width

  cache[hsh] = create_subclass(width, endian, fields.dup.freeze)
end

Instance Method Details

#bit_methods::Array<Symbol>

Since:

  • 0.3.0

Returns:



152
153
154
# File 'lib/bin_struct/bit_attr.rb', line 152

def bit_methods
  self.class.bit_methods
end

#format_inspect::String

Since:

  • 0.3.0

Returns:



202
203
204
205
# File 'lib/bin_struct/bit_attr.rb', line 202

def format_inspect
  str = @int.format_inspect << "\n"
  str << @data.map { |name, value| "#{name}:#{value}" }.join(' ')
end

#from_human(value) ⇒ self

Set fields from associated integer

Since:

  • 0.3.0

Parameters:

Returns:



195
196
197
198
199
# File 'lib/bin_struct/bit_attr.rb', line 195

def from_human(value)
  ivalue = value.to_i
  @int.value = ivalue
  compute_data(ivalue)
end

#initialize_copyObject

Dup internal @data hash

Since:

  • 0.3.0



147
148
149
# File 'lib/bin_struct/bit_attr.rb', line 147

def initialize_copy(*)
  @data = @data.dup
end

#read(str) ⇒ self

Populate bit attribute from str

Since:

  • 0.3.0

Parameters:

Returns:



172
173
174
175
176
177
# File 'lib/bin_struct/bit_attr.rb', line 172

def read(str)
  return self if str.nil?

  @int.read(str)
  compute_data(@int.to_i)
end

#to_iInteger Also known as: to_human

Give integer associated to this attribute

Since:

  • 0.3.0

Returns:



181
182
183
# File 'lib/bin_struct/bit_attr.rb', line 181

def to_i
  @int.to_i
end

#to_s::String

Return binary string

Since:

  • 0.3.0

Returns:



188
189
190
# File 'lib/bin_struct/bit_attr.rb', line 188

def to_s
  @int.to_s
end

#type_name::String

Get type name

Since:

  • 0.3.0

Returns:



158
159
160
161
162
163
164
165
166
167
# File 'lib/bin_struct/bit_attr.rb', line 158

def type_name
  return @type_name if defined? @type_name

  endian_suffix = case @int.endian
                  when :big then ''
                  when :little then 'le'
                  when :native then 'n'
                  end
  @type_name = "BitAttr#{@width}#{endian_suffix}"
end