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.



212
213
214
215
216
217
218
219
# File 'lib/packetfu/structfu.rb', line 212

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



210
211
212
# File 'lib/packetfu/structfu.rb', line 210

def int
  @int
end

#modeObject

Returns the value of attribute mode

Returns:

  • (Object)

    the current value of mode



210
211
212
# File 'lib/packetfu/structfu.rb', line 210

def mode
  @mode
end

#stringObject

Returns the value of attribute string

Returns:

  • (Object)

    the current value of string



210
211
212
# File 'lib/packetfu/structfu.rb', line 210

def string
  @string
end

Instance Method Details

#calcObject

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



222
223
224
225
# File 'lib/packetfu/structfu.rb', line 222

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.



253
254
255
# File 'lib/packetfu/structfu.rb', line 253

def len
  self[:int].value
end

#len=(i) ⇒ Object

Override the size, if you must.



258
259
260
# File 'lib/packetfu/structfu.rb', line 258

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.



288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/packetfu/structfu.rb', line 288

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).



266
267
268
269
270
271
272
273
274
# File 'lib/packetfu/structfu.rb', line 266

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.



228
229
230
231
232
233
234
235
236
237
# File 'lib/packetfu/structfu.rb', line 228

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