class PackedStruct::Package

Manages the struct overall, and keeps track of the directives. Directives are packed in the order that they are joined, such that the first one defined is the first one on the string.

Public Class Methods

new() click to toggle source

Initialize the package.

# File lib/packed_struct/package.rb, line 16
def initialize
  @directives = []
end

Public Instance Methods

directives() click to toggle source

The list of directives that the package has.

@return [Array<Directive>]

# File lib/packed_struct/package.rb, line 11
def directives
  @directives
end
fast_unpack(string) click to toggle source

This unpacks the entire string at once. It assumes that none of the directives will need the values of other directives. If you’re not sure what this means, don’t use it.

@param string [String] the packed string. @return [Hash<Symbol, Object>] the unpacked data.

# File lib/packed_struct/package.rb, line 99
def fast_unpack(string)
  out = string.unpack(to_s)
  parts = {}

  directives.each_with_index do |directive, i|
    parts[directive.name] = out[i]
  end

  parts.delete(:null) {}
  parts
end
finalize_directives!() click to toggle source

Finalizes all of the directives.

@return [void]

# File lib/packed_struct/package.rb, line 114
def finalize_directives!
  @finalized = true
  directives.reject!(&:empty?)
  directives.map(&:finalize!)
end
has_field?(field) click to toggle source

Checks to see if it has a field with the given name.

@return [Boolean]

# File lib/packed_struct/package.rb, line 123
def has_field?(field)
  !!directives.select { |d| d.name == field }.first
end
inspect() click to toggle source

Inspects the package.

@return [String]

# File lib/packed_struct/package.rb, line 130
def inspect
  "#<#{self.class.name}:#{"0x%014x" % directives.map(&:object_id).inject(&:+)}>"
end
method_missing(method, *arguments, &block) click to toggle source

Creates a new directive with the given method and arguments.

@return [Directive] the new directive.

Calls superclass method
# File lib/packed_struct/package.rb, line 137
def method_missing(method, *arguments, &block)
  super if @finalized
  if arguments.length == 1 && arguments.first.is_a?(Directive)
    arguments.first.add_modifier Modifier.new(method)
  else
    (directives.push Directive.new(method)).last
  end
end
pack(data) click to toggle source

Packs the given data into a string. The keys of the data correspond to the names of the directives.

@param data [Hash<Symbol, Object>] the data. @return [String] the packed data.

# File lib/packed_struct/package.rb, line 37
def pack(data)
  values = []
  data.each do |k, v|
    values.push([k, v])
  end

  mapped_directives = @directives.map(&:name)

  values = values.select { |x| mapped_directives.include?(x[0]) }

  values.sort! do |a, b|
    mapped_directives.index(a[0]) <=> mapped_directives.index(b[0])
  end

  ary = values.map(&:last)
  ary.pack to_s(data)
end
to_s(data = {}) click to toggle source

Turn the package into a string. Uses the directives (calls {Directive#to_s} on them), and joins the result.

@param data [Hash<Symbol, Object>] the data to pass to

{Directive#to_s}.

@return [String] the string ready for pack.

# File lib/packed_struct/package.rb, line 26
def to_s(data = {})
  directives.map { |x| x.to_s(data) }.join(' ')
end
Also aliased as: to_str
to_str(data = {})
Alias for: to_s
unpack(string) click to toggle source

Unpacks the given string with the directives. Returns a hash containing the values, with the keys being the names of the directives.

@param string [String] the packed string. @return [Hash<Symbol, Object>] the unpacked data.

# File lib/packed_struct/package.rb, line 61
def unpack(string)
  total = ""
  parts = {}

  directives.each_with_index do |directive, i|
    total << directive.to_s(parts)
    parts[directive.name] = string.unpack(total)[i]
  end

  parts.delete(:null) {}
  parts
end
unpack_from_socket(sock) click to toggle source

Unpacks from a socket.

@param sock [#read] the socket to unpack from. @return [Hash<Symbol, Object>] the unpacked data.

# File lib/packed_struct/package.rb, line 78
def unpack_from_socket(sock)
  read  = ""
  total = ""
  parts = {}

  directives.each_with_index do |directive, i|
    total << directive.to_s(parts)
    read << sock.read(directive.bytesize parts)
    parts[directive.name] = read.unpack(total)[i]
  end

  parts.delete(:null) {}
  parts
end