class Ronin::Support::Binary::CTypes::UnionType
Represents a ‘union` type.
@api private
@since 1.0.0
Attributes
The alignment, in bytes, for the union type, so that all members within the union type are themselves aligned.
@return [Integer]
The members of the union type.
@return [Hash{Symbol => Member}]
The size of the union type.
@return [Integer, Float::INFINITY]
Public Class Methods
Builds the union type from the given fields.
@param [Hash{Symbol => Type}] fields
The field names and types for the union type.
@param [Integer, nil] alignment
Custom alignment to use instead of the union's alignment.
@return [UnionType]
The new union type.
# 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
Initializes the union type.
@param [Hash{Symbol => Member}] members
The members for the union type.
@param [Integer] size
The size of the union type.
@param [Integer] alignment
The alignment of the union type.
# 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
Public Instance Methods
Creates a copy of the union type with a different {#alignment}.
@param [Integer] new_alignment
The new alignment for the new union type.
@return [ScalarType]
The new union type.
# 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
The number of members within the union.
@return [Integer]
# File lib/ronin/support/binary/ctypes/union_type.rb, line 175 def length @members.length end
Packs a hash of values into the member’s binary layout.
@param [Hash{Symbol => Integer
, Float
, String}] hash
The hash of values to pack.
@return [String]
The packed binary data.
# 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
Creates a new Hash of the union’s uninitialized members.
@return [Hash]
The uninitialized values for the new union's members.
# 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
Unpacks binary data into a Hash of values using the union’s binary layout.
@param [String] data
The binary data to unpack.
@return [Hash{Symbol => Integer
, Float
, String
, nil}]
The unpacked hash.
# 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