Class: Ronin::Support::Binary::CTypes::UnionType Private

Inherits:
AggregateType show all
Defined in:
lib/ronin/support/binary/ctypes/union_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 union 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

#[], #dequeue_value, #enqueue_value

Constructor Details

#initialize(members, size:, alignment:) ⇒ UnionType

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 union type.

Parameters:

  • members (Hash{Symbol => Member})

    The members for the union type.

  • size (Integer)

    The size of the union type.

  • alignment (Integer)

    The alignment of the union type.

Since:

  • 1.0.0



118
119
120
121
122
123
124
# File 'lib/ronin/support/binary/ctypes/union_type.rb', line 118

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

  super(pack_string: nil)
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 union type, so that all members within the union type are themselves aligned.

Returns:

Since:

  • 1.0.0



104
105
106
# File 'lib/ronin/support/binary/ctypes/union_type.rb', line 104

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 union type.

Returns:

Since:

  • 1.0.0



93
94
95
# File 'lib/ronin/support/binary/ctypes/union_type.rb', line 93

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 union type.

Returns:

Since:

  • 1.0.0



98
99
100
# File 'lib/ronin/support/binary/ctypes/union_type.rb', line 98

def size
  @size
end

Class Method Details

.build(fields, alignment: nil) ⇒ UnionType

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 union type from the given fields.

Parameters:

  • fields (Hash{Symbol => Type})

    The field names and types for the union type.

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

    Custom alignment to use instead of the union's alignment.

Returns:

Since:

  • 1.0.0



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/ronin/support/binary/ctypes/union_type.rb', line 138

def self.build(fields, alignment: nil)
  members       = {}
  max_size      = 0
  max_alignment = 0

  fields.each do |name,type|
    members[name] = Member.new(type)

    # omit infinite sizes from the union size
    if (type.size > max_size) && (type.size != Float::INFINITY)
      max_size = type.size
    end

    max_alignment = type.alignment if type.alignment > max_alignment
  end

  return new(members, size:      max_size,
                      alignment: alignment || max_alignment)
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 union type with a different #alignment.

Parameters:

  • new_alignment (Integer)

    The new alignment for the new union type.

Returns:

Since:

  • 1.0.0



188
189
190
191
# File 'lib/ronin/support/binary/ctypes/union_type.rb', line 188

def align(new_alignment)
  self.class.new(@members, size:        @size,
                           alignment:   new_alignment)
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 union.

Returns:

Since:

  • 1.0.0



175
176
177
# File 'lib/ronin/support/binary/ctypes/union_type.rb', line 175

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 a hash of values into the member's binary layout.

Parameters:

Returns:

  • (String)

    The packed binary data.

Since:

  • 1.0.0



202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/ronin/support/binary/ctypes/union_type.rb', line 202

def pack(hash)
  unknown_keys = hash.keys - @members.keys

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

  buffer = if @size == Float::INFINITY
             String.new(encoding: Encoding::ASCII_8BIT)
           else
             String.new("\0" * @size, encoding: Encoding::ASCII_8BIT)
           end

  hash.each do |name,value|
    member = @members.fetch(name)
    data   = member.type.pack(value)

    if data.bytesize <= @size
      # if the packed data fits into buffer, overlay it
      buffer[0,data.bytesize] = data
    else
      # otherwise replace the buffer with the larger data
      buffer = data
    end
  end

  return buffer
end

#uninitialized_valueHash

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 union's uninitialized members.

Returns:

  • (Hash)

    The uninitialized values for the new union's members.

Since:

  • 1.0.0



164
165
166
167
168
# File 'lib/ronin/support/binary/ctypes/union_type.rb', line 164

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 union's binary layout.

Parameters:

  • data (String)

    The binary data to unpack.

Returns:

Since:

  • 1.0.0



241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/ronin/support/binary/ctypes/union_type.rb', line 241

def unpack(data)
  hash = {}

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

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

  return hash
end