Class: Ronin::Support::Binary::CTypes::StructType Private

Inherits:
AggregateType show all
Defined in:
lib/ronin/support/binary/ctypes/struct_type.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Represents a struct type.

Since:

  • 1.0.0

Defined Under Namespace

Classes: Member

Instance Attribute Summary collapse

Attributes inherited from Type

#pack_string

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Type

#[]

Constructor Details

#initialize(members, size:, alignment:, pack_string:) ⇒ StructType

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Initializes the struct type.

Parameters:

  • members (Hash{Symbol => Member})

    The members for the struct type.

  • alignment (Integer, nil)

    Optional custom alignment the struct type.

  • pack_string (String, nil)

    The String for Array#pack or String#unpack.

Since:

  • 1.0.0



153
154
155
156
157
158
159
# File 'lib/ronin/support/binary/ctypes/struct_type.rb', line 153

def initialize(members, size: , alignment: , pack_string: )
  @members   = members
  @size      = size
  @alignment = alignment

  super(pack_string: pack_string)
end

Instance Attribute Details

#alignmentInteger (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The alignment, in bytes, for the struct type, so that all members within the struct type are themselves aligned.

Returns:

Since:

  • 1.0.0



139
140
141
# File 'lib/ronin/support/binary/ctypes/struct_type.rb', line 139

def alignment
  @alignment
end

#membersHash{Symbol => Member} (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The members of the struct type.

Returns:

Since:

  • 1.0.0



128
129
130
# File 'lib/ronin/support/binary/ctypes/struct_type.rb', line 128

def members
  @members
end

#sizeInteger, Float::INFINITY (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The size of the struct type.

Returns:

Since:

  • 1.0.0



133
134
135
# File 'lib/ronin/support/binary/ctypes/struct_type.rb', line 133

def size
  @size
end

Class Method Details

.build(fields, alignment: nil, padding: true) ⇒ StructType

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Builds the struct type from the given fields.

Parameters:

  • fields (Hash{Symbol => Type})

    The field names and types for the struct type.

  • alignment (Integer, nil) (defaults to: nil)

    Optional custom alignment the struct type.

  • padding (Boolean) (defaults to: true)

    Controls whether to pad struct members for alignment.

Returns:

Since:

  • 1.0.0



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/ronin/support/binary/ctypes/struct_type.rb', line 176

def self.build(fields, alignment: nil, padding: true)
  members       = {}
  max_alignment = 0
  pack_string   = String.new(encoding: Encoding::ASCII_8BIT)

  offset = 0

  fields.each do |name,type|
    pad = if padding then Member.padding_for(offset,type)
          else            0
          end

    members[name] = Member.new(offset + pad,type)
    max_alignment = type.alignment if type.alignment > max_alignment

    if pack_string
      if type.pack_string
        pack_string << Member.pack_string_for(type,pad)
      else
        pack_string = nil
      end
    end

    # omit infinite sizes from the struct size
    unless type.size == Float::INFINITY
      offset += type.size + pad
    end
  end

  return new(members, size:        offset,
                      alignment:   alignment || max_alignment,
                      pack_string: pack_string)
end

Instance Method Details

#align(new_alignment) ⇒ ScalarType

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Creates a copy of the struct type with a different #alignment.

Parameters:

  • new_alignment (Integer)

    The new alignment for the new struct type.

Returns:

Since:

  • 1.0.0



240
241
242
243
244
# File 'lib/ronin/support/binary/ctypes/struct_type.rb', line 240

def align(new_alignment)
  self.class.new(@members, size:        @size,
                           alignment:   new_alignment,
                           pack_string: pack_string)
end

#dequeue_value(values) ⇒ Hash

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Dequeues a Hash from the flat list of values.

Parameters:

  • values (Array)

    The flat array of values.

Returns:

  • (Hash)

    The dequeued hash.

Since:

  • 1.0.0



345
346
347
348
349
350
351
352
353
# File 'lib/ronin/support/binary/ctypes/struct_type.rb', line 345

def dequeue_value(values)
  hash = {}

  @members.each do |name,member|
    hash[name] = member.type.dequeue_value(values)
  end

  return hash
end

#enqueue_value(values, hash) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Enqueues a Hash of values onto the flat list of values.

Parameters:

  • values (Array)

    The flat array of values.

  • hash (Hash)

    The hash to enqueue.

Since:

  • 1.0.0



320
321
322
323
324
325
326
327
328
329
330
331
332
# File 'lib/ronin/support/binary/ctypes/struct_type.rb', line 320

def enqueue_value(values,hash)
  unknown_keys = hash.keys - @members.keys

  unless unknown_keys.empty?
    raise(ArgumentError,"unknown struct members: #{unknown_keys.map(&:inspect).join(', ')}")
  end

  @members.each do |name,member|
    value = hash[name] || member.type.uninitialized_value

    member.type.enqueue_value(values,value)
  end
end

#lengthInteger

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The number of members within the struct.

Returns:

Since:

  • 1.0.0



227
228
229
# File 'lib/ronin/support/binary/ctypes/struct_type.rb', line 227

def length
  @members.length
end

#pack(hash) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Packs the hash of values into the struct's binary layout.

Parameters:

Returns:

  • (String)

    The packed binary data.

Since:

  • 1.0.0



255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/ronin/support/binary/ctypes/struct_type.rb', line 255

def pack(hash)
  if @pack_string
    super(hash)
  else
    buffer = String.new("\0" * @size, encoding: Encoding::ASCII_8BIT)

    hash.each do |name,value|
      member = @members.fetch(name) do
        raise(ArgumentError,"unknown struct member (#{name.inspect}), must be: #{@members.keys.map(&:inspect).join(', ')}")
      end

      data = member.type.pack(value)

      if member.size == Float::INFINITY
        buffer[member.offset..] = data
      else
        buffer[member.offset,member.size] = data
      end
    end

    return buffer
  end
end

#uninitialized_valueHash{Symbol => Object}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Creates a new Hash of the struct's uninitialized members.

Returns:

  • (Hash{Symbol => Object})

    The uninitialized values for the new struct's members.

Since:

  • 1.0.0



216
217
218
219
220
# File 'lib/ronin/support/binary/ctypes/struct_type.rb', line 216

def uninitialized_value
  @members.transform_values do |member|
    member.type.uninitialized_value
  end
end

#unpack(data) ⇒ Hash{Symbol => Integer, Float, String, nil}

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Unpacks binary data into a Hash of values using the struct's binary layout.

Parameters:

  • data (String)

    The binary data to unpack.

Returns:

Since:

  • 1.0.0



289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/ronin/support/binary/ctypes/struct_type.rb', line 289

def unpack(data)
  if @pack_string
    super(data)
  else
    hash = {}

    @members.each do |name,member|
      slice = if member.size == Float::INFINITY
                data.byteslice(member.offset..)
              else
                data.byteslice(member.offset,member.size)
              end

      hash[name] = member.type.unpack(slice)
    end

    return hash
  end
end