在Ruby

时间:2016-06-07 15:54:08

标签: ruby bindata

我不确定选择是否符合我的要求,但我会解释我想要做的事情。我有以下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 string的值。

  1. 如果类型是&#34; IntProperty&#34;然后接下来的四个字节(int32)是一个int。
  2. 如果type是&#34; FloatProperty&#34;然后接下来的四个字节(float_32)是一个浮点数。
  3. 如果type是&#34; StringProperty&#34;接下来的四个字节(int32)是一个int(字符串的len),下一个(len * 8)是字符串本身。
  4. 如果type是&#34; ArrayProperty&#34;然后接下来的四个字节(int32)是一个int(数组的len),然后接下来很多字节是数组的len很多Property对象(存储在数组中)。
  5. 任何人都可以帮我弄清楚如何导航这些路径并正确设置BinData :: Record吗?

1 个答案:

答案 0 :(得分:0)

根据维基的Choice syntax部分(以及some of the tests),我认为它看起来像这样(警告经理:我没有访问您的数据,所以我真的不知道这是否有效):

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

如果您愿意,还可以make that a 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 }

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