在Ruby中构造BinData记录

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

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

但是,在我得到:data_len后,我需要获取实际数据。 我如何处理接下来的内容取决于:type string的值。

  1. 如果type是“IntProperty”,则接下来的四个字节(int32)是一个int。
  2. 如果type是“FloatProperty”,则接下来的四个字节(float_32)是一个浮点数。
  3. 如果type是“StringProperty”,则接下来的四个字节(int32)是int(字符串的len),下一个(len * 8)是字符串本身。
  4. 如果type是“ArrayProperty”,则接下来的四个字节(int32)是一个int(数组的len),然后接下来很多字节是数组的len很多Property对象(存储在数组中)。

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

基于wiki的选择语法部分(以及一些测试 ),我认为它看起来像这样( 警告:我无法访问您的数据,所以我真的不知道这是否有效):

 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 

如果你愿意,你也可以把它作为原始 。

还有一个"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选项,但如果您使用它来阅读而不写,则可以跳过它们。 我不太确定如何编写:value选项:data_len ; 也许像value: -> { data.num_bytes }

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