From 9bfbbc85e829143a2e4414f0c6c62edc6fc17421 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Concei=C3=A7=C3=A3o?= Date: Mon, 5 Sep 2022 21:53:23 +0100 Subject: [PATCH 1/7] Improve the FieldOffset --- .../Offset/BoundOffsetCurrentNoRewindClass.cs | 17 +++++ .../Offset/BoundOffsetJumpyNoRewindClass.cs | 28 ++++++++ BinarySerializer.Test/Offset/OffsetTests.cs | 19 +++++ BinarySerializer/FieldOffsetAttribute.cs | 47 +++++++++++-- BinarySerializer/Graph/TypeGraph/TypeNode.cs | 11 +++ .../Graph/ValueGraph/ValueNode.cs | 50 ++++++++++--- README.md | 70 ++++++++++++++++++- 7 files changed, 229 insertions(+), 13 deletions(-) create mode 100644 BinarySerializer.Test/Offset/BoundOffsetCurrentNoRewindClass.cs create mode 100644 BinarySerializer.Test/Offset/BoundOffsetJumpyNoRewindClass.cs diff --git a/BinarySerializer.Test/Offset/BoundOffsetCurrentNoRewindClass.cs b/BinarySerializer.Test/Offset/BoundOffsetCurrentNoRewindClass.cs new file mode 100644 index 00000000..c26e209a --- /dev/null +++ b/BinarySerializer.Test/Offset/BoundOffsetCurrentNoRewindClass.cs @@ -0,0 +1,17 @@ +using System.IO; + +namespace BinarySerialization.Test.Offset +{ + public class BoundOffsetCurrentNoRewindClass + { + [FieldOrder(0)] + public uint FieldOffsetField { get; set; } + + [FieldOrder(1)] + [FieldOffset(nameof(FieldOffsetField), SeekOrigin.Current, false)] + public uint Field { get; set; } + + [FieldOrder(2)] + public uint LastUInt { get; set; } +} +} \ No newline at end of file diff --git a/BinarySerializer.Test/Offset/BoundOffsetJumpyNoRewindClass.cs b/BinarySerializer.Test/Offset/BoundOffsetJumpyNoRewindClass.cs new file mode 100644 index 00000000..d0daaca2 --- /dev/null +++ b/BinarySerializer.Test/Offset/BoundOffsetJumpyNoRewindClass.cs @@ -0,0 +1,28 @@ +using System.IO; + +namespace BinarySerialization.Test.Offset +{ + public class BoundOffsetJumpyNoRewindClass + { + [FieldOrder(0)] + public uint FieldOffsetField1 { get; set; } + + [FieldOrder(1)] + [FieldOffset(nameof(FieldOffsetField1), false)] + public uint Field1 { get; set; } + + [FieldOrder(2)] + public uint FieldOffsetField2 { get; set; } + + [FieldOrder(3)] + [FieldOffset(nameof(FieldOffsetField2), false)] + public uint Field2 { get; set; } + + [FieldOrder(4)] + public uint FieldOffsetField3 { get; set; } + + [FieldOrder(5)] + [FieldOffset(nameof(FieldOffsetField3), SeekOrigin.Current, false)] + public uint Field3 { get; set; } + } +} \ No newline at end of file diff --git a/BinarySerializer.Test/Offset/OffsetTests.cs b/BinarySerializer.Test/Offset/OffsetTests.cs index b810a63b..7a6ac68f 100644 --- a/BinarySerializer.Test/Offset/OffsetTests.cs +++ b/BinarySerializer.Test/Offset/OffsetTests.cs @@ -20,5 +20,24 @@ public void BoundOffsetTest() var actual = Roundtrip(expected, expected.FieldOffsetField + expected.Field.Length + 1); Assert.AreEqual(expected.Field, actual.Field); } + + [TestMethod] + public void BoundOffsetCurrentNoRewindTest() + { + var expected = new BoundOffsetCurrentNoRewindClass { FieldOffsetField = 50, Field = 404, LastUInt = 9}; + var actual = Roundtrip(expected, sizeof(uint) + expected.FieldOffsetField + sizeof(uint) + sizeof(uint)); + Assert.AreEqual(expected.Field, actual.Field); + Assert.AreEqual(expected.LastUInt, actual.LastUInt); + } + + [TestMethod] + public void BoundOffsetJumpyNoRewindTest() + { + var expected = new BoundOffsetJumpyNoRewindClass { FieldOffsetField1 = 100, Field1 = 104, FieldOffsetField2 = 200, Field2 = 204, FieldOffsetField3 = sizeof(uint), Field3 = 304 }; + var actual = Roundtrip(expected, expected.FieldOffsetField2 + sizeof(uint) + sizeof(uint) + expected.FieldOffsetField3 + sizeof(uint)); + Assert.AreEqual(expected.Field1, actual.Field1); + Assert.AreEqual(expected.Field2, actual.Field2); + Assert.AreEqual(expected.Field3, actual.Field3); + } } } \ No newline at end of file diff --git a/BinarySerializer/FieldOffsetAttribute.cs b/BinarySerializer/FieldOffsetAttribute.cs index df8fd804..e04b2954 100644 --- a/BinarySerializer/FieldOffsetAttribute.cs +++ b/BinarySerializer/FieldOffsetAttribute.cs @@ -1,4 +1,5 @@ using System; +using System.IO; namespace BinarySerialization { @@ -11,17 +12,45 @@ public sealed class FieldOffsetAttribute : FieldBindingBaseAttribute, IConstAttr /// /// Initializes a new instance of the FieldOffset attribute with a fixed offset. /// - /// - public FieldOffsetAttribute(ulong offset) + /// Offset position from + /// Specifies the position in a stream to use for seeking the field + /// If true it will seek back to position where it was before seek, otherwise stream will continue from the current position + public FieldOffsetAttribute(ulong offset, SeekOrigin seekOrigin = SeekOrigin.Begin, bool rewind = true) { ConstOffset = offset; + SeekOrigin = seekOrigin; + Rewind = rewind; + } + + /// + /// Initializes a new instance of the FieldOffset attribute with a fixed offset. + /// + /// Offset position from + /// If true it will seek back to position where it was before seek, otherwise stream will continue from the current position + /// Specifies the position in a stream to use for seeking the field + public FieldOffsetAttribute(ulong offset, bool rewind, SeekOrigin seekOrigin = SeekOrigin.Begin) : this(offset, seekOrigin, rewind) + { + } + + /// + /// Initializes a new instance of the FieldOffset attribute with a path pointing to a source binding member. + /// + /// A path to the source member + /// Specifies the position in a stream to use for seeking the field + /// If true it will seek back to position where it was before seek, otherwise stream will continue from the current position + public FieldOffsetAttribute(string path, SeekOrigin seekOrigin = SeekOrigin.Begin, bool rewind = true) : base(path) + { + SeekOrigin = seekOrigin; + Rewind = rewind; } /// /// Initializes a new instance of the FieldOffset attribute with a path pointing to a source binding member. /// - /// A path to the source member. - public FieldOffsetAttribute(string path) : base(path) + /// A path to the source member + /// If true it will seek back to position where it was before seek, otherwise stream will continue from the current position + /// Specifies the position in a stream to use for seeking the field + public FieldOffsetAttribute(string path, bool rewind, SeekOrigin seekOrigin = SeekOrigin.Begin) : this(path, seekOrigin, rewind) { } @@ -37,5 +66,15 @@ public object GetConstValue() { return ConstOffset; } + + /// + /// Specifies the position in a stream to use for seeking the field + /// + public SeekOrigin SeekOrigin { get; set; } + + /// + /// If true it will seek back to position where it was before seek, otherwise stream will continue from the current position + /// + public bool Rewind { get; set; } } } \ No newline at end of file diff --git a/BinarySerializer/Graph/TypeGraph/TypeNode.cs b/BinarySerializer/Graph/TypeGraph/TypeNode.cs index 3bdce7e1..31a65e67 100644 --- a/BinarySerializer/Graph/TypeGraph/TypeNode.cs +++ b/BinarySerializer/Graph/TypeGraph/TypeNode.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -141,6 +142,13 @@ protected TypeNode(TypeNode parent, Type parentType, MemberInfo memberInfo, Type Order = fieldOrderAttribute.Order; } + var offsetAttribute = attributes.OfType().SingleOrDefault(); + if (offsetAttribute != null) + { + OffsetSeekOrigin = offsetAttribute.SeekOrigin; + OffsetRewind = offsetAttribute.Rewind; + } + var serializeAsAttribute = attributes.OfType().SingleOrDefault(); if (serializeAsAttribute != null) { @@ -355,6 +363,9 @@ protected TypeNode(TypeNode parent, Type parentType, MemberInfo memberInfo, Type public int? Order { get; } + public SeekOrigin OffsetSeekOrigin { get; } = SeekOrigin.Begin; + public bool OffsetRewind { get; } = true; + public bool AreStringsTerminated { get; } public char StringTerminator { get; } diff --git a/BinarySerializer/Graph/ValueGraph/ValueNode.cs b/BinarySerializer/Graph/ValueGraph/ValueNode.cs index 81ed3ea2..e27ad0d5 100644 --- a/BinarySerializer/Graph/ValueGraph/ValueNode.cs +++ b/BinarySerializer/Graph/ValueGraph/ValueNode.cs @@ -201,9 +201,17 @@ internal void Serialize(BoundedStream stream, EventShuttle eventShuttle, bool al if (offset != null) { - using (new StreamResetter(stream)) + if (TypeNode.OffsetRewind) { - stream.Position = offset.Value; + using (new StreamResetter(stream)) + { + stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); + SerializeInternal(stream, GetConstFieldLength, eventShuttle, measuring); + } + } + else + { + stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); SerializeInternal(stream, GetConstFieldLength, eventShuttle, measuring); } } @@ -255,9 +263,18 @@ internal async Task SerializeAsync(BoundedStream stream, EventShuttle eventShutt if (offset != null) { - using (new StreamResetter(stream)) + if (TypeNode.OffsetRewind) + { + using (new StreamResetter(stream)) + { + stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); + await SerializeInternalAsync(stream, GetConstFieldLength, eventShuttle, cancellationToken) + .ConfigureAwait(false); + } + } + else { - stream.Position = offset.Value; + stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); await SerializeInternalAsync(stream, GetConstFieldLength, eventShuttle, cancellationToken) .ConfigureAwait(false); } @@ -317,9 +334,17 @@ internal void Deserialize(BoundedStream stream, EventShuttle eventShuttle) if (offset != null) { - using (new StreamResetter(stream)) + if (TypeNode.OffsetRewind) { - stream.Position = offset.Value; + using (new StreamResetter(stream)) + { + stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); + DeserializeInternal(stream, GetFieldLength, eventShuttle); + } + } + else + { + stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); DeserializeInternal(stream, GetFieldLength, eventShuttle); } } @@ -368,9 +393,18 @@ internal async Task DeserializeAsync(BoundedStream stream, EventShuttle eventShu if (offset != null) { - using (new StreamResetter(stream)) + if (TypeNode.OffsetRewind) + { + using (new StreamResetter(stream)) + { + stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); + await DeserializeInternalAsync(stream, GetFieldLength, eventShuttle, cancellationToken) + .ConfigureAwait(false); + } + } + else { - stream.Position = offset.Value; + stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); await DeserializeInternalAsync(stream, GetFieldLength, eventShuttle, cancellationToken) .ConfigureAwait(false); } diff --git a/README.md b/README.md index 21f27d91..ddac0ea9 100644 --- a/README.md +++ b/README.md @@ -511,7 +511,75 @@ The FieldCrc32 is identical to the FieldCrc16 with the difference that it operat ### FieldOffsetAttribute ### -The FieldOffset attribute should be used sparingly but can be used if an absolute offset is required. In most cases implicit offset (e.g. just define the structure) is preferable. After moving to the offset the serializer will reset to the origin so subsequent fields must manage their own offsets. This attribute is not supported when serializing to non-seekable streams. +The FieldOffset attribute should be used sparingly but can be used if an absolute(default) or incremental offset is required. +In most cases implicit offset (e.g. just define the structure) is preferable. +By default and after moving to the offset the serializer will reset to the origin so subsequent fields must manage their own offsets, otherwise set `Rewind` to `false`. +This attribute is not supported when serializing to non-seekable streams. + +**Note:** `SeekOrigin.End` is highly inadvisable since you don't have the stream total size while serialization. +If you want to use the `SeekOrigin.End` make sure it's only to deserialize a object or else you will need to set the correct size first with `stream.SetLength()`. + +```c# +public class FileSpec +{ + [FieldOrder(0)] + [FieldLength(12)] + [SerializeAs(SerializedType.TerminatedString)] + public string FileVersion { get; set; } = "FileMarking"; + + [FieldOrder(1)] + public uint FileVersion { get; set; } + + [FieldOrder(2)] + public uint HeaderAddress { get; set; } + + [FieldOrder(3)] + public uint SettingsAddress { get; set; } + + [FieldOrder(4)] + public uint PreviewAddress { get; set; } + + [FieldOrder(5)] + public uint LayersAddress { get; set; } + + [FieldOrder(6)] + [FieldOffset(nameof(HeaderAddress), false)] + public uint HeaderField1 { get; set; } + + [FieldOrder(7)] + public uint HeaderField2 { get; set; } + + [FieldOrder(8)] + public uint HeaderField3 { get; set; } + + [FieldOrder(9)] + [FieldOffset(nameof(SettingsAddress), false)] + public uint SettingsField1 { get; set; } + + [FieldOrder(10)] + public uint SettingsField2 { get; set; } + + [FieldOrder(11)] + [FieldOffset(nameof(PreviewAddress), false)] + public uint PreviewSize { get; set; } + + [FieldOrder(12)] + [FieldCount(nameof(PreviewSize))] + public byte[] PreviewData {get; set; } + + [FieldOrder(13)] + [FieldOffset(nameof(LayersAddress), false)] + public uint LayerCount { get; set; } + + [FieldOrder(14)] + [FieldCount(nameof(LayerCount))] + public Layer[] Layers { get; set; } + + [FieldOrder(15)] + [FieldOffset(4, SeekOrigin.Current), false] // Skip unused 4 bytes first, same as declaring uint Padding + public uint FileChecksum { get; set; } +} +```` ### SubtypeAttribute ### From 5ca01b8a91ac20be21839152db0ff1bfae58e782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Concei=C3=A7=C3=A3o?= Date: Mon, 5 Sep 2022 21:55:47 +0100 Subject: [PATCH 2/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ddac0ea9..4413ae1f 100644 --- a/README.md +++ b/README.md @@ -579,7 +579,7 @@ public class FileSpec [FieldOffset(4, SeekOrigin.Current), false] // Skip unused 4 bytes first, same as declaring uint Padding public uint FileChecksum { get; set; } } -```` +``` ### SubtypeAttribute ### From 79d25195d4d8de60fa2e649650c5eec96a19b3e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Concei=C3=A7=C3=A3o?= Date: Mon, 5 Sep 2022 21:57:56 +0100 Subject: [PATCH 3/7] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4413ae1f..a50aff6d 100644 --- a/README.md +++ b/README.md @@ -576,7 +576,7 @@ public class FileSpec public Layer[] Layers { get; set; } [FieldOrder(15)] - [FieldOffset(4, SeekOrigin.Current), false] // Skip unused 4 bytes first, same as declaring uint Padding + [FieldOffset(4, SeekOrigin.Current, false)] // Skip unused 4 bytes first, same as declaring uint Padding public uint FileChecksum { get; set; } } ``` From 5aab2afc5125515b3ca0647044a2fcdd95865149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Concei=C3=A7=C3=A3o?= Date: Sun, 4 Jun 2023 16:29:50 +0100 Subject: [PATCH 4/7] Update ValueNode.cs Condensed the rewind logic --- .../Graph/ValueGraph/ValueNode.cs | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/BinarySerializer/Graph/ValueGraph/ValueNode.cs b/BinarySerializer/Graph/ValueGraph/ValueNode.cs index e27ad0d5..d5cd6612 100644 --- a/BinarySerializer/Graph/ValueGraph/ValueNode.cs +++ b/BinarySerializer/Graph/ValueGraph/ValueNode.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -201,19 +201,13 @@ internal void Serialize(BoundedStream stream, EventShuttle eventShuttle, bool al if (offset != null) { - if (TypeNode.OffsetRewind) - { - using (new StreamResetter(stream)) - { - stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); - SerializeInternal(stream, GetConstFieldLength, eventShuttle, measuring); - } - } - else + var rewindPosition = stream.Position; + stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); + SerializeInternal(stream, GetConstFieldLength, eventShuttle, measuring); + if (TypeNode.OffsetRewind) { - stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); - SerializeInternal(stream, GetConstFieldLength, eventShuttle, measuring); - } + stream.Position = rewindPosition; + } } else { @@ -985,4 +979,4 @@ private BinarySerializationContext CreateSerializationContext() parent?.CreateSerializationContext(), TypeNode.MemberInfo); } } -} \ No newline at end of file +} From 2398369cf601563d354fd64f7efaae82acf4c001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Concei=C3=A7=C3=A3o?= Date: Sun, 4 Jun 2023 17:17:58 +0100 Subject: [PATCH 5/7] Update ValueNode.cs Update async counterpart --- .../Graph/ValueGraph/ValueNode.cs | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/BinarySerializer/Graph/ValueGraph/ValueNode.cs b/BinarySerializer/Graph/ValueGraph/ValueNode.cs index 189b3010..5ce97ddd 100644 --- a/BinarySerializer/Graph/ValueGraph/ValueNode.cs +++ b/BinarySerializer/Graph/ValueGraph/ValueNode.cs @@ -212,7 +212,7 @@ internal void Serialize(BoundedStream stream, EventShuttle eventShuttle, bool al if (TypeNode.OffsetRewind) { stream.Position = rewindPosition; - } + } } else { @@ -257,21 +257,14 @@ internal async Task SerializeAsync(BoundedStream stream, EventShuttle eventShutt if (offset != null) { - if (TypeNode.OffsetRewind) - { - using (new StreamResetter(stream)) - { - stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); - await SerializeInternalAsync(stream, GetConstFieldLength, eventShuttle, cancellationToken) - .ConfigureAwait(false); - } - } - else - { + var rewindPosition = stream.Position; stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); await SerializeInternalAsync(stream, GetConstFieldLength, eventShuttle, cancellationToken) - .ConfigureAwait(false); - } + .ConfigureAwait(false); + if (TypeNode.OffsetRewind) + { + stream.Position = rewindPosition; + } } else { From 0a4c815898f0ce17a1cccbb9a82ec4d82ed592bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Concei=C3=A7=C3=A3o?= Date: Sun, 4 Jun 2023 19:11:03 +0100 Subject: [PATCH 6/7] Better test --- .../Offset/BoundOffsetClass.cs | 9 ++++++--- .../Offset/ConstOffsetClass.cs | 10 +++++++++- BinarySerializer.Test/Offset/OffsetTests.cs | 17 +++++++++++------ 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/BinarySerializer.Test/Offset/BoundOffsetClass.cs b/BinarySerializer.Test/Offset/BoundOffsetClass.cs index cc5c5092..2bbde837 100644 --- a/BinarySerializer.Test/Offset/BoundOffsetClass.cs +++ b/BinarySerializer.Test/Offset/BoundOffsetClass.cs @@ -3,10 +3,13 @@ public class BoundOffsetClass { [FieldOrder(0)] - public int FieldOffsetField { get; set; } + public uint FieldOffsetField { get; set; } [FieldOrder(1)] - [FieldOffset("FieldOffsetField")] - public string Field { get; set; } + [FieldOffset(nameof(FieldOffsetField))] + public string FieldString { get; set; } + + [FieldOrder(2)] + public uint FieldUint { get; set; } } } \ No newline at end of file diff --git a/BinarySerializer.Test/Offset/ConstOffsetClass.cs b/BinarySerializer.Test/Offset/ConstOffsetClass.cs index 0b2cdc1b..1e0b129f 100644 --- a/BinarySerializer.Test/Offset/ConstOffsetClass.cs +++ b/BinarySerializer.Test/Offset/ConstOffsetClass.cs @@ -2,7 +2,15 @@ { public class ConstOffsetClass { + [FieldOrder(0)] + public uint FieldStringLength { get; set; } + + [FieldOrder(1)] [FieldOffset(100)] - public string Field { get; set; } + [FieldLength(nameof(FieldStringLength))] + public string FieldString { get; set; } + + [FieldOrder(2)] + public uint FieldUint { get; set; } } } \ No newline at end of file diff --git a/BinarySerializer.Test/Offset/OffsetTests.cs b/BinarySerializer.Test/Offset/OffsetTests.cs index 7a6ac68f..e4ca1a4a 100644 --- a/BinarySerializer.Test/Offset/OffsetTests.cs +++ b/BinarySerializer.Test/Offset/OffsetTests.cs @@ -8,17 +8,22 @@ public class OffsetTests : TestBase [TestMethod] public void ConstOffsetTest() { - var expected = new ConstOffsetClass {Field = "FieldValue"}; - var actual = Roundtrip(expected, 100 + expected.Field.Length + 1); - Assert.AreEqual(expected.Field, actual.Field); + var stringVal = "FieldValue"; // 10 length + var expected = new ConstOffsetClass {FieldStringLength = (uint)stringVal.Length, FieldString = stringVal, FieldUint = 100}; + var actual = Roundtrip(expected, 100 + expected.FieldStringLength); + Assert.AreEqual(expected.FieldStringLength, actual.FieldStringLength); + Assert.AreEqual(expected.FieldString, actual.FieldString); + Assert.AreEqual(expected.FieldUint, actual.FieldUint); } [TestMethod] public void BoundOffsetTest() { - var expected = new BoundOffsetClass {FieldOffsetField = 1000, Field = "FieldValue"}; - var actual = Roundtrip(expected, expected.FieldOffsetField + expected.Field.Length + 1); - Assert.AreEqual(expected.Field, actual.Field); + var expected = new BoundOffsetClass {FieldOffsetField = 1000, FieldString = "FieldValue", FieldUint = 100}; + var actual = Roundtrip(expected, expected.FieldOffsetField + expected.FieldString.Length + 1); + Assert.AreEqual(expected.FieldOffsetField, actual.FieldOffsetField); + Assert.AreEqual(expected.FieldString, actual.FieldString); + Assert.AreEqual(expected.FieldUint, actual.FieldUint); } [TestMethod] From d71d9815982bb4489b303ff7686fd28781a8bb8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tiago=20Concei=C3=A7=C3=A3o?= Date: Sun, 4 Jun 2023 19:11:18 +0100 Subject: [PATCH 7/7] Fix offset for deserialization --- .../Graph/ValueGraph/ValueNode.cs | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/BinarySerializer/Graph/ValueGraph/ValueNode.cs b/BinarySerializer/Graph/ValueGraph/ValueNode.cs index 5ce97ddd..0a43c205 100644 --- a/BinarySerializer/Graph/ValueGraph/ValueNode.cs +++ b/BinarySerializer/Graph/ValueGraph/ValueNode.cs @@ -254,17 +254,16 @@ internal async Task SerializeAsync(BoundedStream stream, EventShuttle eventShutt } var offset = GetFieldOffset(); - if (offset != null) { var rewindPosition = stream.Position; - stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); - await SerializeInternalAsync(stream, GetConstFieldLength, eventShuttle, cancellationToken) - .ConfigureAwait(false); - if (TypeNode.OffsetRewind) - { - stream.Position = rewindPosition; - } + stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); + await SerializeInternalAsync(stream, GetConstFieldLength, eventShuttle, cancellationToken) + .ConfigureAwait(false); + if (TypeNode.OffsetRewind) + { + stream.Position = rewindPosition; + } } else { @@ -316,10 +315,12 @@ internal void Deserialize(BoundedStream stream, SerializationOptions options, Ev if (offset != null) { + var rewindPosition = stream.Position; + stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); + DeserializeInternal(stream, GetFieldLength, options, eventShuttle); if (TypeNode.OffsetRewind) { - stream.Position = offset.Value; - DeserializeInternal(stream, GetFieldLength, options, eventShuttle); + stream.Position = rewindPosition; } } else @@ -362,11 +363,13 @@ internal async Task DeserializeAsync(BoundedStream stream, SerializationOptions if (offset != null) { + var rewindPosition = stream.Position; + stream.Seek(offset.Value, TypeNode.OffsetSeekOrigin); + await DeserializeInternalAsync(stream, GetFieldLength, options, eventShuttle, cancellationToken) + .ConfigureAwait(false); if (TypeNode.OffsetRewind) { - stream.Position = offset.Value; - await DeserializeInternalAsync(stream, GetFieldLength, options, eventShuttle, cancellationToken) - .ConfigureAwait(false); + stream.Position = rewindPosition; } } else