Class: PackedStruct::Package

Inherits:
Object
  • Object
show all
Defined in:
lib/packed_struct/package.rb

Overview

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.

Instance Method Summary collapse

Constructor Details

#initializePackage

Initialize the package.



16
17
18
# File 'lib/packed_struct/package.rb', line 16

def initialize
  @directives = []
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *arguments, &block) ⇒ Directive

Creates a new directive with the given method and arguments.

Returns:



137
138
139
140
141
142
143
144
# 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

Instance Method Details

#directivesArray<Directive>

The list of directives that the package has.

Returns:



11
12
13
# File 'lib/packed_struct/package.rb', line 11

def directives
  @directives
end

#fast_unpack(string) ⇒ Hash<Symbol, Object>

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.

Parameters:

  • string (String)

    the packed string.

Returns:

  • (Hash<Symbol, Object>)

    the unpacked data.



99
100
101
102
103
104
105
106
107
108
109
# 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!void

This method returns an undefined value.

Finalizes all of the directives.



114
115
116
117
118
# File 'lib/packed_struct/package.rb', line 114

def finalize_directives!
  @finalized = true
  directives.reject!(&:empty?)
  directives.map(&:finalize!)
end

#has_field?(field) ⇒ Boolean

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

Returns:

  • (Boolean)


123
124
125
# File 'lib/packed_struct/package.rb', line 123

def has_field?(field)
  !!directives.select { |d| d.name == field }.first
end

#inspectString

Inspects the package.

Returns:

  • (String)


130
131
132
# File 'lib/packed_struct/package.rb', line 130

def inspect
  "#<#{self.class.name}:#{"0x%014x" % directives.map(&:object_id).inject(&:+)}>"
end

#pack(data) ⇒ String

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

Parameters:

  • data (Hash<Symbol, Object>)

    the data.

Returns:

  • (String)

    the packed data.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# 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 = {}) ⇒ String Also known as: to_str

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

Parameters:

  • data (Hash<Symbol, Object>) (defaults to: {})

    the data to pass to Directive#to_s.

Returns:

  • (String)

    the string ready for #pack.



26
27
28
# File 'lib/packed_struct/package.rb', line 26

def to_s(data = {})
  directives.map { |x| x.to_s(data) }.join(' ')
end

#unpack(string) ⇒ Hash<Symbol, Object>

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

Parameters:

  • string (String)

    the packed string.

Returns:

  • (Hash<Symbol, Object>)

    the unpacked data.



61
62
63
64
65
66
67
68
69
70
71
72
# 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) ⇒ Hash<Symbol, Object>

Unpacks from a socket.

Parameters:

  • sock (#read)

    the socket to unpack from.

Returns:

  • (Hash<Symbol, Object>)

    the unpacked data.



78
79
80
81
82
83
84
85
86
87
88
89
90
91
# 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