Module: CTypes::Helpers

Extended by:
Helpers
Included in:
CTypes, Bitfield::Builder, Helpers, Importers::CastXML::Loader, Struct::Builder, Union::Builder
Defined in:
lib/ctypes/helpers.rb

Instance Method Summary collapse

Instance Method Details

#array(type, size = nil, terminator: nil) ⇒ Object

create an Array type

Examples:

# greedy array of uint32 values
array(uint32)
# array of 4 uint8 values
array(uint8, 4)
# array of signed 32-bit integers terminated with a -1
array(int32, terminator: -1)

Parameters:

  • type (Type)

    data type contained within the array

  • size (Integer) (defaults to: nil)

    optional array size; no size implies greedy array

  • terminator (defaults to: nil)

    optional unpacked value that represents the array terminator



153
154
155
# File 'lib/ctypes/helpers.rb', line 153

def array(type, size = nil, terminator: nil)
  Array.new(type:, size:, terminator:)
end

#bitfield(type = nil, bits = nil) { ... } ⇒ Object

create a Bitfield type

Examples:

dynamically sized

t = bitfield(a: 1, b: 2, c: 3)
t.pack({c: 0b111})    # => "\x38" (0b00111000)

fixed size to pad to 16 bits.

t = bitfield(uint16, a: 1, b: 2, c: 3)
t.pack({c: 0b111})    # => "\x38\x00" (0b00111000_00000000)

Parameters:

  • type (Type) (defaults to: nil)

    type to use for packed representation

  • bits (Hash) (defaults to: nil)

    map of name to bit count

Yields:



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/ctypes/helpers.rb', line 170

def bitfield(type = nil, bits = nil, &block)
  if bits.nil? && !block
    bits = type
    type = nil
  end

  Class.new(Bitfield) do
    if bits
      layout do
        bytes(type.size) if type
        bits.each do |name, size|
          unsigned name, size
        end
      end
    else
      layout(&block)
    end
  end
end

#bitmap(type = nil, bits = nil) ⇒ Object

create a Bitmap type

Examples:

32-bit bitmap

bitmap({a: 0, b: 1, c: 2})  # => #<Bitmap ...>

32-bit bitmap using block syntax; same as [Enum]

bitmap do |b|
  b << :a
  b << :b
end # => #<Bitmap a: 0, b: 1>

8-bit bitmap

bitmap(uint8, {a: 0, b: 1}) # => #<Bitmap a: 0, b: 1>

Parameters:

  • type (Type) (defaults to: nil)

    integer type to encode as; default min bytes required

  • bits (Hash, Enum) (defaults to: nil)

    map of names to bit position



61
62
63
64
65
66
67
68
69
# File 'lib/ctypes/helpers.rb', line 61

def bitmap(type = nil, bits = nil, &)
  if bits.nil?
    bits = type
    type = uint32
  end

  bits = enum(bits, &) unless bits.is_a?(Enum)
  Bitmap.new(type: type, bits: bits)
end

#enum(type = nil, values = nil) ⇒ Object

create an Enum type

Examples:

8-bit enum with two known values

t = enum(uint8, [:a, :b])
t.pack(:a)                  # => "\x00"
t.pack(:b)                  # => "\x01"
t.pack(:c)                  # Dry::Types::ConstraintError

sparse 32-bit enum

t = enum(uint32, {none: 0, a: 0x1000, b: 0x20})
t.pack(:none)               # => "\0\0\0\0"
t.pack(:a)                  # => "\x00\x10\x00\x00" (little endian)
t.pack(:b)                  # => "\x20\x00\x00\x00" (little endian)

sparse 32-bit enum using builder

t = enum(uint16) do |e|
  e << %i{a b c}            # a = 0, b = 1, c = 2
  e << {d: 16}              # d = 16
  e << :e                   # e = 17
end
t.pack(:e)                  # => "\x11\x00" (little endian)

Parameters:

  • type (Type) (defaults to: nil)

    integer type to encode as; default uint32

  • values (Array, Hash) (defaults to: nil)

    value names, or name-value pairs



41
42
43
# File 'lib/ctypes/helpers.rb', line 41

def enum(type = nil, values = nil, &)
  Enum.new(type, values, &)
end

#string(size = nil, trim: true) ⇒ Object

create a String type

Examples:

5 byte string

s = string(5)
s.unpack("hello world")   # => "hello")

Parameters:

  • size (Integer) (defaults to: nil)

    optional string size in bytes

  • trim (Boolean) (defaults to: true)

    set to false to preserve trailing null bytes when unpacking



79
80
81
# File 'lib/ctypes/helpers.rb', line 79

def string(size = nil, trim: true)
  String.new(size:, trim:)
end

#struct(attributes = nil) { ... } ⇒ Object

create a Struct type

Examples:

hash syntax

t = struct(id: uint32, name: string.terminated)
t.pack({id: 1, name: "Karlach"})    # => "\1\0\0\0Karlach\0"

block syntax

t = struct do
  attribute :id, uint32
  attrubite :name, string.terminated
end
t.pack({id: 1, name: "Karlach"})    # => "\1\0\0\0Karlach\0"

Parameters:

  • attributes (Hash) (defaults to: nil)

    name/type attribute pairs

Yields:



97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/ctypes/helpers.rb', line 97

def struct(attributes = nil, &block)
  Class.new(Struct) do
    if attributes
      layout do
        attributes.each do |name, type|
          attribute name, type
        end
      end
    else
      layout(&block)
    end
  end
end

#union(members = nil) { ... } ⇒ Object

create a Union type

Examples:

hash syntax

t = union(word: uint32, halfword: uint16, byte: uint8)
t.pack({byte: 3})   # => "\x03\x00\x00\x00"

block syntax

t = union do
  member :word, uint32
  member :halfword, uint16
  member :byte, uint8
end
t.pack({byte: 3})   # => "\x03\x00\x00\x00"

Parameters:

  • members (Hash) (defaults to: nil)

    name/type member pairs

Yields:



126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/ctypes/helpers.rb', line 126

def union(members = nil, &block)
  Class.new(Union) do
    if members
      layout do
        members.each do |name, type|
          member name, type
        end
      end
    else
      layout(&block)
    end
  end
end