Module: FFI::BitField::InstanceMethods

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

Overview

InstanceMethods provides methods for reading and writing bit field values. This module is included in BitStruct and ManagedBitStruct classes.

Instance Method Summary collapse

Instance Method Details

#[](member_name) ⇒ Integer

Reads a value from a bit field or regular field.

Examples:

Reading a bit field

struct[:flag1]  # => 1

Parameters:

  • member_name (Symbol)

    The name of the field to read

Returns:

  • (Integer)

    The value of the field



41
42
43
44
45
46
47
48
49
# File 'lib/ffi/bit_field/instance_methods.rb', line 41

def [](member_name)
  parent_name, start, width = member_value_info(member_name)
  if parent_name
    value = get_member_value(parent_name)
    (value >> start) & ((1 << width) - 1)
  else
    get_member_value(member_name)
  end
end

#[]=(member_name, value) ⇒ Integer

Writes a value to a bit field or regular field.

Examples:

Writing to a bit field

struct[:flag1] = 1

Writing a negative value (bit-flipped)

struct[:field] = -1  # Sets all bits to 1

Parameters:

  • member_name (Symbol)

    The name of the field to write

  • value (Integer)

    The value to write

Returns:

  • (Integer)

    The written value

Raises:

  • (ArgumentError)

    If the value is too large for the bit field

  • (ArgumentError)

    If the value is too small (negative) for the bit field

  • (ArgumentError)

    If the member name is not a valid bit field

  • (TypeError)

    If the value is not an Integer



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/ffi/bit_field/instance_methods.rb', line 65

def []=(member_name, value)
  # Ensure value is an Integer
  raise TypeError, "Value must be an Integer, got #{value.class}" unless value.is_a?(Integer)

  # Get bit field information
  field_info = member_value_info(member_name)

  # If not a bit field, delegate to regular field setter
  return set_member_value(member_name, value) unless field_info

  # Extract bit field information
  parent_name, start, width = field_info

  # Calculate max value for this bit width
  max_value = (1 << width) - 1

  # Handle negative values by bit-flipping
  if value.negative?
    # For negative values, we interpret them as bit-flipped positive values
    # For example, with 4 bits, -1 becomes 1111 (15), -2 becomes 1110 (14), etc.

    # Check if the negative value is within range
    # For bit-flipping, valid range is -(2^n) to -1
    min_value = -(1 << width)
    if value < min_value
      raise ArgumentError, "Value #{value} is too small for bit_length: #{width}, minimum is #{min_value}"
    end

    # Convert negative value to bit-flipped positive value
    # -1 -> 15, -2 -> 14, etc.
    value = max_value + value + 1

    # Sanity check after conversion
    if value.negative? || value > max_value
      raise ArgumentError, "Internal error: converted value #{value} is out of range for bit_length: #{width}"
    end
  elsif value > max_value
    # For positive values, check if they fit in the bit width
    raise ArgumentError, "Value #{value} is too large for bit_length: #{width}, maximum is #{max_value}"
  end

  # Update the parent field with the new bit field value
  parent_value = get_member_value(parent_name)
  mask = ((1 << width) - 1) << start
  new_value = (parent_value & ~mask) | ((value & ((1 << width) - 1)) << start)

  set_member_value(parent_name, new_value)
end

#bit_field_membersHash

Returns a hash of bit fields grouped by parent field. Instance method version of the class method with the same name.

Examples:

Get bit field members in a struct instance

flags = Flags.new
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



16
17
18
# File 'lib/ffi/bit_field/instance_methods.rb', line 16

def bit_field_members
  self.class.bit_field_members
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 instance

flags = Flags.new
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



30
31
32
# File 'lib/ffi/bit_field/instance_methods.rb', line 30

def bit_field_offsets
  self.class.bit_field_offsets
end