2

If have multiple BinData Records that take the following form, here are a few examples:

class DebugInfo < BinData::Record
    endian :little

    int32 :num
    array :data, :type => :debug_log, initial_length: :num
end

class GoalInfo < BinData::Record
    endian :little

    int32 :num
    array :data, :type => :goal, initial_length: :num
end

class PackageInfo < BinData::Record
    endian :little

    int32 :num
    array :data, :type => :package, initial_length: :num
end

All of these are essentially the same, they just make an array using different types of objects. Is there a way to just make one of these and somehow pass it the type of object I want it to read into the array?

Fianite
  • 319
  • 2
  • 9

2 Answers2

0
module Info
  @base_classes = {}

  def self.[](type)
    @base_classes[type] ||= Class.new(BinData::Record) {
      endian :little
      int32 :num
      array :data, :type => type, initial_length: :num
    }
  end
end

then

class DebugInfo < Info[:debug_log]
end

class GoalInfo < Info[:goal]
end

class PackageInfo < Info[:package]
end

DISCLAIMER

Not tested.

Aetherus
  • 8,720
  • 1
  • 22
  • 36
0

BinData::Base.read passes all but its first argument (the IO object) directly to #initialize, so I think something like this would work:

class InfoRecord < BinData::Record
  endian :little

  int32 :num
  array :data, type: :array_type, initial_length: :num

  attr_reader :array_type

  def initialize(*args)
    @array_type = args.pop
    super
  end
end

InfoRecord.read(io, :debug_log)

That won't play nice with the DSL (info_record :my_record, ...), however.

To remedy that, I think you could do this instead:

class InfoRecord < BinData::Record
  # ...
  array :data, type: :array_type, initial_length: :num

  def array_type
    @params[:array_type]
  end
end

InfoRecord.read(io, array_type: :debug_log)

I'm less certain about the above because the way BinData::Base#initialize handles its Hash argument is a little complex, but hopefully it'll allow you to do e.g.:

class MyRecord < BinData::Record
  info_record :my_info, array_type: :debug_log
end
Jordan Running
  • 102,619
  • 17
  • 182
  • 182
  • Do I even need that example in the second part? Can't I just read using the InfoRecord itself instead of using it in a new Record? Also, in the second part InfoRecord, I'm getting the following error: `unknown type 'array_type' in InfoRecord` – Fianite Jun 11 '16 at 15:05
  • Hey Jordan, I tried both your solutions now and I seem to be getting to above error for both. – Fianite Jun 14 '16 at 22:22