2

如果有多个采用以下形式的 BinData 记录,这里有几个示例:

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

所有这些本质上都是相同的,它们只是使用不同类型的对象创建一个数组。有没有办法只制作其中一个并以某种方式将我希望它读入数组的对象类型传递给它?

4

2 回答 2

0

BinData::Base.read将除第一个参数(IO 对象)以外的所有参数直接传递给#initialize,所以我认为这样的事情会起作用:

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)

但是,这对 DSL ( info_record :my_record, ...) 来说并不好。

为了解决这个问题,我认为你可以这样做:

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)

我对上述内容不太确定,因为BinData::Base#initialize处理其 Hash 参数的方式有点复杂,但希望它能让你这样做:

class MyRecord < BinData::Record
  info_record :my_info, array_type: :debug_log
end
于 2016-06-11T04:02:07.777 回答
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

然后

class DebugInfo < Info[:debug_log]
end

class GoalInfo < Info[:goal]
end

class PackageInfo < Info[:package]
end

免责声明

未测试。

于 2016-06-11T03:47:30.767 回答