2016-06-07 17 views
1

我不确定选择是否正是我需要的,但我会解释我正在尝试做什么。我有以下BinData结构工作正常。在Ruby中构建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. 如果类型是“StringProperty”,那么接下来的四个字节(int32)是一个int(字符串len),下一个(len * 8)是字符串本身。
  4. 如果类型是“ArrayProperty”,那么接下来的四个字节(int32)是一个int(len的数组),那么next接下来很多字节是len数组中的很多个Property对象(存储在一个数组中)。

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

回答

0

基于维基(和some of the tests),我认为这将是这个样子(买者自负:我没有访问您的数据,所以我真的不知道,如果这个工程)的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 

如果你愿意,你也能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 

现在我们的房地产类看起来会更加清晰:

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选项,但如果你使用这为阅读和不写作你可以跳过他们。我不太确定如何为:data_len编写:value选项;或许就像value: -> { data.num_bytes }

同样,我不知道上述任何一种方法是否有效,但希望它能起作用。

+0

非常感谢乔丹,这正是我需要的! [如果你确实有一分钟,我在这里问了一个更小的问题。](http://stackoverflow.com/questions/37692554/skipping-bytes-when-reading-with-bindata)最后一个,答应! – Fianite