Class: StructFu::IntString

Inherits:
Struct
  • Object
show all
Defined in:
lib/packetfu/structfu.rb

Overview

Provides a primitive for creating strings, preceeded by an Int type of length. By default, a string of length zero with a one-byte length is presumed.

Note that IntStrings aren't used for much, but it seemed like a good idea at the time.

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Struct

#force_binary

Constructor Details

#initialize(string = '', int = Int8, mode = nil) ⇒ IntString

Returns a new instance of IntString


185
186
187
188
189
190
191
192
# File 'lib/packetfu/structfu.rb', line 185

def initialize(string='',int=Int8,mode=nil)
  if int < Int
    super(int.new,string,mode)
    calc
  else
    raise "IntStrings need a StructFu::Int for a length."
  end
end

Instance Attribute Details

#intObject

Returns the value of attribute int

Returns:

  • (Object)

    the current value of int


183
184
185
# File 'lib/packetfu/structfu.rb', line 183

def int
  @int
end

#modeObject

Returns the value of attribute mode

Returns:

  • (Object)

    the current value of mode


183
184
185
# File 'lib/packetfu/structfu.rb', line 183

def mode
  @mode
end

#stringObject

Returns the value of attribute string

Returns:

  • (Object)

    the current value of string


183
184
185
# File 'lib/packetfu/structfu.rb', line 183

def string
  @string
end

Instance Method Details

#calcObject

Calculates the size of a string, and sets it as the value.


195
196
197
198
# File 'lib/packetfu/structfu.rb', line 195

def calc
  int.v = string.to_s.size
  self.to_s
end

#lenObject

Shorthand for querying a length. Note that the usual “length” and “size” refer to the number of elements of this struct.


226
227
228
# File 'lib/packetfu/structfu.rb', line 226

def len
  self[:int].value
end

#len=(i) ⇒ Object

Override the size, if you must.


231
232
233
# File 'lib/packetfu/structfu.rb', line 231

def len=(i)
  self[:int].value=i
end

#parse(s) ⇒ Object

parse() is like read(), except that it interprets the string, either based on the declared length, or the actual length. Which strategy is used is dependant on which :mode is set (with self.mode).

:parse : Read the length, and then read in that many bytes of the string. The string may be truncated or padded out with nulls, as dictated by the value.

:fix : Skip the length, read the rest of the string, then set the length to what it ought to be.

else : If neither of these modes are set, just perfom a normal read(). This is the default.


261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/packetfu/structfu.rb', line 261

def parse(s)
  unless s[0,int.width].size == int.width
    raise StandardError, "String is too short for type #{int.class}"
  else
    case mode 
    when :parse
      int.read(s[0,int.width])
      self[:string] = s[int.width,int.value]
      if string.size < int.value
        self[:string] += ("\x00" * (int.value - self[:string].size))
      end
    when :fix
      self.string = s[int.width,s.size]
    else
      return read(s)
    end
  end
  self.to_s
end

#read(s) ⇒ Object

Read takes a string, assumes an int width as previously defined upon initialization, but makes no guarantees the int value isn't lying. You're on your own to test for that (or use parse() with a :mode set).


239
240
241
242
243
244
245
246
247
# File 'lib/packetfu/structfu.rb', line 239

def read(s)
  unless s[0,int.width].size == int.width
    raise StandardError, "String is too short for type #{int.class}"
  else
    int.read(s[0,int.width])
    self[:string] = s[int.width,s.size]
  end
  self.to_s
end

#to_sObject

Returns the object as a string, depending on the mode set upon object creation.


201
202
203
204
205
206
207
208
209
210
# File 'lib/packetfu/structfu.rb', line 201

def to_s
  if mode == :parse
    "#{int}" + [string].pack("a#{len}")
  elsif mode == :fix
    self.int.v = string.size
    "#{int}#{string}"
  else
    "#{int}#{string}"
  end
end