From c3d355ac7e3eeff53358c58da9ae0f170b37e0ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Sim=C3=B5es?= Date: Fri, 16 Dec 2022 14:29:36 +0000 Subject: [PATCH] Add .NET Helper (#4) --- .github/workflows/pr-checks.yml | 2 + .github/workflows/update-dependencies.yml | 4 +- .runsettings | 15 + .../FieldNoReflectionAttribute.cs | 0 .../Serialization.Shared.projitems | 16 + .../Serialization.Shared.shproj | 13 + .../SerializationHintsAttribute.cs | 0 .../SerializationOptions.cs | 0 Tests/HelperTests/DeserializationTests.cs | 109 + Tests/HelperTests/HelperTests.csproj | 27 + Tests/HelperTests/SerializationTests.cs | 77 + Tests/HelperTests/packages.lock.json | 1089 ++++++++ .../Properties/AssemblyInfo.cs | 31 + .../SerializationTests.nfproj | 69 + Tests/SerializationTests/nano.runsettings | 15 + Tests/SerializationTests/packages.config | 5 + Tests/SerializationTests/packages.lock.json | 19 + Tests/UnitTests.Shared/ComplexClass.cs | 45 + Tests/UnitTests.Shared/Person.cs | 23 + Tests/UnitTests.Shared/UnitTestHelper.cs | 130 + .../UnitTests.Shared.projitems | 16 + .../UnitTests.Shared/UnitTests.Shared.shproj | 13 + azure-pipelines.yml | 381 ++- helper.runsettings | 11 + nanoFramework.Serialization.Helper.sln | 48 + .../BinaryFormatter.cs | 2279 +++++++++++++++++ .../BitStream.cs | 373 +++ .../CrcHelper.cs | 74 + .../ElementType.cs | 79 + .../nanoFramework.Serialization.Helper.csproj | 67 + .../packages.lock.json | 61 + .../version.json | 24 + ...Framework.System.Runtime.Serialization.sln | 22 + .../System.Runtime.Serialization.nfproj | 6 +- 34 files changed, 5111 insertions(+), 32 deletions(-) create mode 100644 .runsettings rename {nanoFramework.System.Runtime.Serialization => Serialization.Shared}/FieldNoReflectionAttribute.cs (100%) create mode 100644 Serialization.Shared/Serialization.Shared.projitems create mode 100644 Serialization.Shared/Serialization.Shared.shproj rename {nanoFramework.System.Runtime.Serialization => Serialization.Shared}/SerializationHintsAttribute.cs (100%) rename {nanoFramework.System.Runtime.Serialization => Serialization.Shared}/SerializationOptions.cs (100%) create mode 100644 Tests/HelperTests/DeserializationTests.cs create mode 100644 Tests/HelperTests/HelperTests.csproj create mode 100644 Tests/HelperTests/SerializationTests.cs create mode 100644 Tests/HelperTests/packages.lock.json create mode 100644 Tests/SerializationTests/Properties/AssemblyInfo.cs create mode 100644 Tests/SerializationTests/SerializationTests.nfproj create mode 100644 Tests/SerializationTests/nano.runsettings create mode 100644 Tests/SerializationTests/packages.config create mode 100644 Tests/SerializationTests/packages.lock.json create mode 100644 Tests/UnitTests.Shared/ComplexClass.cs create mode 100644 Tests/UnitTests.Shared/Person.cs create mode 100644 Tests/UnitTests.Shared/UnitTestHelper.cs create mode 100644 Tests/UnitTests.Shared/UnitTests.Shared.projitems create mode 100644 Tests/UnitTests.Shared/UnitTests.Shared.shproj create mode 100644 helper.runsettings create mode 100644 nanoFramework.Serialization.Helper.sln create mode 100644 nanoFramework.Serialization.Helper/BinaryFormatter.cs create mode 100644 nanoFramework.Serialization.Helper/BitStream.cs create mode 100644 nanoFramework.Serialization.Helper/CrcHelper.cs create mode 100644 nanoFramework.Serialization.Helper/ElementType.cs create mode 100644 nanoFramework.Serialization.Helper/nanoFramework.Serialization.Helper.csproj create mode 100644 nanoFramework.Serialization.Helper/packages.lock.json create mode 100644 nanoFramework.Serialization.Helper/version.json diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 158158b..5bcc350 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -10,6 +10,8 @@ jobs: check_package_lock: name: nanoFramework uses: nanoframework/nf-tools/.github/workflows/check-package-lock.yml@main + with: + solution: 'nanoFramework.System.Runtime.Serialization.sln' check_nuget_latest: name: nanoFramework uses: nanoframework/nf-tools/.github/workflows/check-packages-updated.yml@main diff --git a/.github/workflows/update-dependencies.yml b/.github/workflows/update-dependencies.yml index d77eb1d..732317a 100644 --- a/.github/workflows/update-dependencies.yml +++ b/.github/workflows/update-dependencies.yml @@ -7,8 +7,8 @@ name: Update .NET nanoFramework dependencies on: schedule: - # At 00:00 UTC every day. - - cron: '00 00 * * *' + # At 00:00 UTC every wednesday. + - cron: '00 00 * * Wed' repository_dispatch: types: update-dependencies diff --git a/.runsettings b/.runsettings new file mode 100644 index 0000000..e82b99e --- /dev/null +++ b/.runsettings @@ -0,0 +1,15 @@ + + + + + 1 + .\TestResults + 120000 + net48 + x64 + + + None + False + + \ No newline at end of file diff --git a/nanoFramework.System.Runtime.Serialization/FieldNoReflectionAttribute.cs b/Serialization.Shared/FieldNoReflectionAttribute.cs similarity index 100% rename from nanoFramework.System.Runtime.Serialization/FieldNoReflectionAttribute.cs rename to Serialization.Shared/FieldNoReflectionAttribute.cs diff --git a/Serialization.Shared/Serialization.Shared.projitems b/Serialization.Shared/Serialization.Shared.projitems new file mode 100644 index 0000000..5bfd481 --- /dev/null +++ b/Serialization.Shared/Serialization.Shared.projitems @@ -0,0 +1,16 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + 88d19908-57c1-4b09-9993-de00cee88bf4 + + + Serialization.Shared + + + + + + + \ No newline at end of file diff --git a/Serialization.Shared/Serialization.Shared.shproj b/Serialization.Shared/Serialization.Shared.shproj new file mode 100644 index 0000000..05c55d3 --- /dev/null +++ b/Serialization.Shared/Serialization.Shared.shproj @@ -0,0 +1,13 @@ + + + + 88d19908-57c1-4b09-9993-de00cee88bf4 + 14.0 + + + + + + + + diff --git a/nanoFramework.System.Runtime.Serialization/SerializationHintsAttribute.cs b/Serialization.Shared/SerializationHintsAttribute.cs similarity index 100% rename from nanoFramework.System.Runtime.Serialization/SerializationHintsAttribute.cs rename to Serialization.Shared/SerializationHintsAttribute.cs diff --git a/nanoFramework.System.Runtime.Serialization/SerializationOptions.cs b/Serialization.Shared/SerializationOptions.cs similarity index 100% rename from nanoFramework.System.Runtime.Serialization/SerializationOptions.cs rename to Serialization.Shared/SerializationOptions.cs diff --git a/Tests/HelperTests/DeserializationTests.cs b/Tests/HelperTests/DeserializationTests.cs new file mode 100644 index 0000000..7c79f11 --- /dev/null +++ b/Tests/HelperTests/DeserializationTests.cs @@ -0,0 +1,109 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +using System.Collections; + +#if NANOFRAMEWORK_1_0 +using nanoFramework.TestFramework; +using System; +using BinaryFormatter = System.Runtime.Serialization.Formatters.Binary.BinaryFormatter; +#else +using Microsoft.VisualStudio.TestTools.UnitTesting; +using nanoFramework.Serialization.Helper; +#endif + +namespace nanoFramework.System.Runtime.Serialization.Tests +{ + [TestClass] + public class DeserializationTests + { + [TestMethod] + public void DeserializePersonClassTest() + { + // serialize person class + var personeOne = UnitTestHelper.CreatePersonOne(); + +#if NANOFRAMEWORK_1_0 + var newPersoneOne = BinaryFormatter.Deserialize(UnitTestHelper.PersonOneSerialized) as Person; +#else + var binaryFormatter = new BinaryFormatter(); + var newPersoneOne = binaryFormatter.Deserialize(UnitTestHelper.PersonOneSerialized) as Person; +#endif + + Assert.IsNotNull(newPersoneOne); + Assert.AreEqual(newPersoneOne.LastName, personeOne.LastName); + Assert.AreEqual(newPersoneOne.FirstName, personeOne.FirstName); + Assert.AreEqual(newPersoneOne.ID, personeOne.ID); + Assert.AreEqual(newPersoneOne.Address, personeOne.Address); + Assert.AreEqual(newPersoneOne.Birthday, personeOne.Birthday); + Assert.AreEqual(newPersoneOne.Friend.LastName, personeOne.Friend.LastName); + Assert.AreEqual(newPersoneOne.Friend.FirstName, personeOne.Friend.FirstName); + Assert.AreEqual(newPersoneOne.Friend.ID, personeOne.Friend.ID); + Assert.AreEqual(newPersoneOne.Friend.Address, personeOne.Friend.Address); + Assert.AreEqual(newPersoneOne.Friend.Birthday, personeOne.Friend.Birthday); + } + + [TestMethod] + public void DeserializeComplexClassTest() + { + // serialize Complex class + var complexeClassOne = UnitTestHelper.CreateComplexClassOne(); + +#if NANOFRAMEWORK_1_0 + var newComplexeClassOne = BinaryFormatter.Deserialize(UnitTestHelper.ComplexClassOneSerialized) as ComplexClass; +#else + var binaryFormatter = new BinaryFormatter(); + var newComplexeClassOne = binaryFormatter.Deserialize(UnitTestHelper.ComplexClassOneSerialized) as ComplexClass; +#endif + + Assert.IsNotNull(newComplexeClassOne); + Assert.AreEqual(newComplexeClassOne.aInteger, complexeClassOne.aInteger); + Assert.AreEqual(newComplexeClassOne.aShort, complexeClassOne.aShort); + Assert.AreEqual(newComplexeClassOne.aByte, complexeClassOne.aByte); + Assert.AreEqual(newComplexeClassOne.aString, complexeClassOne.aString); + Assert.AreEqual(newComplexeClassOne.aFloat, complexeClassOne.aFloat); + Assert.AreEqual(newComplexeClassOne.aDouble, complexeClassOne.aDouble); + Assert.AreEqual(newComplexeClassOne.aBoolean, complexeClassOne.aBoolean); + Assert.AreEqual(newComplexeClassOne.Timestamp, complexeClassOne.Timestamp); + Assert.AreEqual(newComplexeClassOne.FixedTimestamp, complexeClassOne.FixedTimestamp); + Assert.AreEqual(newComplexeClassOne.nullObject, complexeClassOne.nullObject); + Assert.AreEqual(newComplexeClassOne.nanFloat, complexeClassOne.nanFloat); + Assert.AreEqual(newComplexeClassOne.nanDouble, complexeClassOne.nanDouble); + + CollectionAssert.AreEqual(newComplexeClassOne.intArray, complexeClassOne.intArray); + CollectionAssert.AreEqual(newComplexeClassOne.shortArray, complexeClassOne.shortArray); + CollectionAssert.AreEqual(newComplexeClassOne.byteArray, complexeClassOne.byteArray); + CollectionAssert.AreEqual(newComplexeClassOne.stringArray, complexeClassOne.stringArray); + CollectionAssert.AreEqual(newComplexeClassOne.floatArray, complexeClassOne.floatArray); + CollectionAssert.AreEqual(newComplexeClassOne.doubleArray, complexeClassOne.doubleArray); + + Assert.AreEqual(newComplexeClassOne.Child.one, complexeClassOne.Child.one); + Assert.AreEqual(newComplexeClassOne.Child.two, complexeClassOne.Child.two); + Assert.AreEqual(newComplexeClassOne.Child.three, complexeClassOne.Child.three); + + Assert.AreEqual(newComplexeClassOne.child1.one, complexeClassOne.child1.one); + Assert.AreEqual(newComplexeClassOne.child1.two, complexeClassOne.child1.two); + Assert.AreEqual(newComplexeClassOne.child1.three, complexeClassOne.child1.three); + } + + [TestMethod] + public void DeserializeArrayListTest() + { + // serialize array list + var personeOne = UnitTestHelper.CreateArrayListOne(); + +#if NANOFRAMEWORK_1_0 + var newArrayListeOne = BinaryFormatter.Deserialize(UnitTestHelper.ArrayListOneSerialized) as ArrayList; +#else + var binaryFormatter = new BinaryFormatter(); + var newArrayListeOne = binaryFormatter.Deserialize(UnitTestHelper.ArrayListOneSerialized) as ArrayList; +#endif + + Assert.IsNotNull(newArrayListeOne); + CollectionAssert.AreEqual(newArrayListeOne, personeOne); + } + } +} diff --git a/Tests/HelperTests/HelperTests.csproj b/Tests/HelperTests/HelperTests.csproj new file mode 100644 index 0000000..0ef9708 --- /dev/null +++ b/Tests/HelperTests/HelperTests.csproj @@ -0,0 +1,27 @@ + + + + net6.0 + disable + enable + false + true + true + + + + + + + + + + + + + + + + + + diff --git a/Tests/HelperTests/SerializationTests.cs b/Tests/HelperTests/SerializationTests.cs new file mode 100644 index 0000000..2a919aa --- /dev/null +++ b/Tests/HelperTests/SerializationTests.cs @@ -0,0 +1,77 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +#if NANOFRAMEWORK_1_0 +using nanoFramework.TestFramework; +using BinaryFormatter = System.Runtime.Serialization.Formatters.Binary.BinaryFormatter; +#else +using Microsoft.VisualStudio.TestTools.UnitTesting; +using nanoFramework.Serialization.Helper; +#endif + +namespace nanoFramework.System.Runtime.Serialization.Tests +{ + [TestClass] + public class SerializationTests + { + [TestMethod] + public void SerializePersonClassTest() + { + // serialize person class + var personeOne = UnitTestHelper.CreatePersonOne(); + +#if NANOFRAMEWORK_1_0 + var serializedPerson = BinaryFormatter.Serialize(personeOne); +#else + var binaryFormatter = new BinaryFormatter(); + var serializedPerson = binaryFormatter.Serialize(personeOne); +#endif + + Assert.IsNotNull(serializedPerson); + Assert.IsTrue(serializedPerson.Length == UnitTestHelper.PersonOneSerialized.Length, "PersonOne serialized data has different length."); + + CollectionAssert.AreEqual(UnitTestHelper.PersonOneSerialized, serializedPerson); + } + + [TestMethod] + public void SerializeComplexClassTest() + { + // serialize complex class + var complexClassOne = UnitTestHelper.CreateComplexClassOne(); + +#if NANOFRAMEWORK_1_0 + var serializedComplexClass = BinaryFormatter.Serialize(complexClassOne); +#else + var binaryFormatter = new BinaryFormatter(); + var serializedComplexClass = binaryFormatter.Serialize(complexClassOne); +#endif + + Assert.IsNotNull(serializedComplexClass); + Assert.IsTrue(serializedComplexClass.Length == UnitTestHelper.ComplexClassOneSerialized.Length, "ComplexClass serialized data has different length."); + + CollectionAssert.AreEqual(UnitTestHelper.ComplexClassOneSerialized, serializedComplexClass); + } + + [TestMethod] + public void SerializeArrayListTest() + { + // serialize array list + var arrayListOne = UnitTestHelper.CreateArrayListOne(); + +#if NANOFRAMEWORK_1_0 + var serializedArrayList = BinaryFormatter.Serialize(arrayListOne); +#else + var binaryFormatter = new BinaryFormatter(); + var serializedArrayList = binaryFormatter.Serialize(arrayListOne); +#endif + + Assert.IsNotNull(serializedArrayList); + Assert.IsTrue(serializedArrayList.Length == UnitTestHelper.ArrayListOneSerialized.Length, "ArrayListOne serialized data has different length."); + + CollectionAssert.AreEqual(UnitTestHelper.ArrayListOneSerialized, serializedArrayList); + } + } +} diff --git a/Tests/HelperTests/packages.lock.json b/Tests/HelperTests/packages.lock.json new file mode 100644 index 0000000..0b0715c --- /dev/null +++ b/Tests/HelperTests/packages.lock.json @@ -0,0 +1,1089 @@ +{ + "version": 1, + "dependencies": { + "net6.0": { + "coverlet.collector": { + "type": "Direct", + "requested": "[3.1.2, )", + "resolved": "3.1.2", + "contentHash": "wuLDIDKD5XMt0A7lE31JPenT7QQwZPFkP5rRpdJeblyXZ9MGLI8rYjvm5fvAKln+2/X+4IxxQDxBtwdrqKNLZw==" + }, + "Microsoft.NET.Test.Sdk": { + "type": "Direct", + "requested": "[17.1.0, )", + "resolved": "17.1.0", + "contentHash": "MVKvOsHIfrZrvg+8aqOF5dknO/qWrR1sWZjMPQ1N42MKMlL/zQL30FQFZxPeWfmVKWUWAOmAHYsqB5OerTKziw==", + "dependencies": { + "Microsoft.CodeCoverage": "17.1.0", + "Microsoft.TestPlatform.TestHost": "17.1.0" + } + }, + "MSTest.TestAdapter": { + "type": "Direct", + "requested": "[2.2.8, )", + "resolved": "2.2.8", + "contentHash": "BzxcfLaOZ25g8usreCBwFvpzH9LcR56pSkMbERO718cTQyAChXBYVuNIU3uK9stCcUWdXxIYl4WloiIu/C/PMQ==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "System.Diagnostics.TextWriterTraceListener": "4.3.0" + } + }, + "MSTest.TestFramework": { + "type": "Direct", + "requested": "[2.2.8, )", + "resolved": "2.2.8", + "contentHash": "phUoHuGTuw9T5yekxPHLLLq8jE56yufmh2yPlJq1IfkT4a3tYZ2htkeTlnQmzmJP3hI5xYhlqwiHcy3JqVt/OA==", + "dependencies": { + "NETStandard.Library": "1.6.1", + "System.Diagnostics.TextWriterTraceListener": "4.3.0" + } + }, + "Microsoft.CodeCoverage": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "0N/ZJ71ncCxQWhgtkEYKOgu2oMHa8h1tsOUbhmIKXF8UwtSUCe4vHAsJ3DVcNWRwNfQzSTy263ZE+QF6MdIhhQ==" + }, + "Microsoft.CSharp": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "17h8b5mXa87XYKrrVqdgZ38JefSUqLChUQpXgSnpzsM0nDOhE40FTeNWOJ/YmySGV6tG6T8+hjz6vxbknHJr6A==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Dynamic.Runtime": "4.0.11", + "System.Globalization": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.ObjectModel": "4.0.12", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.InteropServices": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.TestPlatform.ObjectModel": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "OMo/FYnKGy3lZEK0gfitskRM3ga/YBt6MyCyFPq0xNLeybGOQ6HnYNAAvzyePo5WPuMiw3LX+HiuRWNjnas1fA==", + "dependencies": { + "NuGet.Frameworks": "5.11.0", + "System.Reflection.Metadata": "1.6.0" + } + }, + "Microsoft.TestPlatform.TestHost": { + "type": "Transitive", + "resolved": "17.1.0", + "contentHash": "JS0JDLniDhIzkSPLHz7N/x1CG8ywJOtwInFDYA3KQvbz+ojGoT5MT2YDVReL1b86zmNRV8339vsTSm/zh0RcMg==", + "dependencies": { + "Microsoft.TestPlatform.ObjectModel": "17.1.0", + "Newtonsoft.Json": "9.0.1" + } + }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "9.0.1", + "contentHash": "U82mHQSKaIk+lpSVCbWYKNavmNH1i5xrExDEquU1i6I5pV6UMOqRnJRSlKO3cMPfcpp0RgDY+8jUXHdQ4IfXvw==", + "dependencies": { + "Microsoft.CSharp": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Dynamic.Runtime": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.ObjectModel": "4.0.12", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Text.Encoding": "4.0.11", + "System.Text.Encoding.Extensions": "4.0.11", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XDocument": "4.0.11" + } + }, + "NuGet.Frameworks": { + "type": "Transitive", + "resolved": "5.11.0", + "contentHash": "eaiXkUjC4NPcquGWzAGMXjuxvLwc6XGKMptSyOGQeT0X70BUZObuybJFZLA0OfTdueLd3US23NBPTBb6iF3V1Q==" + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "HdSSp5MnJSsg08KMfZThpuLPJpPwE5hBXvHwoKWosyHHfe8Mh5WKT0ylEOf6yNzX6Ngjxe4Whkafh5q7Ymac4Q==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "+yH1a49wJMy8Zt4yx5RhJrxO/DBDByAiCzNwiETI+1S4mPdCu0OY4djdciC7Vssk0l22wQaDLrXxXkp+3+7bVA==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c3YNH1GQJbfIPJeCnr4avseugSqPrxwIqzthYyZDN6EuOyNOzq+y2KSUfRcXauya1sF4foESTgwM5e1A8arAKw==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "NS1U+700m4KFRHR5o4vo9DSlTmlCKu/u7dtE5sUHVIPB+xpXxYQvgBgA6wEIeCz6Yfn0Z52/72WYsToCEPJnrw==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "b3pthNgxxFcD+Pc0WSEoC0+md3MyhRS6aCEeenvNE3Fdw1HyJ18ZhRFVJJzIeR/O/jpxPboB805Ho0T3Ul7w8A==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KeLz4HClKf+nFS7p/6Fi/CqyLXh81FpiGzcmuS8DGi9lUqSnZ6Es23/gv2O+1XVGfrbNmviF7CckBpavkBoIFQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X7IdhILzr4ROXd8mI1BUCQMSHSQwelUlBjF1JyTKCjXaOGn2fB4EKBxQbCK2VjO3WaWIdlXZL3W6TiIVnrhX4g==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "nyFNiCk/r+VOiIqreLix8yN+q3Wga9+SE8BCgkf+2BwEKiNx6DyvFjCgkfV743/grxv8jHJ8gUK4XEQw7yzRYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ytoewC6wGorL7KoCAvRfsgoJPJbNq+64k2SqW6JcOAebWsFUvCCYgfzQMrnpvPiEl4OrblUlhF2ji+Q1+SVLrQ==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I8bKw2I8k58Wx7fMKQJn2R8lamboCAiHfHeV/pS65ScKWMMI0+wJkLYlEKvgW1D/XvSl/221clBoR2q9QNNM7A==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VB5cn/7OzUfzdnC8tqAIMQciVLiq2epm2NrAm1E9OjNRyG4lVhfR61SMcLizejzQP8R8Uf/0l5qOIbUEi+RdEg==" + }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ratu44uTIHgeBeI0dE8DWvmXVBSo4u7ozRZZHOMmK/JPpYyo0dAfgSiHlpiObMQ5lEtEyIXA40sKRYg5J6A8uQ==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "tD6kosZnTAGdrEa0tZSuFyunMbt/5KYDnHdndJYGqZoNy00XVXyACd5d6KnE1YgYv3ne2CjtAfNXo/fwEhnKUA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Diagnostics.TextWriterTraceListener": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "F11kHWeiwYjFWto+kr8tt9ULMH0k8MsT1XmdCGPTLYHhWgN+2g7JsIZiXDrxlFGccSNkbjfwQy4xIS38gzUiZA==", + "dependencies": { + "System.Diagnostics.TraceSource": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.TraceSource": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VnYp1NxGx8Ww731y2LJ1vpfb/DKVNKEZ8Jsh5SgQTZREL/YpWRArgh9pI8CDLmgHspZmLL697CaLvH85qQpRiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Dynamic.Runtime": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "db34f6LHYM0U0JpE+sOmjar27BnqTVkbLJhgfwMpTdgTigG/Hna3m2MYVwnFzGGKnEJk2UXFuoVTr8WUbU91/A==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.ObjectModel": "4.0.12", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "sYg+FtILtRQuYWSIAuNOELwVuVsxVyJGWQyOnlAzhV4xvhyFnON1bAzYYC+jjRW8JREM45R0R5Dgi8MTC5sEwA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Metadata": { + "type": "Transitive", + "resolved": "1.6.0", + "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==" + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Runtime.Serialization.Primitives": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==", + "dependencies": { + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "03idZOqFlsKRL4W+LuCpJ6dBYDUWReug6lZjBa3uJWnk5sPCUXckocevTaUA8iT/MFSrY/2HXkOt753xQ/cf8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "npvJkVKl5rKXrtl1Kkm6OhOUaYGEiF9wFbppFRWSMoApKzt2PiPHT2Bb8a5sAWxprvdOAtvaARS9QYMznEUtug==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "nanoframework.serialization.helper": { + "type": "Project" + } + } + } +} \ No newline at end of file diff --git a/Tests/SerializationTests/Properties/AssemblyInfo.cs b/Tests/SerializationTests/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..a3735af --- /dev/null +++ b/Tests/SerializationTests/Properties/AssemblyInfo.cs @@ -0,0 +1,31 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyCopyright("Copyright (c) 2021 nanoFramework contributors")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Tests/SerializationTests/SerializationTests.nfproj b/Tests/SerializationTests/SerializationTests.nfproj new file mode 100644 index 0000000..32ef658 --- /dev/null +++ b/Tests/SerializationTests/SerializationTests.nfproj @@ -0,0 +1,69 @@ + + + + $(MSBuildExtensionsPath)\nanoFramework\v1.0\ + + + + + + + Debug + AnyCPU + {11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 7f60df07-8314-4721-b225-377fbc767c7b + Library + Properties + 512 + SerializationTests + NFUnitTest + False + true + UnitTest + v1.0 + true + true + + + + + DeserializationTests.cs + + + SerializationTests.cs + + + + + + ..\..\packages\nanoFramework.CoreLibrary.1.12.0\lib\mscorlib.dll + + + ..\..\packages\nanoFramework.TestFramework.2.1.52\lib\nanoFramework.TestFramework.dll + + + ..\..\packages\nanoFramework.TestFramework.2.1.52\lib\nanoFramework.UnitTestLauncher.exe + + + + + + + + + + + + + + + + + + + + Update the Import path in nfproj to the correct nanoFramework.TestFramework NuGet package folder. + + + + \ No newline at end of file diff --git a/Tests/SerializationTests/nano.runsettings b/Tests/SerializationTests/nano.runsettings new file mode 100644 index 0000000..e82b99e --- /dev/null +++ b/Tests/SerializationTests/nano.runsettings @@ -0,0 +1,15 @@ + + + + + 1 + .\TestResults + 120000 + net48 + x64 + + + None + False + + \ No newline at end of file diff --git a/Tests/SerializationTests/packages.config b/Tests/SerializationTests/packages.config new file mode 100644 index 0000000..98a618b --- /dev/null +++ b/Tests/SerializationTests/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/Tests/SerializationTests/packages.lock.json b/Tests/SerializationTests/packages.lock.json new file mode 100644 index 0000000..b65b72a --- /dev/null +++ b/Tests/SerializationTests/packages.lock.json @@ -0,0 +1,19 @@ +{ + "version": 1, + "dependencies": { + ".NETnanoFramework,Version=v1.0": { + "nanoFramework.CoreLibrary": { + "type": "Direct", + "requested": "[1.12.0, 1.12.0]", + "resolved": "1.12.0", + "contentHash": "qQrFNXmJiStMC4VXk5cVMOJp23/qlT9FW5i9i+igwQVwraQTtvpkam8yK1hj992jqrbjoCIFZP4Hw9E8H0pB7w==" + }, + "nanoFramework.TestFramework": { + "type": "Direct", + "requested": "[2.1.52, 2.1.52]", + "resolved": "2.1.52", + "contentHash": "JRBZfxq02tZDuVNViV9cD6iOR+mRcQsGvVpP9a85Ox9ZIhpvFohEoirqPenCF38V5MGsr9Cli3zecMTfSnrLgQ==" + } + } + } +} \ No newline at end of file diff --git a/Tests/UnitTests.Shared/ComplexClass.cs b/Tests/UnitTests.Shared/ComplexClass.cs new file mode 100644 index 0000000..622dad4 --- /dev/null +++ b/Tests/UnitTests.Shared/ComplexClass.cs @@ -0,0 +1,45 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +using System; + +namespace nanoFramework.System.Runtime.Serialization.Tests +{ + [Serializable] + public class ComplexClass + { + public int aInteger { get; set; } + public short aShort { get; set; } + public byte aByte { get; set; } + public string aString { get; set; } + public float aFloat { get; set; } + public double aDouble { get; set; } + public bool aBoolean { get; set; } + public DateTime Timestamp { get; set; } + public DateTime FixedTimestamp { get; set; } + public int[] intArray { get; set; } + public short[] shortArray { get; set; } + public byte[] byteArray { get; set; } + public string[] stringArray { get; set; } + public float[] floatArray { get; set; } + public double[] doubleArray { get; set; } + public ChildClass child1; + public ChildClass Child { get; set; } + public object nullObject { get; set; } + public float nanFloat { get; set; } + public double nanDouble { get; set; } + private readonly string dontSerializeStr = "dontPublish"; + private string dontSerialize { get; set; } = "dontPublish"; + } + + [Serializable] + public class ChildClass + { + public int one { get; set; } + public int two { get; set; } + public int three { get; set; } + public int four; //not a property on purpose! + } +} diff --git a/Tests/UnitTests.Shared/Person.cs b/Tests/UnitTests.Shared/Person.cs new file mode 100644 index 0000000..60f9413 --- /dev/null +++ b/Tests/UnitTests.Shared/Person.cs @@ -0,0 +1,23 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +using System; +using System.Runtime.Serialization; + +namespace nanoFramework.System.Runtime.Serialization.Tests +{ + [Serializable] + public class Person + { + public string FirstName { get; set; } + public string LastName { get; set; } + public string Address; + public DateTime Birthday { get; set; } + public int ID { get; set; } + [SerializationHints(ArraySize = 2)] + public string[] ArrayProperty { get; set; } + public Person Friend { get; set; } + } +} diff --git a/Tests/UnitTests.Shared/UnitTestHelper.cs b/Tests/UnitTests.Shared/UnitTestHelper.cs new file mode 100644 index 0000000..46abd25 --- /dev/null +++ b/Tests/UnitTests.Shared/UnitTestHelper.cs @@ -0,0 +1,130 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +using System; +using System.Collections; +using System.Diagnostics; + +namespace nanoFramework.System.Runtime.Serialization.Tests +{ + internal static class UnitTestHelper + { + public static byte[] PersonOneSerialized = new byte[] { + 0x91, 0x74, 0x7A, 0xC0, 0x41, 0x12, 0x9B, 0xDA, 0x1B, 0x80, + 0xD1, 0x1B, 0xD9, 0x7F, 0xE0, 0x6C, 0x8E, 0x22, 0x6D, 0x63, + 0x30, 0x00, 0x00, 0x00, 0x00, 0x06, 0xF4, 0x08, 0x15, 0xA1, + 0x95, 0xB1, 0xB1, 0xBC, 0x15, 0xDD, 0xBD, 0xC9, 0xB1, 0x92, + 0x45, 0xD1, 0xEB, 0x01, 0x03, 0x42, 0x6F, 0x62, 0x05, 0x53, + 0x6D, 0x69, 0x74, 0x68, 0x0B, 0x31, 0x32, 0x33, 0x20, 0x53, + 0x6F, 0x6D, 0x65, 0x20, 0x53, 0x74, 0x81, 0xAC, 0xD4, 0xAA, + 0xC8, 0x2B, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x02, 0xD0, 0x20, + 0x26, 0x86, 0x90, 0x67, 0x06, 0xC6, 0x16, 0xE6, 0x57, 0x40}; + + public static Person CreatePersonOne() + { + return new Person() + { + FirstName = "John", + LastName = "Doe", + Birthday = new DateTime(1988, 4, 23), + ID = 27, + Address = null, + ArrayProperty = new string[] { "hello", "world" }, + Friend = new Person() + { + FirstName = "Bob", + LastName = "Smith", + Birthday = new DateTime(1983, 7, 3), + ID = 2, + Address = "123 Some St", + ArrayProperty = new string[] { "hi", "planet" }, + } + }; + } + + public static byte[] ComplexClassOneSerialized = new byte[] { + 0x94, 0x08, 0xE6, 0x6E, 0x40, 0x00, 0x00, 0x02, 0x80, 0x3F, + 0x81, 0x42, 0x10, 0x48, 0x1C, 0xDD, 0x1C, 0x9A, 0x5B, 0x99, + 0xCF, 0xE7, 0x81, 0x06, 0x4F, 0xFC, 0xF0, 0x20, 0xC4, 0x9B, + 0xA5, 0xE3, 0x70, 0x2B, 0x69, 0x5A, 0x98, 0x6C, 0x0F, 0x70, + 0x10, 0x3A, 0xC3, 0xF3, 0x62, 0xB9, 0x53, 0x80, 0x1A, 0x0A, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x0A, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x13, + 0xA0, 0xA0, 0x00, 0x20, 0x00, 0x60, 0x00, 0xA0, 0x00, 0xE0, + 0x01, 0x3A, 0x0A, 0x44, 0x46, 0x48, 0x4A, 0x4D, 0xA0, 0x80, + 0x6E, 0x8E, 0xED, 0xE0, 0x8C, 0xCD, 0xEE, 0xAE, 0x40, 0x6E, + 0x6D, 0x2F, 0x00, 0xAC, 0xAD, 0x2C, 0xED, 0x0E, 0x9A, 0x0A, + 0x7F, 0x19, 0x99, 0x9A, 0x80, 0xA6, 0x66, 0x66, 0x81, 0x60, + 0x00, 0x00, 0x81, 0xEC, 0xCC, 0xCC, 0x82, 0x3C, 0xCC, 0xCD, + 0xA0, 0xA7, 0xFE, 0x3F, 0x34, 0xD6, 0xA1, 0x61, 0xE5, 0x08, + 0x01, 0x58, 0x79, 0x3D, 0xD9, 0x7F, 0x62, 0xC8, 0x02, 0xC8, + 0xB0, 0x9E, 0x98, 0xDC, 0xDB, 0x48, 0x03, 0xE5, 0x01, 0x3A, + 0x92, 0xA3, 0x05, 0x68, 0x04, 0x7A, 0x3F, 0x43, 0x19, 0xE3, + 0xB4, 0x96, 0x1B, 0x57, 0x7B, 0x60, 0x00, 0x00, 0x00, 0x08, + 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x05, 0x86, 0xD5, 0xDE, 0xD8, 0x00, 0x00, 0x00, 0xC8, + 0x00, 0x00, 0x01, 0x90, 0x00, 0x00, 0x02, 0x58, 0x00, 0x00, + 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x7F, 0xFC, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0xB2, 0x37, 0xB7, 0x3A, 0x28, + 0x3A, 0xB1, 0x36, 0x34, 0xB9, 0xB4, 0x05, 0xB2, 0x37, 0xB7, + 0x3A, 0x28, 0x3A, 0xB1, 0x36, 0x34, 0xB9, 0xB4, 0x00}; + + public static ComplexClass CreateComplexClassOne() + { + return new ComplexClass() + { + aInteger = 10, + aShort = 254, + aByte = 0x05, + aString = "A string", + aFloat = 1.2345f, + aDouble = 1.2345, + aBoolean = true, + Timestamp = new DateTime(1910, 10, 10, 07, 30, 59), + FixedTimestamp = new DateTime(2020, 05, 01, 09, 30, 00), + intArray = new[] { 1, 3, 5, 7, 9 }, + shortArray = new[] { (short)1, (short)3, (short)5, (short)7, (short)9 }, + byteArray = new[] { (byte)0x22, (byte)0x23, (byte)0x24, (byte)0x25, (byte)0x26 }, + stringArray = new[] { "two", "four", "six", "eight" }, + floatArray = new[] { 1.1f, 3.3f, 5.5f, 7.7f, 9.9f }, + doubleArray = new[] { 1.12345, 3.3456, 5.56789, 7.78910, 9.910111213 }, + child1 = new ChildClass() { one = 1, two = 2, three = 3 }, + Child = new ChildClass() { one = 100, two = 200, three = 300 }, + nullObject = null, + nanFloat = float.NaN, + nanDouble = double.NaN, + }; + } + + public static byte[] ArrayListOneSerialized = new byte[] { + 0xE0, 0x5C, 0xE0, 0xA7, 0x46, 0x57, 0x37, 0x45, 0x37, 0x47, + 0x26, 0x96, 0xE6, 0x7C, 0x80, 0x00, 0x00, 0x02, 0xA2, 0x99, + 0xDE, 0xD9, 0x44, 0x81, 0x74, 0x56, 0xBD, 0xAD, 0xBC, 0xC0, + 0x00, 0x8A, 0x8D, 0xEF, 0x42, 0x40, 0x00, 0x00, 0x00, 0x0E, + 0xE6, 0xB2, 0x80, 0x00}; + + public static ArrayList CreateArrayListOne() + { + return new ArrayList() + { + { "testString" }, + { 42 }, + { null }, + { new DateTime(1933, 2, 11) }, + { TimeSpan.FromSeconds(100) } + }; + } + + public static void DumpBuffer(byte[] buffer) + { + for (int i = 0; i < buffer.Length; i++) + { + Debug.Write($"0x{buffer[i].ToString("X2")}, "); + } + + Debug.WriteLine(""); + } + } +} diff --git a/Tests/UnitTests.Shared/UnitTests.Shared.projitems b/Tests/UnitTests.Shared/UnitTests.Shared.projitems new file mode 100644 index 0000000..0b013be --- /dev/null +++ b/Tests/UnitTests.Shared/UnitTests.Shared.projitems @@ -0,0 +1,16 @@ + + + + $(MSBuildAllProjects);$(MSBuildThisFileFullPath) + true + 1ce3c165-8fda-494c-a0e0-dfe45a65c526 + + + UnitTests.Shared + + + + + + + \ No newline at end of file diff --git a/Tests/UnitTests.Shared/UnitTests.Shared.shproj b/Tests/UnitTests.Shared/UnitTests.Shared.shproj new file mode 100644 index 0000000..795e51e --- /dev/null +++ b/Tests/UnitTests.Shared/UnitTests.Shared.shproj @@ -0,0 +1,13 @@ + + + + 1ce3c165-8fda-494c-a0e0-dfe45a65c526 + 14.0 + + + + + + + + diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 4a34320..c0e8ab1 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -12,7 +12,6 @@ trigger: - .github_changelog_generator - .gitignore - CHANGELOG.md - - CODE_OF_CONDUCT.md - LICENSE.md - README.md - NuGet.Config @@ -35,28 +34,358 @@ resources: name: nanoframework/nf-tools endpoint: nanoframework -pool: - vmImage: 'windows-latest' - -variables: - DOTNET_NOLOGO: true - solution: 'nanoFramework.System.Runtime.Serialization.sln' - buildPlatform: 'Any CPU' - buildConfiguration: 'Release' - nugetPackageName: 'nanoFramework.System.Runtime.Serialization' - -steps: - -# step from template @ nf-tools repo -# all build, update and publish steps -- template: azure-pipelines-templates/class-lib-build.yml@templates - parameters: - sonarCloudProject: 'nanoframework_System.Runtime.Serialization' - -# step from template @ nf-tools repo -# report error -- template: azure-pipelines-templates/discord-webhook-task.yml@templates - parameters: - status: 'failure' - webhookUrl: '$(DiscordWebhook)' - message: '' +jobs: + +############################## +- job: Check_Build_Options + pool: + vmImage: 'windows-latest' + + steps: + + - checkout: self + + # check what changed + - powershell: | + git config --global user.email "nfbot" + git config --global user.name "nanoframework@outlook.com" + + + $auth = "basic $([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(":$(GitHubToken)"))))" + + if($env:System_PullRequest_PullRequestId -ne $null) + { + # get files changed in PR, if this is a PR + $commit = Invoke-RestMethod -Uri "https://api.github.com/repos/$env:Build_Repository_Name/pulls/$env:System_PullRequest_PullRequestNumber/files" -Header @{"Authorization"="$auth"} -ContentType "application/json" -Method GET + + # filter removed files + $files = $commit.where{$_.status -ne 'removed'} + } + else + { + # get files changed in the commit, if this is NOT a PR + $commit = Invoke-RestMethod -Uri "https://api.github.com/repos/$env:Build_Repository_Name/commits/$(Build.SourceVersion)" -Header @{"Authorization"="$auth"} -ContentType "application/json" -Method GET + + # filter removed files + $files = $commit.files.where{$_.status -ne 'removed'} + } + + # get file names only + $files = $files | % {$_.filename} + + Write-host "Files changed:" + $files | % { Write-host $_ } + Write-host "" + + # set default values + echo "##vso[task.setvariable variable=BUILD_NANO_LIB;isOutput=true]false" + echo "##vso[task.setvariable variable=BUILD_HELPER;isOutput=true]false" + + if( (($files.where{$_.Contains('nanoFramework.Serialization.Helper')}).Count -gt 0) -or (($files.where{$_.Contains('Serialization.Shared')}).Count -gt 0)) + { + # files at nanoFramework.Serialization.Helper or shared folder + echo "##vso[task.setvariable variable=BUILD_HELPER;isOutput=true]true" + + Write-host "Building Helper Library " + } + + if( (($files.where{$_.Contains('nanoFramework.System.Runtime.Serialization')}).Count -gt 0) -or (($files.where{$_.Contains('Serialization.Shared')}).Count -gt 0)) + { + # files at class lib or shared folder + echo "##vso[task.setvariable variable=BUILD_NANO_LIB;isOutput=true]true" + + Write-host "Building nano Library" + } + name: TargetsToBuild + displayName: Check what to build + condition: >- + and( + eq(variables['BUILD_HELPER__'], 'false'), + eq(variables['BUILD_NANO_LIB__'], 'false') + ) + +############## +- job: Build_Helper + condition: >- + or( + eq(dependencies.Check_Build_Options.outputs['TargetsToBuild.BUILD_HELPER'], true), + eq(variables['BUILD_HELPER__'], 'true') + ) + dependsOn: + Check_Build_Options + + pool: + vmImage: 'windows-latest' + + variables: + DOTNET_NOLOGO: true + BuildPlatform: 'Any CPU' + BuildConfiguration: 'Release' + + steps: + + - checkout: self + + - task: DotNetCoreCLI@2 + displayName: Restore NuGet packages + condition: >- + and( + succeeded(), + not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) + ) + inputs: + command: restore + verbosityRestore: minimal + projects: $(System.DefaultWorkingDirectory)/nanoFramework.Serialization.Helper.sln + feedsToUse: 'select' + + - task: SonarCloudPrepare@1 + condition: >- + and( + succeeded(), + not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) + ) + displayName: 'Prepare analysis on SonarCloud' + inputs: + SonarCloud: 'sonarcloud-$(System.TeamProject)' + organization: 'nanoframework' + scannerMode: 'MSBuild' + projectKey: 'nanoframework_System.Runtime.Serialization.Helper' + extraProperties: | + sonar.exclusions=**/obj/**,**/*.dll + sonar.cs.vscoveragexml.reportsPaths=$(Agent.TempDirectory)/**/**.coverage + sonar.cs.vstest.reportsPaths=$(Agent.TempDirectory)/**/**.trx + + - task: VSBuild@1 + displayName: Build solution + condition: >- + and( + succeeded(), + not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) + ) + inputs: + solution: $(System.DefaultWorkingDirectory)/nanoFramework.Serialization.Helper.sln + platform: '$(BuildPlatform)' + configuration: '$(BuildConfiguration)' + msbuildArgs: '/p:PublicRelease=true' + maximumCpuCount: true + + - task: VisualStudioTestPlatformInstaller@1 + condition: >- + and( + succeeded(), + not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) + ) + displayName: 'Visual Studio Test Platform Installer' + inputs: + versionSelector: latestStable + + - task: VSTest@2 + condition: >- + and( + succeeded(), + not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) + ) + displayName: 'Running Unit Tests' + continueOnError: false + inputs: + testSelector: 'testAssemblies' + testAssemblyVer2: | + **\*Tests*.dll + !**\obj\** + searchFolder: '$(System.DefaultWorkingDirectory)/nanoFramework.Serialization.Helper' + platform: '$(BuildPlatform)' + configuration: '$(BuildConfiguration)' + diagnosticsEnabled: true + vsTestVersion: toolsInstaller + codeCoverageEnabled: true + runSettingsFile: '$(System.DefaultWorkingDirectory)/helper.runsettings' + + - task: SonarCloudAnalyze@1 + condition: >- + and( + succeeded(), + not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) + ) + displayName: 'Run Code Analysis' + continueOnError: true + + - task: SonarCloudPublish@1 + condition: >- + and( + succeeded(), + not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) + ) + displayName: 'Publish Quality Gate Result' + continueOnError: true + + - task: CopyFiles@1 + condition: >- + and( + succeeded(), + not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) + ) + displayName: Collecting deployable artifacts + inputs: + sourceFolder: $(Build.SourcesDirectory) + Contents: | + *$(nugetPackageName)*.nupkg + *$(nugetPackageName)*.snupkg + CHANGELOG.md + TargetFolder: '$(Build.ArtifactStagingDirectory)' + flattenFolders: true + + - task: PowerShell@2 + condition: >- + and( + succeeded(), + not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) + ) + displayName: Check deployable artifacts + inputs: + targetType: 'inline' + script: | + $artifacts = (Get-ChildItem -Path "$env:Build_ArtifactStagingDirectory" -Recurse) + + if ($artifacts.Count -eq 0) + { + Write-Error "No deployable artifacts found!" + Exit 1 + } + + - task: DotNetCoreCLI@2 + displayName: Install SignTool tool + condition: >- + and( + succeeded(), + not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) + ) + inputs: + command: custom + custom: tool + arguments: install --tool-path . SignClient + + - pwsh: | + .\SignClient "Sign" ` + --baseDirectory "$(Build.ArtifactStagingDirectory)" ` + --input "**/*.nupkg" ` + --config "$(Build.Repository.LocalPath)\config\SignClient.json" ` + --filelist "$(Build.Repository.LocalPath)\config\filelist.txt" ` + --user "$(SignClientUser)" ` + --secret '$(SignClientSecret)' ` + --name "Binary Formatter Helper" ` + --description "Binary Formatter Helper" ` + --descriptionUrl "https://github.com/$env:Build_Repository_Name" + displayName: Sign packages + continueOnError: true + condition: >- + and( + succeeded(), + eq(variables['System.PullRequest.PullRequestId'], ''), + not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) + ) + + - task: PublishBuildArtifacts@1 + displayName: Publish deployables artifacts + condition: >- + and( + succeeded(), + eq(variables['System.PullRequest.PullRequestId'], ''), + not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) + ) + inputs: + PathtoPublish: '$(Build.ArtifactStagingDirectory)' + ArtifactName: deployables + ArtifactType: Container + + - task: NuGetCommand@2 + condition: >- + and( + succeeded(), + eq(variables['System.PullRequest.PullRequestId'], ''), + not(startsWith(variables['Build.SourceBranch'], 'refs/tags/v')) + ) + continueOnError: true + displayName: Push NuGet packages to NuGet + inputs: + command: push + nuGetFeedType: external + allowPackageConflicts: true + packagesToPush: '$(Build.ArtifactStagingDirectory)/*.nupkg' + includeSymbols: true + publishFeedCredentials: 'NuGet-$(System.TeamProject)' + + - task: GithubRelease@1 + condition: >- + and( + succeeded(), + eq(variables['System.PullRequest.PullRequestId'], ''), + startsWith(variables['Build.SourceBranch'], 'refs/heads/main'), + not(contains(variables['Build.SourceBranch'], 'preview')) + ) + displayName: Create/Update GitHub release + inputs: + action: edit + gitHubConnection: 'github.com_nano-$(System.TeamProject)' + tagSource: userSpecifiedTag + tag: v$(NBGV_NUGETPACKAGEVERSION) + title: '.NET nanoFramework Binary Formatter Helper v$(NBGV_NUGETPACKAGEVERSION)' + assets: '$(Build.ArtifactStagingDirectory)/*.nupkg' + isPreRelease: false + addChangeLog: true + +############## +- job: Build_ClassLib + condition: >- + or( + eq(dependencies.Check_Build_Options.outputs['TargetsToBuild.BUILD_NANO_LIB'], true), + eq(variables['BUILD_NANO_LIB__'], 'true') + ) + dependsOn: + Check_Build_Options + + pool: + vmImage: 'windows-latest' + + variables: + DOTNET_NOLOGO: true + solution: 'nanoFramework.System.Runtime.Serialization.sln' + buildPlatform: 'Any CPU' + buildConfiguration: 'Release' + nugetPackageName: 'nanoFramework.System.Runtime.Serialization' + nugetConfigPath: '$(System.DefaultWorkingDirectory)/NuGet.Config' + + steps: + + # step from template @ nf-tools repo + # all build, update and publish steps + - template: azure-pipelines-templates/class-lib-build.yml@templates + parameters: + sonarCloudProject: 'nanoframework_System.Runtime.Serialization' + +################################## +# report build failure to Discord +- job: Report_Build_Failure + dependsOn: + - Build_Helper + - Build_ClassLib + condition: >- + or( + failed('Build_Helper'), + failed('Build_ClassLib') + ) + + pool: + vmImage: 'windows-latest' + + steps: + + - checkout: self + fetchDepth: 1 + + # step from template @ nf-tools repo + - template: azure-pipelines-templates/discord-webhook.yml@templates + parameters: + status: 'failure' + webhookUrl: '$(DiscordWebhook)' + message: '' diff --git a/helper.runsettings b/helper.runsettings new file mode 100644 index 0000000..b1f76d3 --- /dev/null +++ b/helper.runsettings @@ -0,0 +1,11 @@ + + + + + 1 + .\TestResults + 900000 + net6 + x64 + + \ No newline at end of file diff --git a/nanoFramework.Serialization.Helper.sln b/nanoFramework.Serialization.Helper.sln new file mode 100644 index 0000000..8a4b99b --- /dev/null +++ b/nanoFramework.Serialization.Helper.sln @@ -0,0 +1,48 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33122.133 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "nanoFramework.Serialization.Helper", "nanoFramework.Serialization.Helper\nanoFramework.Serialization.Helper.csproj", "{45E8B3BC-FFA8-45B0-8A14-DE1CFF3400D4}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Serialization.Shared", "Serialization.Shared\Serialization.Shared.shproj", "{88D19908-57C1-4B09-9993-DE00CEE88BF4}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "UnitTests.Shared", "Tests\UnitTests.Shared\UnitTests.Shared.shproj", "{1CE3C165-8FDA-494C-A0E0-DFE45A65C526}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{92246160-9877-4300-8234-B2A298003AF1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HelperTests", "Tests\HelperTests\HelperTests.csproj", "{CC095582-F9FA-4FBD-80A6-E1A9B3866813}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {45E8B3BC-FFA8-45B0-8A14-DE1CFF3400D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {45E8B3BC-FFA8-45B0-8A14-DE1CFF3400D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {45E8B3BC-FFA8-45B0-8A14-DE1CFF3400D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {45E8B3BC-FFA8-45B0-8A14-DE1CFF3400D4}.Release|Any CPU.Build.0 = Release|Any CPU + {CC095582-F9FA-4FBD-80A6-E1A9B3866813}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CC095582-F9FA-4FBD-80A6-E1A9B3866813}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CC095582-F9FA-4FBD-80A6-E1A9B3866813}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CC095582-F9FA-4FBD-80A6-E1A9B3866813}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {1CE3C165-8FDA-494C-A0E0-DFE45A65C526} = {92246160-9877-4300-8234-B2A298003AF1} + {CC095582-F9FA-4FBD-80A6-E1A9B3866813} = {92246160-9877-4300-8234-B2A298003AF1} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3AC242BB-2739-49F8-A2BF-D243BDFBDE9E} + EndGlobalSection + GlobalSection(SharedMSBuildProjectFiles) = preSolution + Tests\UnitTests.Shared\UnitTests.Shared.projitems*{1ce3c165-8fda-494c-a0e0-dfe45a65c526}*SharedItemsImports = 13 + Serialization.Shared\Serialization.Shared.projitems*{45e8b3bc-ffa8-45b0-8a14-de1cff3400d4}*SharedItemsImports = 5 + Serialization.Shared\Serialization.Shared.projitems*{88d19908-57c1-4b09-9993-de00cee88bf4}*SharedItemsImports = 13 + Serialization.Shared\Serialization.Shared.projitems*{cc095582-f9fa-4fbd-80a6-e1a9b3866813}*SharedItemsImports = 5 + Tests\UnitTests.Shared\UnitTests.Shared.projitems*{cc095582-f9fa-4fbd-80a6-e1a9b3866813}*SharedItemsImports = 5 + EndGlobalSection +EndGlobal diff --git a/nanoFramework.Serialization.Helper/BinaryFormatter.cs b/nanoFramework.Serialization.Helper/BinaryFormatter.cs new file mode 100644 index 0000000..f8796e3 --- /dev/null +++ b/nanoFramework.Serialization.Helper/BinaryFormatter.cs @@ -0,0 +1,2279 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +using System; +using System.Collections; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.Serialization; +using System.Text; + +namespace nanoFramework.Serialization.Helper +{ + /// + /// Initializes a new instance of the class. + /// + /// + /// This helper class is meant to serialize/desearilaize binary data .NET nanoFramework. + /// + public class BinaryFormatter + { + private const int TE_L1 = 2; + private const uint TE_L1_Null = 0x00000000; + // N bits for the duplicate id. + private const uint TE_L1_Duplicate = 0x00000001; + // 32 bits for the type. + private const uint TE_L1_Reference = 0x00000002; + private const uint TE_L1_Other = 0x00000003; + + private const int TE_L2 = 2; + // 4 bits for the type. + private const uint TE_L2_Primitive = 0x00000000; + private const uint TE_L2_Array = 0x00000001; + private const uint TE_L2_ArrayList = 0x00000002; + private const uint TE_L2_Other = 0x00000003; + + private const int TE_L3 = 4; + // 32 bits for the type. + private const uint TE_L3_Type = 0x00000000; + // 32 bits for the type, N bits for the signature?? + private const uint TE_L3_Method = 0x00000001; + // 32 bits for the type, N bits for the signature?? + private const uint TE_L3_Field = 0x00000002; + + private const int TE_ElementType = 4; + private const int TE_ArrayDepth = 4; + + private const uint INVALID_HASH_ENTRY = 0xffffffff; + + private struct TypeDescriptorBasic + { + public const int _Primitive = 0x00000001; + public const int _Interface = 0x00000002; + public const int _Class = 0x00000004; + public const int _ValueType = 0x00000008; + public const int _Enum = 0x00000010; + public const int _SemanticMask = 0x0000001F; + + public const int _Array = 0x00010000; + public const int _ArrayList = 0x00020000; + + public Type _referenceType; + public ElementType _et; + public int _flags; + + public void SetType(Type t) + { + _referenceType = t; + _et = ElementType.PELEMENT_TYPE_VOID; + _flags = 0; + + // + // Not supported for now. + // + if (t == typeof(RuntimeFieldHandle)) + { + goto Failure; + } + + if (t == typeof(RuntimeMethodHandle)) + { + goto Failure; + } + + if (t == typeof(bool)) + { + _et = ElementType.PELEMENT_TYPE_BOOLEAN; + } + else if (t == typeof(char)) + { + _et = ElementType.PELEMENT_TYPE_CHAR; + } + else if (t == typeof(sbyte)) + { + _et = ElementType.PELEMENT_TYPE_I1; + } + else if (t == typeof(byte)) + { + _et = ElementType.PELEMENT_TYPE_U1; + } + else if (t == typeof(short)) + { + _et = ElementType.PELEMENT_TYPE_I2; + } + else if (t == typeof(ushort)) + { + _et = ElementType.PELEMENT_TYPE_U2; + } + else if (t == typeof(int)) + { + _et = ElementType.PELEMENT_TYPE_I4; + } + else if (t == typeof(uint)) + { + _et = ElementType.PELEMENT_TYPE_U4; + } + else if (t == typeof(long)) + { + _et = ElementType.PELEMENT_TYPE_I8; + } + else if (t == typeof(ulong)) + { + _et = ElementType.PELEMENT_TYPE_U8; + } + else if (t == typeof(float)) + { + _et = ElementType.PELEMENT_TYPE_R4; + } + else if (t == typeof(double)) + { + _et = ElementType.PELEMENT_TYPE_R8; + } + else if (t == typeof(string)) + { + _et = ElementType.PELEMENT_TYPE_STRING; + } + + if (_et == ElementType.PELEMENT_TYPE_VOID) + { + if (t == typeof(object)) { _et = ElementType.PELEMENT_TYPE_OBJECT; } + else if (t.IsEnum) { _et = ElementType.PELEMENT_TYPE_VALUETYPE; _flags |= _Enum; } + else if (t.IsValueType) { _et = ElementType.PELEMENT_TYPE_VALUETYPE; _flags |= _ValueType; } + else if (t.IsInterface) { _et = ElementType.PELEMENT_TYPE_CLASS; _flags |= _Interface; } + else if (t.IsClass) { _et = ElementType.PELEMENT_TYPE_CLASS; _flags |= _Class; } + else + { + goto Failure; + } + + if (t.IsArray) + { + _flags |= _Array; + } + + if (t == typeof(ArrayList)) + { + _flags |= _ArrayList; + } + } + else + { + _flags |= _Primitive; + } + + return; + + + Failure: + throw Error(string.Format("Unsupported type: {0}", t.FullName)); + } + + public void SetType(ElementType et) + { + _et = et; + _flags = _Primitive; + + switch (_et) + { + case ElementType.PELEMENT_TYPE_BOOLEAN: _referenceType = typeof(bool); break; + case ElementType.PELEMENT_TYPE_CHAR: _referenceType = typeof(char); break; + case ElementType.PELEMENT_TYPE_I1: _referenceType = typeof(sbyte); break; + case ElementType.PELEMENT_TYPE_U1: _referenceType = typeof(byte); break; + case ElementType.PELEMENT_TYPE_I2: _referenceType = typeof(short); break; + case ElementType.PELEMENT_TYPE_U2: _referenceType = typeof(ushort); break; + case ElementType.PELEMENT_TYPE_I4: _referenceType = typeof(int); break; + case ElementType.PELEMENT_TYPE_U4: _referenceType = typeof(uint); break; + case ElementType.PELEMENT_TYPE_I8: _referenceType = typeof(long); break; + case ElementType.PELEMENT_TYPE_U8: _referenceType = typeof(ulong); break; + case ElementType.PELEMENT_TYPE_R4: _referenceType = typeof(float); break; + case ElementType.PELEMENT_TYPE_R8: _referenceType = typeof(double); break; + case ElementType.PELEMENT_TYPE_STRING: _referenceType = typeof(string); break; + + default: throw Error(string.Format("Invalid primitive type: {0}", _et)); + } + } + + static public int NumberOfBits(ElementType et) + { + switch (et) + { + case ElementType.PELEMENT_TYPE_BOOLEAN: return 1; + case ElementType.PELEMENT_TYPE_CHAR: return 16; + case ElementType.PELEMENT_TYPE_I1: return 8; + case ElementType.PELEMENT_TYPE_U1: return 8; + case ElementType.PELEMENT_TYPE_I2: return 16; + case ElementType.PELEMENT_TYPE_U2: return 16; + case ElementType.PELEMENT_TYPE_I4: return 32; + case ElementType.PELEMENT_TYPE_U4: return 32; + case ElementType.PELEMENT_TYPE_I8: return 64; + case ElementType.PELEMENT_TYPE_U8: return 64; + case ElementType.PELEMENT_TYPE_R4: return 32; + case ElementType.PELEMENT_TYPE_R8: return 64; + case ElementType.PELEMENT_TYPE_STRING: return -1; + default: return -2; + } + } + + static public bool IsSigned(ElementType et) + { + switch (et) + { + case ElementType.PELEMENT_TYPE_BOOLEAN: return false; + case ElementType.PELEMENT_TYPE_CHAR: return false; + case ElementType.PELEMENT_TYPE_I1: return true; + case ElementType.PELEMENT_TYPE_U1: return false; + case ElementType.PELEMENT_TYPE_I2: return true; + case ElementType.PELEMENT_TYPE_U2: return false; + case ElementType.PELEMENT_TYPE_I4: return true; + case ElementType.PELEMENT_TYPE_U4: return false; + case ElementType.PELEMENT_TYPE_I8: return true; + case ElementType.PELEMENT_TYPE_U8: return false; + case ElementType.PELEMENT_TYPE_R4: return true; + case ElementType.PELEMENT_TYPE_R8: return true; + default: return false; + } + } + + public Type Type => _referenceType; + + public bool IsPrimitive => (_flags & _Primitive) != 0; + public bool IsInterface => (_flags & _Interface) != 0; + public bool IsClass => (_flags & _Class) != 0; + public bool IsValueType => (_flags & _ValueType) != 0; + public bool IsEnum => (_flags & _Enum) != 0; + + public bool NeedsSignature => !IsPrimitive && !IsEnum && !IsValueType; + + public bool IsArray => (_flags & _Array) != 0; + public bool IsArrayList => (_flags & _ArrayList) != 0; + + public bool IsSealed => _referenceType != null && _referenceType.IsSealed; + + static public Exception Error(string msg) + { + return new SerializationException(msg); + } + } + + private class TypeDescriptor + { + public TypeDescriptorBasic _base; + public int _arrayDepth = 0; + public TypeDescriptorBasic _arrayElement = new TypeDescriptorBasic(); + + public TypeDescriptor(Type t) + { + if (t == null) + { + throw new ArgumentException("Unknown type"); + } + + _base.SetType(t); + + if (_base.IsArray) + { + Type sub = t; + + while (sub.IsArray) + { + _arrayDepth++; + + sub = sub.GetElementType(); + + if (sub == null) + { + throw new ApplicationException("cannot load type"); + } + } + + _arrayElement.SetType(sub); + } + } + + public TypeDescriptor(ElementType et) + { + _base.SetType(et); + } + + public TypeDescriptor( + ElementType et, + int depth) + { + _base._et = et; + _base._flags = TypeDescriptorBasic._Array; + _arrayDepth = depth; + } + + public Type Type + { + get + { + if (_base.IsArray) + { + Type res = _arrayElement.Type; + int depth = _arrayDepth; + + while (depth-- > 0) + { + res = Array.CreateInstance(res, 1).GetType(); + } + + return res; + } + + return _base.Type; + } + } + } + + private class TypeHandler + { + // + // Type of signatures: + // + // 1) NULL + // + // Invalid for NeverNull + // + // 2) DUPLICATE + // + // Invalid for Sealed/FixedType + NeverNull + // + // 3) PRIMITIVE + // + // optional for FixedType + // PRIMITIVE optional for FixedType + NeverNull + // + // 4) REFERENCE + // + // optional for Sealed/FixedType + // REFERENCE optional for Sealed/FixedType + NeverNull + // + // 5) ARRAYLIST + // + // optional for FixedSize + // ARRAYLIST optional for FixedType + NeverNull + // + // 6) ARRAY + // + // optional for FixedSize + // optional for FixedType + // ARRAY optional for FixedType + NeverNull + // + // Always match type if FixedTyped is specified. + // + public const int _Signature_Header = 0x01; + public const int _Signature_Type = 0x02; + public const int _Signature_Length = 0x04; + + public const int _Action_None = 0; + public const int _Action_ObjectData = 1; + public const int _Action_ObjectFields = 2; + public const int _Action_ObjectElements = 3; + + // ticks at origin is different in .NET nanoFramework + // for details check the DateTime class source code + private const long _ticksAtOrigin = 504911232000000000; + // UTC mask it's alway set + private const ulong _UTCMask = 0x8000000000000000L; + + private readonly BinaryFormatter _bf; + + public object _value; + public TypeDescriptor _type; + public SerializationHintsAttribute _hints; + + public TypeDescriptor _typeExpected; + public Type _typeForced; + + public TypeHandler( + BinaryFormatter bf, + SerializationHintsAttribute hints, + TypeDescriptor expected) + { + _bf = bf; + + _value = null; + _type = null; + _hints = hints; + + _typeExpected = expected; + _typeForced = null; + } + + public void SetValue(object v) + { + if (v != null) + { + Type t = v.GetType(); + + if (t.IsEnum + || t.IsPrimitive + || (t.Attributes & TypeAttributes.Serializable) != 0) + { + _value = v; + _type = new TypeDescriptor(v.GetType()); + } + } + } + + public int SignatureRequirements() + { + int res = _Signature_Header | _Signature_Type | _Signature_Length; + + if (Hints_ArraySize != 0) + { + res &= ~_Signature_Length; + } + + _typeForced = null; + + if (_typeExpected != null) + { + if (!_typeExpected._base.NeedsSignature) + { + res = 0; + } + else + { + if (Hints_FixedType) + { + res &= ~_Signature_Type; + } + else + { + TypeDescriptorBasic td; + + if (_typeExpected._base.IsArray) + { + td = _typeExpected._arrayElement; + } + else + { + td = _typeExpected._base; + } + + if (td.IsSealed) + { + res &= ~_Signature_Type; + } + } + } + } + + if ((res & _Signature_Type) == 0) + { + _typeForced = _typeExpected.Type; + + if (Hints_PointerNeverNull) + { + res &= ~_Signature_Header; + } + } + + return res; + } + + public bool Hints_PointerNeverNull => (_hints != null && (_hints.Options & SerializationOptions.PointerNeverNull) != 0); + + public bool Hints_FixedType => (_hints != null && (_hints.Options & SerializationOptions.FixedType) != 0); + + public int Hints_ArraySize => _hints == null ? 0 : _hints.ArraySize; + + public int Hints_BitPacked => _hints == null ? 0 : _hints.BitPacked; + public long Hints_RangeBias => _hints == null ? 0 : _hints.RangeBias; + public ulong Hints_Scale => _hints == null ? 0 : _hints.Scale; + + public int EmitSignature() + { + int mask = SignatureRequirements(); + + if ((mask + & _Signature_Type) == 0) + { + if (_value != null + && _value.GetType() != _typeForced) + { + if (_typeForced == typeof(Type) + && _value.GetType().IsSubclassOf(_typeForced)) + { + } + else + { + throw TypeDescriptorBasic.Error("FixedType violation"); + } + } + } + + if (_value == null) + { + if (mask == 0) + { + // + // Special case for null strings (strings don't emit an hash): send a string of length -1. + // + if (_typeExpected != null + && _typeExpected._base._et == ElementType.PELEMENT_TYPE_STRING) + { + WriteLine("NULL STRING"); + + _bf.WriteCompressedUnsigned(0xFFFFFFFF); + + return _Action_None; + } + + throw TypeDescriptorBasic.Error("NoSignature violation"); + } + + if (Hints_PointerNeverNull) + { + throw TypeDescriptorBasic.Error("PointerNeverNull violation"); + } + + WriteLine("NULL Pointer"); + + _bf.WriteBits(TE_L1_Null, TE_L1); + + return _Action_None; + } + + int idx = _bf.SearchDuplicate(_value); + + if (idx != -1) + { + // + // No duplicates allowed for fixed-type objects. + // + if ((mask + & _Signature_Header) == 0) + { + throw TypeDescriptorBasic.Error("No duplicates for FixedType+PointerNeverNull!"); + } + + WriteLine("Duplicate: {0}", idx); + + _bf.WriteBits(TE_L1_Duplicate, TE_L1); + _bf.WriteCompressedUnsigned((uint)idx); + + return _Action_None; + } + + EmitSignature_Inner(mask, _type._base, _type, _value); + + return _Action_ObjectData; + } + + public void EmitSignature_Inner( + int mask, + TypeDescriptorBasic td, + TypeDescriptor tdBase, + object v) + { + int sizeReal = -1; + + if (td.Type.IsSubclassOf(typeof(Type))) + { + Type t = (Type)v; + + WriteLine("Reference: {0} {1}", mask, t.FullName); + + if ((mask + & _Signature_Header) != 0) + { + _bf.WriteBits(TE_L1_Other, TE_L1); + _bf.WriteBits(TE_L2_Other, TE_L2); + _bf.WriteBits(TE_L3_Type, TE_L3); + } + } + else if (td.IsPrimitive) + { + WriteLine("Primitive: {0} {1}", mask, td._et); + + if ((mask & _Signature_Header) + != 0) + { + _bf.WriteBits(TE_L1_Other, TE_L1); + _bf.WriteBits(TE_L2_Primitive, TE_L2); + } + + if ((mask & _Signature_Type) != 0) + { + _bf.WriteBits((uint)td._et, TE_ElementType); + } + } + else if (td.IsArray) + { + Array arr = (Array)v; + + WriteLine("Array: Depth {0} {1}", mask, tdBase._arrayDepth); + + if ((mask & _Signature_Header) + != 0) + { + _bf.WriteBits(TE_L1_Other, TE_L1); + _bf.WriteBits(TE_L2_Array, TE_L2); + } + + if ((mask & _Signature_Type) != 0) + { + _bf.WriteBits((uint)tdBase._arrayDepth, TE_ArrayDepth); + + EmitSignature_Inner(_Signature_Header | _Signature_Type, tdBase._arrayElement, null, null); + } + + WriteLine("Array: Size {0}", arr.Length); + + sizeReal = arr.Length; + } + else if (td.IsArrayList + && v != null) + { + ArrayList lst = (ArrayList)v; + + WriteLine("ArrayList: Size {0}", lst.Count); + + if ((mask & _Signature_Header) + != 0) + { + _bf.WriteBits(TE_L1_Other, TE_L1); + _bf.WriteBits(TE_L2_ArrayList, TE_L2); + } + + sizeReal = lst.Count; + } + else + { + Type t; + + if (v != null) + { + t = v.GetType(); + } + else + { + t = td.Type; + } + + WriteLine($"Reference: {mask} {t.FullName}"); + + if ((mask & _Signature_Header) + != 0) + { + _bf.WriteBits(TE_L1_Reference, TE_L1); + } + + if ((mask & _Signature_Type) != 0) + { + _bf.WriteType(t); + } + } + + if (sizeReal != -1) + { + if ((mask & _Signature_Length) != 0) + { + int bitsMax = Hints_BitPacked; + + if (bitsMax != 0) + { + if (sizeReal >= (1 << bitsMax)) + { + throw TypeDescriptorBasic.Error(string.Format("Array size outside range: Bits={0}", bitsMax)); + } + + _bf.WriteBits((uint)sizeReal, bitsMax); + } + else + { + _bf.WriteCompressedUnsigned((uint)sizeReal); + } + } + else + { + int sizeExpected = Hints_ArraySize; + + if (sizeExpected > 0 && sizeExpected != sizeReal) + { + throw TypeDescriptorBasic.Error(string.Format("ArraySize violation: (Expected: {0} Got:{1})", sizeReal, sizeExpected)); + } + } + } + } + + public int ReadSignature() + { + int mask = SignatureRequirements(); + + _value = null; + _type = (_typeForced == null) ? null : new TypeDescriptor(_typeForced); + + if ((mask & _Signature_Header) != 0) + { + uint levelOne; + uint levelTwo; + uint levelThree; + + levelOne = _bf.ReadBits(TE_L1); + + if (levelOne == TE_L1_Null) + { + if (Hints_PointerNeverNull) + { + throw TypeDescriptorBasic.Error("PointerNeverNull violation"); + } + + WriteLine("NULL Pointer"); + + return _Action_None; + } + else if (levelOne == TE_L1_Duplicate) + { + int idx = (int)_bf.ReadCompressedUnsigned(); + + _value = _bf.GetDuplicate(idx); + _type = new TypeDescriptor(_value.GetType()); + + WriteLine("Duplicate: {0}", idx); + + return _Action_None; + } + else if (levelOne == TE_L1_Reference) + { + if ((mask & _Signature_Type) != 0) + { + _type = new TypeDescriptor(_bf.ReadType()); + } + + WriteLine("Reference: {0}", _type.Type.FullName); + } + else + { + levelTwo = _bf.ReadBits(TE_L2); + + if (levelTwo == TE_L2_Primitive) + { + if ((mask & _Signature_Type) != 0) + { + _type = new TypeDescriptor((ElementType)_bf.ReadBits(TE_ElementType)); + } + + WriteLine("Primitive: {0}", _type._base._et); + } + else if (levelTwo == TE_L2_Array) + { + if ((mask & _Signature_Type) != 0) + { + _type = new TypeDescriptor(ElementType.PELEMENT_TYPE_CLASS, (int)_bf.ReadBits(TE_ArrayDepth)); + + WriteLine("Array: Depth {0}", _type._arrayDepth); + + levelOne = _bf.ReadBits(TE_L1); + + if (levelOne == TE_L1_Reference) + { + _type._arrayElement.SetType(_bf.ReadType()); + } + else if (levelOne == TE_L1_Other) + { + levelTwo = _bf.ReadBits(TE_L2); + + if (levelTwo == TE_L2_Primitive) + { + _type._arrayElement.SetType((ElementType)_bf.ReadBits(TE_ElementType)); + } + else + { + throw TypeDescriptorBasic.Error(string.Format("Unexpected Level2 value: {0}", levelTwo)); + } + } + else + { + throw TypeDescriptorBasic.Error(string.Format("Unexpected Level1 value: {0}", levelOne)); + } + } + } + else if (levelTwo == TE_L2_ArrayList) + { + if ((mask & _Signature_Type) != 0) + { + _type = new TypeDescriptor(typeof(ArrayList)); + } + } + else if (levelTwo == TE_L2_Other) + { + levelThree = _bf.ReadBits(TE_L3); + if (levelThree == TE_L3_Type) + { + _type = new TypeDescriptor(typeof(Type)); + } + else + { + throw TypeDescriptorBasic.Error(string.Format("Unexpected Level3 value: {0}", levelThree)); + } + } + } + } + + if (_type._base.IsArray || _type._base.IsArrayList) + { + int len; + + if ((mask & _Signature_Length) != 0) + { + int bitsMax = Hints_BitPacked; + + if (bitsMax != 0) + { + len = (int)_bf.ReadBits(bitsMax); + } + else + { + len = (int)_bf.ReadCompressedUnsigned(); + } + } + else + { + len = Hints_ArraySize; + + if (len == -1) + { + int bits = TypeDescriptorBasic.NumberOfBits(_type._arrayElement._et); + + if (bits < 0) + { + throw TypeDescriptorBasic.Error("Only primitive types allowed for ArraySize = -1"); + } + + len = _bf.BitsAvailable() / bits; + } + } + + if (_type._base.IsArrayList) + { + _value = new ArrayList(len); + } + else + { + _value = Array.CreateInstance(_type.Type.GetElementType(), len); + + WriteLine("Array: Size {0}", ((Array)_value).Length); + } + } + else + { + if (_type.Type == typeof(Type)) + { + _value = _bf.ReadType(); + + return _Action_None; + } + + if (_type.Type == typeof(string)) + { + _value = null; + } + else + { + _value = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(_type.Type); + } + } + + return _Action_ObjectData; + } + + public int TrackObject() + { + if (_type._base.IsArray + || _type._base.IsArrayList) + { + _bf.TrackDuplicate(_value); + + return _Action_ObjectElements; + } + else + { + if (_typeExpected == null + || _typeExpected._base.NeedsSignature) + { + _bf.TrackDuplicate(_value); + } + + return _Action_ObjectFields; + } + } + + public int EmitValue() + { + if (_type.Type.IsSubclassOf(typeof(Type))) + { + _bf.WriteType((Type)_value); + + return _Action_None; + } + + ulong val; + int bits; + bool fSigned; + + if (_type._base.IsPrimitive) + { + switch (_type._base._et) + { + case ElementType.PELEMENT_TYPE_BOOLEAN: val = (bool)_value ? 1UL : 0UL; break; + case ElementType.PELEMENT_TYPE_CHAR: val = (char)_value; break; + case ElementType.PELEMENT_TYPE_I1: val = (ulong)(sbyte)_value; break; + case ElementType.PELEMENT_TYPE_U1: val = (byte)_value; break; + case ElementType.PELEMENT_TYPE_I2: val = (ulong)(short)_value; break; + case ElementType.PELEMENT_TYPE_U2: val = (ushort)_value; break; + case ElementType.PELEMENT_TYPE_I4: val = (ulong)(int)_value; break; + case ElementType.PELEMENT_TYPE_U4: val = (uint)_value; break; + case ElementType.PELEMENT_TYPE_I8: val = (ulong)(long)_value; break; + case ElementType.PELEMENT_TYPE_U8: val = (ulong)_value; break; + case ElementType.PELEMENT_TYPE_R4: val = BytesFromFloat((float)_value); break; + case ElementType.PELEMENT_TYPE_R8: val = BytesFromDouble((double)_value); break; + + case ElementType.PELEMENT_TYPE_STRING: + { + byte[] buf = Encoding.UTF8.GetBytes((string)_value); + + _bf.WriteCompressedUnsigned((uint)buf.Length); + _bf.WriteArray(buf, 0, buf.Length); + + WriteLine("Value: STRING {0}", _value); + + return _Action_None; + } + + default: + throw TypeDescriptorBasic.Error("Bad primitive"); + } + + bits = TypeDescriptorBasic.NumberOfBits(_type._base._et); + fSigned = TypeDescriptorBasic.IsSigned(_type._base._et); + } + else if (_value is DateTime) + { + val = (ulong)((DateTime)_value).Ticks; + // subtract ticks at origin and set UTC mask to match .NET nanoFramework ticks + val -= _ticksAtOrigin; + val |= _UTCMask; + bits = 64; + fSigned = false; + } + else if (_value is TimeSpan) + { + val = (ulong)((TimeSpan)_value).Ticks; + bits = 64; + fSigned = true; + } + else + { + return TrackObject(); + } + + WriteLine("Value: NUM {0}", val); + + if (Hints_BitPacked != 0) + { + bits = Hints_BitPacked; + } + + bool fValid = true; + + val -= (ulong)Hints_RangeBias; + + if (fSigned) + { + long valS = (long)val; + + if (Hints_Scale != 0) + { + valS /= (long)Hints_Scale; + } + + if (bits != 64) + { + if (_type._base._et + == ElementType.PELEMENT_TYPE_R4) + { + // special handling if it's a float + // anything goes as long as it's inside the low 32 bits + if (((ulong)valS & 0xFFFFFFFF_00000000) > 0) + { + fValid = false; + } + } + else + { + // all the rest + long maxVal = (1L << (bits - 1)) - 1; + + fValid = (valS <= maxVal) && (valS >= -maxVal - 1); + } + } + + val = (ulong)valS; + } + else + { + ulong valU = val; + + if (Hints_Scale != 0) + { + valU /= Hints_Scale; + } + + if (bits != 64) + { + ulong maxVal = (1UL << bits) - 1; + + fValid = (valU <= maxVal); + } + + val = valU; + } + + if (!fValid) + { + throw TypeDescriptorBasic.Error(string.Format("Value outside range: Bits={0} Bias={1} Scale={2}", bits, Hints_RangeBias, Hints_Scale)); + } + + _bf.WriteBitsLong(val, bits); + + return _Action_None; + } + + public int ReadValue() + { + ulong val; + int bits; + bool fSigned; + + if (_type._base.IsPrimitive) + { + if (_type._base._et + == ElementType.PELEMENT_TYPE_STRING) + { + uint len = _bf.ReadCompressedUnsigned(); + + if (len == 0xFFFFFFFF) + { + _value = null; + } + else + { + byte[] buf = new byte[len]; + + _bf.ReadArray(buf, 0, (int)len); + + _value = Encoding.UTF8.GetString(buf); + } + + WriteLine("Value: STRING {0}", _value); + + return _Action_None; + } + + bits = TypeDescriptorBasic.NumberOfBits(_type._base._et); + fSigned = TypeDescriptorBasic.IsSigned(_type._base._et); + + if (bits < 0) + { + throw TypeDescriptorBasic.Error("Bad primitive"); + } + } + else if (_type.Type == typeof(DateTime)) + { + bits = 64; + fSigned = false; + } + else if (_type.Type == typeof(TimeSpan)) + { + bits = 64; + fSigned = true; + } + else + { + return TrackObject(); + } + + if (Hints_BitPacked != 0) + { + bits = Hints_BitPacked; + } + + val = _bf.ReadBitsLong(bits); + + if (fSigned) + { + long valS; + + if (bits != 64) + { + valS = (long)(val << (64 - bits)); + val = (ulong)(valS >> (64 - bits)); + } + + valS = (long)val; + + if (Hints_Scale != 0) + { + valS *= (long)Hints_Scale; + } + + val = (ulong)valS; + } + else + { + ulong valU; + + if (bits != 64) + { + valU = val << (64 - bits); + val = valU >> (64 - bits); + } + + valU = val; + + if (Hints_Scale != 0) + { + valU *= Hints_Scale; + } + + val = valU; + } + + val += (ulong)Hints_RangeBias; + + WriteLine("Value: NUM {0}", val); + + if (_type.Type == typeof(DateTime)) + { + // add at origin and clear UTC mask to transform from .NET nanoFramework ticks + val += _ticksAtOrigin; + val &= ~_UTCMask; + + _value = new DateTime((long)val, DateTimeKind.Utc); + } + else if (_type.Type == typeof(TimeSpan)) + { + _value = new TimeSpan((long)val); + } + else + { + switch (_type._base._et) + { + case ElementType.PELEMENT_TYPE_BOOLEAN: _value = val != 0; break; + case ElementType.PELEMENT_TYPE_CHAR: _value = (char)val; break; + case ElementType.PELEMENT_TYPE_I1: _value = (sbyte)val; break; + case ElementType.PELEMENT_TYPE_U1: _value = (byte)val; break; + case ElementType.PELEMENT_TYPE_I2: _value = (short)val; break; + case ElementType.PELEMENT_TYPE_U2: _value = (ushort)val; break; + case ElementType.PELEMENT_TYPE_I4: _value = (int)val; break; + case ElementType.PELEMENT_TYPE_U4: _value = (uint)val; break; + case ElementType.PELEMENT_TYPE_I8: _value = (long)val; break; + case ElementType.PELEMENT_TYPE_U8: _value = val; break; + case ElementType.PELEMENT_TYPE_R4: _value = FloatFromBytes(val); break; + case ElementType.PELEMENT_TYPE_R8: _value = DoubleFromBytes(val); break; + } + } + + return _Action_None; + } + + unsafe public float FloatFromBytes(ulong val) + { + float ret = 0.0f; + + // assume always floating point + uint val2 = (uint)val; + uint* ptr = &val2; + ret = *(float*)ptr; + + return ret; + } + + unsafe public double DoubleFromBytes(ulong val) + { + double ret = 0.0; + + // assume always floating point + ulong* ptr = &val; + ret = *(double*)ptr; + + return ret; + } + + unsafe public ulong BytesFromFloat(float val) + { + ulong ret = 0; + + // assume always floating point + float* ptr = &val; + ret = *(uint*)ptr; + + return ret; + } + + unsafe public ulong BytesFromDouble(double val) + { + ulong ret = 0; + + // assume always floating point + double* ptr = &val; + ret = *(ulong*)ptr; + + return ret; + } + } + + private class State + { + private readonly BinaryFormatter _parent; + private State _next = null; + private State _prev = null; + + private bool _value_NeedProcessing = true; + private readonly TypeHandler _value; + + private bool _fields_NeedProcessing = false; + private Type _fields_CurrentClass = null; + private FieldInfo[] _fields_Fields = null; + private int _fields_CurrentField = 0; + + private bool _array_NeedProcessing = false; + private Type _array_ExpectedType = null; + private int _array_CurrentPos = 0; + private int _array_LastPos = 0; + + public State( + BinaryFormatter parent, + SerializationHintsAttribute hints, + Type t) + { + WriteLine("New State: {0}", t != null ? t.FullName : ""); + + TypeDescriptor td = (t != null) ? new TypeDescriptor(t) : null; + + _parent = parent; + _value = new TypeHandler(parent, hints, td); + } + + private State CreateInstance( + SerializationHintsAttribute hints, + Type t) + { + State next = new( + _parent, + hints, + t); + + _next = next; + next._prev = this; + + return next; + } + + private void GetValue() + { + State prev = _prev; + object o = null; + + if (prev == null) + { + o = _parent._value; + } + else + { + if (prev._fields_NeedProcessing) + { + o = prev._fields_Fields[prev._fields_CurrentField - 1].GetValue(prev._value._value); + } + + if (prev._array_NeedProcessing) + { + if (prev._value._type._base.IsArrayList) + { + ArrayList lst = (ArrayList)prev._value._value; + + o = lst[prev._array_CurrentPos - 1]; + } + else + { + Array arr = (Array)prev._value._value; + + o = arr.GetValue(prev._array_CurrentPos - 1); + } + } + } + + WriteLine("New Object: {0}", o != null ? o.GetType().FullName : ""); + + _value.SetValue(o); + } + + private State SetValueAndDestroyInstance() + { + State prev = _prev; + + if (prev == null) + { + if (_parent._fDeserialize) + { + _parent._value = _value._value; + } + } + else + { + if (_parent._fDeserialize) + { + object o = _value._value; + + if (prev._fields_NeedProcessing) + { + prev._fields_Fields[prev._fields_CurrentField - 1].SetValue(prev._value._value, o); + } + + if (prev._array_NeedProcessing) + { + if (prev._value._type._base.IsArrayList) + { + ArrayList lst = (ArrayList)prev._value._value; + + lst.Add(o); + } + else + { + Array arr = (Array)prev._value._value; + + arr.SetValue(o, prev._array_CurrentPos - 1); + } + } + } + + prev._next = null; + } + + return prev; + } + + public State Advance() + { + if (_value_NeedProcessing) + { + int res; + + _value_NeedProcessing = false; + + if (_parent._fDeserialize) + { + res = _value.ReadSignature(); + } + else + { + GetValue(); + + res = _value.EmitSignature(); + } + + if (res != TypeHandler._Action_None) + { + object o; + + if (_parent._fDeserialize) + { + res = _value.ReadValue(); + } + else + { + + res = _value.EmitValue(); + } + + o = _value._value; + + switch (res) + { + case TypeHandler._Action_None: + break; + + case TypeHandler._Action_ObjectFields: + { + _fields_NeedProcessing = true; + _fields_CurrentClass = o.GetType(); + _fields_Fields = null; + break; + } + + case TypeHandler._Action_ObjectElements: + { + _array_NeedProcessing = true; + _array_CurrentPos = 0; + + if (o is ArrayList) + { + ArrayList lst = (ArrayList)o; + + _array_ExpectedType = null; + _array_LastPos = _parent._fDeserialize ? lst.Capacity : lst.Count; + } + else + { + Array arr = (Array)o; + + _array_ExpectedType = arr.GetType().GetElementType(); + _array_LastPos = arr.Length; + } + + break; + } + + default: + throw new System.Runtime.Serialization.SerializationException(); + } + } + } + + if (_fields_NeedProcessing) + { + return AdvanceToTheNextField(); + } + + if (_array_NeedProcessing) + { + return AdvanceToTheNextElement(); + } + + return SetValueAndDestroyInstance(); + } + + private State AdvanceToTheNextField() + { + while (_fields_CurrentClass != null) + { + if (_fields_Fields == null) + { + _fields_Fields = _fields_CurrentClass.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + _fields_CurrentField = 0; + } + + if (_fields_CurrentField < _fields_Fields.Length) + { + FieldInfo f = _fields_Fields[_fields_CurrentField++]; + + if ((f.Attributes & FieldAttributes.NotSerialized) == 0) + { + SerializationHintsAttribute hints; + + if (_value._type._base.IsEnum) + { + hints = _value._hints; + } + else + { + hints = GetHints(f); + } + + WriteLine("Field: {0} {1}", f.Name, f.FieldType); + + return CreateInstance(hints, f.FieldType); + } + } + else + { + _fields_CurrentClass = _fields_CurrentClass.BaseType; + _fields_Fields = null; + } + } + + return SetValueAndDestroyInstance(); + } + + private State AdvanceToTheNextElement() + { + if (_array_CurrentPos++ < _array_LastPos) + { + SerializationHintsAttribute hints; + + if (_value._hints != null && (_value._hints.Options & (SerializationOptions.FixedType | SerializationOptions.PointerNeverNull)) != 0) + { + hints = new SerializationHintsAttribute + { + BitPacked = 0, + Options = _value._hints.Options & (SerializationOptions.FixedType | SerializationOptions.PointerNeverNull) + }; + } + else + { + hints = null; + } + + return CreateInstance(hints, _array_ExpectedType); + } + + return SetValueAndDestroyInstance(); + } + } + + private bool _fOnlySerializableObjects = false; + private Hashtable _htLookupType = new Hashtable(); + private Hashtable _htLookupHash = new Hashtable(); + private ArrayList _lstProcessedAssemblies = new ArrayList(); + + private BitStream _stream; + private State _first; + private object _value; + private bool _fDeserialize; + + private readonly Hashtable _htDuplicates = new(); + private readonly ArrayList _lstObjects = new(); + + /// + /// Initializes a new instance of the class. + /// + public BinaryFormatter() + { + + } + + private void Initialize( + Type t, + bool fDeserialize) + { + _first = new State(this, BuildHints(t), t); + _fDeserialize = fDeserialize; + _htDuplicates.Clear(); + LstObjects.Clear(); + + if (fDeserialize) + { + foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + foreach (var type in assembly.GetTypes()) + { + LookupHash(type); + } + } + } + } + + private void InitializeForSerialization( + Type t, + object o) + { + _stream = new BitStream(); + _value = o; + Initialize(t, false); + } + + private void InitializeForDeserialization( + Type t, + byte[] data, + int pos, + int len) + { + _stream = new BitStream(data, pos, len); + _value = null; + Initialize(t, true); + } + + private SerializationHintsAttribute BuildHints(Type t) + { + if (t == null) + { + return null; + } + + SerializationHintsAttribute hints = new SerializationHintsAttribute + { + Options = SerializationOptions.FixedType | SerializationOptions.PointerNeverNull + }; + + return hints; + } + + private ArrayList LstObjects => _lstObjects; + + private static void ConvertObject( + object dst, + object src) + { + BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; + FieldInfo[] fi = src.GetType().GetFields(bindingFlags); + + for (int iField = 0; iField < fi.Length; iField++) + { + FieldInfo fieldSrc = fi[iField]; + + FieldInfo fieldDst = dst.GetType().GetField(fieldSrc.Name, bindingFlags); + + if (fieldSrc.FieldType == typeof(Type)) + { + continue; + } + + if (fieldDst == null) + { + Debug.Assert(false, "ConvertObject Incompatibility"); + continue; + } + + object valSrc = fieldSrc.GetValue(src); + object valDst = null; + + if ((fieldSrc.FieldType.IsValueType || fieldSrc.FieldType.IsEnum) && (!fieldSrc.FieldType.IsPrimitive)) + { + valDst = fieldDst.GetValue(dst); + + ConvertObject(valDst, valSrc); + } + else + { + valDst = valSrc; + } + + fieldDst.SetValue(dst, valDst); + } + } + + static private SerializationHintsAttribute GetHints(MemberInfo mi) + { + SerializationHintsAttribute hintsDst = null; + + if (mi != null) + { + object[] lst = mi.GetCustomAttributes(false); + bool fFoundSerializationHints = false; + + for (int iAttr = 0; iAttr < lst.Length; iAttr++) + { + object hintsSrc = lst[iAttr]; + + if (hintsSrc.GetType().FullName == "System.Runtime.Serialization.SerializationHintsAttribute") + { + if (fFoundSerializationHints) + { + throw new NotSupportedException("Only one attribute per type!"); + } + + fFoundSerializationHints = true; + + hintsDst = new SerializationHintsAttribute(); + + ConvertObject(hintsDst, hintsSrc); + } + } + } + + return hintsDst; + } + + /// + /// Serializes the object, or graph of objects with the specified top (root), to a byte array. + /// + /// The object at the root of the graph to serialize. + /// A byte array with the serialized graph. + /// This implementation is specific to serialized data in binary format that can be used in .NET nanoFramework applications. + /// An error has occurred during serialization. + public byte[] Serialize(object graph) + { + return Serialize(null, graph); + } + + /// + /// Deserializes the specified byte array into an object graph. + /// + /// The byte array from which to deserialize the object graph. + /// The top (root) of the object graph. + /// This implementation is specific to serialize binary data generated by .NET nanoFramework . + /// An error occurred while deserializing an object from the byte array. + public object Deserialize(byte[] buffer) => Deserialize( + null, + buffer, + 0, + buffer.Length); + + private object Deserialize( + Type t, + byte[] v) + { + return Deserialize(t, v, 0, v.Length); + } + + private byte[] Serialize( + Type t, + object o) + { + InitializeForSerialization(t, o); + + State current = _first; + + while (current != null) + { + current = current.Advance(); + } + + return _stream.ToArray(); + } + + private object Deserialize( + Type t, + byte[] v, + int pos, + int len) + { + InitializeForDeserialization(t, v, pos, len); + + State current = _first; + + while (current != null) + { + current = current.Advance(); + } + + return _value; + } + + private void TrackDuplicate(object o) + { + if (o is Type) + { + return; + } + + _htDuplicates[o] = _htDuplicates.Count; + LstObjects.Add(o); + } + + private int SearchDuplicate(object o) + { + if (o is Type) + { + return -1; + } + + if (!_htDuplicates.Contains(o)) + { + return -1; + } + + return (int)_htDuplicates[o]; + } + + private object GetDuplicate(int idx) + { + return LstObjects[idx]; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + internal bool AddType(Type t) + { + if (t == null) + { + return true; + } + + if (_htLookupHash.Contains(t)) + { + return true; + } + + //Ok, this is really evil. But it's this or 800 exceptions trying to load assemblies through BF.Initialize + + //This is for dealing with generics + if (t.FullName.IndexOf('`') >= 0) + { + return false; + } + + //Lots of autogenerated code to ignore + if (t.FullName.StartsWith("Microsoft.Internal.Deployment") + || t.FullName == "ThisAssembly" + || t.FullName == "AssemblyRef" + || t.FullName.StartsWith("")) + { + return false; + } + + AddTypeCore(t); + + AddType(t.GetElementType()); + AddType(t.BaseType); + + foreach (FieldInfo f in t.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) + { + if ((f.Attributes & FieldAttributes.NotSerialized) != 0) + { + continue; + } + + AddType(f.FieldType); + } + + return true; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + private void AddTypeCore(Type t) + { + try + { + uint hash = 0; + + // + // Handling of special cases. + // + if (t == typeof(ArrayList)) + { + hash = 0xEDDD427F; + } + else + { + hash = ComputeHashForType(t, 0); + } + + Type tExists = _htLookupType[hash] as Type; + if (tExists != null) + { + string error = string.Format("Hash conflict: 0x{0:x8} {1}", hash, t.AssemblyQualifiedName, tExists.AssemblyQualifiedName); + WriteLine(error); + + throw new ApplicationException(error); + } + + WriteLine("Hash: 0x{0:x8} {1}", hash, t.FullName); + + _htLookupType[hash] = t; + _htLookupHash[t] = hash; + } + catch + { + WriteLine("AddType failed: {0}", t.FullName); + _htLookupHash[t] = INVALID_HASH_ENTRY; + } + } + + [MethodImpl(MethodImplOptions.Synchronized)] + private Type LookupType(uint hash) + { + Type t = _htLookupType[hash] as Type; + + return t; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + private uint LookupHash( + Type t, + bool throwOnTypeNotFound = false) + { + object o = _htLookupHash[t]; + + if (o == null) + { + if (AddType(t)) + { + o = _htLookupHash[t]; + + return (uint)o; + } + } + else + { + return (uint)o; + } + + if (o == null + && throwOnTypeNotFound) + { + throw new System.Runtime.Serialization.SerializationException(); + } + + return 0xFFFFFFFF; + } + + private uint LookupAssemblyHash(Assembly assm) + { + AssemblyName name = assm.GetName(); + + return LookupAssemblyHash(name.Name, name.Version); + } + + private uint LookupAssemblyHash(string assemblyName, Version version) + { + uint hash; + + hash = ComputeHashForName(assemblyName, 0); + hash = ComputeHashForUShort((ushort)version.Major, hash); + hash = ComputeHashForUShort((ushort)version.Minor, hash); + hash = ComputeHashForUShort((ushort)version.Build, hash); + hash = ComputeHashForUShort((ushort)version.Revision, hash); + + return hash; + } + + private uint ComputeHashForType( + Type t, + uint hash) + { + hash = ComputeHashForName(t.FullName, hash); + + while (t != null) + { + foreach (FieldInfo f in t.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) + { + if ((f.Attributes & FieldAttributes.NotSerialized) != 0) + { + continue; + } + + hash = ComputeHashForField(f, hash); + } + + t = t.BaseType; + } + + return hash; + } + + private uint ComputeHashForField(FieldInfo f, uint hash) + { + Type t = f.FieldType; + TypeDescriptor td; + TypeDescriptorBasic tdSub; + string name = f.Name; + + // + // Special case for core types that have different representation on client and server. + // + if (f.DeclaringType == typeof(MemberInfo)) + { + if (name == "m_cachedData") + { + return hash; + } + } + + if (f.DeclaringType == typeof(DateTime)) + { + if (name == "ticks") + { + name = "_ticks"; + } + + if (name == "dateData" || + name == "_dateData") + { + name = "_ticks"; + t = typeof(ulong); + } + } + + td = new TypeDescriptor(t); + + if (td._base.IsArray) + { + int depth = td._arrayDepth; + while (depth-- > 0) + { + hash = ComputeHashForType(ElementType.PELEMENT_TYPE_SZARRAY, hash); + } + + tdSub = td._arrayElement; + } + else + { + tdSub = td._base; + } + + hash = ComputeHashForType(tdSub._et, hash); + + switch (tdSub._et) + { + case ElementType.PELEMENT_TYPE_CLASS: + case ElementType.PELEMENT_TYPE_VALUETYPE: + hash = ComputeHashForName(tdSub.Type.FullName, hash); + break; + } + + hash = ComputeHashForName(name, hash); + + return hash; + } + + private uint ComputeHashForType(ElementType et, uint hash) + { + uint hashPost = CrcHelper.ComputeCrc((byte)et, hash); + + return hashPost; + } + + private uint ComputeHashForName(string s, uint hash) + { + uint hashPost = CrcHelper.ComputeCrc(Encoding.UTF8.GetBytes(s), hash); + + return hashPost; + } + + private uint ComputeHashForUShort(ushort val, uint hash) + { + hash = CrcHelper.ComputeCrc((byte)(val >> 0), hash); + hash = CrcHelper.ComputeCrc((byte)(val >> 8), hash); + + return hash; + } + + [Conditional("TRACE_SERIALIZATION")] + public static void WriteLine(string fmt, params object[] lst) + { + Console.WriteLine(fmt, lst); + } + + internal int BitsAvailable() + { + return _stream.BitsAvailable; + } + + internal void WriteBits(uint val, int bits) + { + _stream.WriteBits(val, bits); + } + + internal uint ReadBits(int bits) + { + return _stream.ReadBits(bits); + } + + internal void WriteBitsLong(ulong val, int bits) + { + int extra = bits - 32; + + if (extra > 0) + { + _stream.WriteBits((uint)(val >> 32), extra); + + bits = 32; + } + + _stream.WriteBits((uint)val, bits); + } + + internal ulong ReadBitsLong(int bits) + { + ulong val; + + int extra = bits - 32; + + if (extra > 0) + { + val = (ulong)_stream.ReadBits(extra) << 32; + bits = 32; + } + else + { + val = 0; + } + + val |= _stream.ReadBits(bits); + + return val; + } + + internal void WriteArray(byte[] data, int pos, int len) + { + _stream.WriteArray(data, pos, len); + } + + internal void ReadArray(byte[] data, int pos, int len) + { + _stream.ReadArray(data, pos, len); + } + + internal void WriteCompressedUnsigned(uint val) + { + if (val == 0xFFFFFFFF) + { + _stream.WriteBits(0xFF, 8); + } + else if (val < 0x80) + { + _stream.WriteBits(val, 8); + } + else + { + if (val < 0x3F00) + { + _stream.WriteBits(0x8000 | val, 16); + } + else if (val < 0x3F000000) + { + _stream.WriteBits(0xC0000000 | val, 32); + } + else + { + throw new ArgumentException("Max value is 0x3F000000"); + } + } + } + + internal uint ReadCompressedUnsigned() + { + uint val = _stream.ReadBits(8); + + if (val == 0xFF) + { + return 0xFFFFFFFF; + } + + switch (val & 0xC0) + { + case 0x00: break; + case 0x40: break; + case 0x80: val = ((val & ~0xC0U) << 8) | _stream.ReadBits(8); break; + case 0xC0: val = ((val & ~0xC0U) << 24) | _stream.ReadBits(24); break; + } + + return val; + } + + internal void WriteType(Type t) + { + _stream.WriteBits(LookupHash(t, true), 32); + } + + internal Type ReadType() + { + uint hash = _stream.ReadBits(32); + Type t = LookupType(hash); + + if (t == null) + { + throw new System.Runtime.Serialization.SerializationException(string.Format("Cannot find type for hash {0:X8}", hash)); + } + + return t; + } + +#if DEBUG + + public byte[] DebugSerialize( + object graph, + string pathPrefix) + { + return DebugSerialize( + graph, + null, + pathPrefix); + } + + public byte[] DebugSerialize( + object graph, + Type type, + string pathPrefix) + { + byte[] buf; + + try + { + buf = Serialize(type, graph); + } + catch + { + DateTime dt = DateTime.Now; + + TraceDumpOriginalObject( + graph, + pathPrefix, + dt); + + throw; + } + + if (buf != null) + { + object o2; + + try + { + o2 = Deserialize(type, buf); + } + catch + { + DateTime dt = DateTime.Now; + + TraceDumpOriginalObject( + graph, + pathPrefix, + dt); + + TraceDumpSerializedObject( + buf, + pathPrefix, + dt); + + throw; + } + } + + return buf; + } + + void TraceDumpOriginalObject( + object graph, + string pathPrefix, + DateTime dt) + { + try + { + MemoryStream stream = new MemoryStream(); + System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); + + bf.Serialize(stream, graph); + + SaveToFile(stream.ToArray(), pathPrefix, "orig", dt); + } + catch + { + } + } + + void TraceDumpSerializedObject( + byte[] buffer, + string pathPrefix, + DateTime dt) + { + try + { + SaveToFile(buffer, pathPrefix, "ser", dt); + } + catch + { + } + } + + void SaveToFile( + byte[] buffer, + string pathPrefix, + string pathSuffix, + DateTime dt) + { + string file = string.Format("{0}_{2:yyyyMMdd}_{2:Hmmss}.{1}", pathPrefix, pathSuffix, dt); + + using (FileStream s = new( + file, + FileMode.Create, + FileAccess.Write)) + { + s.Write(buffer, 0, buffer.Length); + s.Close(); + } + } + +#endif //DEBUG + + } +} \ No newline at end of file diff --git a/nanoFramework.Serialization.Helper/BitStream.cs b/nanoFramework.Serialization.Helper/BitStream.cs new file mode 100644 index 0000000..0b9e14b --- /dev/null +++ b/nanoFramework.Serialization.Helper/BitStream.cs @@ -0,0 +1,373 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +using System; +using System.IO; +using System.Threading; + +namespace nanoFramework.Serialization.Helper +{ + internal class BitStream + { + public class Buffer + { + const int c_BufferSize = 512; + + internal Buffer _next; + internal byte[] _data; + internal int _length; + //Bits available at last position. + internal int _avail; + + internal Buffer() + { + _data = new byte[c_BufferSize]; + _length = 0; + _next = null; + } + + internal Buffer( + byte[] data, + int pos, + int len) + { + _data = new byte[len]; + _length = len; + _next = null; + + Array.Copy(data, pos, _data, 0, len); + } + + internal Buffer( + byte[] data, + int pos, + int len, + int bitsInLastPos) + { + if (bitsInLastPos < 1 || bitsInLastPos > 8) + { + throw new ArgumentException("bits"); + } + + _data = new byte[len]; + _length = len; + _avail = bitsInLastPos; + _next = null; + + Array.Copy(data, pos, _data, 0, len); + } + } + + private Buffer _first; + private Buffer _current; + private Buffer _last; + private int _pos; + private int _avail; + + private readonly bool _blockingRead; + private bool _streamEnded; + + private readonly object _lock; + + public BitStream() + { + _first = new Buffer(); + _last = _first; + _blockingRead = false; + _streamEnded = false; + _lock = new object(); + Rewind(); + } + + public BitStream(bool blockingRead) : this() => _blockingRead = blockingRead; + + public BitStream( + byte[] data, + int pos, + int len) : this() + { + AppendChunk(data, pos, len * 8); + } + + public void MarkStreamEnd() + { + lock (_lock) + { + _streamEnded = true; + Monitor.Pulse(_lock); + } + } + + public void AppendChunk( + byte[] data, + int pos, + int bitlen) + { + lock (_lock) + { + if (bitlen > 0) + { + int len = bitlen / 8; + int bitsInLast = bitlen % 8; + + if (bitsInLast == 0) + { + bitsInLast = 8; + } + else + { + len++; + } + + Buffer next = new( + data, + pos, + len, + bitsInLast); + + if (_last == null) + { + _first = _last = _current = next; + Rewind(); + } + else + { + _last._next = next; + _last = next; + } + + Monitor.Pulse(_lock); + } + } + } + + public void Rewind() + { + lock (_lock) + { + _current = _first; + _pos = -1; + _avail = 0; + } + } + + public byte[] ToArray() + { + /* + * WARNING: Buffer._avail is the number of bits written in the last byte of the buffer. + * This function doesn't account for buffers whose contents don't end on a byte-boundary. + * Under normal circumstances this isn't an issue because such a situation only occurs by + * calling AppendChunk where (bitLen % 8 != 0) on a stream before calling ToArray(). + * AppendChunk is currently exclusively used by the profiling stream, which doesn't use ToArray() + * so currently there is no problem. + */ + + byte[] res = null; + + lock (_lock) + { + for (int pass = 0; pass < 2; pass++) + { + int tot = 0; + Buffer ptr = _first; + + while (ptr != null) + { + if (pass == 1) + { + Array.Copy(ptr._data, 0, res, tot, ptr._length); + } + + tot += ptr._length; + ptr = ptr._next; + } + + if (pass == 0) + { + res = new byte[tot]; + } + } + } + + return res; + } + + public int BitsAvailable + { + get + { + int val; + + lock (_lock) + { + Buffer ptr = _current; + val = 8 * (ptr._length - _pos) + _avail - 8; + + while (ptr._next != null) + { + ptr = ptr._next; + + val += 8 * (ptr._length - 1) + ptr._avail; + } + } + + return val; + } + } + + public void WriteBits( + uint val, + int bits) + { + if (bits > 32) + { + throw new ArgumentException("Max number of bits per write is 32"); + } + + BinaryFormatter.WriteLine("OUTPUT: {0:X8} {1}", val & (0xFFFFFFFF >> (32 - bits)), bits); + + int pos = bits; + + lock (_lock) + { + while (bits > 0) + { + while (_avail == 0) + { + _pos++; + _avail = 8; + + if (_pos >= _current._data.Length) + { + //WriteBits will always try to fill the last bits of a buffer. + _current._avail = 8; + _current._next = new Buffer(); + + _current = _current._next; + _pos = 0; + } + + if (_pos >= _current._length) + { + _current._length = _pos + 1; + } + } + + int insert = Math.Min(bits, _avail); + uint mask = ((1U << insert) - 1U); + + pos -= insert; _current._data[_pos] |= (byte)(((val >> pos) & mask) << (_avail - insert)); + bits -= insert; + _avail -= insert; + } + + if (_pos == _current._length - 1) + { + _current._avail = 8 - _avail; + } + + Monitor.Pulse(_lock); + } + } + + public uint ReadBits(int bits) + { + if (bits > 32) + { + throw new ArgumentException("Max number of bits per read is 32"); + } + + uint val = 0; + int pos = bits; + int bitsOrig = bits; + + lock (_lock) + { + while (bits > 0) + { + while (_avail == 0) + { + _pos++; + + while (_pos >= _current._length) + { + if (_current._next == null) + { + if (_blockingRead && !_streamEnded) //Don't wait if stream has ended. + { + Monitor.Wait(_lock); + } + else + { + throw new EndOfStreamException(); + } + } + else + { + _current = _current._next; + _pos = 0; + } + } + + if (_pos < _current._length - 1) + { + _avail = 8; + } + else + { + _avail = _current._avail; + } + } + + int insert = Math.Min(bits, _avail); + uint mask = ((1U << insert) - 1U); + int shift = _avail - insert; + + if (_pos == _current._length - 1) + { + shift += 8 - _current._avail; + } + + pos -= insert; val |= (((uint)_current._data[_pos] >> shift) & mask) << pos; + bits -= insert; + _avail -= insert; + } + } + + BinaryFormatter.WriteLine("INPUT: {0:X8}, {1}", val, bitsOrig); + + return val; + } + + public void WriteArray( + byte[] data, + int pos, + int len) + { + lock (_lock) + { + while (len-- > 0) + { + WriteBits(data[pos++], 8); + } + } + } + + public void ReadArray( + byte[] data, + int pos, + int len) + { + lock (_lock) + { + while (len-- > 0) + { + data[pos++] = (byte)ReadBits(8); + } + } + } + } +} diff --git a/nanoFramework.Serialization.Helper/CrcHelper.cs b/nanoFramework.Serialization.Helper/CrcHelper.cs new file mode 100644 index 0000000..2988f52 --- /dev/null +++ b/nanoFramework.Serialization.Helper/CrcHelper.cs @@ -0,0 +1,74 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Serialization.Helper +{ + internal class CrcHelper + { + static uint[] _CrcTable = new uint[256] + { + 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, + 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, + 0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, + 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD, + 0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, + 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, + 0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95, + 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, + 0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, + 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, + 0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, + 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, + 0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692, + 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, + 0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, + 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A, + 0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, + 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, + 0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B, + 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, + 0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, + 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3, + 0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, + 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, + 0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, + 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, + 0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, + 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, + 0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, + 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, + 0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C, + 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4 + }; + + static public uint ComputeCrc( + byte[] buf, + int offset, + int length, + uint crc) + { + while (length-- > 0) + { + crc = _CrcTable[((crc >> 24) ^ (buf[offset++])) & 0xFF] ^ (crc << 8); + } + + return crc; + } + + static public uint ComputeCrc( + byte val, + uint crc) => _CrcTable[((crc >> 24) + ^ (val)) & 0xff] ^ (crc << 8); + + static public uint ComputeCrc( + byte[] buf, + uint crc) => ComputeCrc( + buf, + 0, + buf.Length, + crc); + } +} diff --git a/nanoFramework.Serialization.Helper/ElementType.cs b/nanoFramework.Serialization.Helper/ElementType.cs new file mode 100644 index 0000000..4d20929 --- /dev/null +++ b/nanoFramework.Serialization.Helper/ElementType.cs @@ -0,0 +1,79 @@ +// +// Copyright (c) .NET Foundation and Contributors +// Portions Copyright (c) Microsoft Corporation. All rights reserved. +// See LICENSE file in the project root for full license information. +// + +namespace nanoFramework.Serialization.Helper +{ + // KEEP IN SYNC WITH CLR_CorElementType!! + internal enum ElementType : byte + { + // + // This is based on CorElementType, but adds a few types for support of boxing/unboxing. + // + PELEMENT_TYPE_END = 0x0, + PELEMENT_TYPE_VOID = 0x1, + PELEMENT_TYPE_BOOLEAN = 0x2, + PELEMENT_TYPE_CHAR = 0x3, + PELEMENT_TYPE_I1 = 0x4, + PELEMENT_TYPE_U1 = 0x5, + PELEMENT_TYPE_I2 = 0x6, + PELEMENT_TYPE_U2 = 0x7, + PELEMENT_TYPE_I4 = 0x8, + PELEMENT_TYPE_U4 = 0x9, + PELEMENT_TYPE_I8 = 0xa, + PELEMENT_TYPE_U8 = 0xb, + PELEMENT_TYPE_R4 = 0xc, + PELEMENT_TYPE_R8 = 0xd, + PELEMENT_TYPE_STRING = 0xe, + + // every type above PTR will be simple type + // PTR + PELEMENT_TYPE_PTR = 0xf, + // BYREF + PELEMENT_TYPE_BYREF = 0x10, + + // Please use ELEMENT_TYPE_VALUETYPE. ELEMENT_TYPE_VALUECLASS is deprecated. + // VALUETYPE + PELEMENT_TYPE_VALUETYPE = 0x11, + // CLASS + PELEMENT_TYPE_CLASS = 0x12, + + // MDARRAY ... ... + PELEMENT_TYPE_ARRAY = 0x14, + + // This is a simple type. + PELEMENT_TYPE_TYPEDBYREF = 0x16, + + // native integer size + PELEMENT_TYPE_I = 0x18, + // native unsigned integer size + PELEMENT_TYPE_U = 0x19, + // FNPTR + PELEMENT_TYPE_FNPTR = 0x1B, + // Shortcut for System.Object + PELEMENT_TYPE_OBJECT = 0x1C, + // Shortcut for single dimension zero lower bound array + PELEMENT_TYPE_SZARRAY = 0x1D, + // SZARRAY + + // This is only for binding + // required C modifier : E_T_CMOD_REQD + PELEMENT_TYPE_CMOD_REQD = 0x1F, + // optional C modifier : E_T_CMOD_OPT + PELEMENT_TYPE_CMOD_OPT = 0x20, + + // This is for signatures generated internally (which will not be persisted in any way). + // INTERNAL + PELEMENT_TYPE_INTERNAL = 0x21, + + // Note that this is the max of base type excluding modifiers + // first invalid element type + PELEMENT_TYPE_MAX = 0x22, + + // + // End of overlap with CorElementType. + // + }; +} \ No newline at end of file diff --git a/nanoFramework.Serialization.Helper/nanoFramework.Serialization.Helper.csproj b/nanoFramework.Serialization.Helper/nanoFramework.Serialization.Helper.csproj new file mode 100644 index 0000000..be0cf57 --- /dev/null +++ b/nanoFramework.Serialization.Helper/nanoFramework.Serialization.Helper.csproj @@ -0,0 +1,67 @@ + + + + net6.0;net48 + enable + enable + True + disable + 9.0 + True + False + True + true + true + true + true + true + + + + nanoFramework.Serialization.Helper + nanoFramework.Serialization.Helper + + nanoframework + .NET nanoFramework Binary Formatter + Copyright (c) .NET Foundation and Contributors + .NET nanoFramework + git + https://github.com/nanoframework/System.Runtime.Serialization + https://github.com/nanoframework/System.Runtime.Serialization + + LICENSE.md + images\nf-logo.png + .NET nanoFramework binary formatter to serialize and deserialize binary data exchanged with nanoFramework devices. + nanoFramework;nano Framework;NETNF;NETMF;Micro Framework;.net;serialization + README.md + True + snupkg + + + + true + + + + + + + + + + + + True + \ + + + True + images + + + True + + + + + diff --git a/nanoFramework.Serialization.Helper/packages.lock.json b/nanoFramework.Serialization.Helper/packages.lock.json new file mode 100644 index 0000000..8f874a3 --- /dev/null +++ b/nanoFramework.Serialization.Helper/packages.lock.json @@ -0,0 +1,61 @@ +{ + "version": 1, + "dependencies": { + ".NETFramework,Version=v4.8": { + "Microsoft.SourceLink.GitHub": { + "type": "Direct", + "requested": "[1.1.1, )", + "resolved": "1.1.1", + "contentHash": "IaJGnOv/M7UQjRJks7B6p7pbPnOwisYGOIzqCz5ilGFTApZ3ktOR+6zJ12ZRPInulBmdAf1SrGdDG2MU8g6XTw==", + "dependencies": { + "Microsoft.Build.Tasks.Git": "1.1.1", + "Microsoft.SourceLink.Common": "1.1.1" + } + }, + "Nerdbank.GitVersioning": { + "type": "Direct", + "requested": "[3.5.119, )", + "resolved": "3.5.119", + "contentHash": "x8k4zV6YKZA5Rr810439lG9NngdbyPtFv0QpIYz32m1Im59kvSbEHO8gKGZoNvsfZSquayjEDUCa8acbut372g==" + }, + "Microsoft.Build.Tasks.Git": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "AT3HlgTjsqHnWpBHSNeR0KxbLZD7bztlZVj7I8vgeYG9SYqbeFGh0TM/KVtC6fg53nrWHl3VfZFvb5BiQFcY6Q==" + }, + "Microsoft.SourceLink.Common": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "WMcGpWKrmJmzrNeuaEb23bEMnbtR/vLmvZtkAP5qWu7vQsY59GqfRJd65sFpBszbd2k/bQ8cs8eWawQKAabkVg==" + } + }, + "net6.0": { + "Microsoft.SourceLink.GitHub": { + "type": "Direct", + "requested": "[1.1.1, )", + "resolved": "1.1.1", + "contentHash": "IaJGnOv/M7UQjRJks7B6p7pbPnOwisYGOIzqCz5ilGFTApZ3ktOR+6zJ12ZRPInulBmdAf1SrGdDG2MU8g6XTw==", + "dependencies": { + "Microsoft.Build.Tasks.Git": "1.1.1", + "Microsoft.SourceLink.Common": "1.1.1" + } + }, + "Nerdbank.GitVersioning": { + "type": "Direct", + "requested": "[3.5.119, )", + "resolved": "3.5.119", + "contentHash": "x8k4zV6YKZA5Rr810439lG9NngdbyPtFv0QpIYz32m1Im59kvSbEHO8gKGZoNvsfZSquayjEDUCa8acbut372g==" + }, + "Microsoft.Build.Tasks.Git": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "AT3HlgTjsqHnWpBHSNeR0KxbLZD7bztlZVj7I8vgeYG9SYqbeFGh0TM/KVtC6fg53nrWHl3VfZFvb5BiQFcY6Q==" + }, + "Microsoft.SourceLink.Common": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "WMcGpWKrmJmzrNeuaEb23bEMnbtR/vLmvZtkAP5qWu7vQsY59GqfRJd65sFpBszbd2k/bQ8cs8eWawQKAabkVg==" + } + } + } +} \ No newline at end of file diff --git a/nanoFramework.Serialization.Helper/version.json b/nanoFramework.Serialization.Helper/version.json new file mode 100644 index 0000000..648cb06 --- /dev/null +++ b/nanoFramework.Serialization.Helper/version.json @@ -0,0 +1,24 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "1.0", + "assemblyVersion": { + "precision": "revision" + }, + "semVer1NumericIdentifierPadding": 3, + "nuGetPackageVersion": { + "semVer": 2.0 + }, + "publicReleaseRefSpec": [ + "^refs/heads/develop$", + "^refs/heads/main$", + "^refs/heads/v\\d+(?:\\.\\d+)?$" + ], + "cloudBuild": { + "setAllVariables": true + }, + "release": { + "branchName": "release-v{version}", + "versionIncrement": "build", + "firstUnstableTag": "preview" + } +} diff --git a/nanoFramework.System.Runtime.Serialization.sln b/nanoFramework.System.Runtime.Serialization.sln index 4ef4815..1aabbb0 100644 --- a/nanoFramework.System.Runtime.Serialization.sln +++ b/nanoFramework.System.Runtime.Serialization.sln @@ -13,6 +13,14 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution version.json = version.json EndProjectSection EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Serialization.Shared", "Serialization.Shared\Serialization.Shared.shproj", "{88D19908-57C1-4B09-9993-DE00CEE88BF4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{EE61E67C-3D91-4792-9520-5C105FBDC736}" +EndProject +Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "UnitTests.Shared", "Tests\UnitTests.Shared\UnitTests.Shared.shproj", "{1CE3C165-8FDA-494C-A0E0-DFE45A65C526}" +EndProject +Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "SerializationTests", "Tests\SerializationTests\SerializationTests.nfproj", "{7F60DF07-8314-4721-B225-377FBC767C7B}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -25,11 +33,25 @@ Global {8D051613-D5BC-4C55-82DB-F67FF789F147}.Release|Any CPU.ActiveCfg = Release|Any CPU {8D051613-D5BC-4C55-82DB-F67FF789F147}.Release|Any CPU.Build.0 = Release|Any CPU {8D051613-D5BC-4C55-82DB-F67FF789F147}.Release|Any CPU.Deploy.0 = Release|Any CPU + {7F60DF07-8314-4721-B225-377FBC767C7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F60DF07-8314-4721-B225-377FBC767C7B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F60DF07-8314-4721-B225-377FBC767C7B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {7F60DF07-8314-4721-B225-377FBC767C7B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F60DF07-8314-4721-B225-377FBC767C7B}.Release|Any CPU.Build.0 = Release|Any CPU + {7F60DF07-8314-4721-B225-377FBC767C7B}.Release|Any CPU.Deploy.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {1CE3C165-8FDA-494C-A0E0-DFE45A65C526} = {EE61E67C-3D91-4792-9520-5C105FBDC736} + {7F60DF07-8314-4721-B225-377FBC767C7B} = {EE61E67C-3D91-4792-9520-5C105FBDC736} + EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {DD6E2FC7-1FB4-4B1F-92CE-0565C1A88083} EndGlobalSection + GlobalSection(SharedMSBuildProjectFiles) = preSolution + Tests\UnitTests.Shared\UnitTests.Shared.projitems*{1ce3c165-8fda-494c-a0e0-dfe45a65c526}*SharedItemsImports = 13 + Serialization.Shared\Serialization.Shared.projitems*{88d19908-57c1-4b09-9993-de00cee88bf4}*SharedItemsImports = 13 + EndGlobalSection EndGlobal diff --git a/nanoFramework.System.Runtime.Serialization/System.Runtime.Serialization.nfproj b/nanoFramework.System.Runtime.Serialization/System.Runtime.Serialization.nfproj index 4b40726..93f1ed2 100644 --- a/nanoFramework.System.Runtime.Serialization/System.Runtime.Serialization.nfproj +++ b/nanoFramework.System.Runtime.Serialization/System.Runtime.Serialization.nfproj @@ -45,12 +45,9 @@ - - - - + @@ -63,6 +60,7 @@ +