首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Ruby构造BinData记录

用Ruby构造BinData记录
EN

Stack Overflow用户
提问于 2016-06-07 15:54:08
回答 1查看 654关注 0票数 1

我不确定选择到底是我在这里需要的,但我会解释我想做什么。下面的BinData结构工作得很好。

代码语言:javascript
复制
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 of string),下一个字节(len * 8)是字符串本身。
  4. 如果类型是"ArrayProperty“,那么接下来的四个字节(int32)是一个int (数组的len ),那么接下来多少字节是数组的len--许多属性对象(存储在数组中)。

有人能帮我找到如何导航这些路径并正确设置BinData::Record吗?

EN

回答 1

Stack Overflow用户

发布于 2016-06-07 21:11:04

基于wiki的选择语法部分(和一些测试),我认为它应该是这样的(注意:我不能访问您的数据,所以我真的不知道这是否有效):

代码语言:javascript
复制
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对,所以让我们将它们抽象到自己的类中:

代码语言:javascript
复制
class StringRecord < BinData::Record
  endian :little

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

如果你愿意,你也可以使之成为原始人

其中一种是"PropertyArray"类型:

代码语言:javascript
复制
class ArrayOfProperties < BinData::Record
  endian :little

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

现在,我们的属性类看起来要干净得多:

代码语言:javascript
复制
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

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

再一次,我不知道上面的任何一个是否会起作用,但希望它会有帮助。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37684026

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档