From 5b96b5cbbf3b4c65503265877d4c8d37fa7ad640 Mon Sep 17 00:00:00 2001 From: Nikolay Gekht Date: Tue, 2 Feb 2021 13:10:00 -0500 Subject: [PATCH 1/4] - add support of IEnumerable with Add method (i.e. implementation enough for var x = new T() { e1, e2, e3 } syntax. - add debug code --- src/Binaron.Serializer.Debug.sln | 43 + .../Binaron.Serializer.Debug.csproj | 18 + src/Binaron.Serializer.Debug/Program.cs | 58 + .../CustomTestCollection.cs | 39 + .../ListSerializationTests.cs | 57 +- .../Infrastructure/GenericReader.cs | 1839 +++++++++++------ .../Infrastructure/IEnumerableExtension.cs | 27 + 7 files changed, 1427 insertions(+), 654 deletions(-) create mode 100644 src/Binaron.Serializer.Debug.sln create mode 100644 src/Binaron.Serializer.Debug/Binaron.Serializer.Debug.csproj create mode 100644 src/Binaron.Serializer.Debug/Program.cs create mode 100644 src/Binaron.Serializer.Tests/CustomTestCollection.cs create mode 100644 src/Binaron.Serializer/Infrastructure/IEnumerableExtension.cs diff --git a/src/Binaron.Serializer.Debug.sln b/src/Binaron.Serializer.Debug.sln new file mode 100644 index 0000000..ad798fe --- /dev/null +++ b/src/Binaron.Serializer.Debug.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29411.108 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Binaron.Serializer", "Binaron.Serializer\Binaron.Serializer.csproj", "{7A418C08-D0C0-4080-88C5-8A104C8D3FC1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Binaron.Serializer.Benchmark", "Binaron.Serializer.Benchmark\Binaron.Serializer.Benchmark.csproj", "{20A3FAA1-27F4-4001-8302-7FE5352AB066}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Binaron.Serializer.Tests", "Binaron.Serializer.Tests\Binaron.Serializer.Tests.csproj", "{47AACE5E-DC48-42AB-8CBD-ADB1FA771E2B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Binaron.Serializer.Debug", "Binaron.Serializer.Debug\Binaron.Serializer.Debug.csproj", "{387628B3-F233-43AD-B06A-7896C56C1B07}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7A418C08-D0C0-4080-88C5-8A104C8D3FC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7A418C08-D0C0-4080-88C5-8A104C8D3FC1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7A418C08-D0C0-4080-88C5-8A104C8D3FC1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7A418C08-D0C0-4080-88C5-8A104C8D3FC1}.Release|Any CPU.Build.0 = Release|Any CPU + {20A3FAA1-27F4-4001-8302-7FE5352AB066}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {20A3FAA1-27F4-4001-8302-7FE5352AB066}.Debug|Any CPU.Build.0 = Debug|Any CPU + {20A3FAA1-27F4-4001-8302-7FE5352AB066}.Release|Any CPU.ActiveCfg = Release|Any CPU + {20A3FAA1-27F4-4001-8302-7FE5352AB066}.Release|Any CPU.Build.0 = Release|Any CPU + {47AACE5E-DC48-42AB-8CBD-ADB1FA771E2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {47AACE5E-DC48-42AB-8CBD-ADB1FA771E2B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {47AACE5E-DC48-42AB-8CBD-ADB1FA771E2B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {47AACE5E-DC48-42AB-8CBD-ADB1FA771E2B}.Release|Any CPU.Build.0 = Release|Any CPU + {387628B3-F233-43AD-B06A-7896C56C1B07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {387628B3-F233-43AD-B06A-7896C56C1B07}.Debug|Any CPU.Build.0 = Debug|Any CPU + {387628B3-F233-43AD-B06A-7896C56C1B07}.Release|Any CPU.ActiveCfg = Release|Any CPU + {387628B3-F233-43AD-B06A-7896C56C1B07}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BD282BEE-F832-48AE-ABA4-40DB1F133E3F} + EndGlobalSection +EndGlobal diff --git a/src/Binaron.Serializer.Debug/Binaron.Serializer.Debug.csproj b/src/Binaron.Serializer.Debug/Binaron.Serializer.Debug.csproj new file mode 100644 index 0000000..3393268 --- /dev/null +++ b/src/Binaron.Serializer.Debug/Binaron.Serializer.Debug.csproj @@ -0,0 +1,18 @@ + + + + Exe + netcoreapp5.0 + BinSerializerTest + + + + + + + + + + + + diff --git a/src/Binaron.Serializer.Debug/Program.cs b/src/Binaron.Serializer.Debug/Program.cs new file mode 100644 index 0000000..e201967 --- /dev/null +++ b/src/Binaron.Serializer.Debug/Program.cs @@ -0,0 +1,58 @@ +using Binaron.Serializer; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace BinSerializerTest +{ + class Program + { + class TestObject + { + public int A { get; set; } + public TestObject() + { + + } + + public TestObject(int a) + { + A = a; + } + } + + class Collector : IEnumerable + { + private List mData = new List(); + + public T this[int index] => mData[index]; + public int Count => mData.Count; + + public void Add(T element) => mData.Add(element); + + public IEnumerator GetEnumerator() => mData.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => mData.GetEnumerator(); + } + + public static void Main(string[] args) + { + Collector c = new Collector() { new TestObject(1), new TestObject(2) }; + using (var ms1 = new MemoryStream()) + { + BinaronConvert.Serialize(c, ms1); + using (var ms2 = new MemoryStream(ms1.ToArray())) + { + var c2 = BinaronConvert.Deserialize>(ms2); + ; + } + } + + + } + } +} diff --git a/src/Binaron.Serializer.Tests/CustomTestCollection.cs b/src/Binaron.Serializer.Tests/CustomTestCollection.cs new file mode 100644 index 0000000..1bcb5d0 --- /dev/null +++ b/src/Binaron.Serializer.Tests/CustomTestCollection.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Binaron.Serializer.Tests +{ + public class CustomTestCollection : IEnumerable + { + private List mList = new List(); + + public T this[int index] => mList[index]; + + public int Count => mList.Count; + + public void Add(T value) => mList.Add(value); + + + public IEnumerator GetEnumerator() => mList.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => mList.GetEnumerator(); + + public class TestCollectionObject + { + public T A { get; set; } + + public TestCollectionObject() + { + } + + public TestCollectionObject(T a) + { + A = a; + } + } + } +} diff --git a/src/Binaron.Serializer.Tests/ListSerializationTests.cs b/src/Binaron.Serializer.Tests/ListSerializationTests.cs index 6ea38b6..fc688e3 100644 --- a/src/Binaron.Serializer.Tests/ListSerializationTests.cs +++ b/src/Binaron.Serializer.Tests/ListSerializationTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.IO; @@ -265,5 +265,60 @@ private static TList AddItem(TList source, TItem item) where TList throw new NotSupportedException(); } } + + [Test] + public void CustomCollectionIntTest() + { + CustomTestCollection collection = new CustomTestCollection() + { + 0, 1, 2, 3, 4 + }; + + var dest = Tester.TestRoundTrip>(collection); + Assert.AreEqual(5, dest.Count); + Assert.AreEqual(0, dest[0]); + Assert.AreEqual(1, dest[1]); + Assert.AreEqual(2, dest[2]); + Assert.AreEqual(3, dest[3]); + Assert.AreEqual(4, dest[4]); + } + + [Test] + public void CustomCollectionStringTest() + { + CustomTestCollection collection = new CustomTestCollection() + { + "0", "1", "2", "3", "4" + }; + + var dest = Tester.TestRoundTrip>(collection); + Assert.AreEqual(5, dest.Count); + Assert.AreEqual("0", dest[0]); + Assert.AreEqual("1", dest[1]); + Assert.AreEqual("2", dest[2]); + Assert.AreEqual("3", dest[3]); + Assert.AreEqual("4", dest[4]); + } + + [Test] + public void CustomCollectionObjectTest() + { + CustomTestCollection.TestCollectionObject> collection = new CustomTestCollection.TestCollectionObject>() + { + new CustomTestCollection.TestCollectionObject(0), + new CustomTestCollection.TestCollectionObject(1), + new CustomTestCollection.TestCollectionObject(2), + new CustomTestCollection.TestCollectionObject(3), + new CustomTestCollection.TestCollectionObject(4), + }; + + var dest = Tester.TestRoundTrip(collection); + Assert.AreEqual(5, dest.Count); + Assert.AreEqual(0, dest[0].A); + Assert.AreEqual(1, dest[1].A); + Assert.AreEqual(2, dest[2].A); + Assert.AreEqual(3, dest[3].A); + Assert.AreEqual(4, dest[4].A); + } } } \ No newline at end of file diff --git a/src/Binaron.Serializer/Infrastructure/GenericReader.cs b/src/Binaron.Serializer/Infrastructure/GenericReader.cs index c0d8709..1bef71e 100644 --- a/src/Binaron.Serializer/Infrastructure/GenericReader.cs +++ b/src/Binaron.Serializer/Infrastructure/GenericReader.cs @@ -44,417 +44,520 @@ public static object ReadHEnumerable(ReaderState reader) { switch (TypeOf.TypeCode) { - case TypeCode.Object: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsObject(reader, valueType); - l.Add((TElement) v); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Boolean: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Bool) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadBool(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsBool(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Byte: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Byte) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadByte(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsByte(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Char: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Char) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadChar(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsChar(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.DateTime: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.DateTime) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadDateTime(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsDateTime(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Guid: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Guid) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadGuid(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsGuid(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Decimal: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Decimal) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadDecimal(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsDecimal(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Double: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Double) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadDouble(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsDouble(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Int16: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Short) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadShort(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsShort(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Int32: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Int) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadInt(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsInt(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Int64: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Long) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadLong(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsLong(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.SByte: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.SByte) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadSByte(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsSByte(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Single: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Float) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadFloat(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsFloat(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.String: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.String) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadString(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsString(reader, valueType); - l.Add(v); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.UInt16: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.UShort) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadUShort(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsUShort(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; + case TypeCode.Object: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsObject(reader, valueType); + l.Add((TElement)v); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsObject(reader, valueType); + l1.Add((TElement)v); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Boolean: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Bool) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadBool(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsBool(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Bool) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadBool(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsBool(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Byte: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Byte) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadByte(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsByte(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Byte) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadByte(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsByte(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + Discarder.Discard(reader); + return result; + } + case TypeCode.Char: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Char) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadChar(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsChar(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Char) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadChar(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsChar(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.DateTime: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.DateTime) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadDateTime(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsDateTime(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.DateTime) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadDateTime(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsDateTime(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Guid: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Guid) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadGuid(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsGuid(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Guid) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadGuid(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsGuid(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Decimal: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Decimal) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadDecimal(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsDecimal(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Decimal) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadDecimal(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsDecimal(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Double: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Double) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadDouble(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsDouble(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Double) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadDouble(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsDouble(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Int16: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Short) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadShort(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsShort(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Short) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadShort(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsShort(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Int32: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Int) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadInt(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsInt(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Int) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadInt(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsInt(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Int64: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Long) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadLong(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsLong(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Long) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadLong(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsLong(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; } - - Discarder.Discard(reader); - return result; - } - case TypeCode.UInt32: + case TypeCode.SByte: { var result = CreateResultObject(); - if (result is ICollection l) + if (result is ICollection l) { var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.UInt) + if (valueType == SerializedType.SByte) { while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadUInt(reader)); + l.Add(Reader.ReadSByte(reader)); } else { while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { - var v = SelfUpgradingReader.ReadAsUInt(reader, valueType); + var v = SelfUpgradingReader.ReadAsSByte(reader, valueType); if (v.HasValue) l.Add(v.Value); } @@ -462,37 +565,265 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - - Discarder.Discard(reader); - return result; - } - case TypeCode.UInt64: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.ULong) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadULong(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsULong(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.SByte) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadSByte(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsSByte(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Single: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Float) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadFloat(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsFloat(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Float) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadFloat(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsFloat(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.String: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.String) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadString(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsString(reader, valueType); + l.Add(v); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.String) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadString(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsString(reader, valueType); + l1.Add(v); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.UInt16: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.UShort) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadUShort(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsUShort(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.UShort) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadUShort(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsUShort(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.UInt32: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.UInt) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadUInt(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsUInt(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.UInt) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadUInt(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsUInt(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.UInt64: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.ULong) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadULong(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsULong(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + + } + else if (result is IEnumerable l1) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.ULong) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadULong(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsULong(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + + Discarder.Discard(reader); + return result; } - - Discarder.Discard(reader); - return result; - } } return null; @@ -502,62 +833,97 @@ public static object ReadTypedEnumerable(ReaderState reader) { switch (TypeOf.TypeCode) { - case TypeCode.Object: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsObject(reader, valueType); - l.Add((TElement) v); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Boolean: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsBool(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Byte: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsByte(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; + case TypeCode.Object: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsObject(reader, valueType); + l.Add((TElement)v); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsObject(reader, valueType); + l1.Add((TElement)v); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Boolean: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsBool(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsBool(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Byte: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsByte(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsByte(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; } - - Discarder.Discard(reader); - return result; - } case TypeCode.Char: { var result = CreateResultObject(); @@ -573,105 +939,177 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - - Discarder.Discard(reader); - return result; - } - case TypeCode.DateTime: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsDateTime(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Guid: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsGuid(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Decimal: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsDecimal(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Double: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsDouble(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Int16: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsShort(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsChar(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.DateTime: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsDateTime(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsDateTime(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Guid: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsGuid(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsGuid(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Decimal: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsDecimal(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsDecimal(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Double: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsDouble(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsDouble(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Int16: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsShort(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsShort(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; } - - Discarder.Discard(reader); - return result; - } case TypeCode.Int32: { var result = CreateResultObject(); @@ -687,8 +1125,20 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - - Discarder.Discard(reader); + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsInt(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); return result; } case TypeCode.Int64: @@ -706,48 +1156,84 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - - Discarder.Discard(reader); - return result; - } - case TypeCode.SByte: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsSByte(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Single: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsFloat(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsLong(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.SByte: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsSByte(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsSByte(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Single: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsFloat(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsFloat(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; } - - Discarder.Discard(reader); - return result; - } case TypeCode.String: { var result = CreateResultObject(); @@ -761,9 +1247,20 @@ public static object ReadTypedEnumerable(ReaderState reader) } return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); + } + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsString(reader, valueType); + l1.Add(v); + } + + return result; + } + + Discarder.Discard(reader); return result; } case TypeCode.UInt16: @@ -780,9 +1277,21 @@ public static object ReadTypedEnumerable(ReaderState reader) } return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); + } + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsUShort(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); return result; } case TypeCode.UInt32: @@ -800,29 +1309,53 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - - Discarder.Discard(reader); - return result; - } - case TypeCode.UInt64: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsULong(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsUInt(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.UInt64: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsULong(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable l1) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsULong(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; } - - Discarder.Discard(reader); - return result; - } } return null; diff --git a/src/Binaron.Serializer/Infrastructure/IEnumerableExtension.cs b/src/Binaron.Serializer/Infrastructure/IEnumerableExtension.cs new file mode 100644 index 0000000..114db1f --- /dev/null +++ b/src/Binaron.Serializer/Infrastructure/IEnumerableExtension.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace Binaron.Serializer.Infrastructure +{ + internal static class IEnumerableExtension + { + private static ConcurrentDictionary> gAdders = new ConcurrentDictionary>(); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Add(this IEnumerable enumerable, T value) + { + if (!gAdders.TryGetValue(enumerable.GetType(), out Action action)) + { + var method = enumerable.GetType().GetMethod("Add", new Type[] { typeof(T) }); + if (method == null) + action = (o, v) => { }; + else + action = (o, v) => method.Invoke(o, new object[] { v }); + gAdders.TryAdd(enumerable.GetType(), action); + } + action(enumerable, value); + } + } +} \ No newline at end of file From 781cd64fc1f47175b695aee039be174839b9ec53 Mon Sep 17 00:00:00 2001 From: Nikolay Gekht Date: Tue, 2 Feb 2021 13:12:18 -0500 Subject: [PATCH 2/4] - remove local development infrastructure files --- src/Binaron.Serializer.Debug.sln | 43 -------------- .../Binaron.Serializer.Debug.csproj | 18 ------ src/Binaron.Serializer.Debug/Program.cs | 58 ------------------- 3 files changed, 119 deletions(-) delete mode 100644 src/Binaron.Serializer.Debug.sln delete mode 100644 src/Binaron.Serializer.Debug/Binaron.Serializer.Debug.csproj delete mode 100644 src/Binaron.Serializer.Debug/Program.cs diff --git a/src/Binaron.Serializer.Debug.sln b/src/Binaron.Serializer.Debug.sln deleted file mode 100644 index ad798fe..0000000 --- a/src/Binaron.Serializer.Debug.sln +++ /dev/null @@ -1,43 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29411.108 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Binaron.Serializer", "Binaron.Serializer\Binaron.Serializer.csproj", "{7A418C08-D0C0-4080-88C5-8A104C8D3FC1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Binaron.Serializer.Benchmark", "Binaron.Serializer.Benchmark\Binaron.Serializer.Benchmark.csproj", "{20A3FAA1-27F4-4001-8302-7FE5352AB066}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Binaron.Serializer.Tests", "Binaron.Serializer.Tests\Binaron.Serializer.Tests.csproj", "{47AACE5E-DC48-42AB-8CBD-ADB1FA771E2B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Binaron.Serializer.Debug", "Binaron.Serializer.Debug\Binaron.Serializer.Debug.csproj", "{387628B3-F233-43AD-B06A-7896C56C1B07}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {7A418C08-D0C0-4080-88C5-8A104C8D3FC1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7A418C08-D0C0-4080-88C5-8A104C8D3FC1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7A418C08-D0C0-4080-88C5-8A104C8D3FC1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7A418C08-D0C0-4080-88C5-8A104C8D3FC1}.Release|Any CPU.Build.0 = Release|Any CPU - {20A3FAA1-27F4-4001-8302-7FE5352AB066}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {20A3FAA1-27F4-4001-8302-7FE5352AB066}.Debug|Any CPU.Build.0 = Debug|Any CPU - {20A3FAA1-27F4-4001-8302-7FE5352AB066}.Release|Any CPU.ActiveCfg = Release|Any CPU - {20A3FAA1-27F4-4001-8302-7FE5352AB066}.Release|Any CPU.Build.0 = Release|Any CPU - {47AACE5E-DC48-42AB-8CBD-ADB1FA771E2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {47AACE5E-DC48-42AB-8CBD-ADB1FA771E2B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {47AACE5E-DC48-42AB-8CBD-ADB1FA771E2B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {47AACE5E-DC48-42AB-8CBD-ADB1FA771E2B}.Release|Any CPU.Build.0 = Release|Any CPU - {387628B3-F233-43AD-B06A-7896C56C1B07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {387628B3-F233-43AD-B06A-7896C56C1B07}.Debug|Any CPU.Build.0 = Debug|Any CPU - {387628B3-F233-43AD-B06A-7896C56C1B07}.Release|Any CPU.ActiveCfg = Release|Any CPU - {387628B3-F233-43AD-B06A-7896C56C1B07}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {BD282BEE-F832-48AE-ABA4-40DB1F133E3F} - EndGlobalSection -EndGlobal diff --git a/src/Binaron.Serializer.Debug/Binaron.Serializer.Debug.csproj b/src/Binaron.Serializer.Debug/Binaron.Serializer.Debug.csproj deleted file mode 100644 index 3393268..0000000 --- a/src/Binaron.Serializer.Debug/Binaron.Serializer.Debug.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - Exe - netcoreapp5.0 - BinSerializerTest - - - - - - - - - - - - diff --git a/src/Binaron.Serializer.Debug/Program.cs b/src/Binaron.Serializer.Debug/Program.cs deleted file mode 100644 index e201967..0000000 --- a/src/Binaron.Serializer.Debug/Program.cs +++ /dev/null @@ -1,58 +0,0 @@ -using Binaron.Serializer; -using System; -using System.Collections; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace BinSerializerTest -{ - class Program - { - class TestObject - { - public int A { get; set; } - public TestObject() - { - - } - - public TestObject(int a) - { - A = a; - } - } - - class Collector : IEnumerable - { - private List mData = new List(); - - public T this[int index] => mData[index]; - public int Count => mData.Count; - - public void Add(T element) => mData.Add(element); - - public IEnumerator GetEnumerator() => mData.GetEnumerator(); - - IEnumerator IEnumerable.GetEnumerator() => mData.GetEnumerator(); - } - - public static void Main(string[] args) - { - Collector c = new Collector() { new TestObject(1), new TestObject(2) }; - using (var ms1 = new MemoryStream()) - { - BinaronConvert.Serialize(c, ms1); - using (var ms2 = new MemoryStream(ms1.ToArray())) - { - var c2 = BinaronConvert.Deserialize>(ms2); - ; - } - } - - - } - } -} From d55afd53d998b690d3749225441813548fd9ccc1 Mon Sep 17 00:00:00 2001 From: Nikolay Gekht Date: Fri, 12 Feb 2021 15:51:56 -0500 Subject: [PATCH 3/4] - refactor the method of restoring IEnumerable with Add method (#31) - support of nullable in collections and as properties (#34, #35, #36) --- .../CustomTestCollection.cs | 12 +- .../ListSerializationTests.cs | 77 +++++- .../MemberGetSetterTests.cs | 1 + .../ValueSerializationTests.cs | 62 +++++ .../EnumerableWrapperWithAdd.cs | 48 ++++ .../Infrastructure/GenericReader.cs | 240 +++++++++++------- .../Infrastructure/GenericWriter.cs | 16 +- .../Infrastructure/IEnumerableExtension.cs | 27 -- src/Binaron.Serializer/Serializer.cs | 52 ++-- 9 files changed, 382 insertions(+), 153 deletions(-) create mode 100644 src/Binaron.Serializer/Infrastructure/EnumerableWrapperWithAdd.cs delete mode 100644 src/Binaron.Serializer/Infrastructure/IEnumerableExtension.cs diff --git a/src/Binaron.Serializer.Tests/CustomTestCollection.cs b/src/Binaron.Serializer.Tests/CustomTestCollection.cs index 1bcb5d0..ebea1de 100644 --- a/src/Binaron.Serializer.Tests/CustomTestCollection.cs +++ b/src/Binaron.Serializer.Tests/CustomTestCollection.cs @@ -9,18 +9,18 @@ namespace Binaron.Serializer.Tests { public class CustomTestCollection : IEnumerable { - private List mList = new List(); + private List List = new List(); - public T this[int index] => mList[index]; + public T this[int index] => List[index]; - public int Count => mList.Count; + public int Count => List.Count; - public void Add(T value) => mList.Add(value); + public void Add(T value) => List.Add(value); - public IEnumerator GetEnumerator() => mList.GetEnumerator(); + public IEnumerator GetEnumerator() => List.GetEnumerator(); - IEnumerator IEnumerable.GetEnumerator() => mList.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => List.GetEnumerator(); public class TestCollectionObject { diff --git a/src/Binaron.Serializer.Tests/ListSerializationTests.cs b/src/Binaron.Serializer.Tests/ListSerializationTests.cs index fc688e3..d53edd6 100644 --- a/src/Binaron.Serializer.Tests/ListSerializationTests.cs +++ b/src/Binaron.Serializer.Tests/ListSerializationTests.cs @@ -283,23 +283,20 @@ public void CustomCollectionIntTest() Assert.AreEqual(4, dest[4]); } - [Test] - public void CustomCollectionStringTest() + [TestCaseSource(typeof(AllTestCases), nameof(AllTestCases.TestCaseOfValues))] + public void CustomCollectionOfTypeTest(TSource v) { - CustomTestCollection collection = new CustomTestCollection() + CustomTestCollection collection = new CustomTestCollection() { - "0", "1", "2", "3", "4" + v }; - var dest = Tester.TestRoundTrip>(collection); - Assert.AreEqual(5, dest.Count); - Assert.AreEqual("0", dest[0]); - Assert.AreEqual("1", dest[1]); - Assert.AreEqual("2", dest[2]); - Assert.AreEqual("3", dest[3]); - Assert.AreEqual("4", dest[4]); + var dest = Tester.TestRoundTrip>(collection); + Assert.AreEqual(1, dest.Count); + Assert.AreEqual(v, dest[0]); } + [Test] public void CustomCollectionObjectTest() { @@ -320,5 +317,63 @@ public void CustomCollectionObjectTest() Assert.AreEqual(3, dest[3].A); Assert.AreEqual(4, dest[4].A); } + + [Test] + public void TestListWithNullInside() + { + CustomTestCollection.TestCollectionObject> collection = new CustomTestCollection.TestCollectionObject>() + { + new CustomTestCollection.TestCollectionObject(0), + new CustomTestCollection.TestCollectionObject(1), + null, + new CustomTestCollection.TestCollectionObject(3), + new CustomTestCollection.TestCollectionObject(4), + }; + + var dest = Tester.TestRoundTrip(collection); + Assert.AreEqual(5, dest.Count); + Assert.AreEqual(0, dest[0].A); + Assert.AreEqual(1, dest[1].A); + Assert.AreEqual(null, dest[2]); + Assert.AreEqual(3, dest[3].A); + Assert.AreEqual(4, dest[4].A); + } + + [Test] + public void TestListOfNullables1() + { + var collection = new CustomTestCollection() { 1, null, 2 }; + using (var ms1 = new MemoryStream()) + { + var so = new SerializerOptions(); + BinaronConvert.Serialize(collection, ms1, so); + using (var ms2 = new MemoryStream(ms1.ToArray())) + { + var cr2 = BinaronConvert.Deserialize>(ms2); + Assert.AreEqual(3, cr2.Count); + Assert.AreEqual(1, cr2[0]); + Assert.AreEqual(null, cr2[1]); + Assert.AreEqual(2, cr2[2]); + } + } + } + [Test] + public void TestListOfNullables2() + { + var collection = new List() { 1, null, 2 }; + using (var ms1 = new MemoryStream()) + { + var so = new SerializerOptions(); + BinaronConvert.Serialize(collection, ms1, so); + using (var ms2 = new MemoryStream(ms1.ToArray())) + { + var cr2 = BinaronConvert.Deserialize>(ms2); + Assert.AreEqual(3, cr2.Count); + Assert.AreEqual(1, cr2[0]); + Assert.AreEqual(null, cr2[1]); + Assert.AreEqual(2, cr2[2]); + } + } + } } } \ No newline at end of file diff --git a/src/Binaron.Serializer.Tests/MemberGetSetterTests.cs b/src/Binaron.Serializer.Tests/MemberGetSetterTests.cs index b84bc5a..7fe6eff 100644 --- a/src/Binaron.Serializer.Tests/MemberGetSetterTests.cs +++ b/src/Binaron.Serializer.Tests/MemberGetSetterTests.cs @@ -49,5 +49,6 @@ public int NoRead set { } } } + } } \ No newline at end of file diff --git a/src/Binaron.Serializer.Tests/ValueSerializationTests.cs b/src/Binaron.Serializer.Tests/ValueSerializationTests.cs index 24e1172..24a15dc 100644 --- a/src/Binaron.Serializer.Tests/ValueSerializationTests.cs +++ b/src/Binaron.Serializer.Tests/ValueSerializationTests.cs @@ -394,6 +394,68 @@ private static object GetEnumNumeric(object source) } } + [TestCase(1)] + [TestCase(null)] + public void NullableTest1(int? value) + { + using (var ms1 = new MemoryStream()) + { + BinaronConvert.Serialize(value, ms1); + using (var ms2 = new MemoryStream(ms1.ToArray())) + { + Assert.AreEqual(value, BinaronConvert.Deserialize(ms2)); + + } + } + } + + [TestCase(1, "a")] + [TestCase(null, null)] + [TestCase(1, null)] + [TestCase(null, "abcd")] + + public void MemberSetterNullableType1(int? v1, string v2) + { + TestClass1 tc1 = new TestClass1() { IntValue = v1, StringValue = v2 }; + using (MemoryStream ms = new MemoryStream()) + { + BinaronConvert.Serialize(tc1, ms); + using (MemoryStream ms1 = new MemoryStream(ms.ToArray())) + { + var tc2 = BinaronConvert.Deserialize(ms1); + Assert.AreEqual(v1, tc2.IntValue); + Assert.AreEqual(v2, tc2.StringValue); + } + } + } + + [TestCase(1, "a")] + [TestCase(null, null)] + [TestCase(1, null)] + [TestCase(null, "abcd")] + + public void MemberSetterNullableType2(int? v1, string v2) + { + List tc1 = new List() { new TestClass1() { IntValue = v1, StringValue = v2 } }; + using (MemoryStream ms = new MemoryStream()) + { + BinaronConvert.Serialize(tc1, ms); + using (MemoryStream ms1 = new MemoryStream(ms.ToArray())) + { + var tc2 = BinaronConvert.Deserialize>(ms1); + Assert.AreEqual(1, tc2.Count); + Assert.AreEqual(v1, tc2[0].IntValue); + Assert.AreEqual(v2, tc2[0].StringValue); + } + } + } + + private class TestClass1 + { + public int? IntValue { get; set; } + public string StringValue { get; set; } + } + private class TestClass { public DateTime RootValue { get; set; } diff --git a/src/Binaron.Serializer/Infrastructure/EnumerableWrapperWithAdd.cs b/src/Binaron.Serializer/Infrastructure/EnumerableWrapperWithAdd.cs new file mode 100644 index 0000000..27cc0a1 --- /dev/null +++ b/src/Binaron.Serializer/Infrastructure/EnumerableWrapperWithAdd.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Reflection.Emit; +using System.Runtime.CompilerServices; + +namespace Binaron.Serializer.Infrastructure +{ + internal class EnumerableWrapperWithAdd + { + private readonly Action Action; + private readonly object Result; + public bool HasAddAction { get; private set; } = false; + + public EnumerableWrapperWithAdd(IEnumerable result) + { + Result = result; + var method = result.GetType().GetMethod("Add", new Type[] { typeof(T) }); + + if (method == null) + Action = (o, v) => { }; + else + { + HasAddAction = true; + DynamicMethod action = new DynamicMethod( + "Add", + null, + new Type[] { typeof(object), typeof(T) }, + this.GetType().Module); + + var il = action.GetILGenerator(); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldarg_1); + il.Emit(method.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, method); + il.Emit(OpCodes.Ret); + + Action = (Action)action.CreateDelegate(typeof(Action)); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Add(T value) + { + Action(Result, value); + } + } +} \ No newline at end of file diff --git a/src/Binaron.Serializer/Infrastructure/GenericReader.cs b/src/Binaron.Serializer/Infrastructure/GenericReader.cs index 1bef71e..7ede49c 100644 --- a/src/Binaron.Serializer/Infrastructure/GenericReader.cs +++ b/src/Binaron.Serializer/Infrastructure/GenericReader.cs @@ -58,8 +58,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { @@ -96,8 +97,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); if (valueType == SerializedType.Bool) { @@ -143,8 +145,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); if (valueType == SerializedType.Byte) { @@ -189,8 +192,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); if (valueType == SerializedType.Char) { @@ -236,8 +240,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); if (valueType == SerializedType.DateTime) { @@ -283,8 +288,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); if (valueType == SerializedType.Guid) { @@ -330,8 +336,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); if (valueType == SerializedType.Decimal) { @@ -377,8 +384,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); if (valueType == SerializedType.Double) { @@ -424,8 +432,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); if (valueType == SerializedType.Short) { @@ -471,8 +480,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); if (valueType == SerializedType.Int) { @@ -518,8 +528,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); if (valueType == SerializedType.Long) { @@ -565,8 +576,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); if (valueType == SerializedType.SByte) { @@ -612,8 +624,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); if (valueType == SerializedType.Float) { @@ -658,8 +671,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); if (valueType == SerializedType.String) { @@ -704,8 +718,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); if (valueType == SerializedType.UShort) { @@ -751,8 +766,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); if (valueType == SerializedType.UInt) { @@ -799,8 +815,9 @@ public static object ReadHEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); var valueType = Reader.ReadSerializedType(reader); if (valueType == SerializedType.ULong) { @@ -847,8 +864,9 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -877,8 +895,9 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -908,8 +927,9 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -939,8 +959,9 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -970,8 +991,9 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -1001,8 +1023,9 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -1032,8 +1055,9 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -1063,8 +1087,9 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -1094,8 +1119,9 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -1110,23 +1136,24 @@ public static object ReadTypedEnumerable(ReaderState reader) Discarder.Discard(reader); return result; } - case TypeCode.Int32: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsInt(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - else if (result is IEnumerable l1) + case TypeCode.Int32: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsInt(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -1138,9 +1165,9 @@ public static object ReadTypedEnumerable(ReaderState reader) return result; } - Discarder.Discard(reader); - return result; - } + Discarder.Discard(reader); + return result; + } case TypeCode.Int64: { var result = CreateResultObject(); @@ -1156,8 +1183,9 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -1187,8 +1215,9 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -1218,8 +1247,9 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -1234,22 +1264,23 @@ public static object ReadTypedEnumerable(ReaderState reader) Discarder.Discard(reader); return result; } - case TypeCode.String: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsString(reader, valueType); - l.Add(v); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - else if (result is IEnumerable l1) + case TypeCode.String: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsString(reader, valueType); + l.Add(v); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -1260,26 +1291,27 @@ public static object ReadTypedEnumerable(ReaderState reader) return result; } - Discarder.Discard(reader); - return result; - } - case TypeCode.UInt16: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsUShort(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - else if (result is IEnumerable l1) + Discarder.Discard(reader); + return result; + } + case TypeCode.UInt16: + { + var result = CreateResultObject(); + if (result is ICollection l) { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsUShort(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -1291,9 +1323,9 @@ public static object ReadTypedEnumerable(ReaderState reader) return result; } - Discarder.Discard(reader); - return result; - } + Discarder.Discard(reader); + return result; + } case TypeCode.UInt32: { var result = CreateResultObject(); @@ -1309,8 +1341,9 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -1340,8 +1373,9 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - else if (result is IEnumerable l1) + else if (result is IEnumerable e1) { + var l1 = new EnumerableWrapperWithAdd(e1); while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); @@ -1455,8 +1489,36 @@ private static class EnumerableAdder { public static (bool Success, object Result) AddEnums(ReaderState reader, object list, bool convertToArray) where T : struct { - if (!(list is ICollection l)) - return (false, list); + if (!(list is ICollection l)) + { + if (!(list is IEnumerable e)) + return (false, list); + + EnumerableWrapperWithAdd adder = new EnumerableWrapperWithAdd(e); + if (!adder.HasAddAction) + return (false, list); + + do + { + try + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var val = ReadEnum(reader); + if (val.HasValue) + adder.Add(val.Value); + } + break; + } + catch (InvalidCastException) + { + } + catch (OverflowException) + { + } + } while (true); + return (true, list); + } do { diff --git a/src/Binaron.Serializer/Infrastructure/GenericWriter.cs b/src/Binaron.Serializer/Infrastructure/GenericWriter.cs index 5d97204..3da3022 100644 --- a/src/Binaron.Serializer/Infrastructure/GenericWriter.cs +++ b/src/Binaron.Serializer/Infrastructure/GenericWriter.cs @@ -40,7 +40,7 @@ public void Write(WriterState writer, IEnumerable list) foreach (var item in (IEnumerable) list) { writer.Write((byte) EnumerableType.HasItem); - Serializer.WriteNonPrimitive(writer, item); + Serializer.WriteValue(writer, item); } writer.Write((byte) EnumerableType.End); } @@ -312,8 +312,18 @@ private class GenericListWriter : IGenericListWriter { public void Write(WriterState writer, ICollection list) { - foreach (var item in (ICollection) list) - Serializer.WriteNonPrimitive(writer, item); + var type = typeof(T); + var type1 = Nullable.GetUnderlyingType(type); + if (type1 != null && type1 != type) + { + foreach (var item in (ICollection)list) + Serializer.WriteValue(writer, item); + } + else + { + foreach (var item in (ICollection)list) + Serializer.WriteNonPrimitive(writer, item); + } } } } diff --git a/src/Binaron.Serializer/Infrastructure/IEnumerableExtension.cs b/src/Binaron.Serializer/Infrastructure/IEnumerableExtension.cs deleted file mode 100644 index 114db1f..0000000 --- a/src/Binaron.Serializer/Infrastructure/IEnumerableExtension.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -namespace Binaron.Serializer.Infrastructure -{ - internal static class IEnumerableExtension - { - private static ConcurrentDictionary> gAdders = new ConcurrentDictionary>(); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void Add(this IEnumerable enumerable, T value) - { - if (!gAdders.TryGetValue(enumerable.GetType(), out Action action)) - { - var method = enumerable.GetType().GetMethod("Add", new Type[] { typeof(T) }); - if (method == null) - action = (o, v) => { }; - else - action = (o, v) => method.Invoke(o, new object[] { v }); - gAdders.TryAdd(enumerable.GetType(), action); - } - action(enumerable, value); - } - } -} \ No newline at end of file diff --git a/src/Binaron.Serializer/Serializer.cs b/src/Binaron.Serializer/Serializer.cs index 1d6ca76..3670b41 100644 --- a/src/Binaron.Serializer/Serializer.cs +++ b/src/Binaron.Serializer/Serializer.cs @@ -102,22 +102,30 @@ private static void WriteNonPrimitive(WriterState writer, object val) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void WriteObject(WriterState writer, T val) { - var type = val.GetType(); - if (writer.CustomObjectIdentifierProviders == null || !writer.CustomObjectIdentifierProviders.TryGetValue(typeof(T), out var customObjectIdentifierProvider)) - { - writer.Write((byte) SerializedType.Object); + if (val == null) + { + writer.Write((byte)SerializedType.Null); } - else - { - writer.Write((byte) SerializedType.CustomObject); - WriteValue(writer, customObjectIdentifierProvider.GetIdentifier(type)); + else + { + var type = val.GetType(); + if (writer.CustomObjectIdentifierProviders == null || !writer.CustomObjectIdentifierProviders.TryGetValue(typeof(T), out var customObjectIdentifierProvider)) + { + writer.Write((byte)SerializedType.Object); + } + else + { + writer.Write((byte)SerializedType.CustomObject); + WriteValue(writer, customObjectIdentifierProvider.GetIdentifier(type)); + } + + + var getters = type == typeof(T) ? GetterHandler.GetterHandlers.Getters : GetterHandler.GetGetterHandlers(type); + foreach (var getter in getters) + getter.Handle(writer, val); + writer.Write((byte)EnumerableType.End); } - - var getters = type == typeof(T) ? GetterHandler.GetterHandlers.Getters : GetterHandler.GetGetterHandlers(type); - foreach (var getter in getters) - getter.Handle(writer, val); - - writer.Write((byte) EnumerableType.End); + } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -242,14 +250,24 @@ private static void WriteEnumerableFallback(WriterState writer, IEnumerable enum [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool WritePrimitive(WriterState writer, object value) - { - return WritePrimitive(writer, value.GetType().GetTypeCode(), value); + { + var type = value.GetType(); + var type1 = Nullable.GetUnderlyingType(type); + if (type1 != null && type1 != type) + type = type1; + + return WritePrimitive(writer, type.GetTypeCode(), value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool WritePrimitive(WriterState writer, T value) { - return WritePrimitive(writer, TypeOf.TypeCode, value); + var type = typeof(T); + var type1 = Nullable.GetUnderlyingType(type); + if (type1 != null && type1 != type) + type = type1; + + return WritePrimitive(writer, type.GetTypeCode(), value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] From 83e9fbf136675e0fe3d682f87e48438e4c1c4375 Mon Sep 17 00:00:00 2001 From: Nikolay Gekht Date: Tue, 2 Feb 2021 13:10:00 -0500 Subject: [PATCH 4/4] - add support of IEnumerable with Add method (i.e. implementation enough for var x = new T() { e1, e2, e3 } syntax. - add debug code - refactor the method of restoring IEnumerable with Add method (#31) - support of nullable in collections and as properties (#34, #35, #36) --- .../CustomTestCollection.cs | 39 + .../ListSerializationTests.cs | 112 +- .../MemberGetSetterTests.cs | 1 + .../ValueSerializationTests.cs | 62 + .../EnumerableWrapperWithAdd.cs | 48 + .../Infrastructure/GenericReader.cs | 2037 +++++++++++------ .../Infrastructure/GenericWriter.cs | 16 +- src/Binaron.Serializer/Serializer.cs | 52 +- 8 files changed, 1625 insertions(+), 742 deletions(-) create mode 100644 src/Binaron.Serializer.Tests/CustomTestCollection.cs create mode 100644 src/Binaron.Serializer/Infrastructure/EnumerableWrapperWithAdd.cs diff --git a/src/Binaron.Serializer.Tests/CustomTestCollection.cs b/src/Binaron.Serializer.Tests/CustomTestCollection.cs new file mode 100644 index 0000000..ebea1de --- /dev/null +++ b/src/Binaron.Serializer.Tests/CustomTestCollection.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Binaron.Serializer.Tests +{ + public class CustomTestCollection : IEnumerable + { + private List List = new List(); + + public T this[int index] => List[index]; + + public int Count => List.Count; + + public void Add(T value) => List.Add(value); + + + public IEnumerator GetEnumerator() => List.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => List.GetEnumerator(); + + public class TestCollectionObject + { + public T A { get; set; } + + public TestCollectionObject() + { + } + + public TestCollectionObject(T a) + { + A = a; + } + } + } +} diff --git a/src/Binaron.Serializer.Tests/ListSerializationTests.cs b/src/Binaron.Serializer.Tests/ListSerializationTests.cs index 6ea38b6..d53edd6 100644 --- a/src/Binaron.Serializer.Tests/ListSerializationTests.cs +++ b/src/Binaron.Serializer.Tests/ListSerializationTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.IO; @@ -265,5 +265,115 @@ private static TList AddItem(TList source, TItem item) where TList throw new NotSupportedException(); } } + + [Test] + public void CustomCollectionIntTest() + { + CustomTestCollection collection = new CustomTestCollection() + { + 0, 1, 2, 3, 4 + }; + + var dest = Tester.TestRoundTrip>(collection); + Assert.AreEqual(5, dest.Count); + Assert.AreEqual(0, dest[0]); + Assert.AreEqual(1, dest[1]); + Assert.AreEqual(2, dest[2]); + Assert.AreEqual(3, dest[3]); + Assert.AreEqual(4, dest[4]); + } + + [TestCaseSource(typeof(AllTestCases), nameof(AllTestCases.TestCaseOfValues))] + public void CustomCollectionOfTypeTest(TSource v) + { + CustomTestCollection collection = new CustomTestCollection() + { + v + }; + + var dest = Tester.TestRoundTrip>(collection); + Assert.AreEqual(1, dest.Count); + Assert.AreEqual(v, dest[0]); + } + + + [Test] + public void CustomCollectionObjectTest() + { + CustomTestCollection.TestCollectionObject> collection = new CustomTestCollection.TestCollectionObject>() + { + new CustomTestCollection.TestCollectionObject(0), + new CustomTestCollection.TestCollectionObject(1), + new CustomTestCollection.TestCollectionObject(2), + new CustomTestCollection.TestCollectionObject(3), + new CustomTestCollection.TestCollectionObject(4), + }; + + var dest = Tester.TestRoundTrip(collection); + Assert.AreEqual(5, dest.Count); + Assert.AreEqual(0, dest[0].A); + Assert.AreEqual(1, dest[1].A); + Assert.AreEqual(2, dest[2].A); + Assert.AreEqual(3, dest[3].A); + Assert.AreEqual(4, dest[4].A); + } + + [Test] + public void TestListWithNullInside() + { + CustomTestCollection.TestCollectionObject> collection = new CustomTestCollection.TestCollectionObject>() + { + new CustomTestCollection.TestCollectionObject(0), + new CustomTestCollection.TestCollectionObject(1), + null, + new CustomTestCollection.TestCollectionObject(3), + new CustomTestCollection.TestCollectionObject(4), + }; + + var dest = Tester.TestRoundTrip(collection); + Assert.AreEqual(5, dest.Count); + Assert.AreEqual(0, dest[0].A); + Assert.AreEqual(1, dest[1].A); + Assert.AreEqual(null, dest[2]); + Assert.AreEqual(3, dest[3].A); + Assert.AreEqual(4, dest[4].A); + } + + [Test] + public void TestListOfNullables1() + { + var collection = new CustomTestCollection() { 1, null, 2 }; + using (var ms1 = new MemoryStream()) + { + var so = new SerializerOptions(); + BinaronConvert.Serialize(collection, ms1, so); + using (var ms2 = new MemoryStream(ms1.ToArray())) + { + var cr2 = BinaronConvert.Deserialize>(ms2); + Assert.AreEqual(3, cr2.Count); + Assert.AreEqual(1, cr2[0]); + Assert.AreEqual(null, cr2[1]); + Assert.AreEqual(2, cr2[2]); + } + } + } + [Test] + public void TestListOfNullables2() + { + var collection = new List() { 1, null, 2 }; + using (var ms1 = new MemoryStream()) + { + var so = new SerializerOptions(); + BinaronConvert.Serialize(collection, ms1, so); + using (var ms2 = new MemoryStream(ms1.ToArray())) + { + var cr2 = BinaronConvert.Deserialize>(ms2); + Assert.AreEqual(3, cr2.Count); + Assert.AreEqual(1, cr2[0]); + Assert.AreEqual(null, cr2[1]); + Assert.AreEqual(2, cr2[2]); + } + } + } } } \ No newline at end of file diff --git a/src/Binaron.Serializer.Tests/MemberGetSetterTests.cs b/src/Binaron.Serializer.Tests/MemberGetSetterTests.cs index b84bc5a..7fe6eff 100644 --- a/src/Binaron.Serializer.Tests/MemberGetSetterTests.cs +++ b/src/Binaron.Serializer.Tests/MemberGetSetterTests.cs @@ -49,5 +49,6 @@ public int NoRead set { } } } + } } \ No newline at end of file diff --git a/src/Binaron.Serializer.Tests/ValueSerializationTests.cs b/src/Binaron.Serializer.Tests/ValueSerializationTests.cs index 24e1172..24a15dc 100644 --- a/src/Binaron.Serializer.Tests/ValueSerializationTests.cs +++ b/src/Binaron.Serializer.Tests/ValueSerializationTests.cs @@ -394,6 +394,68 @@ private static object GetEnumNumeric(object source) } } + [TestCase(1)] + [TestCase(null)] + public void NullableTest1(int? value) + { + using (var ms1 = new MemoryStream()) + { + BinaronConvert.Serialize(value, ms1); + using (var ms2 = new MemoryStream(ms1.ToArray())) + { + Assert.AreEqual(value, BinaronConvert.Deserialize(ms2)); + + } + } + } + + [TestCase(1, "a")] + [TestCase(null, null)] + [TestCase(1, null)] + [TestCase(null, "abcd")] + + public void MemberSetterNullableType1(int? v1, string v2) + { + TestClass1 tc1 = new TestClass1() { IntValue = v1, StringValue = v2 }; + using (MemoryStream ms = new MemoryStream()) + { + BinaronConvert.Serialize(tc1, ms); + using (MemoryStream ms1 = new MemoryStream(ms.ToArray())) + { + var tc2 = BinaronConvert.Deserialize(ms1); + Assert.AreEqual(v1, tc2.IntValue); + Assert.AreEqual(v2, tc2.StringValue); + } + } + } + + [TestCase(1, "a")] + [TestCase(null, null)] + [TestCase(1, null)] + [TestCase(null, "abcd")] + + public void MemberSetterNullableType2(int? v1, string v2) + { + List tc1 = new List() { new TestClass1() { IntValue = v1, StringValue = v2 } }; + using (MemoryStream ms = new MemoryStream()) + { + BinaronConvert.Serialize(tc1, ms); + using (MemoryStream ms1 = new MemoryStream(ms.ToArray())) + { + var tc2 = BinaronConvert.Deserialize>(ms1); + Assert.AreEqual(1, tc2.Count); + Assert.AreEqual(v1, tc2[0].IntValue); + Assert.AreEqual(v2, tc2[0].StringValue); + } + } + } + + private class TestClass1 + { + public int? IntValue { get; set; } + public string StringValue { get; set; } + } + private class TestClass { public DateTime RootValue { get; set; } diff --git a/src/Binaron.Serializer/Infrastructure/EnumerableWrapperWithAdd.cs b/src/Binaron.Serializer/Infrastructure/EnumerableWrapperWithAdd.cs new file mode 100644 index 0000000..27cc0a1 --- /dev/null +++ b/src/Binaron.Serializer/Infrastructure/EnumerableWrapperWithAdd.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Reflection.Emit; +using System.Runtime.CompilerServices; + +namespace Binaron.Serializer.Infrastructure +{ + internal class EnumerableWrapperWithAdd + { + private readonly Action Action; + private readonly object Result; + public bool HasAddAction { get; private set; } = false; + + public EnumerableWrapperWithAdd(IEnumerable result) + { + Result = result; + var method = result.GetType().GetMethod("Add", new Type[] { typeof(T) }); + + if (method == null) + Action = (o, v) => { }; + else + { + HasAddAction = true; + DynamicMethod action = new DynamicMethod( + "Add", + null, + new Type[] { typeof(object), typeof(T) }, + this.GetType().Module); + + var il = action.GetILGenerator(); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldarg_1); + il.Emit(method.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, method); + il.Emit(OpCodes.Ret); + + Action = (Action)action.CreateDelegate(typeof(Action)); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public void Add(T value) + { + Action(Result, value); + } + } +} \ No newline at end of file diff --git a/src/Binaron.Serializer/Infrastructure/GenericReader.cs b/src/Binaron.Serializer/Infrastructure/GenericReader.cs index c0d8709..7ede49c 100644 --- a/src/Binaron.Serializer/Infrastructure/GenericReader.cs +++ b/src/Binaron.Serializer/Infrastructure/GenericReader.cs @@ -44,653 +44,1130 @@ public static object ReadHEnumerable(ReaderState reader) { switch (TypeOf.TypeCode) { - case TypeCode.Object: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsObject(reader, valueType); - l.Add((TElement) v); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Boolean: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Bool) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadBool(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsBool(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Byte: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Byte) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadByte(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsByte(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Char: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Char) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadChar(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsChar(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.DateTime: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.DateTime) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadDateTime(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsDateTime(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Guid: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Guid) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadGuid(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsGuid(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Decimal: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Decimal) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadDecimal(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsDecimal(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Double: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Double) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadDouble(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsDouble(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Int16: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Short) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadShort(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsShort(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Int32: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Int) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadInt(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsInt(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Int64: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Long) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadLong(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsLong(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.SByte: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.SByte) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadSByte(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsSByte(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Single: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.Float) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadFloat(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsFloat(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.String: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.String) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadString(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsString(reader, valueType); - l.Add(v); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.UInt16: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.UShort) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadUShort(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsUShort(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.UInt32: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.UInt) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadUInt(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsUInt(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.UInt64: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - var valueType = Reader.ReadSerializedType(reader); - if (valueType == SerializedType.ULong) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - l.Add(Reader.ReadULong(reader)); - } - else - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var v = SelfUpgradingReader.ReadAsULong(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - } - - return null; - } - - public static object ReadTypedEnumerable(ReaderState reader) - { - switch (TypeOf.TypeCode) - { - case TypeCode.Object: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsObject(reader, valueType); - l.Add((TElement) v); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Boolean: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsBool(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Byte: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsByte(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Char: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsChar(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; + case TypeCode.Object: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsObject(reader, valueType); + l.Add((TElement)v); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsObject(reader, valueType); + l1.Add((TElement)v); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Boolean: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Bool) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadBool(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsBool(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Bool) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadBool(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsBool(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Byte: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Byte) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadByte(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsByte(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Byte) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadByte(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsByte(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + Discarder.Discard(reader); + return result; + } + case TypeCode.Char: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Char) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadChar(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsChar(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Char) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadChar(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsChar(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.DateTime: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.DateTime) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadDateTime(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsDateTime(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.DateTime) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadDateTime(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsDateTime(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Guid: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Guid) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadGuid(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsGuid(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Guid) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadGuid(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsGuid(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Decimal: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Decimal) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadDecimal(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsDecimal(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Decimal) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadDecimal(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsDecimal(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Double: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Double) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadDouble(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsDouble(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Double) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadDouble(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsDouble(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Int16: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Short) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadShort(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsShort(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Short) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadShort(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsShort(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Int32: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Int) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadInt(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsInt(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Int) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadInt(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsInt(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Int64: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Long) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadLong(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsLong(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Long) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadLong(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsLong(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; } - - Discarder.Discard(reader); - return result; - } - case TypeCode.DateTime: + case TypeCode.SByte: { var result = CreateResultObject(); - if (result is ICollection l) + if (result is ICollection l) { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.SByte) { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsDateTime(reader, valueType); - if (v.HasValue) - l.Add(v.Value); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadSByte(reader)); } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Guid: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + else { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsGuid(reader, valueType); - if (v.HasValue) - l.Add(v.Value); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsSByte(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } } return typeof(T).IsArray ? ToArray(l) : result; } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Decimal: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsDecimal(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.SByte) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadSByte(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsSByte(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Single: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Float) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadFloat(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsFloat(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.Float) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadFloat(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsFloat(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.String: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.String) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadString(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsString(reader, valueType); + l.Add(v); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.String) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadString(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsString(reader, valueType); + l1.Add(v); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.UInt16: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.UShort) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadUShort(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsUShort(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.UShort) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadUShort(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsUShort(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.UInt32: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.UInt) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadUInt(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsUInt(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.UInt) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadUInt(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsUInt(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.UInt64: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.ULong) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l.Add(Reader.ReadULong(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsULong(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + } + + return typeof(T).IsArray ? ToArray(l) : result; + + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + var valueType = Reader.ReadSerializedType(reader); + if (valueType == SerializedType.ULong) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + l1.Add(Reader.ReadULong(reader)); + } + else + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var v = SelfUpgradingReader.ReadAsULong(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + } + + return result; + } + + + Discarder.Discard(reader); + return result; } + } - Discarder.Discard(reader); - return result; - } - case TypeCode.Double: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsDouble(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } + return null; + } - return typeof(T).IsArray ? ToArray(l) : result; + public static object ReadTypedEnumerable(ReaderState reader) + { + switch (TypeOf.TypeCode) + { + case TypeCode.Object: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsObject(reader, valueType); + l.Add((TElement)v); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsObject(reader, valueType); + l1.Add((TElement)v); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Boolean: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsBool(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsBool(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Byte: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsByte(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsByte(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Int16: + case TypeCode.Char: { var result = CreateResultObject(); - if (result is ICollection l) + if (result is ICollection l) { while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) { var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsShort(reader, valueType); + var v = SelfUpgradingReader.ReadAsChar(reader, valueType); if (v.HasValue) l.Add(v.Value); } return typeof(T).IsArray ? ToArray(l) : result; } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Int32: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsInt(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsChar(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.DateTime: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsDateTime(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsDateTime(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Guid: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsGuid(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsGuid(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Decimal: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsDecimal(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsDecimal(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Double: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsDouble(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsDouble(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Int16: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsShort(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsShort(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Int32: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsInt(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsInt(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; } - - Discarder.Discard(reader); - return result; - } case TypeCode.Int64: { var result = CreateResultObject(); @@ -706,85 +1183,149 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - - Discarder.Discard(reader); - return result; - } - case TypeCode.SByte: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsSByte(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.Single: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsFloat(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.String: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsString(reader, valueType); - l.Add(v); - } - - return typeof(T).IsArray ? ToArray(l) : result; - } - - Discarder.Discard(reader); - return result; - } - case TypeCode.UInt16: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsUShort(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsLong(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.SByte: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsSByte(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsSByte(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.Single: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsFloat(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsFloat(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.String: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsString(reader, valueType); + l.Add(v); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsString(reader, valueType); + l1.Add(v); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.UInt16: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsUShort(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsUShort(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; } - - Discarder.Discard(reader); - return result; - } case TypeCode.UInt32: { var result = CreateResultObject(); @@ -800,29 +1341,55 @@ public static object ReadTypedEnumerable(ReaderState reader) return typeof(T).IsArray ? ToArray(l) : result; } - - Discarder.Discard(reader); - return result; - } - case TypeCode.UInt64: - { - var result = CreateResultObject(); - if (result is ICollection l) - { - while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) - { - var valueType = Reader.ReadSerializedType(reader); - var v = SelfUpgradingReader.ReadAsULong(reader, valueType); - if (v.HasValue) - l.Add(v.Value); - } - - return typeof(T).IsArray ? ToArray(l) : result; + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsUInt(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; + } + case TypeCode.UInt64: + { + var result = CreateResultObject(); + if (result is ICollection l) + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsULong(reader, valueType); + if (v.HasValue) + l.Add(v.Value); + } + + return typeof(T).IsArray ? ToArray(l) : result; + } + else if (result is IEnumerable e1) + { + var l1 = new EnumerableWrapperWithAdd(e1); + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var valueType = Reader.ReadSerializedType(reader); + var v = SelfUpgradingReader.ReadAsULong(reader, valueType); + if (v.HasValue) + l1.Add(v.Value); + } + + return result; + } + + Discarder.Discard(reader); + return result; } - - Discarder.Discard(reader); - return result; - } } return null; @@ -922,8 +1489,36 @@ private static class EnumerableAdder { public static (bool Success, object Result) AddEnums(ReaderState reader, object list, bool convertToArray) where T : struct { - if (!(list is ICollection l)) - return (false, list); + if (!(list is ICollection l)) + { + if (!(list is IEnumerable e)) + return (false, list); + + EnumerableWrapperWithAdd adder = new EnumerableWrapperWithAdd(e); + if (!adder.HasAddAction) + return (false, list); + + do + { + try + { + while (Reader.ReadEnumerableType(reader) == EnumerableType.HasItem) + { + var val = ReadEnum(reader); + if (val.HasValue) + adder.Add(val.Value); + } + break; + } + catch (InvalidCastException) + { + } + catch (OverflowException) + { + } + } while (true); + return (true, list); + } do { diff --git a/src/Binaron.Serializer/Infrastructure/GenericWriter.cs b/src/Binaron.Serializer/Infrastructure/GenericWriter.cs index 5d97204..3da3022 100644 --- a/src/Binaron.Serializer/Infrastructure/GenericWriter.cs +++ b/src/Binaron.Serializer/Infrastructure/GenericWriter.cs @@ -40,7 +40,7 @@ public void Write(WriterState writer, IEnumerable list) foreach (var item in (IEnumerable) list) { writer.Write((byte) EnumerableType.HasItem); - Serializer.WriteNonPrimitive(writer, item); + Serializer.WriteValue(writer, item); } writer.Write((byte) EnumerableType.End); } @@ -312,8 +312,18 @@ private class GenericListWriter : IGenericListWriter { public void Write(WriterState writer, ICollection list) { - foreach (var item in (ICollection) list) - Serializer.WriteNonPrimitive(writer, item); + var type = typeof(T); + var type1 = Nullable.GetUnderlyingType(type); + if (type1 != null && type1 != type) + { + foreach (var item in (ICollection)list) + Serializer.WriteValue(writer, item); + } + else + { + foreach (var item in (ICollection)list) + Serializer.WriteNonPrimitive(writer, item); + } } } } diff --git a/src/Binaron.Serializer/Serializer.cs b/src/Binaron.Serializer/Serializer.cs index 1d6ca76..3670b41 100644 --- a/src/Binaron.Serializer/Serializer.cs +++ b/src/Binaron.Serializer/Serializer.cs @@ -102,22 +102,30 @@ private static void WriteNonPrimitive(WriterState writer, object val) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void WriteObject(WriterState writer, T val) { - var type = val.GetType(); - if (writer.CustomObjectIdentifierProviders == null || !writer.CustomObjectIdentifierProviders.TryGetValue(typeof(T), out var customObjectIdentifierProvider)) - { - writer.Write((byte) SerializedType.Object); + if (val == null) + { + writer.Write((byte)SerializedType.Null); } - else - { - writer.Write((byte) SerializedType.CustomObject); - WriteValue(writer, customObjectIdentifierProvider.GetIdentifier(type)); + else + { + var type = val.GetType(); + if (writer.CustomObjectIdentifierProviders == null || !writer.CustomObjectIdentifierProviders.TryGetValue(typeof(T), out var customObjectIdentifierProvider)) + { + writer.Write((byte)SerializedType.Object); + } + else + { + writer.Write((byte)SerializedType.CustomObject); + WriteValue(writer, customObjectIdentifierProvider.GetIdentifier(type)); + } + + + var getters = type == typeof(T) ? GetterHandler.GetterHandlers.Getters : GetterHandler.GetGetterHandlers(type); + foreach (var getter in getters) + getter.Handle(writer, val); + writer.Write((byte)EnumerableType.End); } - - var getters = type == typeof(T) ? GetterHandler.GetterHandlers.Getters : GetterHandler.GetGetterHandlers(type); - foreach (var getter in getters) - getter.Handle(writer, val); - - writer.Write((byte) EnumerableType.End); + } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -242,14 +250,24 @@ private static void WriteEnumerableFallback(WriterState writer, IEnumerable enum [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool WritePrimitive(WriterState writer, object value) - { - return WritePrimitive(writer, value.GetType().GetTypeCode(), value); + { + var type = value.GetType(); + var type1 = Nullable.GetUnderlyingType(type); + if (type1 != null && type1 != type) + type = type1; + + return WritePrimitive(writer, type.GetTypeCode(), value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool WritePrimitive(WriterState writer, T value) { - return WritePrimitive(writer, TypeOf.TypeCode, value); + var type = typeof(T); + var type1 = Nullable.GetUnderlyingType(type); + if (type1 != null && type1 != type) + type = type1; + + return WritePrimitive(writer, type.GetTypeCode(), value); } [MethodImpl(MethodImplOptions.AggressiveInlining)]