1

我不确定选择是否正是我在这里需要的,但我会解释我正在尝试做的事情。我有以下可以正常工作的 BinData 结构。

class Property < BinData::Record
    endian :little

    int32  :name_len
    string :name, :read_length => :name_len
    int32  :type_len
    string :type, :read_length => :type_len
    int64  :data_len
end

但是,在获得 :data_len 之后,我需要获取实际数据。我如何处理接下来的事情取决于 :type 字符串的值。

  1. 如果类型是“IntProperty”,那么接下来的四个字节 (int32) 是一个 int。
  2. 如果类型是“FloatProperty”,那么接下来的四个字节(float_32)是一个浮点数。
  3. 如果 type 是 "StringProperty" 那么接下来的四个字节 (int32) 是一个 int (len of string) 并且下一个 (len * 8) 是字符串本身。
  4. 如果类型是“ArrayProperty”,那么接下来的四个字节(int32)是一个 int(数组的 len),那么接下来的字节数是数组的许多属性对象的 len(存储在一个数组中)。

任何人都可以帮助我弄清楚如何导航这些路径并正确设置 BinData::Record 吗?

4

1 回答 1

0

根据 wiki 的Choice syntax部分(和一些测试),我认为它看起来像这样(警告:我无权访问您的数据,所以我真的不知道这是否有效):

class Property < BinData::Record
  endian :little

  int32  :name_len
  string :name, read_length: :name_len

  int32 :type_len
  string :type, read_length: :type_len

  int64 :data_len    
  choice :data, selection: :type do
    # if type is "IntProperty" then the next four bytes (int32) is an int.
    int32 "IntProperty"

    # if type is "FloatProperty" then the next four bytes (float_32) is a float.
    float "FloatProperty"

    # if type is "StringProperty" then the next four bytes (int32) is an int (len
    # of string) and the next (len * 8) are the string itself.
    struct "StringProperty" do
      int32 :len
      string :data, read_length: :len
    end

    # if type is "ArrayProperty" then the next four bytes (int32) is an int (len
    # of array), then next however many bytes is len of array many Property objects
    # (to store in an array).
    struct "ArrayProperty" do
      int32 :num_properties
      array :properties, type: :property, initial_length: :num_items
    end
  end
end

但是,我认为将其分成几类是有益的。我们在几个地方有int32/string对,所以让我们将它们抽象到他们自己的类中:

class StringRecord < BinData::Record
  endian :little

  int32 :len, value: -> { data.length }
  string :data, read_length: :len
end

如果您愿意,您也可以将其设为 Primitive

还有一种"PropertyArray"类型:

class ArrayOfProperties < BinData::Record
  endian :little

  int32 :num_properties, value: -> { properties.size }
  array :properties, type: :property, initial_length: :num_items
end

现在我们的 Property 类看起来干净多了:

class Property < BinData::Record
  endian :little

  string_record :name
  string_record :type

  int64 :data_len    
  choice :data, selection: :type do
    int32 "IntProperty"
    float "FloatProperty"
    string_record "StringProperty"
    array_of_properties "ArrayProperty"
  end
end

我已经:value为长度字段指定了选项,但是如果您将其用于阅读而不是写作,则可以跳过它们。我不太确定如何为;编写:value选项。:data_len也许像value: -> { data.num_bytes }.

同样,我不知道上述任何一项是否有效,但希望它会有所帮助。

于 2016-06-07T21:11:04.357 回答