diff --git a/src/ZeroFormatter/Segments/DynamicObjectSegment.cs b/src/ZeroFormatter/Segments/DynamicObjectSegment.cs index 37e3eb3..3cdb33f 100644 --- a/src/ZeroFormatter/Segments/DynamicObjectSegment.cs +++ b/src/ZeroFormatter/Segments/DynamicObjectSegment.cs @@ -34,16 +34,28 @@ public static int GetOffset(ArraySegment originalBytes, int index, int las return originalBytes.Offset + readOffset; } - public static ArraySegment GetSegment(ArraySegment originalBytes, int index, int lastIndex, DirtyTracker tracker) + public static ArraySegment GetSegment(ArraySegment originalBytes, int index, int nextIndex, int lastIndex, DirtyTracker tracker) { var offset = GetOffset(originalBytes, index, lastIndex, tracker); if (offset == -1) { return default(ArraySegment); // note:very very dangerous. } - - var sliceLength = originalBytes.Offset + originalBytes.Count; - return new ArraySegment(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); // note: precondition failed. + } + count = nextOffset - offset; + } + return new ArraySegment(originalBytes.Array, offset, count); } public static T DeserializeSegment(ArraySegment originalBytes, int index, int lastIndex, DirtyTracker tracker) @@ -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 { @@ -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); diff --git a/tests/ZeroFormatter.Tests/CacheSegmentTest.cs b/tests/ZeroFormatter.Tests/CacheSegmentTest.cs new file mode 100644 index 0000000..c0841ca --- /dev/null +++ b/tests/ZeroFormatter.Tests/CacheSegmentTest.cs @@ -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 NestDict { get; set; } + [Index(1)] + public virtual int Int { get; set; } + } + + [TestClass] + public class CacheSegmentTest + { + [TestMethod] + public void Dictionary() + { + var _ = ZeroFormatterSerializer.Serialize( + new Dictionary + { + {"hoge", new DictionaryValueTest{Int=1}}, + {"foo", new DictionaryValueTest{Int=2}} + }); + var size = _.Length; + var dict = ZeroFormatterSerializer.Deserialize>(_); + + ZeroFormatterSerializer.Serialize(dict).Length.Is(size); + + dict["hoge"] = new DictionaryValueTest{Int=1}; + + ZeroFormatterSerializer.Serialize(dict).Length.Is(size); + } + } +} \ No newline at end of file diff --git a/tests/ZeroFormatter.Tests/ZeroFormatter.Tests.csproj b/tests/ZeroFormatter.Tests/ZeroFormatter.Tests.csproj index 1e5d935..a62ed15 100644 --- a/tests/ZeroFormatter.Tests/ZeroFormatter.Tests.csproj +++ b/tests/ZeroFormatter.Tests/ZeroFormatter.Tests.csproj @@ -65,6 +65,7 @@ +