Search code examples
arraysbinary-databindata

BinData::Record with Array read fails while write works


Per the example below, I am able to create a new BinData::Record that includes a BinData::Array element, and am able to create a binary string from new objects of that class type. However, when I then try to instantiate a new object from that binary string, the new object is not properly created.

require 'bindata'

class IntegerArray < BinData::Array
  uint16le initial_value: 0
end

class Test < BinData::Record
  integer_array :field
end

obj = Test.new
obj[:field] << 15

str = obj.to_binary_s

puts obj.inspect # {"field"=>[15]}
puts str.inspect # "\x0F\x00"
puts str.unpack("S<*") # 15

newobj = Test.read(str)

puts newobj.inspect # {"field"=>[]}

I've tried removing the array's initial_value with the same results. Thanks in advance for your help.


Solution

  • After experimenting a bit, I found the following solution works:

    require 'bindata'
    
    
    class NumberArray < BinData::Array
      uint16le initial_value: 0
    end
    
    class Test < BinData::Record
      number_array :field, read_until: :eof
    end
    
    obj = Test.new
    obj[:field].assign([1, 2, 3, 4, 5])
    
    str = obj.to_binary_s
    
    puts obj.num_bytes # 10
    puts obj.inspect # {"field"=>[1, 2, 3, 4, 5]}
    puts str.inspect # "\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00"
    
    newobj = Test.read(str)
    puts newobj.num_bytes # 10
    puts newobj.inspect # {"field"=>[1, 2, 3, 4, 5]}
    

    Note the use of read_until: :eof when defining the array field. Without this the read operation will only read to the defined value of initial_length (which is mutually exclusive with read_until).