Module: FFI::BitField::ClassMethods

Included in:
FFI::BitStruct, ManagedBitStruct
Defined in:
lib/ffi/bit_field/class_methods.rb

Overview

ClassMethods provides methods for defining bit field layouts. This module is extended by BitStruct and ManagedBitStruct classes.

Instance Method Summary collapse

Instance Method Details

#bit_field_layoutHash

Returns a hash of bit fields with detailed layout information.

Examples:

Get detailed bit field layout in a struct

class Flags < FFI::BitStruct
  layout \
    :value, :uint8

  bit_fields :value,
    :read,    1,
    :write,   1,
    :execute, 1,
    :unused,  5
end

Flags.bit_field_layout
# => {
#      :value => {
#        :read    => { :start => 0, :width => 1 },
#        :write   => { :start => 1, :width => 1 },
#        :execute => { :start => 2, :width => 1 },
#        :unused  => { :start => 3, :width => 5 }
#      }
#    }

Returns:

  • (Hash)

    A hash where keys are parent field names and values are hashes of bit field details



62
63
64
65
66
67
68
69
70
71
72
# File 'lib/ffi/bit_field/class_methods.rb', line 62

def bit_field_layout
  return {} unless instance_variable_defined?(:@bit_field_hash_table)

  result = {}
  @bit_field_hash_table.each do |field_name, info|
    parent_name, start, width = info
    result[parent_name] ||= {}
    result[parent_name][field_name] = { start: start, width: width }
  end
  result
end

#bit_field_membersHash

Returns a hash of bit fields grouped by parent field.

Examples:

Get bit field members in a struct

class Flags < FFI::BitStruct
  layout \
    :value, :uint8

  bit_fields :value,
    :read,    1,
    :write,   1,
    :execute, 1,
    :unused,  5
end

Flags.bit_field_members  # => {:value => [:read, :write, :execute, :unused]}

Returns:

  • (Hash)

    A hash where keys are parent field names and values are arrays of bit field names



25
26
27
28
29
30
31
32
33
34
35
# File 'lib/ffi/bit_field/class_methods.rb', line 25

def bit_field_members
  return {} unless instance_variable_defined?(:@bit_field_hash_table)

  result = {}
  @bit_field_hash_table.each do |field_name, info|
    parent_name = info[0]
    result[parent_name] ||= []
    result[parent_name] << field_name
  end
  result
end

#bit_field_offsetsHash

Returns a hash of bit fields with their bit offsets, grouped by parent field.

Examples:

Get bit field offsets in a struct

class Flags < FFI::BitStruct
  layout \
    :value, :uint8

  bit_fields :value,
    :read,    1,
    :write,   1,
    :execute, 1,
    :unused,  5
end

Flags.bit_field_offsets
# => {
#      :value => [[:read, 0], [:write, 1], [:execute, 2], [:unused, 3]]
#    }

Returns:

  • (Hash)

    A hash where keys are parent field names and values are arrays of [bit_field_name, bit_offset] pairs



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/ffi/bit_field/class_methods.rb', line 94

def bit_field_offsets
  return {} unless instance_variable_defined?(:@bit_field_hash_table)

  result = {}

  # Get byte offsets of parent fields
  field_offsets = offsets.to_h

  # Process each bit field
  @bit_field_hash_table.each do |field_name, info|
    parent_name, start, _width = info

    # Get byte offset of parent field
    parent_offset = field_offsets[parent_name]
    next unless parent_offset

    # Convert byte offset to bit offset and add bit field's start position
    bit_offset = parent_offset * 8 + start

    # Add to result
    result[parent_name] ||= []
    result[parent_name] << [field_name, bit_offset]
  end

  # Return result
  result
end

#bit_fields(*layout_args) ⇒ Symbol Also known as: bit_field

Note:

The total bit width should not exceed the size of the parent field. For example, a :uint8 field can hold at most 8 bits.

Defines bit fields within a parent field.

Examples:

Define bit fields in an 8-bit integer

bit_fields :flags,
  :read,    1,  # 1 bit for read permission
  :write,   1,  # 1 bit for write permission
  :execute, 1,  # 1 bit for execute permission
  :unused,  5   # 5 unused bits

Parameters:

  • layout_args (Array)

    An array where the first element is the parent field name, followed by alternating field name and bit width pairs

Returns:

  • (Symbol)

    parent_name The name of the parent field



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/ffi/bit_field/class_methods.rb', line 137

def bit_fields(*layout_args)
  # The reason for using class instance variable here instead of class variable
  # is not because class instance variables are clean,
  # but because sub-class of FFI::Struct cannot be inherited again.
  @bit_field_hash_table = {} unless instance_variable_defined?(:@bit_field_hash_table)

  parent_name = layout_args.shift.to_sym
  member_names = []
  widths = []
  layout_args.each_slice(2) do |name, width|
    member_names << name.to_sym
    widths << width.to_i
  end
  starts = widths.inject([0]) do |result, width|
    result << (result.last + width)
  end
  member_names.zip(starts, widths).each do |name, start, width|
    @bit_field_hash_table[name] = [parent_name, start, width]
  end

  parent_name
end