Permalink
Browse files

Array wip support

  • Loading branch information...
1 parent dead68e commit 177c73350c3b75451882d68f4f063d0f89d680e6 @aki017 committed Nov 28, 2016
@@ -46,11 +46,65 @@ def dump(value)
data_headers[field[:index]] = header_size + data.bytesize
v = value.send(field[:name])
+
if field[:options][:nullable]
+ # nullable
+ #
+ # [hasValue:bool(1)]
+ # [T]
+ #
data << Utils.write_u1(v.nil? ? 0 : 1)
end
- data << get_serializer(field[:type]).serialize(v)
+ if field[:options][:array]
+ serializer = get_serializer(field[:type])
+ bytesize = serializer.bytesize
+
+ if bytesize >= 0
+ # fixed-length format
+ #
+ # [length:int(4)]
+ # [elements:T...]
+ #
+ if v.nil?
+ data << Utils.write_s4(-1)
+ next
+ end
+
+ data << Utils.write_s4(v.size)
+
+ v.each do |vv|
+ data << serializer.serialize(vv)
+ end
+ else
+ # variable-length format
+ #
+ # [byteSize:int(4)]
+ # [length:int(4)]
+ # [elementOffset...:int(4 * length)]
+ # [elements:T...]
+ #
+ offsets = ""
+ elements = ""
+
+ if v.nil?
+ bytesize = 8
+ length = -1
+ else
+ length = v.size
+ v.each do |vv|
+ offsets << Utils.write_s4(8+v.size*4+elements.size)
+ elements << get_serializer(field[:type]).serialize(vv)
+ end
+ end
+ data << Utils.write_s4(8+offsets.bytesize+elements.bytesize)
+ data << Utils.write_s4(length)
+ data << offsets
+ data << elements
+ end
+ else
+ data << get_serializer(field[:type]).serialize(v)
+ end
end
data_headers.each do |h|
@@ -80,15 +134,58 @@ def load(klass, bytes)
klass.fields.each do |field|
index = field[:index]
offset = Utils.read_s4(bytes, 8+4*index)
+
if field[:options][:nullable]
+ # nullable
+ #
+ # [hasValue:bool(1)]
+ # [T]
+ #
if Utils.read_u1(bytes, offset) == 0
result.send("#{field[:name]}=", nil)
next
end
offset += 1
end
- value = get_serializer(field[:type]).deserialize(bytes, offset, field)
+ if field[:options][:array]
+ serializer = get_serializer(field[:type])
+ bytesize = serializer.bytesize
+
+ if bytesize >= 0
+ # fixed-length format
+ #
+ # [length:int(4)]
+ # [elements:T...]
+ #
+ obj_count = Utils.read_s4(bytes, offset)
+ if obj_count == -1
+ value = nil
+ else
+ value = (0..(obj_count-1)).map{|i|
+ serializer.deserialize(bytes, offset+4+i*bytesize, field)
+ }
+ end
+ else
+ # variable-length format
+ #
+ # [byteSize:int(4)]
+ # [length:int(4)]
+ # [elementOffset...:int(4 * length)]
+ # [elements:T...]
+ #
+ elements_length = Utils.read_s4(bytes, offset + 4)
+
+ if elements_length == -1
+ value = nil
+ else
+ elements_offsets = elements_length.times.map{|i| Utils.read_s4(bytes, offset + 8 + 4 * i)}
+ value = elements_offsets.map{|o| serializer.deserialize(bytes, offset+o) }
+ end
+ end
+ else
+ value = get_serializer(field[:type]).deserialize(bytes, offset, field)
+ end
result.send("#{field[:name]}=", value)
end
@@ -3,6 +3,11 @@ class Serializer
module BoolSerializer
extend self
Alias = %i(bool boolean)
+
+ def bytesize
+ 1
+ end
+
def serialize(value)
Utils.write_u1(value ? 1 : 0)
end
@@ -3,6 +3,11 @@ class Serializer
module FloatSerializer
extend self
Alias = %i(single float)
+
+ def bytesize
+ 4
+ end
+
def serialize(value)
Utils.write_f4(value)
end
@@ -15,6 +20,11 @@ def deserialize(bytes, offset=0, options={})
module DoubleSerializer
extend self
Alias = %i(double)
+
+ def bytesize
+ 8
+ end
+
def serialize(value)
Utils.write_d8(value)
end
@@ -3,6 +3,11 @@ class Serializer
module Int8Serializer
extend self
Alias = %i(sbyte int8 int_8)
+
+ def bytesize
+ 1
+ end
+
def serialize(value)
Utils.write_s1(value)
end
@@ -15,6 +20,11 @@ def deserialize(bytes, offset=0, options={})
module Int16Serializer
extend self
Alias = %i(short int16 int_16)
+
+ def bytesize
+ 2
+ end
+
def serialize(value)
Utils.write_s2(value)
end
@@ -27,6 +37,11 @@ def deserialize(bytes, offset=0, options={})
module Int32Serializer
extend self
Alias = %i(int int32 int_32)
+
+ def bytesize
+ 4
+ end
+
def serialize(value)
Utils.write_s4(value)
end
@@ -39,6 +54,11 @@ def deserialize(bytes, offset=0, options={})
module Int64Serializer
extend self
Alias = %i(long int64 int_64)
+
+ def bytesize
+ 8
+ end
+
def serialize(value)
Utils.write_s8(value)
end
@@ -3,6 +3,11 @@ class Serializer
module ObjectSerializer
extend self
Alias = %i(object)
+
+ def bytesize
+ -1
+ end
+
def serialize(value)
ZeroFormatter.dump(value)
end
@@ -3,6 +3,11 @@ class Serializer
module CharSerializer
extend self
Alias = %i(char)
+
+ def bytesize
+ 2
+ end
+
def serialize(value)
bytesize = (value || "").bytesize
result = value || ""
@@ -17,6 +22,11 @@ def deserialize(bytes, offset=0, options={})
module StringSerializer
extend self
Alias = %i(string str)
+
+ def bytesize
+ -1
+ end
+
def serialize(value)
value ||= ""
@@ -3,6 +3,11 @@ class Serializer
module TimeSpanSerializer
extend self
Alias = %i(timespan duration)
+
+ def bytesize
+ 12
+ end
+
def serialize(value)
value ||= { seconds: 0, nanos: 0 }
Utils.write_s8(value[:seconds]) + Utils.write_s4(value[:nanos])
@@ -19,6 +24,11 @@ def deserialize(bytes, offset=0, options={})
module TimeSerializer
extend self
Alias = %i(datetime time)
+
+ def bytesize
+ 12
+ end
+
def serialize(value)
value ||= Time.at(0)
Utils.write_s8(value.to_i) << Utils.write_s4(value.nsec)
@@ -32,6 +42,11 @@ def deserialize(bytes, offset=0, options={})
module TimeWithOffsetSerializer
extend self
Alias = %i(datetime_with_offset time_with_offset)
+
+ def bytesize
+ 14
+ end
+
def serialize(value)
value ||= {time: Time.at(0), time_offset: 0}
Utils.write_s8(value[:time].to_i + value[:time_offset]*60) << Utils.write_s4(value[:time].nsec) << Utils.write_s2(value[:time_offset])
@@ -3,6 +3,11 @@ class Serializer
module UInt8Serializer
extend self
Alias = %i(byte uint8 uint_8)
+
+ def bytesize
+ 1
+ end
+
def serialize(value)
Utils.write_u1(value)
end
@@ -15,6 +20,11 @@ def deserialize(bytes, offset=0, options={})
module UInt16Serializer
extend self
Alias = %i(ushort uint16 uint_16)
+
+ def bytesize
+ 2
+ end
+
def serialize(value)
Utils.write_u2(value)
end
@@ -27,6 +37,11 @@ def deserialize(bytes, offset=0, options={})
module UInt32Serializer
extend self
Alias = %i(uint uint32 uint_32)
+
+ def bytesize
+ 4
+ end
+
def serialize(value)
Utils.write_u4(value)
end
@@ -39,6 +54,11 @@ def deserialize(bytes, offset=0, options={})
module UInt64Serializer
extend self
Alias = %i(ulong uint64 uint_64)
+
+ def bytesize
+ 8
+ end
+
def serialize(value)
Utils.write_u8(value)
end
View
@@ -0,0 +1,30 @@
+require 'test_helper'
+
+class RecursiveTest < Minitest::Test
+ def test_fixed
+ value = FixedDataClass.new
+ value.values = [1,2,3,4,5]
+
+ bytes = ZeroFormatter.dump(value)
+ assert_equal bytes.bytes, ZeroFormatter.dump(ZeroFormatter.load(FixedDataClass, bytes)).bytes
+ assert_equal [1,2,3,4,5], ZeroFormatter.load(FixedDataClass, bytes).values
+ end
+
+ def test_variable
+ value = VariableDataClass.new
+ value.messages = ["hello", "world"]
+
+ bytes = ZeroFormatter.dump(value)
+ assert_equal ["hello", "world"], ZeroFormatter.load(VariableDataClass, bytes).messages
+ assert_equal bytes.bytes, ZeroFormatter.dump(ZeroFormatter.load(VariableDataClass, bytes)).bytes
+ end
+
+ class FixedDataClass
+ include ZeroFormatter::ZeroFormattable
+ field :values, :int, array: true
+ end
+ class VariableDataClass
+ include ZeroFormatter::ZeroFormattable
+ field :messages, :string, array: true
+ end
+end

0 comments on commit 177c733

Please sign in to comment.