diff options
author | Andrew Arnott <andrewarnott@gmail.com> | 2021-12-25 04:02:46 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-25 04:02:46 +0300 |
commit | 0dc9c785e74b50e8b3217988239ed3bf5c0b4e6a (patch) | |
tree | ae4b3621d50715e637071715eb2777f957099060 | |
parent | 5e3b1073fb51df8d70998e02792e83d8d956fdf8 (diff) | |
parent | 76f3f651e712f113c25f4593d36cd8a9e73c1a2b (diff) |
Merge pull request #1365 from neuecc/master
Merge master to develop
16 files changed, 426 insertions, 149 deletions
diff --git a/sandbox/DynamicCodeDumper/DynamicCodeDumper.csproj b/sandbox/DynamicCodeDumper/DynamicCodeDumper.csproj index 7c86c1eb..633265af 100644 --- a/sandbox/DynamicCodeDumper/DynamicCodeDumper.csproj +++ b/sandbox/DynamicCodeDumper/DynamicCodeDumper.csproj @@ -132,6 +132,9 @@ <Compile Include="..\..\src\MessagePack.UnityClient\Assets\Scripts\MessagePack\Resolvers\DynamicUnionResolver.cs"> <Link>Code\DynamicUnionResolver.cs</Link> </Compile> + <Compile Include="..\..\src\MessagePack.UnityClient\Assets\Scripts\MessagePack\Resolvers\ResolverUtilities.cs"> + <Link>Code\ResolverUtilities.cs</Link> + </Compile> <Compile Include="..\..\src\MessagePack.UnityClient\Assets\Scripts\MessagePack\StringEncoding.cs"> <Link>Code\StringEncoding.cs</Link> </Compile> diff --git a/sandbox/DynamicCodeDumper/Program.cs b/sandbox/DynamicCodeDumper/Program.cs index 14f6199e..0d74db48 100644 --- a/sandbox/DynamicCodeDumper/Program.cs +++ b/sandbox/DynamicCodeDumper/Program.cs @@ -44,6 +44,7 @@ namespace DynamicCodeDumper ////DynamicObjectResolver.Instance.GetFormatter<StringKeySerializerTarget>(); ////DynamicObjectResolver.Instance.GetFormatter<LongestString>(); IMessagePackFormatter<MyClass> f = DynamicObjectResolverAllowPrivate.Instance.GetFormatter<MyClass>(); + ////IMessagePackFormatter<MessagePackFormatterFieldUser> f = DynamicObjectResolver.Instance.GetFormatter<MessagePackFormatterFieldUser>(); ////DynamicObjectResolver.Instance.GetFormatter<StringKeySerializerTargetBinary>(); ////DynamicObjectResolver.Instance.GetFormatter<Callback1>(); ////DynamicObjectResolver.Instance.GetFormatter<Callback1_2>(); diff --git a/sandbox/Sandbox/Generated.cs b/sandbox/Sandbox/Generated.cs index 6db29c4c..64f68f84 100644 --- a/sandbox/Sandbox/Generated.cs +++ b/sandbox/Sandbox/Generated.cs @@ -49,7 +49,7 @@ namespace MessagePack.Resolvers static GeneratedResolverGetFormatterHelper() { - lookup = new global::System.Collections.Generic.Dictionary<Type, int>(71) + lookup = new global::System.Collections.Generic.Dictionary<Type, int>(72) { { typeof(global::GlobalMyEnum[,]), 0 }, { typeof(global::GlobalMyEnum[]), 1 }, @@ -72,56 +72,57 @@ namespace MessagePack.Resolvers { typeof(global::ComplexModel), 18 }, { typeof(global::GlobalMan), 19 }, { typeof(global::Message), 20 }, - { typeof(global::PerfBenchmarkDotNet.StringKeySerializerTarget), 21 }, - { typeof(global::QuestMessageBody), 22 }, - { typeof(global::SharedData.ArrayOptimizeClass), 23 }, - { typeof(global::SharedData.BarClass), 24 }, - { typeof(global::SharedData.Callback1), 25 }, - { typeof(global::SharedData.Callback1_2), 26 }, - { typeof(global::SharedData.Callback2), 27 }, - { typeof(global::SharedData.Callback2_2), 28 }, - { typeof(global::SharedData.DefaultValueIntKeyClassWithExplicitConstructor), 29 }, - { typeof(global::SharedData.DefaultValueIntKeyClassWithoutExplicitConstructor), 30 }, - { typeof(global::SharedData.DefaultValueIntKeyStructWithExplicitConstructor), 31 }, - { typeof(global::SharedData.DefaultValueStringKeyClassWithExplicitConstructor), 32 }, - { typeof(global::SharedData.DefaultValueStringKeyClassWithoutExplicitConstructor), 33 }, - { typeof(global::SharedData.DefaultValueStringKeyStructWithExplicitConstructor), 34 }, - { typeof(global::SharedData.Empty1), 35 }, - { typeof(global::SharedData.Empty2), 36 }, - { typeof(global::SharedData.EmptyClass), 37 }, - { typeof(global::SharedData.EmptyStruct), 38 }, - { typeof(global::SharedData.FirstSimpleData), 39 }, - { typeof(global::SharedData.FooClass), 40 }, - { typeof(global::SharedData.HolderV0), 41 }, - { typeof(global::SharedData.HolderV1), 42 }, - { typeof(global::SharedData.HolderV2), 43 }, - { typeof(global::SharedData.MyClass), 44 }, - { typeof(global::SharedData.MySubUnion1), 45 }, - { typeof(global::SharedData.MySubUnion2), 46 }, - { typeof(global::SharedData.MySubUnion3), 47 }, - { typeof(global::SharedData.MySubUnion4), 48 }, - { typeof(global::SharedData.NestParent.NestContract), 49 }, - { typeof(global::SharedData.NonEmpty1), 50 }, - { typeof(global::SharedData.NonEmpty2), 51 }, - { typeof(global::SharedData.SimpleIntKeyData), 52 }, - { typeof(global::SharedData.SimpleStringKeyData), 53 }, - { typeof(global::SharedData.SimpleStructIntKeyData), 54 }, - { typeof(global::SharedData.SimpleStructStringKeyData), 55 }, - { typeof(global::SharedData.SubUnionType1), 56 }, - { typeof(global::SharedData.SubUnionType2), 57 }, - { typeof(global::SharedData.UnVersionBlockTest), 58 }, - { typeof(global::SharedData.Vector2), 59 }, - { typeof(global::SharedData.Vector3Like), 60 }, - { typeof(global::SharedData.VectorLike2), 61 }, - { typeof(global::SharedData.Version0), 62 }, - { typeof(global::SharedData.Version1), 63 }, - { typeof(global::SharedData.Version2), 64 }, - { typeof(global::SharedData.VersionBlockTest), 65 }, - { typeof(global::SharedData.VersioningUnion), 66 }, - { typeof(global::SharedData.WithIndexer), 67 }, - { typeof(global::SimpleModel), 68 }, - { typeof(global::StampMessageBody), 69 }, - { typeof(global::TextMessageBody), 70 }, + { typeof(global::MessagePackFormatterFieldUser), 21 }, + { typeof(global::PerfBenchmarkDotNet.StringKeySerializerTarget), 22 }, + { typeof(global::QuestMessageBody), 23 }, + { typeof(global::SharedData.ArrayOptimizeClass), 24 }, + { typeof(global::SharedData.BarClass), 25 }, + { typeof(global::SharedData.Callback1), 26 }, + { typeof(global::SharedData.Callback1_2), 27 }, + { typeof(global::SharedData.Callback2), 28 }, + { typeof(global::SharedData.Callback2_2), 29 }, + { typeof(global::SharedData.DefaultValueIntKeyClassWithExplicitConstructor), 30 }, + { typeof(global::SharedData.DefaultValueIntKeyClassWithoutExplicitConstructor), 31 }, + { typeof(global::SharedData.DefaultValueIntKeyStructWithExplicitConstructor), 32 }, + { typeof(global::SharedData.DefaultValueStringKeyClassWithExplicitConstructor), 33 }, + { typeof(global::SharedData.DefaultValueStringKeyClassWithoutExplicitConstructor), 34 }, + { typeof(global::SharedData.DefaultValueStringKeyStructWithExplicitConstructor), 35 }, + { typeof(global::SharedData.Empty1), 36 }, + { typeof(global::SharedData.Empty2), 37 }, + { typeof(global::SharedData.EmptyClass), 38 }, + { typeof(global::SharedData.EmptyStruct), 39 }, + { typeof(global::SharedData.FirstSimpleData), 40 }, + { typeof(global::SharedData.FooClass), 41 }, + { typeof(global::SharedData.HolderV0), 42 }, + { typeof(global::SharedData.HolderV1), 43 }, + { typeof(global::SharedData.HolderV2), 44 }, + { typeof(global::SharedData.MyClass), 45 }, + { typeof(global::SharedData.MySubUnion1), 46 }, + { typeof(global::SharedData.MySubUnion2), 47 }, + { typeof(global::SharedData.MySubUnion3), 48 }, + { typeof(global::SharedData.MySubUnion4), 49 }, + { typeof(global::SharedData.NestParent.NestContract), 50 }, + { typeof(global::SharedData.NonEmpty1), 51 }, + { typeof(global::SharedData.NonEmpty2), 52 }, + { typeof(global::SharedData.SimpleIntKeyData), 53 }, + { typeof(global::SharedData.SimpleStringKeyData), 54 }, + { typeof(global::SharedData.SimpleStructIntKeyData), 55 }, + { typeof(global::SharedData.SimpleStructStringKeyData), 56 }, + { typeof(global::SharedData.SubUnionType1), 57 }, + { typeof(global::SharedData.SubUnionType2), 58 }, + { typeof(global::SharedData.UnVersionBlockTest), 59 }, + { typeof(global::SharedData.Vector2), 60 }, + { typeof(global::SharedData.Vector3Like), 61 }, + { typeof(global::SharedData.VectorLike2), 62 }, + { typeof(global::SharedData.Version0), 63 }, + { typeof(global::SharedData.Version1), 64 }, + { typeof(global::SharedData.Version2), 65 }, + { typeof(global::SharedData.VersionBlockTest), 66 }, + { typeof(global::SharedData.VersioningUnion), 67 }, + { typeof(global::SharedData.WithIndexer), 68 }, + { typeof(global::SimpleModel), 69 }, + { typeof(global::StampMessageBody), 70 }, + { typeof(global::TextMessageBody), 71 }, }; } @@ -156,56 +157,57 @@ namespace MessagePack.Resolvers case 18: return new MessagePack.Formatters.ComplexModelFormatter(); case 19: return new MessagePack.Formatters.GlobalManFormatter(); case 20: return new MessagePack.Formatters.MessageFormatter(); - case 21: return new MessagePack.Formatters.PerfBenchmarkDotNet.StringKeySerializerTargetFormatter(); - case 22: return new MessagePack.Formatters.QuestMessageBodyFormatter(); - case 23: return new MessagePack.Formatters.SharedData.ArrayOptimizeClassFormatter(); - case 24: return new MessagePack.Formatters.SharedData.BarClassFormatter(); - case 25: return new MessagePack.Formatters.SharedData.Callback1Formatter(); - case 26: return new MessagePack.Formatters.SharedData.Callback1_2Formatter(); - case 27: return new MessagePack.Formatters.SharedData.Callback2Formatter(); - case 28: return new MessagePack.Formatters.SharedData.Callback2_2Formatter(); - case 29: return new MessagePack.Formatters.SharedData.DefaultValueIntKeyClassWithExplicitConstructorFormatter(); - case 30: return new MessagePack.Formatters.SharedData.DefaultValueIntKeyClassWithoutExplicitConstructorFormatter(); - case 31: return new MessagePack.Formatters.SharedData.DefaultValueIntKeyStructWithExplicitConstructorFormatter(); - case 32: return new MessagePack.Formatters.SharedData.DefaultValueStringKeyClassWithExplicitConstructorFormatter(); - case 33: return new MessagePack.Formatters.SharedData.DefaultValueStringKeyClassWithoutExplicitConstructorFormatter(); - case 34: return new MessagePack.Formatters.SharedData.DefaultValueStringKeyStructWithExplicitConstructorFormatter(); - case 35: return new MessagePack.Formatters.SharedData.Empty1Formatter(); - case 36: return new MessagePack.Formatters.SharedData.Empty2Formatter(); - case 37: return new MessagePack.Formatters.SharedData.EmptyClassFormatter(); - case 38: return new MessagePack.Formatters.SharedData.EmptyStructFormatter(); - case 39: return new MessagePack.Formatters.SharedData.FirstSimpleDataFormatter(); - case 40: return new MessagePack.Formatters.SharedData.FooClassFormatter(); - case 41: return new MessagePack.Formatters.SharedData.HolderV0Formatter(); - case 42: return new MessagePack.Formatters.SharedData.HolderV1Formatter(); - case 43: return new MessagePack.Formatters.SharedData.HolderV2Formatter(); - case 44: return new MessagePack.Formatters.SharedData.MyClassFormatter(); - case 45: return new MessagePack.Formatters.SharedData.MySubUnion1Formatter(); - case 46: return new MessagePack.Formatters.SharedData.MySubUnion2Formatter(); - case 47: return new MessagePack.Formatters.SharedData.MySubUnion3Formatter(); - case 48: return new MessagePack.Formatters.SharedData.MySubUnion4Formatter(); - case 49: return new MessagePack.Formatters.SharedData.NestParent_NestContractFormatter(); - case 50: return new MessagePack.Formatters.SharedData.NonEmpty1Formatter(); - case 51: return new MessagePack.Formatters.SharedData.NonEmpty2Formatter(); - case 52: return new MessagePack.Formatters.SharedData.SimpleIntKeyDataFormatter(); - case 53: return new MessagePack.Formatters.SharedData.SimpleStringKeyDataFormatter(); - case 54: return new MessagePack.Formatters.SharedData.SimpleStructIntKeyDataFormatter(); - case 55: return new MessagePack.Formatters.SharedData.SimpleStructStringKeyDataFormatter(); - case 56: return new MessagePack.Formatters.SharedData.SubUnionType1Formatter(); - case 57: return new MessagePack.Formatters.SharedData.SubUnionType2Formatter(); - case 58: return new MessagePack.Formatters.SharedData.UnVersionBlockTestFormatter(); - case 59: return new MessagePack.Formatters.SharedData.Vector2Formatter(); - case 60: return new MessagePack.Formatters.SharedData.Vector3LikeFormatter(); - case 61: return new MessagePack.Formatters.SharedData.VectorLike2Formatter(); - case 62: return new MessagePack.Formatters.SharedData.Version0Formatter(); - case 63: return new MessagePack.Formatters.SharedData.Version1Formatter(); - case 64: return new MessagePack.Formatters.SharedData.Version2Formatter(); - case 65: return new MessagePack.Formatters.SharedData.VersionBlockTestFormatter(); - case 66: return new MessagePack.Formatters.SharedData.VersioningUnionFormatter(); - case 67: return new MessagePack.Formatters.SharedData.WithIndexerFormatter(); - case 68: return new MessagePack.Formatters.SimpleModelFormatter(); - case 69: return new MessagePack.Formatters.StampMessageBodyFormatter(); - case 70: return new MessagePack.Formatters.TextMessageBodyFormatter(); + case 21: return new MessagePack.Formatters.MessagePackFormatterFieldUserFormatter(); + case 22: return new MessagePack.Formatters.PerfBenchmarkDotNet.StringKeySerializerTargetFormatter(); + case 23: return new MessagePack.Formatters.QuestMessageBodyFormatter(); + case 24: return new MessagePack.Formatters.SharedData.ArrayOptimizeClassFormatter(); + case 25: return new MessagePack.Formatters.SharedData.BarClassFormatter(); + case 26: return new MessagePack.Formatters.SharedData.Callback1Formatter(); + case 27: return new MessagePack.Formatters.SharedData.Callback1_2Formatter(); + case 28: return new MessagePack.Formatters.SharedData.Callback2Formatter(); + case 29: return new MessagePack.Formatters.SharedData.Callback2_2Formatter(); + case 30: return new MessagePack.Formatters.SharedData.DefaultValueIntKeyClassWithExplicitConstructorFormatter(); + case 31: return new MessagePack.Formatters.SharedData.DefaultValueIntKeyClassWithoutExplicitConstructorFormatter(); + case 32: return new MessagePack.Formatters.SharedData.DefaultValueIntKeyStructWithExplicitConstructorFormatter(); + case 33: return new MessagePack.Formatters.SharedData.DefaultValueStringKeyClassWithExplicitConstructorFormatter(); + case 34: return new MessagePack.Formatters.SharedData.DefaultValueStringKeyClassWithoutExplicitConstructorFormatter(); + case 35: return new MessagePack.Formatters.SharedData.DefaultValueStringKeyStructWithExplicitConstructorFormatter(); + case 36: return new MessagePack.Formatters.SharedData.Empty1Formatter(); + case 37: return new MessagePack.Formatters.SharedData.Empty2Formatter(); + case 38: return new MessagePack.Formatters.SharedData.EmptyClassFormatter(); + case 39: return new MessagePack.Formatters.SharedData.EmptyStructFormatter(); + case 40: return new MessagePack.Formatters.SharedData.FirstSimpleDataFormatter(); + case 41: return new MessagePack.Formatters.SharedData.FooClassFormatter(); + case 42: return new MessagePack.Formatters.SharedData.HolderV0Formatter(); + case 43: return new MessagePack.Formatters.SharedData.HolderV1Formatter(); + case 44: return new MessagePack.Formatters.SharedData.HolderV2Formatter(); + case 45: return new MessagePack.Formatters.SharedData.MyClassFormatter(); + case 46: return new MessagePack.Formatters.SharedData.MySubUnion1Formatter(); + case 47: return new MessagePack.Formatters.SharedData.MySubUnion2Formatter(); + case 48: return new MessagePack.Formatters.SharedData.MySubUnion3Formatter(); + case 49: return new MessagePack.Formatters.SharedData.MySubUnion4Formatter(); + case 50: return new MessagePack.Formatters.SharedData.NestParent_NestContractFormatter(); + case 51: return new MessagePack.Formatters.SharedData.NonEmpty1Formatter(); + case 52: return new MessagePack.Formatters.SharedData.NonEmpty2Formatter(); + case 53: return new MessagePack.Formatters.SharedData.SimpleIntKeyDataFormatter(); + case 54: return new MessagePack.Formatters.SharedData.SimpleStringKeyDataFormatter(); + case 55: return new MessagePack.Formatters.SharedData.SimpleStructIntKeyDataFormatter(); + case 56: return new MessagePack.Formatters.SharedData.SimpleStructStringKeyDataFormatter(); + case 57: return new MessagePack.Formatters.SharedData.SubUnionType1Formatter(); + case 58: return new MessagePack.Formatters.SharedData.SubUnionType2Formatter(); + case 59: return new MessagePack.Formatters.SharedData.UnVersionBlockTestFormatter(); + case 60: return new MessagePack.Formatters.SharedData.Vector2Formatter(); + case 61: return new MessagePack.Formatters.SharedData.Vector3LikeFormatter(); + case 62: return new MessagePack.Formatters.SharedData.VectorLike2Formatter(); + case 63: return new MessagePack.Formatters.SharedData.Version0Formatter(); + case 64: return new MessagePack.Formatters.SharedData.Version1Formatter(); + case 65: return new MessagePack.Formatters.SharedData.Version2Formatter(); + case 66: return new MessagePack.Formatters.SharedData.VersionBlockTestFormatter(); + case 67: return new MessagePack.Formatters.SharedData.VersioningUnionFormatter(); + case 68: return new MessagePack.Formatters.SharedData.WithIndexerFormatter(); + case 69: return new MessagePack.Formatters.SimpleModelFormatter(); + case 70: return new MessagePack.Formatters.StampMessageBodyFormatter(); + case 71: return new MessagePack.Formatters.TextMessageBodyFormatter(); default: return null; } } @@ -1173,6 +1175,51 @@ namespace MessagePack.Formatters } } + public sealed class MessagePackFormatterFieldUserFormatter : global::MessagePack.Formatters.IMessagePackFormatter<global::MessagePackFormatterFieldUser> + { + private readonly global::MessagePack.Formatters.NativeDateTimeFormatter __TimestampCustomFormatter__ = new global::MessagePack.Formatters.NativeDateTimeFormatter(); + + public void Serialize(ref global::MessagePack.MessagePackWriter writer, global::MessagePackFormatterFieldUser value, global::MessagePack.MessagePackSerializerOptions options) + { + if (value == null) + { + writer.WriteNil(); + return; + } + + writer.WriteArrayHeader(1); + this.__TimestampCustomFormatter__.Serialize(ref writer, value.Timestamp, options); + } + + public global::MessagePackFormatterFieldUser Deserialize(ref global::MessagePack.MessagePackReader reader, global::MessagePack.MessagePackSerializerOptions options) + { + if (reader.TryReadNil()) + { + return null; + } + + options.Security.DepthStep(ref reader); + var length = reader.ReadArrayHeader(); + var ____result = new global::MessagePackFormatterFieldUser(); + + for (int i = 0; i < length; i++) + { + switch (i) + { + case 0: + ____result.Timestamp = this.__TimestampCustomFormatter__.Deserialize(ref reader, options); + break; + default: + reader.Skip(); + break; + } + } + + reader.Depth--; + return ____result; + } + } + public sealed class QuestMessageBodyFormatter : global::MessagePack.Formatters.IMessagePackFormatter<global::QuestMessageBody> { diff --git a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/HashCode.cs b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/HashCode.cs index 8d48c08f..79a44fcf 100644 --- a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/HashCode.cs +++ b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/HashCode.cs @@ -42,7 +42,7 @@ https://raw.githubusercontent.com/Cyan4973/xxHash/5c174cfa4e45a42f94082dc0d4539b */ -#if !NETCOREAPP +#if !(NETCOREAPP || UNITY_2021_2_OR_NEWER) using System.Collections.Generic; using System.ComponentModel; diff --git a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/MessagePackSecurity.cs b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/MessagePackSecurity.cs index 2136d125..2b743afa 100644 --- a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/MessagePackSecurity.cs +++ b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/MessagePackSecurity.cs @@ -334,8 +334,8 @@ namespace MessagePack value = float.NaN; } - long l = *(long*)&value; - return HashCode.Combine((int)(l >> 32), unchecked((int)l)); + int l = *(int*)&value; + return l; } } diff --git a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/AttributeFormatterResolver.cs b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/AttributeFormatterResolver.cs index 00e5b075..8dde36ff 100644 --- a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/AttributeFormatterResolver.cs +++ b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/AttributeFormatterResolver.cs @@ -1,10 +1,10 @@ // Copyright (c) All contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; -using System.Linq; // require UNITY_2018_3_OR_NEWER +using System.Linq; using System.Reflection; using MessagePack.Formatters; +using MessagePack.Internal; namespace MessagePack.Resolvers { @@ -49,14 +49,7 @@ namespace MessagePack.Resolvers formatterType = formatterType.MakeGenericType(typeof(T).GetGenericArguments()); } - if (attr.Arguments == null) - { - Formatter = (IMessagePackFormatter<T>)Activator.CreateInstance(formatterType); - } - else - { - Formatter = (IMessagePackFormatter<T>)Activator.CreateInstance(formatterType, attr.Arguments); - } + Formatter = (IMessagePackFormatter<T>)ResolverUtilities.ActivateFormatter(formatterType, attr.Arguments); } } } diff --git a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/DynamicObjectResolver.cs b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/DynamicObjectResolver.cs index 62a34d7a..52b92b0e 100644 --- a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/DynamicObjectResolver.cs +++ b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/DynamicObjectResolver.cs @@ -14,6 +14,7 @@ using System.Text.RegularExpressions; using System.Threading; using MessagePack.Formatters; using MessagePack.Internal; +using MessagePack.Resolvers; #pragma warning disable SA1403 // File may only contain a single namespace @@ -110,7 +111,7 @@ namespace MessagePack.Resolvers return; } - Formatter = (IMessagePackFormatter<T>)Activator.CreateInstance(formatterTypeInfo.AsType()); + Formatter = (IMessagePackFormatter<T>)ResolverUtilities.ActivateFormatter(formatterTypeInfo.AsType()); } } } @@ -495,7 +496,7 @@ namespace MessagePack.Internal MessagePackFormatterAttribute attr = item.GetMessagePackFormatterAttribute(); if (attr != null) { - var formatter = Activator.CreateInstance(attr.FormatterType, attr.Arguments); + IMessagePackFormatter formatter = ResolverUtilities.ActivateFormatter(attr.FormatterType, attr.Arguments); serializeCustomFormatters.Add(formatter); } else @@ -510,7 +511,7 @@ namespace MessagePack.Internal MessagePackFormatterAttribute attr = item.GetMessagePackFormatterAttribute(); if (attr != null) { - var formatter = Activator.CreateInstance(attr.FormatterType, attr.Arguments); + IMessagePackFormatter formatter = ResolverUtilities.ActivateFormatter(attr.FormatterType, attr.Arguments); deserializeCustomFormatters.Add(formatter); } else @@ -626,38 +627,55 @@ namespace MessagePack.Internal MessagePackFormatterAttribute attr = item.GetMessagePackFormatterAttribute(); if (attr != null) { - FieldBuilder f = builder.DefineField(item.Name + "_formatter", attr.FormatterType, FieldAttributes.Private | FieldAttributes.InitOnly); - - var bindingFlags = (int)(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); + // Verify that the specified formatter implements the required interface. + // Doing this now provides a more helpful error message than if we let the CLR throw an EntryPointNotFoundException later. + if (!attr.FormatterType.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMessagePackFormatter<>) && i.GenericTypeArguments[0].IsEquivalentTo(item.Type))) + { + throw new MessagePackSerializationException($"{info.Type.FullName}.{item.Name} is declared as type {item.Type.FullName}, but the prescribed {attr.FormatterType.FullName} does not implement IMessagePackFormatter<{item.Type.Name}>."); + } - LocalBuilder attrVar = il.DeclareLocal(typeof(MessagePackFormatterAttribute)); + FieldBuilder f = builder.DefineField(item.Name + "_formatter", attr.FormatterType, FieldAttributes.Private | FieldAttributes.InitOnly); - il.Emit(OpCodes.Ldtoken, info.Type); - il.EmitCall(EmitInfo.GetTypeFromHandle); - il.Emit(OpCodes.Ldstr, item.Name); - il.EmitLdc_I4(bindingFlags); - if (item.IsProperty) + // If no args were provided and the formatter implements the singleton pattern, fetch the formatter from the field. + if ((attr.Arguments == null || attr.Arguments.Length == 0) && ResolverUtilities.FetchSingletonField(attr.FormatterType) is FieldInfo singletonField) { - il.EmitCall(EmitInfo.TypeGetProperty); + il.EmitLoadThis(); + il.EmitLdsfld(singletonField); } else { - il.EmitCall(EmitInfo.TypeGetField); - } + var bindingFlags = (int)(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); - il.EmitTrue(); - il.EmitCall(EmitInfo.GetCustomAttributeMessagePackFormatterAttribute); - il.EmitStloc(attrVar); + LocalBuilder attrVar = il.DeclareLocal(typeof(MessagePackFormatterAttribute)); - il.EmitLoadThis(); + il.Emit(OpCodes.Ldtoken, info.Type); + il.EmitCall(EmitInfo.GetTypeFromHandle); + il.Emit(OpCodes.Ldstr, item.Name); + il.EmitLdc_I4(bindingFlags); + if (item.IsProperty) + { + il.EmitCall(EmitInfo.TypeGetProperty); + } + else + { + il.EmitCall(EmitInfo.TypeGetField); + } - il.EmitLdloc(attrVar); - il.EmitCall(EmitInfo.MessagePackFormatterAttr.FormatterType); - il.EmitLdloc(attrVar); - il.EmitCall(EmitInfo.MessagePackFormatterAttr.Arguments); - il.EmitCall(EmitInfo.ActivatorCreateInstance); + il.EmitTrue(); + il.EmitCall(EmitInfo.GetCustomAttributeMessagePackFormatterAttribute); + il.EmitStloc(attrVar); + + il.EmitLoadThis(); + + il.EmitLdloc(attrVar); + il.EmitCall(EmitInfo.MessagePackFormatterAttr.FormatterType); + il.EmitLdloc(attrVar); + il.EmitCall(EmitInfo.MessagePackFormatterAttr.Arguments); + il.EmitCall(EmitInfo.ActivatorCreateInstance); + + il.Emit(OpCodes.Castclass, attr.FormatterType); + } - il.Emit(OpCodes.Castclass, attr.FormatterType); il.Emit(OpCodes.Stfld, f); dict.Add(item, f); diff --git a/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/ResolverUtilities.cs b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/ResolverUtilities.cs new file mode 100644 index 00000000..a6622181 --- /dev/null +++ b/src/MessagePack.UnityClient/Assets/Scripts/MessagePack/Resolvers/ResolverUtilities.cs @@ -0,0 +1,45 @@ +// Copyright (c) All contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Reflection; +using MessagePack.Formatters; + +namespace MessagePack.Internal +{ + internal static class ResolverUtilities + { + internal static IMessagePackFormatter ActivateFormatter(Type formatterType, object[] args = null) + { + if (args == null || args.Length == 0) + { + if (formatterType.GetConstructor(Type.EmptyTypes) is ConstructorInfo ctor) + { + return (IMessagePackFormatter)ctor.Invoke(Array.Empty<object>()); + } + else if (FetchSingletonField(formatterType) is FieldInfo instance) + { + return (IMessagePackFormatter)instance.GetValue(null); + } + else + { + throw new MessagePackSerializationException($"The {formatterType.FullName} formatter has no default constructor nor implements the singleton pattern."); + } + } + else + { + return (IMessagePackFormatter)Activator.CreateInstance(formatterType, args); + } + } + + internal static FieldInfo FetchSingletonField(Type formatterType) + { + if (formatterType.GetField("Instance", BindingFlags.Static | BindingFlags.Public) is FieldInfo fieldInfo && fieldInfo.IsInitOnly) + { + return fieldInfo; + } + + return null; + } + } +} diff --git a/src/MessagePack.UnityClient/Assets/Scripts/Tests/Class1.cs b/src/MessagePack.UnityClient/Assets/Scripts/Tests/Class1.cs index 9d95efa3..3325e3c3 100644 --- a/src/MessagePack.UnityClient/Assets/Scripts/Tests/Class1.cs +++ b/src/MessagePack.UnityClient/Assets/Scripts/Tests/Class1.cs @@ -1149,6 +1149,13 @@ public class SimpleModel } } +[MessagePackObject] +public class MessagePackFormatterFieldUser +{ + [Key(0), MessagePackFormatter(typeof(NativeDateTimeFormatter))] + public DateTime Timestamp { get; set; } +} + namespace PerfBenchmarkDotNet { [MessagePackObject(true)] diff --git a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/DataContractTest.cs b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/DataContractTest.cs index c14649e3..d4defb9e 100644 --- a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/DataContractTest.cs +++ b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/DataContractTest.cs @@ -191,6 +191,8 @@ namespace MessagePack.Tests public bool Equals(Detail other) => other != null && this.B1 == other.B1 && this.B2 == other.B2; } +#if !UNITY_2018_3_OR_NEWER + [Fact] public void DataContractSerializerCompatibility() { @@ -219,6 +221,8 @@ namespace MessagePack.Tests Assert.Equal(dcsValue, mpValue); } +#endif + private static T DataContractSerializerRoundTrip<T>(T value) { var ms = new MemoryStream(); diff --git a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/DynamicObjectFallbackTest.cs b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/DynamicObjectFallbackTest.cs index 4ac2331d..a16b9f0b 100644 --- a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/DynamicObjectFallbackTest.cs +++ b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/DynamicObjectFallbackTest.cs @@ -1,7 +1,7 @@ // Copyright (c) All contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -#if !ENABLE_IL2CPP +#if !UNITY_2018_3_OR_NEWER using System; using System.Collections.Generic; diff --git a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/ExpandoObjectTests.cs b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/ExpandoObjectTests.cs index 45b17ede..99f3b808 100644 --- a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/ExpandoObjectTests.cs +++ b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/ExpandoObjectTests.cs @@ -1,6 +1,8 @@ // Copyright (c) All contributors. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +#if !UNITY_2018_3_OR_NEWER + using System.Dynamic; using System.Runtime.Serialization; using MessagePack.Resolvers; @@ -115,3 +117,5 @@ namespace MessagePack.Tests } } } + +#endif diff --git a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/MessagePackFormatterPerFieldTest.cs b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/MessagePackFormatterPerFieldTest.cs index 6be33a46..b0dca2c3 100644 --- a/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/MessagePackFormatterPerFieldTest.cs +++ b/src/MessagePack.UnityClient/Assets/Scripts/Tests/ShareTests/MessagePackFormatterPerFieldTest.cs @@ -5,16 +5,27 @@ using System; using System.Buffers; using System.Collections.Generic; using System.Linq; +using System.Net.Sockets; +using System.Reflection; +using System.Runtime.Serialization; using System.Text; using System.Threading.Tasks; using MessagePack.Formatters; using MessagePack.Resolvers; using Xunit; +using Xunit.Abstractions; namespace MessagePack.Tests { public class MessagePackFormatterPerFieldTest { + private readonly ITestOutputHelper logger; + + public MessagePackFormatterPerFieldTest(ITestOutputHelper logger) + { + this.logger = logger; + } + [MessagePackObject] public class MyClass { @@ -105,5 +116,129 @@ namespace MessagePack.Tests r2.MyProperty4.Is("bar"); } } + + [MessagePackObject] + public class BlockFormattedIntegers + { + [Key(0)] [MessagePackFormatter(typeof(ForceByteBlockFormatter))] public byte UInt8Property { get; set; } + + [Key(1)] [MessagePackFormatter(typeof(ForceUInt16BlockFormatter))] public ushort UInt16Property { get; set; } + + [Key(2)] [MessagePackFormatter(typeof(ForceUInt32BlockFormatter))] public uint UInt32Property { get; set; } + + [Key(3)] [MessagePackFormatter(typeof(ForceUInt64BlockFormatter))] public ulong UInt64Property { get; set; } + + [Key(4)] [MessagePackFormatter(typeof(ForceSByteBlockFormatter))] public sbyte Int8Property { get; set; } + + [Key(5)] [MessagePackFormatter(typeof(ForceInt16BlockFormatter))] public short Int16Property { get; set; } + + [Key(6)] [MessagePackFormatter(typeof(ForceInt32BlockFormatter))] public int Int32Property { get; set; } + + [Key(7)] [MessagePackFormatter(typeof(ForceInt64BlockFormatter))] public long Int64Property { get; set; } + + [Key(8)] [MessagePackFormatter(typeof(NullableForceByteBlockFormatter))] public byte? NullableUInt8Property { get; set; } + + [Key(9)] [MessagePackFormatter(typeof(NullableForceUInt16BlockFormatter))] public ushort? NullableUInt16Property { get; set; } + + [Key(10)] [MessagePackFormatter(typeof(NullableForceUInt32BlockFormatter))] public uint? NullableUInt32Property { get; set; } + + [Key(11)] [MessagePackFormatter(typeof(NullableForceUInt64BlockFormatter))] public ulong? NullableUInt64Property { get; set; } + + [Key(12)] [MessagePackFormatter(typeof(NullableForceSByteBlockFormatter))] public sbyte? NullableInt8Property { get; set; } + + [Key(13)] [MessagePackFormatter(typeof(NullableForceInt16BlockFormatter))] public short? NullableInt16Property { get; set; } + + [Key(14)] [MessagePackFormatter(typeof(NullableForceInt32BlockFormatter))] public int? NullableInt32Property { get; set; } + + [Key(15)] [MessagePackFormatter(typeof(NullableForceInt64BlockFormatter))] public long? NullableInt64Property { get; set; } + } + + /// <summary> + /// Asserts that every formatter offers the public API required for use by + /// <see cref="MessagePackFormatterAttribute"/>. + /// </summary> + [Fact] + public void AllFormattersOfferAreAvailableViaAttribute() + { + var formatters = (from type in typeof(ForceByteBlockFormatter).Assembly.GetTypes() + where typeof(IMessagePackFormatter).IsAssignableFrom(type) && !type.IsAbstract + let ctor = GetDefaultConstructor(type) + where ctor is object // skip formatters that require special initialization. + select new { Type = type, DefaultConstructor = ctor }).ToList(); + this.logger.WriteLine("Found {0} applicable formatters to check.", formatters.Count); + + Assert.All(formatters, formatter => Assert.True(formatter.DefaultConstructor.IsPublic || UsesSingletonPattern(formatter.Type))); + } + + [Fact] + public void ForceBlockFormatters() + { + var block = new BlockFormattedIntegers + { + UInt8Property = 1, + UInt16Property = 2, + UInt32Property = 3, + UInt64Property = 4, + + Int8Property = 1, + Int16Property = 2, + Int32Property = 3, + Int64Property = 4, + + NullableUInt8Property = 1, + NullableUInt16Property = 2, + NullableUInt32Property = 3, + NullableUInt64Property = 4, + + NullableInt8Property = 1, + NullableInt16Property = 2, + NullableInt32Property = 3, + NullableInt64Property = 4, + }; + byte[] packed = MessagePackSerializer.Serialize(block, MessagePackSerializerOptions.Standard); + var reader = new MessagePackReader(packed); + + reader.ReadArrayHeader(); + + Assert.Equal(MessagePackCode.UInt8, reader.NextCode); + Assert.Equal(1, reader.ReadByte()); + Assert.Equal(MessagePackCode.UInt16, reader.NextCode); + Assert.Equal(2, reader.ReadUInt16()); + Assert.Equal(MessagePackCode.UInt32, reader.NextCode); + Assert.Equal(3u, reader.ReadUInt32()); + Assert.Equal(MessagePackCode.UInt64, reader.NextCode); + Assert.Equal(4u, reader.ReadUInt64()); + + Assert.Equal(MessagePackCode.Int8, reader.NextCode); + Assert.Equal(1, reader.ReadSByte()); + Assert.Equal(MessagePackCode.Int16, reader.NextCode); + Assert.Equal(2, reader.ReadInt16()); + Assert.Equal(MessagePackCode.Int32, reader.NextCode); + Assert.Equal(3, reader.ReadInt32()); + Assert.Equal(MessagePackCode.Int64, reader.NextCode); + Assert.Equal(4, reader.ReadInt64()); + + Assert.Equal(MessagePackCode.UInt8, reader.NextCode); + Assert.Equal(1, reader.ReadByte()); + Assert.Equal(MessagePackCode.UInt16, reader.NextCode); + Assert.Equal(2, reader.ReadUInt16()); + Assert.Equal(MessagePackCode.UInt32, reader.NextCode); + Assert.Equal(3u, reader.ReadUInt32()); + Assert.Equal(MessagePackCode.UInt64, reader.NextCode); + Assert.Equal(4u, reader.ReadUInt64()); + + Assert.Equal(MessagePackCode.Int8, reader.NextCode); + Assert.Equal(1, reader.ReadSByte()); + Assert.Equal(MessagePackCode.Int16, reader.NextCode); + Assert.Equal(2, reader.ReadInt16()); + Assert.Equal(MessagePackCode.Int32, reader.NextCode); + Assert.Equal(3, reader.ReadInt32()); + Assert.Equal(MessagePackCode.Int64, reader.NextCode); + Assert.Equal(4, reader.ReadInt64()); + } + + private static ConstructorInfo GetDefaultConstructor(Type formatterType) => formatterType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault(c => c.GetParameters().Length == 0); + + private static bool UsesSingletonPattern(Type formatterType) => formatterType.GetField("Instance", BindingFlags.Static | BindingFlags.Public)?.IsInitOnly is true; } } diff --git a/src/MessagePack.UnityClient/Assets/Scripts/Tests/Shims/XUnit.cs b/src/MessagePack.UnityClient/Assets/Scripts/Tests/Shims/XUnit.cs index ef9a80b4..f1eee269 100644 --- a/src/MessagePack.UnityClient/Assets/Scripts/Tests/Shims/XUnit.cs +++ b/src/MessagePack.UnityClient/Assets/Scripts/Tests/Shims/XUnit.cs @@ -92,6 +92,14 @@ namespace Xunit Assert.False(enumerable.GetEnumerator().MoveNext()); } + public static void All<T>(IEnumerable<T> collection, Action<T> predicate) + { + foreach (T item in collection) + { + predicate(item); + } + } + public static T IsType<T>(object o) { NUnit.Framework.Assert.AreEqual(typeof(T), o.GetType()); diff --git a/src/MessagePack.UnityClient/Assets/Scripts/Tests/Tests.asmdef b/src/MessagePack.UnityClient/Assets/Scripts/Tests/Tests.asmdef index 9fb3f171..b02d5a89 100644 --- a/src/MessagePack.UnityClient/Assets/Scripts/Tests/Tests.asmdef +++ b/src/MessagePack.UnityClient/Assets/Scripts/Tests/Tests.asmdef @@ -1,19 +1,30 @@ { "name": "MessagePack.Tests", + "rootNamespace": "", "references": [ "MessagePack", "MessagePack.Annotations", - "RuntimeUnitTestToolkit" - ], - "optionalUnityReferences": [ - "TestAssemblies" + "RuntimeUnitTestToolkit", + "UnityEngine.TestRunner", + "UnityEditor.TestRunner" ], "includePlatforms": [], "excludePlatforms": [], "allowUnsafeCode": true, - "overrideReferences": false, - "precompiledReferences": [], - "autoReferenced": true, - "defineConstraints": [], - "versionDefines": [] + "overrideReferences": true, + "precompiledReferences": [ + "System.Memory.dll", + "System.Buffers.dll", + "System.Threading.Tasks.Extensions.dll", + "System.Runtime.CompilerServices.Unsafe.dll", + "System.Runtime.Extensions.dll", + "nunit.framework.dll", + "MsgPack.dll" + ], + "autoReferenced": false, + "defineConstraints": [ + "UNITY_INCLUDE_TESTS" + ], + "versionDefines": [], + "noEngineReferences": false }
\ No newline at end of file diff --git a/src/MessagePackAnalyzer/MessagePackAnalyzer.csproj b/src/MessagePackAnalyzer/MessagePackAnalyzer.csproj index 51952963..5a5a18f8 100644 --- a/src/MessagePackAnalyzer/MessagePackAnalyzer.csproj +++ b/src/MessagePackAnalyzer/MessagePackAnalyzer.csproj @@ -11,6 +11,7 @@ <TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);PackBuildOutputs</TargetsForTfmSpecificContentInPackage> <SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking> <IncludeSymbols>false</IncludeSymbols> + <DevelopmentDependency>true</DevelopmentDependency> </PropertyGroup> <ItemGroup> <Content Include="tools\*.ps1" Pack="true" PackagePath="tools\" /> |