Skip to content
This repository was archived by the owner on May 16, 2022. It is now read-only.

Fix unnecessary data is written when re-serializing non-trailing property #101

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions src/ZeroFormatter/Segments/DynamicObjectSegment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,28 @@ public static int GetOffset(ArraySegment<byte> originalBytes, int index, int las
return originalBytes.Offset + readOffset;
}

public static ArraySegment<byte> GetSegment(ArraySegment<byte> originalBytes, int index, int lastIndex, DirtyTracker tracker)
public static ArraySegment<byte> GetSegment(ArraySegment<byte> originalBytes, int index, int nextIndex, int lastIndex, DirtyTracker tracker)
{
var offset = GetOffset(originalBytes, index, lastIndex, tracker);
if (offset == -1)
{
return default(ArraySegment<byte>); // note:very very dangerous.
}

var sliceLength = originalBytes.Offset + originalBytes.Count;
return new ArraySegment<byte>(originalBytes.Array, offset, (sliceLength - offset));
int count;
if (nextIndex == -1 || nextIndex > lastIndex)
{
count = originalBytes.Offset + originalBytes.Count - offset; // last index
}
else
{
var nextOffset = GetOffset(originalBytes, nextIndex, lastIndex, tracker);
if (nextOffset == -1)
{
return default(ArraySegment<byte>); // note: precondition failed.
}
count = nextOffset - offset;
}
return new ArraySegment<byte>(originalBytes.Array, offset, count);
}

public static T DeserializeSegment<TTypeResolver, T>(ArraySegment<byte> originalBytes, int index, int lastIndex, DirtyTracker tracker)
Expand Down Expand Up @@ -430,13 +442,15 @@ static void BuildConstructor(TypeBuilder type, FieldInfo originalBytesField, Fie
il.Emit(OpCodes.Call, typeof(ObjectSegmentHelper).GetTypeInfo().GetMethod("CreateExtraFixedBytes"));
il.Emit(OpCodes.Stfld, extraFixedBytes);

foreach (var item in properties)
for (var i = 0; i < properties.Length; i++)
{
var item = properties[i];
if (item.IsFixedSize) continue;

if (item.IsCacheSegment)
{
AssignCacheSegment(il, item.Index, trackerField, lastIndexField, item.SegmentField);
var nextIndex = i + 1 < properties.Length ? properties[i + 1].Index : -1;
AssignCacheSegment(il, item.Index, nextIndex, trackerField, lastIndexField, item.SegmentField);
}
else
{
Expand All @@ -461,13 +475,14 @@ static void EmitNewArray(ILGenerator il, int[] array)
}
}

static void AssignCacheSegment(ILGenerator il, int index, FieldInfo tracker, FieldInfo lastIndex, FieldInfo field)
static void AssignCacheSegment(ILGenerator il, int index, int nextIndex, FieldInfo tracker, FieldInfo lastIndex, FieldInfo field)
{
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, tracker);
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Ldc_I4, index);
il.Emit(OpCodes.Ldc_I4, nextIndex);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldfld, lastIndex);
il.Emit(OpCodes.Ldarg_0);
Expand Down
39 changes: 39 additions & 0 deletions tests/ZeroFormatter.Tests/CacheSegmentTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ZeroFormatter.Formatters;
using ZeroFormatter.Segments;

namespace ZeroFormatter.Tests
{
[ZeroFormattable]
public class DictionaryValueTest
{
[Index(0)]
public virtual Dictionary<string, string> NestDict { get; set; }
[Index(1)]
public virtual int Int { get; set; }
}

[TestClass]
public class CacheSegmentTest
{
[TestMethod]
public void Dictionary()
{
var _ = ZeroFormatterSerializer.Serialize(
new Dictionary<string, DictionaryValueTest>
{
{"hoge", new DictionaryValueTest{Int=1}},
{"foo", new DictionaryValueTest{Int=2}}
});
var size = _.Length;
var dict = ZeroFormatterSerializer.Deserialize<Dictionary<string, DictionaryValueTest>>(_);

ZeroFormatterSerializer.Serialize(dict).Length.Is(size);

dict["hoge"] = new DictionaryValueTest{Int=1};

ZeroFormatterSerializer.Serialize(dict).Length.Is(size);
}
}
}
1 change: 1 addition & 0 deletions tests/ZeroFormatter.Tests/ZeroFormatter.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
</Otherwise>
</Choose>
<ItemGroup>
<Compile Include="CacheSegmentTest.cs" />
<Compile Include="EnumArraySerialize.cs" />
<Compile Include="MoreAdditionalCollectionTest.cs" />
<Compile Include="RelativeTest.cs" />
Expand Down