Эх сурвалжийг харах

换用支持ILRuntime的protobuf-net,为热更协议做准备

tanghai 8 жил өмнө
parent
commit
b69234f849
100 өөрчлөгдсөн 9249 нэмэгдсэн , 883 устгасан
  1. 0 55
      Unity/Assets/Plugins/protobuf-net/Serializers/DateTimeSerializer.cs
  2. 0 40
      Unity/Assets/Plugins/protobuf-net/Serializers/KeyValuePairDecorator.cs
  3. 0 12
      Unity/Assets/Plugins/protobuf-net/Serializers/KeyValuePairDecorator.cs.meta
  4. 0 56
      Unity/Assets/Plugins/protobuf-net/Serializers/TimeSpanSerializer.cs
  5. 9 0
      Unity/Assets/ThirdParty/Protobuf.meta
  6. 9 0
      Unity/Assets/ThirdParty/Protobuf/Editor.meta
  7. 38 0
      Unity/Assets/ThirdParty/Protobuf/Editor/Protogen.cs
  8. 12 0
      Unity/Assets/ThirdParty/Protobuf/Editor/Protogen.cs.meta
  9. 9 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection.meta
  10. 814 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/CSharpCodeGenerator.cs
  11. 12 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/CSharpCodeGenerator.cs.meta
  12. 158 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/CodeGenerator.OneOfStub.cs
  13. 12 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/CodeGenerator.OneOfStub.cs.meta
  14. 476 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/CodeGenerator.cs
  15. 12 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/CodeGenerator.cs.meta
  16. 141 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/CustomOptions.cs
  17. 12 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/CustomOptions.cs.meta
  18. 1149 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/Descriptor.cs
  19. 12 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/Descriptor.cs.meta
  20. 221 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/NameNormalizer.cs
  21. 12 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/NameNormalizer.cs.meta
  22. 2841 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/Parsers.cs
  23. 12 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/Parsers.cs.meta
  24. 55 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/Peekable.cs
  25. 12 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/Peekable.cs.meta
  26. 83 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/Token.cs
  27. 12 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/Token.cs.meta
  28. 643 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/TokenExtensions.cs
  29. 12 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/TokenExtensions.cs.meta
  30. 11 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/TokenType.cs
  31. 12 0
      Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/TokenType.cs.meta
  32. 68 0
      Unity/Assets/ThirdParty/Protobuf/IExtensibleAdapter.cs
  33. 12 0
      Unity/Assets/ThirdParty/Protobuf/IExtensibleAdapter.cs.meta
  34. 2 2
      Unity/Assets/ThirdParty/Protobuf/protobuf-net.meta
  35. 186 14
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/BclHelpers.cs
  36. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/BclHelpers.cs.meta
  37. 8 2
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/BufferExtension.cs
  38. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/BufferExtension.cs.meta
  39. 0 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/BufferPool.cs
  40. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/BufferPool.cs.meta
  41. 4 4
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/CallbackAttributes.cs
  42. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/CallbackAttributes.cs.meta
  43. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Compiler.meta
  44. 224 167
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Compiler/CompilerContext.cs
  45. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Compiler/CompilerContext.cs.meta
  46. 0 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Compiler/CompilerDelegates.cs
  47. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Compiler/CompilerDelegates.cs.meta
  48. 0 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Compiler/Local.cs
  49. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Compiler/Local.cs.meta
  50. 8 1
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/DataFormat.cs
  51. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/DataFormat.cs.meta
  52. 395 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/DiscriminatedUnion.cs
  53. 12 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/DiscriminatedUnion.cs.meta
  54. 0 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Extensible.cs
  55. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Extensible.cs.meta
  56. 2 2
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/ExtensibleUtil.cs
  57. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/ExtensibleUtil.cs.meta
  58. 0 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/GlobalSuppressions.cs
  59. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/GlobalSuppressions.cs.meta
  60. 134 59
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Helpers.cs
  61. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Helpers.cs.meta
  62. 0 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/IExtensible.cs
  63. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/IExtensible.cs.meta
  64. 11 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/IExtension.cs
  65. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/IExtension.cs.meta
  66. 0 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/ImplicitFields.cs
  67. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/ImplicitFields.cs.meta
  68. 0 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/KeyValuePairProxy.cs
  69. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/KeyValuePairProxy.cs.meta
  70. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta.meta
  71. 7 5
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/AttributeMap.cs
  72. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/AttributeMap.cs.meta
  73. 0 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/BasicList.cs
  74. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/BasicList.cs.meta
  75. 0 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/CallbackSet.cs
  76. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/CallbackSet.cs.meta
  77. 400 134
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/MetaType.cs
  78. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/MetaType.cs.meta
  79. 17 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/ProtoSyntax.cs
  80. 12 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/ProtoSyntax.cs.meta
  81. 204 61
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/RuntimeTypeModel.cs
  82. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/RuntimeTypeModel.cs.meta
  83. 0 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/SubType.cs
  84. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/SubType.cs.meta
  85. 0 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/TypeFormatEventArgs.cs
  86. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/TypeFormatEventArgs.cs.meta
  87. 179 84
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/TypeModel.cs
  88. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/TypeModel.cs.meta
  89. 356 86
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/ValueMember.cs
  90. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/ValueMember.cs.meta
  91. 0 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/NetObjectCache.cs
  92. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/NetObjectCache.cs.meta
  93. 83 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/PType.cs
  94. 12 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/PType.cs.meta
  95. 0 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/PrefixStyle.cs
  96. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/PrefixStyle.cs.meta
  97. 19 6
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/ProtoContractAttribute.cs
  98. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/ProtoContractAttribute.cs.meta
  99. 0 0
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/ProtoConverterAttribute.cs
  100. 3 3
      Unity/Assets/ThirdParty/Protobuf/protobuf-net/ProtoConverterAttribute.cs.meta

+ 0 - 55
Unity/Assets/Plugins/protobuf-net/Serializers/DateTimeSerializer.cs

@@ -1,55 +0,0 @@
-#if !NO_RUNTIME
-using System;
-
-#if FEAT_IKVM
-using Type = IKVM.Reflection.Type;
-using IKVM.Reflection;
-#else
-using System.Reflection;
-#endif
-
-namespace ProtoBuf.Serializers
-{
-    sealed class DateTimeSerializer : IProtoSerializer
-    {
-#if FEAT_IKVM
-        readonly Type expectedType;
-#else
-        static readonly Type expectedType = typeof(DateTime);
-#endif
-        public Type ExpectedType { get { return expectedType; } }
-
-        bool IProtoSerializer.RequiresOldValue { get { return false; } }
-        bool IProtoSerializer.ReturnsValue { get { return true; } }
-
-        public DateTimeSerializer(ProtoBuf.Meta.TypeModel model)
-        {
-#if FEAT_IKVM
-            expectedType = model.MapType(typeof(DateTime));
-#endif
-        }
-#if !FEAT_IKVM
-        public object Read(object value, ProtoReader source)
-        {
-            Helpers.DebugAssert(value == null); // since replaces
-            return BclHelpers.ReadDateTime(source);
-        }
-        public void Write(object value, ProtoWriter dest)
-        {
-            BclHelpers.WriteDateTime((DateTime)value, dest);
-        }
-#endif
-#if FEAT_COMPILER
-        void IProtoSerializer.EmitWrite(Compiler.CompilerContext ctx, Compiler.Local valueFrom)
-        {
-            ctx.EmitWrite(ctx.MapType(typeof(BclHelpers)), "WriteDateTime", valueFrom);
-        }
-        void IProtoSerializer.EmitRead(Compiler.CompilerContext ctx, Compiler.Local valueFrom)
-        {
-            ctx.EmitBasicRead(ctx.MapType(typeof(BclHelpers)), "ReadDateTime", ExpectedType);
-        }
-#endif
-
-    }
-}
-#endif

+ 0 - 40
Unity/Assets/Plugins/protobuf-net/Serializers/KeyValuePairDecorator.cs

@@ -1,40 +0,0 @@
-
-namespace ProtoBuf.Serializers
-{
-    /*
-    sealed class KeyValuePairDecorator : IProtoSerializer
-    {
-        private readonly Type pairType;
-        private readonly IProtoSerializer keyTail, valueTail;
-        public KeyValuePairDecorator(Type pairType, IProtoSerializer keyTail, IProtoSerializer valueTail) {
-            Helpers.DebugAssert(pairType != null);
-            Helpers.DebugAssert(keyTail != null);
-            Helpers.DebugAssert(valueTail != null);
-            Helpers.DebugAssert(pairType == typeof(System.Collections.Generic.KeyValuePair<,>).MakeGenericType(keyTail.ExpectedType,valueTail.ExpectedType), "Key/value type mismatch");
-            this.pairType = pairType;
-            this.keyTail = keyTail;
-            this.valueTail = valueTail;
-        }
-
-        public Type ExpectedType { get { return pairType;}}
-        public bool ReturnsValue { get { return true; } }
-        public bool RequiresOldValue { get { return true; } }
-        public abstract void Write(object value, ProtoWriter dest)
-        {
-
-        }
-        public abstract object Read(object value, ProtoReader source)
-        {
-
-        }
-#if FEAT_COMPILER
-        void IProtoSerializer.EmitWrite(Compiler.CompilerContext ctx, Compiler.Local valueFrom)
-        {
-            throw new NotImplementedException();
-        }
-        void IProtoSerializer.EmitRead(Compiler.CompilerContext ctx, Compiler.Local valueFrom) {
-            throw new NotImplementedException();
-        }
-#endif
-    }*/
-}

+ 0 - 12
Unity/Assets/Plugins/protobuf-net/Serializers/KeyValuePairDecorator.cs.meta

@@ -1,12 +0,0 @@
-fileFormatVersion: 2
-guid: e9fc41b7e63a19746bb5c129f48061e2
-timeCreated: 1515899114
-licenseType: Pro
-MonoImporter:
-  serializedVersion: 2
-  defaultReferences: []
-  executionOrder: 0
-  icon: {instanceID: 0}
-  userData: 
-  assetBundleName: 
-  assetBundleVariant: 

+ 0 - 56
Unity/Assets/Plugins/protobuf-net/Serializers/TimeSpanSerializer.cs

@@ -1,56 +0,0 @@
-#if !NO_RUNTIME
-using System;
-
-#if FEAT_IKVM
-using Type = IKVM.Reflection.Type;
-using IKVM.Reflection;
-#else
-using System.Reflection;
-#endif
-
-
-
-namespace ProtoBuf.Serializers
-{
-    sealed class TimeSpanSerializer : IProtoSerializer
-    {
-#if FEAT_IKVM
-        readonly Type expectedType;
-#else
-        static readonly Type expectedType = typeof(TimeSpan);
-#endif
-        public TimeSpanSerializer(ProtoBuf.Meta.TypeModel model)
-        {
-#if FEAT_IKVM
-            expectedType = model.MapType(typeof(TimeSpan));
-#endif
-        }
-        public Type ExpectedType { get { return expectedType; } }
-
-        bool IProtoSerializer.RequiresOldValue { get { return false; } }
-        bool IProtoSerializer.ReturnsValue { get { return true; } }
-#if !FEAT_IKVM
-        public object Read(object value, ProtoReader source)
-        {
-            Helpers.DebugAssert(value == null); // since replaces
-            return BclHelpers.ReadTimeSpan(source);
-        }
-        public void Write(object value, ProtoWriter dest)
-        {
-            BclHelpers.WriteTimeSpan((TimeSpan)value, dest);
-        }
-#endif
-#if FEAT_COMPILER
-        void IProtoSerializer.EmitWrite(Compiler.CompilerContext ctx, Compiler.Local valueFrom)
-        {
-            ctx.EmitWrite(ctx.MapType(typeof(BclHelpers)), "WriteTimeSpan", valueFrom);
-        }
-        void IProtoSerializer.EmitRead(Compiler.CompilerContext ctx, Compiler.Local valueFrom)
-        {
-            ctx.EmitBasicRead(ctx.MapType(typeof(BclHelpers)), "ReadTimeSpan", ExpectedType);
-        }
-#endif
-
-    }
-}
-#endif

+ 9 - 0
Unity/Assets/ThirdParty/Protobuf.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 44b468f70e36c914a906f4875c457513
+folderAsset: yes
+timeCreated: 1517401476
+licenseType: Free
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
Unity/Assets/ThirdParty/Protobuf/Editor.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: c089ef16fa1b4b944a448e2da307bc74
+folderAsset: yes
+timeCreated: 1517401476
+licenseType: Free
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 38 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/Protogen.cs

@@ -0,0 +1,38 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEditor;
+using ProtoBuf;
+using Google.Protobuf.Reflection;
+using ProtoBuf.Reflection;
+using System.IO;
+
+public class Protogen {
+    [MenuItem("Bundle/Generate Protocs")]
+    public static void GenerateProtobufCS(){
+		Generate(Application.dataPath + "/../Proto/",new string[] { "mmopb.proto" }, Application.dataPath + "/../HotFix/");
+    }
+    static void Generate(string inpath,string[] inprotos,string outpath)
+    {
+
+		var set = new FileDescriptorSet();
+
+		set.AddImportPath(inpath);
+		foreach (var inproto in inprotos) {
+			set.Add (inproto, true);
+		}
+
+		set.Process();
+		var errors = set.GetErrors();
+		CSharpCodeGenerator.ClearTypeNames ();
+		var files = CSharpCodeGenerator.Default.Generate(set);
+
+		foreach (var file in files)
+		{
+			var path = Path.Combine(outpath, file.Name);
+			File.WriteAllText(path, file.Text);
+
+			Debug.Log($"generated: {path}");
+		}
+    }
+}

+ 12 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/Protogen.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: de9067302637f414bb5afb37d586a4e2
+timeCreated: 1517401477
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 9 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection.meta

@@ -0,0 +1,9 @@
+fileFormatVersion: 2
+guid: 9cfe4d3bb4f7dfd43b49e2e3f66cddde
+folderAsset: yes
+timeCreated: 1517401476
+licenseType: Free
+DefaultImporter:
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 814 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/CSharpCodeGenerator.cs

@@ -0,0 +1,814 @@
+using Google.Protobuf.Reflection;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace ProtoBuf.Reflection
+{
+    /// <summary>
+    /// A coded generator that writes C#
+    /// </summary>
+    public class CSharpCodeGenerator : CommonCodeGenerator
+    {
+        /// <summary>
+        /// Reusable code-generator instance
+        /// </summary>
+        public static CSharpCodeGenerator Default { get; } = new CSharpCodeGenerator();
+        /// <summary>
+        /// Create a new CSharpCodeGenerator instance
+        /// </summary>
+        protected CSharpCodeGenerator() { }
+        /// <summary>
+        /// Returns the language name
+        /// </summary>
+        public override string Name => "C#";
+        /// <summary>
+        /// Returns the default file extension
+        /// </summary>
+        protected override string DefaultFileExtension => "cs";
+        /// <summary>
+        /// Escapes language keywords
+        /// </summary>
+        protected override string Escape(string identifier)
+        {
+            switch (identifier)
+            {
+                case "abstract":
+                case "event":
+                case "new":
+                case "struct":
+                case "as":
+                case "explicit":
+                case "null":
+                case "switch":
+                case "base":
+                case "extern":
+                case "object":
+                case "this":
+                case "bool":
+                case "false":
+                case "operator":
+                case "throw":
+                case "break":
+                case "finally":
+                case "out":
+                case "true":
+                case "byte":
+                case "fixed":
+                case "override":
+                case "try":
+                case "case":
+                case "float":
+                case "params":
+                case "typeof":
+                case "catch":
+                case "for":
+                case "private":
+                case "uint":
+                case "char":
+                case "foreach":
+                case "protected":
+                case "ulong":
+                case "checked":
+                case "goto":
+                case "public":
+                case "unchecked":
+                case "class":
+                case "if":
+                case "readonly":
+                case "unsafe":
+                case "const":
+                case "implicit":
+                case "ref":
+                case "ushort":
+                case "continue":
+                case "in":
+                case "return":
+                case "using":
+                case "decimal":
+                case "int":
+                case "sbyte":
+                case "virtual":
+                case "default":
+                case "interface":
+                case "sealed":
+                case "volatile":
+                case "delegate":
+                case "internal":
+                case "short":
+                case "void":
+                case "do":
+                case "is":
+                case "sizeof":
+                case "while":
+                case "double":
+                case "lock":
+                case "stackalloc":
+                case "else":
+                case "long":
+                case "static":
+                case "enum":
+                case "namespace":
+                case "string":
+                    return "@" + identifier;
+                default:
+                    return identifier;
+            }
+        }
+        /// <summary>
+        /// Start a file
+        /// </summary>
+        protected override void WriteFileHeader(GeneratorContext ctx, FileDescriptorProto file, ref object state)
+        {
+            ctx.WriteLine("// This file was generated by a tool; you should avoid making direct changes.")
+               .WriteLine("// Consider using 'partial classes' to extend these types")
+               .WriteLine($"// Input: {Path.GetFileName(ctx.File.Name)}").WriteLine()
+               .WriteLine("#pragma warning disable CS1591, CS0612, CS3021").WriteLine();
+
+
+            var @namespace = ctx.NameNormalizer.GetName(file);
+
+            if (!string.IsNullOrWhiteSpace(@namespace))
+            {
+                state = @namespace;
+                ctx.WriteLine($"namespace {@namespace}");
+                ctx.WriteLine("{").Indent().WriteLine();
+            }
+
+        }
+        /// <summary>
+        /// End a file
+        /// </summary>
+        protected override void WriteFileFooter(GeneratorContext ctx, FileDescriptorProto file, ref object state)
+        {
+            var @namespace = (string)state;
+            if (!string.IsNullOrWhiteSpace(@namespace))
+            {
+                ctx.Outdent().WriteLine("}").WriteLine();
+            }
+            var @filename = file.Name.Substring(0, file.Name.IndexOf("."));
+            ctx.WriteLine($"public class ILRuntime_{@filename}");
+            ctx.WriteLine("{").Indent();
+            ctx.WriteLine($"static ILRuntime_{@filename}()");
+            ctx.WriteLine("{");
+            ctx.WriteLine().Indent();
+            ctx.WriteLine($"//Initlize();");
+            ctx.WriteLine().Outdent();
+            ctx.WriteLine("}");
+            ctx.WriteLine($"public static void Initlize()");
+            ctx.WriteLine("{");
+            ctx.WriteLine().Indent();
+            foreach(var T in TypeNames2)
+            {
+                ctx.WriteLine($@"ProtoBuf.PType.RegisterType(""{T}"", typeof({T}));");
+            }
+            ctx.WriteLine().Outdent();
+            ctx.WriteLine("}").Outdent();
+            ctx.WriteLine("}").WriteLine();
+            ctx.WriteLine("#pragma warning restore CS1591, CS0612, CS3021");
+        }
+        /// <summary>
+        /// Start an enum
+        /// </summary>
+        protected override void WriteEnumHeader(GeneratorContext ctx, EnumDescriptorProto obj, ref object state)
+        {
+            var name = ctx.NameNormalizer.GetName(obj);
+            var tw = ctx.Write($@"[global::ProtoBuf.ProtoContract(");
+            if (name != obj.Name) tw.Write($@"Name = @""{obj.Name}""");
+            tw.WriteLine(")]");
+            WriteOptions(ctx, obj.Options);
+            ctx.WriteLine($"{GetAccess(GetAccess(obj))} enum {Escape(name)}").WriteLine("{").Indent();
+        }
+        /// <summary>
+        /// End an enum
+        /// </summary>
+
+        protected override void WriteEnumFooter(GeneratorContext ctx, EnumDescriptorProto obj, ref object state)
+        {
+            ctx.Outdent().WriteLine("}").WriteLine();
+        }
+        /// <summary>
+        /// Write an enum value
+        /// </summary>
+        protected override void WriteEnumValue(GeneratorContext ctx, EnumValueDescriptorProto obj, ref object state)
+        {
+            var name = ctx.NameNormalizer.GetName(obj);
+            if (name != obj.Name)
+            {
+                var tw = ctx.Write($@"[global::ProtoBuf.ProtoEnum(");
+                tw.Write($@"Name = @""{obj.Name}""");
+                tw.WriteLine(")]");
+            }
+            
+            WriteOptions(ctx, obj.Options);
+            ctx.WriteLine($"{Escape(name)} = {obj.Number},");
+        }
+
+        /// <summary>
+        /// End a message
+        /// </summary>
+        protected override void WriteMessageFooter(GeneratorContext ctx, DescriptorProto obj, ref object state)
+        {
+            ctx.Outdent().WriteLine("}").WriteLine();
+        }
+        /// <summary>
+        /// Start a message
+        /// </summary>
+        protected override void WriteMessageHeader(GeneratorContext ctx, DescriptorProto obj, ref object state)
+        {
+            var name = ctx.NameNormalizer.GetName(obj);
+            GetTypeName2(obj.FullyQualifiedName);
+            var tw = ctx.Write($@"[global::ProtoBuf.ProtoContract(");
+            if (name != obj.Name) tw.Write($@"Name = @""{obj.Name}""");
+            tw.WriteLine(")]");
+            WriteOptions(ctx, obj.Options);
+            tw = ctx.Write($"{GetAccess(GetAccess(obj))} partial class {Escape(name)}");
+            if (obj.ExtensionRanges.Count != 0) tw.Write(" : global::ProtoBuf.IExtensible");
+            tw.WriteLine();
+            ctx.WriteLine("{").Indent();
+            if (obj.Options?.MessageSetWireFormat == true)
+            {
+                ctx.WriteLine("#error message_set_wire_format is not currently implemented").WriteLine();
+            }
+            if (obj.ExtensionRanges.Count != 0)
+            {
+                ctx.WriteLine($"private global::ProtoBuf.IExtension {FieldPrefix}extensionData;")
+                    .WriteLine($"global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)").Indent()
+                    .WriteLine($"=> global::ProtoBuf.Extensible.GetExtensionObject(ref {FieldPrefix}extensionData, createIfMissing);").Outdent().WriteLine();
+            }
+        }
+
+        private static void WriteOptions<T>(GeneratorContext ctx, T obj) where T : class, ISchemaOptions
+        {
+            if (obj == null) return;
+            if (obj.Deprecated)
+            {
+                ctx.WriteLine($"[global::System.Obsolete]");
+            }
+        }
+
+        const string FieldPrefix = "__pbn__";
+
+        /// <summary>
+        /// Get the language specific keyword representing an access level
+        /// </summary>
+        public override string GetAccess(Access access)
+        {
+            switch (access)
+            {
+                case Access.Internal: return "internal";
+                case Access.Public: return "public";
+                case Access.Private: return "private";
+                default: return base.GetAccess(access);
+            }
+        }
+        static HashSet<string> TypeNames2 = new HashSet<string>();
+        static string GetTypeName2(string type) {
+            if (type.StartsWith(".")) { type = type.Substring(1); }
+            TypeNames2.Add(type);
+            return type;
+        }
+		public static void ClearTypeNames(){
+			TypeNames2.Clear ();
+		}
+        /// <summary>
+        /// Write a field
+        /// </summary>
+        protected override void WriteField(GeneratorContext ctx, FieldDescriptorProto obj, ref object state, OneOfStub[] oneOfs)
+        {
+            var name = ctx.NameNormalizer.GetName(obj);
+            var tw = ctx.Write($@"[global::ProtoBuf.ProtoMember({obj.Number}");
+            if (name != obj.Name)
+            {
+                tw.Write($@", Name = @""{obj.Name}""");
+            }
+            var options = obj.Options?.GetOptions();
+            if (options?.AsReference == true)
+            {
+                tw.Write($@", AsReference = true");
+            }
+            if (options?.DynamicType == true)
+            {
+                tw.Write($@", DynamicType = true");
+            }
+			string dataFormat;
+			bool isMap;
+			var typeName = GetTypeName(ctx, obj, out dataFormat, out isMap);
+            bool isOptional = obj.label == FieldDescriptorProto.Label.LabelOptional;
+            bool isRepeated = obj.label == FieldDescriptorProto.Label.LabelRepeated;
+            if (isRepeated && obj.type == FieldDescriptorProto.Type.TypeMessage)
+            {
+                if(!isMap){
+                    tw.Write($@", TypeName = ""{GetTypeName2(obj.TypeName)}""");
+                }else{
+					var mapMsgType = isMap ? ctx.TryFind<DescriptorProto>(obj.TypeName) : null;
+                    if (mapMsgType != null)
+                    {
+                        var keyTypeName = mapMsgType.Fields.Single(x => x.Number == 1).TypeName;
+                        var valueTypeName = mapMsgType.Fields.Single(x => x.Number == 2).TypeName;
+                        if(!string.IsNullOrEmpty(keyTypeName)){
+							tw.Write($@", KeyTypeName = ""{GetTypeName2(keyTypeName)}""");
+                        }
+                        if(!string.IsNullOrEmpty(valueTypeName)){
+							tw.Write($@", TypeName = ""{GetTypeName2(valueTypeName)}""");
+                        }
+                    }
+                }
+            }
+            OneOfStub oneOf = obj.ShouldSerializeOneofIndex() ? oneOfs?[obj.OneofIndex] : null;
+            if (oneOf != null && oneOf.CountTotal == 1)
+            {
+                oneOf = null; // not really a one-of, then!
+            }
+            bool explicitValues = isOptional && oneOf == null && ctx.Syntax == FileDescriptorProto.SyntaxProto2
+                && obj.type != FieldDescriptorProto.Type.TypeMessage
+                && obj.type != FieldDescriptorProto.Type.TypeGroup;
+
+
+            string defaultValue = null;
+            bool suppressDefaultAttribute = !isOptional;
+            if (isOptional || obj.type == FieldDescriptorProto.Type.TypeEnum)
+            {
+				//GetTypeName2(obj.TypeName);
+                defaultValue = obj.DefaultValue;
+
+                if (obj.type == FieldDescriptorProto.Type.TypeString)
+                {
+                    defaultValue = string.IsNullOrEmpty(defaultValue) ? "\"\""
+                        : ("@\"" + (defaultValue ?? "").Replace("\"", "\"\"") + "\"");
+                }
+                else if (obj.type == FieldDescriptorProto.Type.TypeDouble)
+                {
+                    switch (defaultValue)
+                    {
+                        case "inf": defaultValue = "double.PositiveInfinity"; break;
+                        case "-inf": defaultValue = "double.NegativeInfinity"; break;
+                        case "nan": defaultValue = "double.NaN"; break;
+                    }
+                }
+                else if (obj.type == FieldDescriptorProto.Type.TypeFloat)
+                {
+                    switch (defaultValue)
+                    {
+                        case "inf": defaultValue = "float.PositiveInfinity"; break;
+                        case "-inf": defaultValue = "float.NegativeInfinity"; break;
+                        case "nan": defaultValue = "float.NaN"; break;
+                    }
+                }
+                else if (obj.type == FieldDescriptorProto.Type.TypeEnum)
+                {
+                    var enumType = ctx.TryFind<EnumDescriptorProto>(obj.TypeName);
+                    if (enumType != null)
+                    {
+                        EnumValueDescriptorProto found = null;
+                        if (!string.IsNullOrEmpty(defaultValue))
+                        {
+                            found = enumType.Values.FirstOrDefault(x => x.Name == defaultValue);
+                        }
+                        else if (ctx.Syntax == FileDescriptorProto.SyntaxProto2)
+                        {
+                            // find the first one; if that is a zero, we don't need it after all
+                            found = enumType.Values.FirstOrDefault();
+                            if(found != null && found.Number == 0)
+                            {
+                                if(!isOptional) found = null; // we don't need it after all
+                            }
+                        }
+                        // for proto3 the default is 0, so no need to do anything - GetValueOrDefault() will do it all
+
+                        if (found != null)
+                        {
+                            defaultValue = ctx.NameNormalizer.GetName(found);
+                        }
+                        if (!string.IsNullOrWhiteSpace(defaultValue))
+                        {
+                            //defaultValue = ctx.NameNormalizer.GetName(enumType) + "." + defaultValue;
+
+							defaultValue = "global::"+enumType.FullyQualifiedName.Substring(1) + "." + defaultValue;
+                        }
+                    }
+                }
+            }
+
+            if (!string.IsNullOrWhiteSpace(dataFormat))
+            {
+                tw.Write($", DataFormat = global::ProtoBuf.DataFormat.{dataFormat}");
+            }
+            if (obj.IsPacked(ctx.Syntax))
+            {
+                tw.Write($", IsPacked = true");
+            }
+            if (obj.label == FieldDescriptorProto.Label.LabelRequired)
+            {
+                tw.Write($", IsRequired = true");
+            }
+            tw.WriteLine(")]");
+            if (!isRepeated && !string.IsNullOrWhiteSpace(defaultValue) && !suppressDefaultAttribute)
+            {
+                ctx.WriteLine($"[global::System.ComponentModel.DefaultValue({defaultValue})]");
+            }
+            WriteOptions(ctx, obj.Options);
+            if (isRepeated)
+            {
+                var mapMsgType = isMap ? ctx.TryFind<DescriptorProto>(obj.TypeName) : null;
+                if (mapMsgType != null)
+                {
+                    string keyDataFormat;
+                    bool _;
+                    var keyTypeName = GetTypeName(ctx, mapMsgType.Fields.Single(x => x.Number == 1),
+                        out keyDataFormat, out _);
+                    string valueDataFormat;
+                    var valueTypeName = GetTypeName(ctx, mapMsgType.Fields.Single(x => x.Number == 2),
+                        out valueDataFormat, out _);
+
+                    bool first = true;
+                    tw = ctx.Write($"[global::ProtoBuf.ProtoMap");
+                    if (!string.IsNullOrWhiteSpace(keyDataFormat))
+                    {
+                        tw.Write($"{(first ? "(" : ", ")}KeyFormat = global::ProtoBuf.DataFormat.{keyDataFormat}");
+                        first = false;
+                    }
+                    if (!string.IsNullOrWhiteSpace(valueDataFormat))
+                    {
+                        tw.Write($"{(first ? "(" : ", ")}ValueFormat = global::ProtoBuf.DataFormat.{valueDataFormat}");
+                        first = false;
+                    }
+                    tw.WriteLine(first ? "]" : ")]");
+                    ctx.WriteLine($"{GetAccess(GetAccess(obj))} global::System.Collections.Generic.Dictionary<{keyTypeName}, {valueTypeName}> {Escape(name)} {{ get; }} = new global::System.Collections.Generic.Dictionary<{keyTypeName}, {valueTypeName}>();");
+                }
+                else if (UseArray(obj))
+                {
+                    ctx.WriteLine($"{GetAccess(GetAccess(obj))} {typeName}[] {Escape(name)} {{ get; set; }}");
+                }
+                else
+                {
+                    ctx.WriteLine($"{GetAccess(GetAccess(obj))} global::System.Collections.Generic.List<{typeName}> {Escape(name)} {{ get; }} = new global::System.Collections.Generic.List<{typeName}>();");
+                }
+            }
+            else if (oneOf != null)
+            {
+                var defValue = string.IsNullOrWhiteSpace(defaultValue) ? $"default({typeName})" : defaultValue;
+                var fieldName = FieldPrefix + oneOf.OneOf.Name;
+                var storage = oneOf.GetStorage(obj.type, obj.TypeName);
+                ctx.WriteLine($"{GetAccess(GetAccess(obj))} {typeName} {Escape(name)}").WriteLine("{").Indent();
+
+                switch (obj.type)
+                {
+                    case FieldDescriptorProto.Type.TypeMessage:
+                    case FieldDescriptorProto.Type.TypeGroup:
+                    case FieldDescriptorProto.Type.TypeEnum:
+                    case FieldDescriptorProto.Type.TypeBytes:
+                    case FieldDescriptorProto.Type.TypeString:
+                        ctx.WriteLine($"get {{ return {fieldName}.Is({obj.Number}) ? (({typeName}){fieldName}.{storage}) : {defValue}; }}");
+                        break;
+                    default:
+                        ctx.WriteLine($"get {{ return {fieldName}.Is({obj.Number}) ? {fieldName}.{storage} : {defValue}; }}");
+                        break;
+                }
+                var unionType = oneOf.GetUnionType();
+                ctx.WriteLine($"set {{ {fieldName} = new global::ProtoBuf.{unionType}({obj.Number}, value); }}")
+                    .Outdent().WriteLine("}")
+                    .WriteLine($"{GetAccess(GetAccess(obj))} bool ShouldSerialize{name}() => {fieldName}.Is({obj.Number});")
+                    .WriteLine($"{GetAccess(GetAccess(obj))} void Reset{name}() => global::ProtoBuf.{unionType}.Reset(ref {fieldName}, {obj.Number});");
+
+                if (oneOf.IsFirst())
+                {
+                    ctx.WriteLine().WriteLine($"private global::ProtoBuf.{unionType} {fieldName};");
+                }
+            }
+            else if (explicitValues)
+            {
+                string fieldName = FieldPrefix + name, fieldType;
+                bool isRef = false;
+                switch (obj.type)
+                {
+                    case FieldDescriptorProto.Type.TypeString:
+                    case FieldDescriptorProto.Type.TypeBytes:
+                        fieldType = typeName;
+                        isRef = true;
+                        break;
+                    default:
+                        fieldType = typeName + "?";
+                        break;
+                }
+                ctx.WriteLine($"{GetAccess(GetAccess(obj))} {typeName} {Escape(name)}").WriteLine("{").Indent();
+                tw = ctx.Write($"get {{ return {fieldName}");
+                if (!string.IsNullOrWhiteSpace(defaultValue))
+                {
+                    tw.Write(" ?? ");
+                    tw.Write(defaultValue);
+                }
+                else if (!isRef)
+                {
+                    tw.Write(".GetValueOrDefault()");
+                }
+                tw.WriteLine("; }");
+                ctx.WriteLine($"set {{ {fieldName} = value; }}")
+                    .Outdent().WriteLine("}")
+                    .WriteLine($"{GetAccess(GetAccess(obj))} bool ShouldSerialize{name}() => {fieldName} != null;")
+                    .WriteLine($"{GetAccess(GetAccess(obj))} void Reset{name}() => {fieldName} = null;")
+                    .WriteLine($"private {fieldType} {fieldName};");
+            }
+            else
+            {
+                tw = ctx.Write($"{GetAccess(GetAccess(obj))} {typeName} {Escape(name)} {{ get; set; }}");
+                if (!string.IsNullOrWhiteSpace(defaultValue)) tw.Write($" = {defaultValue};");
+                tw.WriteLine();
+            }
+            ctx.WriteLine();
+        }
+        /// <summary>
+        /// Starts an extgensions block
+        /// </summary>
+        protected override void WriteExtensionsHeader(GeneratorContext ctx, FileDescriptorProto obj, ref object state)
+        {
+            var name = obj?.Options?.GetOptions()?.ExtensionTypeName;
+            if (string.IsNullOrWhiteSpace(name)) name = "Extensions";
+            ctx.WriteLine($"{GetAccess(GetAccess(obj))} static class {Escape(name)}").WriteLine("{").Indent();
+        }
+        /// <summary>
+        /// Ends an extgensions block
+        /// </summary>
+        protected override void WriteExtensionsFooter(GeneratorContext ctx, FileDescriptorProto obj, ref object state)
+        {
+            ctx.Outdent().WriteLine("}");
+        }
+        /// <summary>
+        /// Starts an extensions block
+        /// </summary>
+        protected override void WriteExtensionsHeader(GeneratorContext ctx, DescriptorProto obj, ref object state)
+        {
+            var name = obj?.Options?.GetOptions()?.ExtensionTypeName;
+            if (string.IsNullOrWhiteSpace(name)) name = "Extensions";
+            ctx.WriteLine($"{GetAccess(GetAccess(obj))} static class {Escape(name)}").WriteLine("{").Indent();
+        }
+        /// <summary>
+        /// Ends an extensions block
+        /// </summary>
+        protected override void WriteExtensionsFooter(GeneratorContext ctx, DescriptorProto obj, ref object state)
+        {
+            ctx.Outdent().WriteLine("}");
+        }
+        /// <summary>
+        /// Write an extension
+        /// </summary>
+        protected override void WriteExtension(GeneratorContext ctx, FieldDescriptorProto field)
+        {
+            string dataFormat;
+            bool isMap;
+            var type = GetTypeName(ctx, field, out dataFormat, out isMap);
+
+            if (isMap)
+            {
+                ctx.WriteLine("#error map extensions not yet implemented");
+            }
+            else if (field.label == FieldDescriptorProto.Label.LabelRepeated)
+            {
+                ctx.WriteLine("#error repeated extensions not yet implemented");
+            }
+            else
+            {
+                var msg = ctx.TryFind<DescriptorProto>(field.Extendee);
+                var extendee = MakeRelativeName(field, msg, ctx.NameNormalizer);
+
+                var @this = field.Parent is FileDescriptorProto ? "this " : "";
+                string name = ctx.NameNormalizer.GetName(field);
+                var tw = ctx.WriteLine($"{GetAccess(GetAccess(field))} static {type} Get{name}({@this}{extendee} obj)")
+                    .Write($"=> obj == null ? default({type}) : global::ProtoBuf.Extensible.GetValue<{type}>(obj, {field.Number}");
+                if (!string.IsNullOrEmpty(dataFormat))
+                {
+                    tw.Write($", global::ProtoBuf.DataFormat.{dataFormat}");
+                }
+                tw.WriteLine(");");
+                ctx.WriteLine();
+                //  GetValue<TValue>(IExtensible instance, int tag, DataFormat format)
+            }
+        }
+
+        private static bool UseArray(FieldDescriptorProto field)
+        {
+            switch (field.type)
+            {
+                case FieldDescriptorProto.Type.TypeBool:
+                case FieldDescriptorProto.Type.TypeDouble:
+                case FieldDescriptorProto.Type.TypeFixed32:
+                case FieldDescriptorProto.Type.TypeFixed64:
+                case FieldDescriptorProto.Type.TypeFloat:
+                case FieldDescriptorProto.Type.TypeInt32:
+                case FieldDescriptorProto.Type.TypeInt64:
+                case FieldDescriptorProto.Type.TypeSfixed32:
+                case FieldDescriptorProto.Type.TypeSfixed64:
+                case FieldDescriptorProto.Type.TypeSint32:
+                case FieldDescriptorProto.Type.TypeSint64:
+                case FieldDescriptorProto.Type.TypeUint32:
+                case FieldDescriptorProto.Type.TypeUint64:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        private string GetTypeName(GeneratorContext ctx, FieldDescriptorProto field, out string dataFormat, out bool isMap)
+        {
+            dataFormat = "";
+            isMap = false;
+            switch (field.type)
+            {
+                case FieldDescriptorProto.Type.TypeDouble:
+                    return "double";
+                case FieldDescriptorProto.Type.TypeFloat:
+                    return "float";
+                case FieldDescriptorProto.Type.TypeBool:
+                    return "bool";
+                case FieldDescriptorProto.Type.TypeString:
+                    return "string";
+                case FieldDescriptorProto.Type.TypeSint32:
+                    dataFormat = nameof(DataFormat.ZigZag);
+                    return "int";
+                case FieldDescriptorProto.Type.TypeInt32:
+                    return "int";
+                case FieldDescriptorProto.Type.TypeSfixed32:
+                    dataFormat = nameof(DataFormat.FixedSize);
+                    return "int";
+                case FieldDescriptorProto.Type.TypeSint64:
+                    dataFormat = nameof(DataFormat.ZigZag);
+                    return "long";
+                case FieldDescriptorProto.Type.TypeInt64:
+                    return "long";
+                case FieldDescriptorProto.Type.TypeSfixed64:
+                    dataFormat = nameof(DataFormat.FixedSize);
+                    return "long";
+                case FieldDescriptorProto.Type.TypeFixed32:
+                    dataFormat = nameof(DataFormat.FixedSize);
+                    return "uint";
+                case FieldDescriptorProto.Type.TypeUint32:
+                    return "uint";
+                case FieldDescriptorProto.Type.TypeFixed64:
+                    dataFormat = nameof(DataFormat.FixedSize);
+                    return "ulong";
+                case FieldDescriptorProto.Type.TypeUint64:
+                    return "ulong";
+                case FieldDescriptorProto.Type.TypeBytes:
+                    return "byte[]";
+                case FieldDescriptorProto.Type.TypeEnum:
+                    switch (field.TypeName)
+                    {
+                        case ".bcl.DateTime.DateTimeKind":
+                            return "global::System.DateTimeKind";
+                    }
+                    var enumType = ctx.TryFind<EnumDescriptorProto>(field.TypeName);
+                    return MakeRelativeName(field, enumType, ctx.NameNormalizer);
+                case FieldDescriptorProto.Type.TypeGroup:
+                case FieldDescriptorProto.Type.TypeMessage:
+                    switch (field.TypeName)
+                    {
+                        case WellKnownTypeTimestamp:
+                            dataFormat = "WellKnown";
+                            return "global::System.DateTime?";
+                        case WellKnownTypeDuration:
+                            dataFormat = "WellKnown";
+                            return "global::System.TimeSpan?";
+                        case ".bcl.NetObjectProxy":
+                            return "object";
+                        case ".bcl.DateTime":
+                            return "global::System.DateTime?";
+                        case ".bcl.TimeSpan":
+                            return "global::System.TimeSpan?";
+                        case ".bcl.Decimal":
+                            return "decimal?";
+                        case ".bcl.Guid":
+                            return "global::System.Guid?";
+                    }
+                    var msgType = ctx.TryFind<DescriptorProto>(field.TypeName);
+                    if (field.type == FieldDescriptorProto.Type.TypeGroup)
+                    {
+                        dataFormat = nameof(DataFormat.Group);
+                    }
+                    isMap = msgType?.Options?.MapEntry ?? false;
+                    return MakeRelativeName(field, msgType, ctx.NameNormalizer);
+                default:
+                    return field.TypeName;
+            }
+        }
+
+        private string MakeRelativeName(FieldDescriptorProto field, IType target, NameNormalizer normalizer)
+        {
+            if (target == null) return Escape(field.TypeName); // the only thing we know
+
+            var declaringType = field.Parent;
+
+            if (declaringType is IType)
+            {
+                var name = FindNameFromCommonAncestor((IType)declaringType, target, normalizer);
+                if (!string.IsNullOrWhiteSpace(name)) return name;
+            }
+            return Escape(field.TypeName); // give up!
+        }
+
+        // k, what we do is; we have two types; each knows the parent, but nothing else, so:
+        // for each, use a stack to build the ancestry tree - the "top" of the stack will be the
+        // package, the bottom of the stack will be the type itself. They will often be stacks
+        // of different heights.
+        //
+        // Find how many is in the smallest stack; now take that many items, in turn, until we
+        // get something that is different (at which point, put that one back on the stack), or 
+        // we run out of items in one of the stacks.
+        //
+        // There are now two options:
+        // - we ran out of things in the "target" stack - in which case, they are common enough to not
+        //   need any resolution - just give back the fixed name
+        // - we have things left in the "target" stack - in which case we have found a common ancestor,
+        //   or the target is a descendent; either way, just concat what is left (including the package
+        //   if the package itself was different)
+
+        private string FindNameFromCommonAncestor(IType declaring, IType target, NameNormalizer normalizer)
+        {
+            // trivial case; asking for self, or asking for immediate child
+            if (ReferenceEquals(declaring, target) || ReferenceEquals(declaring, target.Parent))
+            {
+                if (target is DescriptorProto) return Escape(normalizer.GetName((DescriptorProto)target));
+                if (target is EnumDescriptorProto) return Escape(normalizer.GetName((EnumDescriptorProto)target));
+                return null;
+            }
+
+            var origTarget = target;
+            var xStack = new Stack<IType>();
+
+            while (declaring != null)
+            {
+                xStack.Push(declaring);
+                declaring = declaring.Parent;
+            }
+            var yStack = new Stack<IType>();
+
+            while (target != null)
+            {
+                yStack.Push(target);
+                target = target.Parent;
+            }
+            int lim = Math.Min(xStack.Count, yStack.Count);
+            for (int i = 0; i < lim; i++)
+            {
+                declaring = xStack.Peek();
+                target = yStack.Pop();
+                if (!ReferenceEquals(target, declaring))
+                {
+                    // special-case: if both are the package (file), and they have the same namespace: we're OK
+                    if (target is FileDescriptorProto && declaring is FileDescriptorProto &&
+                        normalizer.GetName((FileDescriptorProto)declaring) == normalizer.GetName((FileDescriptorProto)target))
+                    {
+                        // that's fine, keep going
+                    }
+                    else
+                    {
+                        // put it back
+                        yStack.Push(target);
+                        break;
+                    }
+                }
+            }
+            // if we used everything, then the target is an ancestor-or-self
+            if (yStack.Count == 0)
+            {
+                target = origTarget;
+                if (target is DescriptorProto) return Escape(normalizer.GetName((DescriptorProto)target));
+                if (target is EnumDescriptorProto) return Escape(normalizer.GetName((EnumDescriptorProto)target));
+                return null;
+            }
+
+            var sb = new StringBuilder();
+            while (yStack.Count != 0)
+            {
+                target = yStack.Pop();
+
+                string nextName;
+                if (target is FileDescriptorProto) nextName = normalizer.GetName((FileDescriptorProto)target);
+                else if (target is DescriptorProto) nextName = normalizer.GetName((DescriptorProto)target);
+                else if (target is EnumDescriptorProto) nextName = normalizer.GetName((EnumDescriptorProto)target);
+                else return null;
+
+                if (!string.IsNullOrWhiteSpace(nextName))
+                {
+                    if (sb.Length == 0 && target is FileDescriptorProto) sb.Append("global::");
+                    else if (sb.Length != 0) sb.Append('.');
+                    sb.Append(Escape(nextName));
+                }
+            }
+            return sb.ToString();
+        }
+
+        static bool IsAncestorOrSelf(IType parent, IType child)
+        {
+            while (parent != null)
+            {
+                if (ReferenceEquals(parent, child)) return true;
+                parent = parent.Parent;
+            }
+            return false;
+        }
+        const string WellKnownTypeTimestamp = ".google.protobuf.Timestamp",
+                     WellKnownTypeDuration = ".google.protobuf.Duration";
+    }
+}

+ 12 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/CSharpCodeGenerator.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 9dd6ca7bc326d2b40b4ef50492e16a8d
+timeCreated: 1517401477
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 158 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/CodeGenerator.OneOfStub.cs

@@ -0,0 +1,158 @@
+using Google.Protobuf.Reflection;
+
+namespace ProtoBuf.Reflection
+{
+    partial class CommonCodeGenerator
+    {
+        /// <summary>
+        /// Represents the union summary of a one-of declaration
+        /// </summary>
+        protected class OneOfStub
+        {
+            /// <summary>
+            /// The underlying descriptor
+            /// </summary>
+            public OneofDescriptorProto OneOf { get; }
+
+            internal OneOfStub(OneofDescriptorProto decl)
+            {
+                OneOf = decl;
+            }
+            internal int Count32 { get; private set; }
+            internal int Count64 { get; private set; }
+            internal int Count128 { get; private set; }
+            internal int CountRef { get; private set; }
+            internal int CountTotal => CountRef + Count32 + Count64;
+
+            private void AccountFor(FieldDescriptorProto.Type type, string typeName)
+            {
+                switch (type)
+                {
+                    case FieldDescriptorProto.Type.TypeBool:
+                    case FieldDescriptorProto.Type.TypeEnum:
+                    case FieldDescriptorProto.Type.TypeFixed32:
+                    case FieldDescriptorProto.Type.TypeFloat:
+                    case FieldDescriptorProto.Type.TypeInt32:
+                    case FieldDescriptorProto.Type.TypeSfixed32:
+                    case FieldDescriptorProto.Type.TypeSint32:
+                    case FieldDescriptorProto.Type.TypeUint32:
+                        Count32++;
+                        break;
+                    case FieldDescriptorProto.Type.TypeDouble:
+                    case FieldDescriptorProto.Type.TypeFixed64:
+                    case FieldDescriptorProto.Type.TypeInt64:
+                    case FieldDescriptorProto.Type.TypeSfixed64:
+                    case FieldDescriptorProto.Type.TypeSint64:
+                    case FieldDescriptorProto.Type.TypeUint64:
+                        Count32++;
+                        Count64++;
+                        break;
+                    case FieldDescriptorProto.Type.TypeMessage:
+                        switch(typeName)
+                        {
+                            case ".google.protobuf.Timestamp":
+                            case ".google.protobuf.Duration":
+                                Count64++;
+                                break;
+                            case ".bcl.Guid":
+                                Count128++;
+                                break;
+                            default:
+                                CountRef++;
+                                break;
+                        }
+                        break;
+                    default:
+                        CountRef++;
+                        break;
+                }
+            }
+            internal string GetStorage(FieldDescriptorProto.Type type, string typeName)
+            {
+                switch (type)
+                {
+                    case FieldDescriptorProto.Type.TypeBool:
+                        return "Boolean";
+                    case FieldDescriptorProto.Type.TypeInt32:
+                    case FieldDescriptorProto.Type.TypeSfixed32:
+                    case FieldDescriptorProto.Type.TypeSint32:
+                    case FieldDescriptorProto.Type.TypeFixed32:
+                    case FieldDescriptorProto.Type.TypeEnum:
+                        return "Int32";
+                    case FieldDescriptorProto.Type.TypeFloat:
+                        return "Single";
+                    case FieldDescriptorProto.Type.TypeUint32:
+                        return "UInt32";
+                    case FieldDescriptorProto.Type.TypeDouble:
+                        return "Double";
+                    case FieldDescriptorProto.Type.TypeFixed64:
+                    case FieldDescriptorProto.Type.TypeInt64:
+                    case FieldDescriptorProto.Type.TypeSfixed64:
+                    case FieldDescriptorProto.Type.TypeSint64:
+                        return "Int64";
+                    case FieldDescriptorProto.Type.TypeUint64:
+                        return "UInt64";
+                    case FieldDescriptorProto.Type.TypeMessage:
+                        switch (typeName)
+                        {
+                            case ".google.protobuf.Timestamp":
+                                return "DateTime";
+                            case ".google.protobuf.Duration":
+                                return "TimeSpan";
+                            case ".bcl.Guid":
+                                return "Guid";
+                            default:
+                                return "Object";
+                        }
+                    default:
+                        return "Object";
+                }
+            }
+            internal static OneOfStub[] Build(GeneratorContext context, DescriptorProto message)
+            {
+                if (message.OneofDecls.Count == 0) return null;
+                var stubs = new OneOfStub[message.OneofDecls.Count];
+                int index = 0;
+                foreach (var decl in message.OneofDecls)
+                {
+                    stubs[index++] = new OneOfStub(decl);
+                }
+                foreach (var field in message.Fields)
+                {
+                    if (field.ShouldSerializeOneofIndex())
+                    {
+                        stubs[field.OneofIndex].AccountFor(field.type, field.TypeName);
+                    }
+                }
+                return stubs;
+            }
+            private bool isFirst = true;
+            internal bool IsFirst()
+            {
+                if (isFirst)
+                {
+                    isFirst = false;
+                    return true;
+                }
+                return false;
+            }
+
+            internal string GetUnionType()
+            {
+                if (Count128 != 0)
+                {
+                    return CountRef == 0 ? "DiscriminatedUnion128" : "DiscriminatedUnion128Object";
+                }
+                if (Count64 != 0)
+                {
+                    return CountRef == 0 ? "DiscriminatedUnion64" : "DiscriminatedUnion64Object";
+                }
+                if (Count32 != 0)
+                {
+                    return CountRef == 0 ? "DiscriminatedUnion32" : "DiscriminatedUnion32Object";
+                }
+                return "DiscriminatedUnionObject";
+            }
+        }
+    }
+}

+ 12 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/CodeGenerator.OneOfStub.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: eadc7291e5760b049b3413444376b292
+timeCreated: 1517401477
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 476 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/CodeGenerator.cs

@@ -0,0 +1,476 @@
+using Google.Protobuf.Reflection;
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace ProtoBuf.Reflection
+{
+    /// <summary>
+    /// Abstract root for a general purpose code-generator
+    /// </summary>
+    public abstract class CodeGenerator
+    {
+        /// <summary>
+        /// The logical name of this code generator
+        /// </summary>
+        public abstract string Name { get; }
+        /// <summary>
+        /// Get a string representation of the instance
+        /// </summary>
+        public override string ToString() => Name;
+
+        /// <summary>
+        /// Execute the code generator against a FileDescriptorSet, yielding a sequence of files
+        /// </summary>
+        public abstract IEnumerable<CodeFile> Generate(FileDescriptorSet set, NameNormalizer normalizer = null);
+
+        /// <summary>
+        /// Eexecute this code generator against a code file
+        /// </summary>
+        public CompilerResult Compile(CodeFile file) => Compile(new[] { file });
+        /// <summary>
+        /// Eexecute this code generator against a set of code file
+        /// </summary>
+        public CompilerResult Compile(params CodeFile[] files)
+        {
+            var set = new FileDescriptorSet();
+            foreach (var file in files)
+            {
+                using (var reader = new StringReader(file.Text))
+                {
+                    Console.WriteLine($"Parsing {file.Name}...");
+                    set.Add(file.Name, true, reader);
+                }
+            }
+            set.Process();
+            var results = new List<CodeFile>();
+            //var newErrors = new List<Error>();
+
+            try
+            {
+                results.AddRange(Generate(set));
+            }
+            catch (Exception ex)
+            {
+                set.Errors.Add(new Error(default(Token), ex.Message, true));
+            }
+            var errors = set.GetErrors();
+
+            return new CompilerResult(errors, results.ToArray());
+        }
+    }
+    /// <summary>
+    /// Abstract base class for a code generator that uses a visitor pattern
+    /// </summary>
+    public abstract partial class CommonCodeGenerator : CodeGenerator
+    {
+        private Access? GetAccess(IType parent)
+        {
+            if (parent is DescriptorProto)
+                return GetAccess((DescriptorProto)parent);
+            if (parent is EnumDescriptorProto)
+                return GetAccess((EnumDescriptorProto)parent);
+            if (parent is FileDescriptorProto)
+                return GetAccess((FileDescriptorProto)parent);
+            return null;
+        }
+        /// <summary>
+        /// Obtain the access of an item, accounting for the model's hierarchy
+        /// </summary>
+        protected Access GetAccess(FileDescriptorProto obj)
+            => obj?.Options?.GetOptions()?.Access ?? Access.Public;
+
+        static Access? NullIfInherit(Access? access)
+            => access == Access.Inherit ? null : access;
+        /// <summary>
+        /// Obtain the access of an item, accounting for the model's hierarchy
+        /// </summary>
+        protected Access GetAccess(DescriptorProto obj)
+            => NullIfInherit(obj?.Options?.GetOptions()?.Access)
+            ?? GetAccess(obj?.Parent) ?? Access.Public;
+        /// <summary>
+        /// Obtain the access of an item, accounting for the model's hierarchy
+        /// </summary>
+        protected Access GetAccess(FieldDescriptorProto obj)
+            => NullIfInherit(obj?.Options?.GetOptions()?.Access)
+            ?? GetAccess(obj?.Parent as IType) ?? Access.Public;
+        /// <summary>
+        /// Obtain the access of an item, accounting for the model's hierarchy
+        /// </summary>
+        protected Access GetAccess(EnumDescriptorProto obj)
+            => NullIfInherit(obj?.Options?.GetOptions()?.Access)
+                ?? GetAccess(obj?.Parent) ?? Access.Public;
+        /// <summary>
+        /// Get the textual name of a given access level
+        /// </summary>
+        public virtual string GetAccess(Access access)
+            => access.ToString();
+        
+        /// <summary>
+        /// The indentation used by this code generator
+        /// </summary>
+        public virtual string Indent => "    ";
+        /// <summary>
+        /// The file extension of the files generatred by this generator
+        /// </summary>
+        protected abstract string DefaultFileExtension { get; }
+        /// <summary>
+        /// Handle keyword escaping in the language of this code generator
+        /// </summary>
+        /// <param name="identifier"></param>
+        /// <returns></returns>
+        protected abstract string Escape(string identifier);
+        /// <summary>
+        /// Execute the code generator against a FileDescriptorSet, yielding a sequence of files
+        /// </summary>
+        public override IEnumerable<CodeFile> Generate(FileDescriptorSet set, NameNormalizer normalizer = null)
+        {
+            foreach (var file in set.Files)
+            {
+                if (!file.IncludeInOutput) continue;
+
+                var fileName = Path.ChangeExtension(file.Name, DefaultFileExtension);
+
+                string generated;
+                using (var buffer = new StringWriter())
+                {
+                    var ctx = new GeneratorContext(file, normalizer ?? NameNormalizer.Default, buffer, Indent);
+
+                    ctx.BuildTypeIndex(); // populates for TryFind<T>
+                    WriteFile(ctx, file);
+                    generated = buffer.ToString();
+                }
+                yield return new CodeFile(fileName, generated);
+
+            }
+
+        }
+
+        /// <summary>
+        /// Emits the code for a file in a descriptor-set
+        /// </summary>
+        protected virtual void WriteFile(GeneratorContext ctx, FileDescriptorProto obj)
+        {
+            var file = ctx.File;
+            object state = null;
+            WriteFileHeader(ctx, obj, ref state);
+
+            foreach (var inner in file.MessageTypes)
+            {
+                WriteMessage(ctx, inner);
+            }
+            foreach (var inner in file.EnumTypes)
+            {
+                WriteEnum(ctx, inner);
+            }
+            foreach (var inner in file.Services)
+            {
+                WriteService(ctx, inner);
+            }
+            if(file.Extensions.Count != 0)
+            {
+                object extState = null;
+                WriteExtensionsHeader(ctx, file, ref extState);
+                foreach(var ext in file.Extensions)
+                {
+                    WriteExtension(ctx, ext);
+                }
+                WriteExtensionsFooter(ctx, file, ref extState);
+            }
+            WriteFileFooter(ctx, obj, ref state);
+        }
+        /// <summary>
+        /// Emit code representing an extension field
+        /// </summary>
+        protected virtual void WriteExtension(GeneratorContext ctx, FieldDescriptorProto ext) { }
+        /// <summary>
+        /// Emit code preceeding a set of extension fields
+        /// </summary>
+        protected virtual void WriteExtensionsHeader(GeneratorContext ctx, FileDescriptorProto file, ref object state) { }
+        /// <summary>
+        /// Emit code following a set of extension fields
+        /// </summary>
+        protected virtual void WriteExtensionsFooter(GeneratorContext ctx, FileDescriptorProto file, ref object state) { }
+        /// <summary>
+        /// Emit code preceeding a set of extension fields
+        /// </summary>
+        protected virtual void WriteExtensionsHeader(GeneratorContext ctx, DescriptorProto file, ref object state) { }
+        /// <summary>
+        /// Emit code following a set of extension fields
+        /// </summary>
+        protected virtual void WriteExtensionsFooter(GeneratorContext ctx, DescriptorProto file, ref object state) { }
+        /// <summary>
+        /// Emit code representing a service
+        /// </summary>
+        protected virtual void WriteService(GeneratorContext ctx, ServiceDescriptorProto obj)
+        {
+            object state = null;
+            WriteServiceHeader(ctx, obj, ref state);
+            foreach (var inner in obj.Methods)
+            {
+                WriteServiceMethod(ctx, inner, ref state);
+            }
+            WriteServiceFooter(ctx, obj, ref state);
+        }
+        /// <summary>
+        /// Emit code following a set of service methods
+        /// </summary>
+        protected virtual void WriteServiceFooter(GeneratorContext ctx, ServiceDescriptorProto obj, ref object state) { }
+
+        /// <summary>
+        /// Emit code representing a service method
+        /// </summary>
+        protected virtual void WriteServiceMethod(GeneratorContext ctx, MethodDescriptorProto inner, ref object state) { }
+        /// <summary>
+        /// Emit code following preceeding a set of service methods
+        /// </summary>
+        protected virtual void WriteServiceHeader(GeneratorContext ctx, ServiceDescriptorProto obj, ref object state) { }
+        /// <summary>
+        /// Check whether a particular message should be suppressed - for example because it represents a map
+        /// </summary>
+        protected virtual bool ShouldOmitMessage(GeneratorContext ctx, DescriptorProto obj, ref object state)
+            => obj.Options?.MapEntry ?? false; // don't write this type - use a dictionary instead
+
+        /// <summary>
+        /// Emit code representing a message type
+        /// </summary>
+        protected virtual void WriteMessage(GeneratorContext ctx, DescriptorProto obj)
+        {
+            object state = null;
+            if (ShouldOmitMessage(ctx, obj, ref state)) return;
+
+            WriteMessageHeader(ctx, obj, ref state);
+            var oneOfs = OneOfStub.Build(ctx, obj);
+            foreach (var inner in obj.Fields)
+            {
+                WriteField(ctx, inner, ref state, oneOfs);
+            }
+            foreach (var inner in obj.NestedTypes)
+            {
+                WriteMessage(ctx, inner);
+            }
+            foreach (var inner in obj.EnumTypes)
+            {
+                WriteEnum(ctx, inner);
+            }
+            if (obj.Extensions.Count != 0)
+            {
+                object extState = null;
+                WriteExtensionsHeader(ctx, obj, ref extState);
+                foreach (var ext in obj.Extensions)
+                {
+                    WriteExtension(ctx, ext);
+                }
+                WriteExtensionsFooter(ctx, obj, ref extState);
+            }
+            WriteMessageFooter(ctx, obj, ref state);
+        }
+        /// <summary>
+        /// Emit code representing a message field
+        /// </summary>
+        protected abstract void WriteField(GeneratorContext ctx, FieldDescriptorProto obj, ref object state, OneOfStub[] oneOfs);
+        /// <summary>
+        /// Emit code following a set of message fields
+        /// </summary>
+        protected abstract void WriteMessageFooter(GeneratorContext ctx, DescriptorProto obj, ref object state);
+        /// <summary>
+        /// Emit code preceeding a set of message fields
+        /// </summary>
+        protected abstract void WriteMessageHeader(GeneratorContext ctx, DescriptorProto obj, ref object state);
+        /// <summary>
+        /// Emit code representing an enum type
+        /// </summary>
+        protected virtual void WriteEnum(GeneratorContext ctx, EnumDescriptorProto obj)
+        {
+            object state = null;
+            WriteEnumHeader(ctx, obj, ref state);
+            foreach (var inner in obj.Values)
+            {
+                WriteEnumValue(ctx, inner, ref state);
+            }
+            WriteEnumFooter(ctx, obj, ref state);
+        }
+
+        /// <summary>
+        /// Emit code preceeding a set of enum values
+        /// </summary>
+        protected abstract void WriteEnumHeader(GeneratorContext ctx, EnumDescriptorProto obj, ref object state);
+        /// <summary>
+        /// Emit code representing an enum value
+        /// </summary>
+        protected abstract void WriteEnumValue(GeneratorContext ctx, EnumValueDescriptorProto obj, ref object state);
+        /// <summary>
+        /// Emit code following a set of enum values
+        /// </summary>
+        protected abstract void WriteEnumFooter(GeneratorContext ctx, EnumDescriptorProto obj, ref object state);
+        /// <summary>
+        /// Emit code at the start of a file
+        /// </summary>
+        protected virtual void WriteFileHeader(GeneratorContext ctx, FileDescriptorProto obj, ref object state) { }
+        /// <summary>
+        /// Emit code at the end of a file
+        /// </summary>
+        protected virtual void WriteFileFooter(GeneratorContext ctx, FileDescriptorProto obj, ref object state) { }
+
+        /// <summary>
+        /// Represents the state of a code-generation invocation
+        /// </summary>
+        protected class GeneratorContext
+        {
+            /// <summary>
+            /// The file being processed
+            /// </summary>
+            public FileDescriptorProto File { get; }
+            /// <summary>
+            /// The token to use for indentation
+            /// </summary>
+            public string IndentToken { get; }
+            /// <summary>
+            /// The current indent level
+            /// </summary>
+            public int IndentLevel { get; private set; }
+            /// <summary>
+            /// The mechanism to use for name normalization
+            /// </summary>
+            public NameNormalizer NameNormalizer { get; }
+            /// <summary>
+            /// The output for this code generation
+            /// </summary>
+            public TextWriter Output { get; }
+            /// <summary>
+            /// The effective syntax of this code-generation cycle, defaulting to "proto2" if not explicity specified
+            /// </summary>
+            public string Syntax => string.IsNullOrWhiteSpace(File.Syntax) ? FileDescriptorProto.SyntaxProto2 : File.Syntax;
+            /// <summary>
+            /// Create a new GeneratorContext instance
+            /// </summary>
+            internal GeneratorContext(FileDescriptorProto file, NameNormalizer nameNormalizer, TextWriter output, string indentToken)
+            {
+                File = file;
+                NameNormalizer = nameNormalizer;
+                Output = output;
+                IndentToken = indentToken;
+            }
+
+            /// <summary>
+            /// Ends the current line
+            /// </summary>
+            public GeneratorContext WriteLine()
+            {
+                Output.WriteLine();
+                return this;
+            }
+            /// <summary>
+            /// Appends a value and ends the current line
+            /// </summary>
+            public GeneratorContext WriteLine(string line)
+            {
+                var indentLevel = IndentLevel;
+                var target = Output;
+                while (indentLevel-- > 0)
+                {
+                    target.Write(IndentToken);
+                }
+                target.WriteLine(line);
+                return this;
+            }
+            /// <summary>
+            /// Appends a value to the current line
+            /// </summary>
+            public TextWriter Write(string value)
+            {
+                var indentLevel = IndentLevel;
+                var target = Output;
+                while (indentLevel-- > 0)
+                {
+                    target.Write(IndentToken);
+                }
+                target.Write(value);
+                return target;
+            }
+            /// <summary>
+            /// Increases the indentation level
+            /// </summary>
+            public GeneratorContext Indent()
+            {
+                IndentLevel++;
+                return this;
+            }
+            /// <summary>
+            /// Decreases the indentation level
+            /// </summary>
+            public GeneratorContext Outdent()
+            {
+                IndentLevel--;
+                return this;
+            }
+
+            /// <summary>
+            /// Try to find a descriptor of the type specified by T with the given full name
+            /// </summary>
+            public T TryFind<T>(string typeName) where T : class
+            {
+                object obj;
+                if (!_knownTypes.TryGetValue(typeName, out obj) || obj == null)
+                {
+                    return null;
+                }
+                return obj as T;
+            }
+
+            private Dictionary<string, object> _knownTypes = new Dictionary<string, object>();
+			void AddMessage(DescriptorProto message)
+			{
+				_knownTypes[message.FullyQualifiedName] = message;
+				foreach (var @enum in message.EnumTypes)
+				{
+					_knownTypes[@enum.FullyQualifiedName] = @enum;
+				}
+				foreach (var msg in message.NestedTypes)
+				{
+					AddMessage(msg);
+				}
+			}
+            internal void BuildTypeIndex()
+            {
+                {
+                    var processedFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
+                    var pendingFiles = new Queue<FileDescriptorProto>();
+
+                    _knownTypes.Clear();
+                    processedFiles.Add(File.Name);
+                    pendingFiles.Enqueue(File);
+
+                    while (pendingFiles.Count != 0)
+                    {
+                        var file = pendingFiles.Dequeue();
+
+                        foreach (var @enum in file.EnumTypes)
+                        {
+                            _knownTypes[@enum.FullyQualifiedName] = @enum;
+                        }
+                        foreach (var msg in file.MessageTypes)
+                        {
+                            AddMessage(msg);
+                        }
+
+                        if (file.HasImports())
+                        {
+                            foreach (var import in file.GetImports())
+                            {
+                                if (processedFiles.Add(import.Path))
+                                {
+                                    var importFile = file.Parent.GetFile(import.Path);
+                                    if (importFile != null) pendingFiles.Enqueue(importFile);
+                                }
+                            }
+                        }
+
+                    }
+                }
+            }
+        }
+    }
+
+
+}

+ 12 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/CodeGenerator.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: c84b4838bf8353749b0aef2f3445a446
+timeCreated: 1517401477
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 141 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/CustomOptions.cs

@@ -0,0 +1,141 @@
+// This file was generated by a tool; you should avoid making direct changes.
+// Consider using 'partial classes' to extend these types
+// Input: protogen.proto
+
+#pragma warning disable CS1591, CS0612, CS3021
+
+namespace ProtoBuf.Reflection
+{
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class ProtogenFileOptions
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"namespace")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Namespace { get; set; } = "";
+
+        [global::ProtoBuf.ProtoMember(2, Name = @"access")]
+        public Access Access { get; set; }
+
+        [global::ProtoBuf.ProtoMember(3, Name = @"extensions")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string ExtensionTypeName { get; set; } = "";
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class ProtogenMessageOptions
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"name")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Name { get; set; } = "";
+
+        [global::ProtoBuf.ProtoMember(2, Name = @"access")]
+        public Access Access { get; set; }
+
+        [global::ProtoBuf.ProtoMember(3, Name = @"extensions")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string ExtensionTypeName { get; set; } = "";
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class ProtogenFieldOptions
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"name")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Name { get; set; } = "";
+
+        [global::ProtoBuf.ProtoMember(2, Name = @"access")]
+        public Access Access { get; set; }
+
+        [global::ProtoBuf.ProtoMember(3, Name = @"asRef")]
+        public bool AsReference { get; set; }
+
+        [global::ProtoBuf.ProtoMember(4, Name = @"dynamicType")]
+        public bool DynamicType { get; set; }
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class ProtogenEnumOptions
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"name")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Name { get; set; } = "";
+
+        [global::ProtoBuf.ProtoMember(2, Name = @"access")]
+        public Access Access { get; set; }
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class ProtogenEnumValueOptions
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"name")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Name { get; set; } = "";
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class ProtogenServiceOptions
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"name")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Name { get; set; } = "";
+
+        [global::ProtoBuf.ProtoMember(2, Name = @"access")]
+        public Access Access { get; set; }
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class ProtogenMethodOptions
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"name")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Name { get; set; } = "";
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public enum Access
+    {
+        [global::ProtoBuf.ProtoEnum(Name = @"INHERIT")]
+        Inherit = 0,
+        [global::ProtoBuf.ProtoEnum(Name = @"PUBLIC")]
+        Public = 1,
+        [global::ProtoBuf.ProtoEnum(Name = @"PRIVATE")]
+        Private = 2,
+        [global::ProtoBuf.ProtoEnum(Name = @"INTERNAL")]
+        Internal = 3,
+    }
+
+    public static class Extensions
+    {
+        public static ProtogenFileOptions GetOptions(this global::Google.Protobuf.Reflection.FileOptions obj)
+        => obj == null ? default(ProtogenFileOptions) : global::ProtoBuf.Extensible.GetValue<ProtogenFileOptions>(obj, 1037);
+
+        public static ProtogenMessageOptions GetOptions(this global::Google.Protobuf.Reflection.MessageOptions obj)
+        => obj == null ? default(ProtogenMessageOptions) : global::ProtoBuf.Extensible.GetValue<ProtogenMessageOptions>(obj, 1037);
+
+        public static ProtogenFieldOptions GetOptions(this global::Google.Protobuf.Reflection.FieldOptions obj)
+        => obj == null ? default(ProtogenFieldOptions) : global::ProtoBuf.Extensible.GetValue<ProtogenFieldOptions>(obj, 1037);
+
+        public static ProtogenEnumOptions GetOptions(this global::Google.Protobuf.Reflection.EnumOptions obj)
+        => obj == null ? default(ProtogenEnumOptions) : global::ProtoBuf.Extensible.GetValue<ProtogenEnumOptions>(obj, 1037);
+
+        public static ProtogenEnumValueOptions GetOptions(this global::Google.Protobuf.Reflection.EnumValueOptions obj)
+        => obj == null ? default(ProtogenEnumValueOptions) : global::ProtoBuf.Extensible.GetValue<ProtogenEnumValueOptions>(obj, 1037);
+
+        public static ProtogenServiceOptions GetOptions(this global::Google.Protobuf.Reflection.ServiceOptions obj)
+        => obj == null ? default(ProtogenServiceOptions) : global::ProtoBuf.Extensible.GetValue<ProtogenServiceOptions>(obj, 1037);
+
+        public static ProtogenMethodOptions GetOptions(this global::Google.Protobuf.Reflection.MethodOptions obj)
+        => obj == null ? default(ProtogenMethodOptions) : global::ProtoBuf.Extensible.GetValue<ProtogenMethodOptions>(obj, 1037);
+
+    }
+}
+
+#pragma warning restore CS1591, CS0612, CS3021

+ 12 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/CustomOptions.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 8ce0ba0763ec97548aa101c6bfddad8b
+timeCreated: 1517401477
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 1149 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/Descriptor.cs

@@ -0,0 +1,1149 @@
+// This file was generated by a tool; you should avoid making direct changes.
+// Consider using 'partial classes' to extend these types
+// Input: descriptor.proto
+
+#pragma warning disable CS1591, CS0612, CS3021
+
+namespace Google.Protobuf.Reflection
+{
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class FileDescriptorSet
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"file")]
+        public global::System.Collections.Generic.List<FileDescriptorProto> Files { get; } = new global::System.Collections.Generic.List<FileDescriptorProto>();
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class FileDescriptorProto
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"name")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Name
+        {
+            get { return __pbn__Name ?? ""; }
+            set { __pbn__Name = value; }
+        }
+        public bool ShouldSerializeName() => __pbn__Name != null;
+        public void ResetName() => __pbn__Name = null;
+        private string __pbn__Name;
+
+        [global::ProtoBuf.ProtoMember(2, Name = @"package")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Package
+        {
+            get { return __pbn__Package ?? ""; }
+            set { __pbn__Package = value; }
+        }
+        public bool ShouldSerializePackage() => __pbn__Package != null;
+        public void ResetPackage() => __pbn__Package = null;
+        private string __pbn__Package;
+
+        [global::ProtoBuf.ProtoMember(3, Name = @"dependency")]
+        public global::System.Collections.Generic.List<string> Dependencies { get; } = new global::System.Collections.Generic.List<string>();
+
+        [global::ProtoBuf.ProtoMember(10, Name = @"public_dependency")]
+        public int[] PublicDependencies { get; set; }
+
+        [global::ProtoBuf.ProtoMember(11, Name = @"weak_dependency")]
+        public int[] WeakDependencies { get; set; }
+
+        [global::ProtoBuf.ProtoMember(4, Name = @"message_type")]
+        public global::System.Collections.Generic.List<DescriptorProto> MessageTypes { get; } = new global::System.Collections.Generic.List<DescriptorProto>();
+
+        [global::ProtoBuf.ProtoMember(5, Name = @"enum_type")]
+        public global::System.Collections.Generic.List<EnumDescriptorProto> EnumTypes { get; } = new global::System.Collections.Generic.List<EnumDescriptorProto>();
+
+        [global::ProtoBuf.ProtoMember(6, Name = @"service")]
+        public global::System.Collections.Generic.List<ServiceDescriptorProto> Services { get; } = new global::System.Collections.Generic.List<ServiceDescriptorProto>();
+
+        [global::ProtoBuf.ProtoMember(7, Name = @"extension")]
+        public global::System.Collections.Generic.List<FieldDescriptorProto> Extensions { get; } = new global::System.Collections.Generic.List<FieldDescriptorProto>();
+
+        [global::ProtoBuf.ProtoMember(8, Name = @"options")]
+        public FileOptions Options { get; set; }
+
+        [global::ProtoBuf.ProtoMember(9, Name = @"source_code_info")]
+        public SourceCodeInfo SourceCodeInfo { get; set; }
+
+        [global::ProtoBuf.ProtoMember(12, Name = @"syntax")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Syntax
+        {
+            get { return __pbn__Syntax ?? ""; }
+            set { __pbn__Syntax = value; }
+        }
+        public bool ShouldSerializeSyntax() => __pbn__Syntax != null;
+        public void ResetSyntax() => __pbn__Syntax = null;
+        private string __pbn__Syntax;
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class DescriptorProto
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"name")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Name
+        {
+            get { return __pbn__Name ?? ""; }
+            set { __pbn__Name = value; }
+        }
+        public bool ShouldSerializeName() => __pbn__Name != null;
+        public void ResetName() => __pbn__Name = null;
+        private string __pbn__Name;
+
+        [global::ProtoBuf.ProtoMember(2, Name = @"field")]
+        public global::System.Collections.Generic.List<FieldDescriptorProto> Fields { get; } = new global::System.Collections.Generic.List<FieldDescriptorProto>();
+
+        [global::ProtoBuf.ProtoMember(6, Name = @"extension")]
+        public global::System.Collections.Generic.List<FieldDescriptorProto> Extensions { get; } = new global::System.Collections.Generic.List<FieldDescriptorProto>();
+
+        [global::ProtoBuf.ProtoMember(3, Name = @"nested_type")]
+        public global::System.Collections.Generic.List<DescriptorProto> NestedTypes { get; } = new global::System.Collections.Generic.List<DescriptorProto>();
+
+        [global::ProtoBuf.ProtoMember(4, Name = @"enum_type")]
+        public global::System.Collections.Generic.List<EnumDescriptorProto> EnumTypes { get; } = new global::System.Collections.Generic.List<EnumDescriptorProto>();
+
+        [global::ProtoBuf.ProtoMember(5, Name = @"extension_range")]
+        public global::System.Collections.Generic.List<ExtensionRange> ExtensionRanges { get; } = new global::System.Collections.Generic.List<ExtensionRange>();
+
+        [global::ProtoBuf.ProtoMember(8, Name = @"oneof_decl")]
+        public global::System.Collections.Generic.List<OneofDescriptorProto> OneofDecls { get; } = new global::System.Collections.Generic.List<OneofDescriptorProto>();
+
+        [global::ProtoBuf.ProtoMember(7, Name = @"options")]
+        public MessageOptions Options { get; set; }
+
+        [global::ProtoBuf.ProtoMember(9, Name = @"reserved_range")]
+        public global::System.Collections.Generic.List<ReservedRange> ReservedRanges { get; } = new global::System.Collections.Generic.List<ReservedRange>();
+
+        [global::ProtoBuf.ProtoMember(10, Name = @"reserved_name")]
+        public global::System.Collections.Generic.List<string> ReservedNames { get; } = new global::System.Collections.Generic.List<string>();
+
+        [global::ProtoBuf.ProtoContract()]
+        public partial class ExtensionRange
+        {
+            [global::ProtoBuf.ProtoMember(1, Name = @"start")]
+            public int Start
+            {
+                get { return __pbn__Start.GetValueOrDefault(); }
+                set { __pbn__Start = value; }
+            }
+            public bool ShouldSerializeStart() => __pbn__Start != null;
+            public void ResetStart() => __pbn__Start = null;
+            private int? __pbn__Start;
+
+            [global::ProtoBuf.ProtoMember(2, Name = @"end")]
+            public int End
+            {
+                get { return __pbn__End.GetValueOrDefault(); }
+                set { __pbn__End = value; }
+            }
+            public bool ShouldSerializeEnd() => __pbn__End != null;
+            public void ResetEnd() => __pbn__End = null;
+            private int? __pbn__End;
+
+        }
+
+        [global::ProtoBuf.ProtoContract()]
+        public partial class ReservedRange
+        {
+            [global::ProtoBuf.ProtoMember(1, Name = @"start")]
+            public int Start
+            {
+                get { return __pbn__Start.GetValueOrDefault(); }
+                set { __pbn__Start = value; }
+            }
+            public bool ShouldSerializeStart() => __pbn__Start != null;
+            public void ResetStart() => __pbn__Start = null;
+            private int? __pbn__Start;
+
+            [global::ProtoBuf.ProtoMember(2, Name = @"end")]
+            public int End
+            {
+                get { return __pbn__End.GetValueOrDefault(); }
+                set { __pbn__End = value; }
+            }
+            public bool ShouldSerializeEnd() => __pbn__End != null;
+            public void ResetEnd() => __pbn__End = null;
+            private int? __pbn__End;
+
+        }
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class FieldDescriptorProto
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"name")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Name
+        {
+            get { return __pbn__Name ?? ""; }
+            set { __pbn__Name = value; }
+        }
+        public bool ShouldSerializeName() => __pbn__Name != null;
+        public void ResetName() => __pbn__Name = null;
+        private string __pbn__Name;
+
+        [global::ProtoBuf.ProtoMember(3, Name = @"number")]
+        public int Number
+        {
+            get { return __pbn__Number.GetValueOrDefault(); }
+            set { __pbn__Number = value; }
+        }
+        public bool ShouldSerializeNumber() => __pbn__Number != null;
+        public void ResetNumber() => __pbn__Number = null;
+        private int? __pbn__Number;
+
+        [global::ProtoBuf.ProtoMember(4)]
+        public Label label
+        {
+            get { return __pbn__label.GetValueOrDefault(); }
+            set { __pbn__label = value; }
+        }
+        public bool ShouldSerializelabel() => __pbn__label != null;
+        public void Resetlabel() => __pbn__label = null;
+        private Label? __pbn__label;
+
+        [global::ProtoBuf.ProtoMember(5)]
+        public Type type
+        {
+            get { return __pbn__type.GetValueOrDefault(); }
+            set { __pbn__type = value; }
+        }
+        public bool ShouldSerializetype() => __pbn__type != null;
+        public void Resettype() => __pbn__type = null;
+        private Type? __pbn__type;
+
+        [global::ProtoBuf.ProtoMember(6, Name = @"type_name")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string TypeName
+        {
+            get { return __pbn__TypeName ?? ""; }
+            set { __pbn__TypeName = value; }
+        }
+        public bool ShouldSerializeTypeName() => __pbn__TypeName != null;
+        public void ResetTypeName() => __pbn__TypeName = null;
+        private string __pbn__TypeName;
+
+        [global::ProtoBuf.ProtoMember(2, Name = @"extendee")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Extendee
+        {
+            get { return __pbn__Extendee ?? ""; }
+            set { __pbn__Extendee = value; }
+        }
+        public bool ShouldSerializeExtendee() => __pbn__Extendee != null;
+        public void ResetExtendee() => __pbn__Extendee = null;
+        private string __pbn__Extendee;
+
+        [global::ProtoBuf.ProtoMember(7, Name = @"default_value")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string DefaultValue
+        {
+            get { return __pbn__DefaultValue ?? ""; }
+            set { __pbn__DefaultValue = value; }
+        }
+        public bool ShouldSerializeDefaultValue() => __pbn__DefaultValue != null;
+        public void ResetDefaultValue() => __pbn__DefaultValue = null;
+        private string __pbn__DefaultValue;
+
+        [global::ProtoBuf.ProtoMember(9, Name = @"oneof_index")]
+        public int OneofIndex
+        {
+            get { return __pbn__OneofIndex.GetValueOrDefault(); }
+            set { __pbn__OneofIndex = value; }
+        }
+        public bool ShouldSerializeOneofIndex() => __pbn__OneofIndex != null;
+        public void ResetOneofIndex() => __pbn__OneofIndex = null;
+        private int? __pbn__OneofIndex;
+
+        [global::ProtoBuf.ProtoMember(10, Name = @"json_name")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string JsonName
+        {
+            get { return __pbn__JsonName ?? ""; }
+            set { __pbn__JsonName = value; }
+        }
+        public bool ShouldSerializeJsonName() => __pbn__JsonName != null;
+        public void ResetJsonName() => __pbn__JsonName = null;
+        private string __pbn__JsonName;
+
+        [global::ProtoBuf.ProtoMember(8, Name = @"options")]
+        public FieldOptions Options { get; set; }
+
+        [global::ProtoBuf.ProtoContract()]
+        public enum Type
+        {
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_DOUBLE")]
+            TypeDouble = 1,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_FLOAT")]
+            TypeFloat = 2,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_INT64")]
+            TypeInt64 = 3,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_UINT64")]
+            TypeUint64 = 4,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_INT32")]
+            TypeInt32 = 5,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_FIXED64")]
+            TypeFixed64 = 6,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_FIXED32")]
+            TypeFixed32 = 7,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_BOOL")]
+            TypeBool = 8,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_STRING")]
+            TypeString = 9,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_GROUP")]
+            TypeGroup = 10,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_MESSAGE")]
+            TypeMessage = 11,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_BYTES")]
+            TypeBytes = 12,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_UINT32")]
+            TypeUint32 = 13,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_ENUM")]
+            TypeEnum = 14,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_SFIXED32")]
+            TypeSfixed32 = 15,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_SFIXED64")]
+            TypeSfixed64 = 16,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_SINT32")]
+            TypeSint32 = 17,
+            [global::ProtoBuf.ProtoEnum(Name = @"TYPE_SINT64")]
+            TypeSint64 = 18,
+        }
+
+        [global::ProtoBuf.ProtoContract()]
+        public enum Label
+        {
+            [global::ProtoBuf.ProtoEnum(Name = @"LABEL_OPTIONAL")]
+            LabelOptional = 1,
+            [global::ProtoBuf.ProtoEnum(Name = @"LABEL_REQUIRED")]
+            LabelRequired = 2,
+            [global::ProtoBuf.ProtoEnum(Name = @"LABEL_REPEATED")]
+            LabelRepeated = 3,
+        }
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class OneofDescriptorProto
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"name")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Name
+        {
+            get { return __pbn__Name ?? ""; }
+            set { __pbn__Name = value; }
+        }
+        public bool ShouldSerializeName() => __pbn__Name != null;
+        public void ResetName() => __pbn__Name = null;
+        private string __pbn__Name;
+
+        [global::ProtoBuf.ProtoMember(2, Name = @"options")]
+        public OneofOptions Options { get; set; }
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class EnumDescriptorProto
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"name")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Name
+        {
+            get { return __pbn__Name ?? ""; }
+            set { __pbn__Name = value; }
+        }
+        public bool ShouldSerializeName() => __pbn__Name != null;
+        public void ResetName() => __pbn__Name = null;
+        private string __pbn__Name;
+
+        [global::ProtoBuf.ProtoMember(2, Name = @"value")]
+        public global::System.Collections.Generic.List<EnumValueDescriptorProto> Values { get; } = new global::System.Collections.Generic.List<EnumValueDescriptorProto>();
+
+        [global::ProtoBuf.ProtoMember(3, Name = @"options")]
+        public EnumOptions Options { get; set; }
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class EnumValueDescriptorProto
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"name")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Name
+        {
+            get { return __pbn__Name ?? ""; }
+            set { __pbn__Name = value; }
+        }
+        public bool ShouldSerializeName() => __pbn__Name != null;
+        public void ResetName() => __pbn__Name = null;
+        private string __pbn__Name;
+
+        [global::ProtoBuf.ProtoMember(2, Name = @"number")]
+        public int Number
+        {
+            get { return __pbn__Number.GetValueOrDefault(); }
+            set { __pbn__Number = value; }
+        }
+        public bool ShouldSerializeNumber() => __pbn__Number != null;
+        public void ResetNumber() => __pbn__Number = null;
+        private int? __pbn__Number;
+
+        [global::ProtoBuf.ProtoMember(3, Name = @"options")]
+        public EnumValueOptions Options { get; set; }
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class ServiceDescriptorProto
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"name")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Name
+        {
+            get { return __pbn__Name ?? ""; }
+            set { __pbn__Name = value; }
+        }
+        public bool ShouldSerializeName() => __pbn__Name != null;
+        public void ResetName() => __pbn__Name = null;
+        private string __pbn__Name;
+
+        [global::ProtoBuf.ProtoMember(2, Name = @"method")]
+        public global::System.Collections.Generic.List<MethodDescriptorProto> Methods { get; } = new global::System.Collections.Generic.List<MethodDescriptorProto>();
+
+        [global::ProtoBuf.ProtoMember(3, Name = @"options")]
+        public ServiceOptions Options { get; set; }
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class MethodDescriptorProto
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"name")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string Name
+        {
+            get { return __pbn__Name ?? ""; }
+            set { __pbn__Name = value; }
+        }
+        public bool ShouldSerializeName() => __pbn__Name != null;
+        public void ResetName() => __pbn__Name = null;
+        private string __pbn__Name;
+
+        [global::ProtoBuf.ProtoMember(2, Name = @"input_type")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string InputType
+        {
+            get { return __pbn__InputType ?? ""; }
+            set { __pbn__InputType = value; }
+        }
+        public bool ShouldSerializeInputType() => __pbn__InputType != null;
+        public void ResetInputType() => __pbn__InputType = null;
+        private string __pbn__InputType;
+
+        [global::ProtoBuf.ProtoMember(3, Name = @"output_type")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string OutputType
+        {
+            get { return __pbn__OutputType ?? ""; }
+            set { __pbn__OutputType = value; }
+        }
+        public bool ShouldSerializeOutputType() => __pbn__OutputType != null;
+        public void ResetOutputType() => __pbn__OutputType = null;
+        private string __pbn__OutputType;
+
+        [global::ProtoBuf.ProtoMember(4, Name = @"options")]
+        public MethodOptions Options { get; set; }
+
+        [global::ProtoBuf.ProtoMember(5, Name = @"client_streaming")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool ClientStreaming
+        {
+            get { return __pbn__ClientStreaming ?? false; }
+            set { __pbn__ClientStreaming = value; }
+        }
+        public bool ShouldSerializeClientStreaming() => __pbn__ClientStreaming != null;
+        public void ResetClientStreaming() => __pbn__ClientStreaming = null;
+        private bool? __pbn__ClientStreaming;
+
+        [global::ProtoBuf.ProtoMember(6, Name = @"server_streaming")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool ServerStreaming
+        {
+            get { return __pbn__ServerStreaming ?? false; }
+            set { __pbn__ServerStreaming = value; }
+        }
+        public bool ShouldSerializeServerStreaming() => __pbn__ServerStreaming != null;
+        public void ResetServerStreaming() => __pbn__ServerStreaming = null;
+        private bool? __pbn__ServerStreaming;
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class FileOptions : global::ProtoBuf.IExtensible
+    {
+        private global::ProtoBuf.IExtension __pbn__extensionData;
+        global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
+            => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing);
+
+        [global::ProtoBuf.ProtoMember(1, Name = @"java_package")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string JavaPackage
+        {
+            get { return __pbn__JavaPackage ?? ""; }
+            set { __pbn__JavaPackage = value; }
+        }
+        public bool ShouldSerializeJavaPackage() => __pbn__JavaPackage != null;
+        public void ResetJavaPackage() => __pbn__JavaPackage = null;
+        private string __pbn__JavaPackage;
+
+        [global::ProtoBuf.ProtoMember(8, Name = @"java_outer_classname")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string JavaOuterClassname
+        {
+            get { return __pbn__JavaOuterClassname ?? ""; }
+            set { __pbn__JavaOuterClassname = value; }
+        }
+        public bool ShouldSerializeJavaOuterClassname() => __pbn__JavaOuterClassname != null;
+        public void ResetJavaOuterClassname() => __pbn__JavaOuterClassname = null;
+        private string __pbn__JavaOuterClassname;
+
+        [global::ProtoBuf.ProtoMember(10, Name = @"java_multiple_files")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool JavaMultipleFiles
+        {
+            get { return __pbn__JavaMultipleFiles ?? false; }
+            set { __pbn__JavaMultipleFiles = value; }
+        }
+        public bool ShouldSerializeJavaMultipleFiles() => __pbn__JavaMultipleFiles != null;
+        public void ResetJavaMultipleFiles() => __pbn__JavaMultipleFiles = null;
+        private bool? __pbn__JavaMultipleFiles;
+
+        [global::ProtoBuf.ProtoMember(20, Name = @"java_generate_equals_and_hash")]
+        [global::System.Obsolete]
+        public bool JavaGenerateEqualsAndHash
+        {
+            get { return __pbn__JavaGenerateEqualsAndHash.GetValueOrDefault(); }
+            set { __pbn__JavaGenerateEqualsAndHash = value; }
+        }
+        public bool ShouldSerializeJavaGenerateEqualsAndHash() => __pbn__JavaGenerateEqualsAndHash != null;
+        public void ResetJavaGenerateEqualsAndHash() => __pbn__JavaGenerateEqualsAndHash = null;
+        private bool? __pbn__JavaGenerateEqualsAndHash;
+
+        [global::ProtoBuf.ProtoMember(27, Name = @"java_string_check_utf8")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool JavaStringCheckUtf8
+        {
+            get { return __pbn__JavaStringCheckUtf8 ?? false; }
+            set { __pbn__JavaStringCheckUtf8 = value; }
+        }
+        public bool ShouldSerializeJavaStringCheckUtf8() => __pbn__JavaStringCheckUtf8 != null;
+        public void ResetJavaStringCheckUtf8() => __pbn__JavaStringCheckUtf8 = null;
+        private bool? __pbn__JavaStringCheckUtf8;
+
+        [global::ProtoBuf.ProtoMember(9, Name = @"optimize_for")]
+        [global::System.ComponentModel.DefaultValue(OptimizeMode.Speed)]
+        public OptimizeMode OptimizeFor
+        {
+            get { return __pbn__OptimizeFor ?? OptimizeMode.Speed; }
+            set { __pbn__OptimizeFor = value; }
+        }
+        public bool ShouldSerializeOptimizeFor() => __pbn__OptimizeFor != null;
+        public void ResetOptimizeFor() => __pbn__OptimizeFor = null;
+        private OptimizeMode? __pbn__OptimizeFor;
+
+        [global::ProtoBuf.ProtoMember(11, Name = @"go_package")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string GoPackage
+        {
+            get { return __pbn__GoPackage ?? ""; }
+            set { __pbn__GoPackage = value; }
+        }
+        public bool ShouldSerializeGoPackage() => __pbn__GoPackage != null;
+        public void ResetGoPackage() => __pbn__GoPackage = null;
+        private string __pbn__GoPackage;
+
+        [global::ProtoBuf.ProtoMember(16, Name = @"cc_generic_services")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool CcGenericServices
+        {
+            get { return __pbn__CcGenericServices ?? false; }
+            set { __pbn__CcGenericServices = value; }
+        }
+        public bool ShouldSerializeCcGenericServices() => __pbn__CcGenericServices != null;
+        public void ResetCcGenericServices() => __pbn__CcGenericServices = null;
+        private bool? __pbn__CcGenericServices;
+
+        [global::ProtoBuf.ProtoMember(17, Name = @"java_generic_services")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool JavaGenericServices
+        {
+            get { return __pbn__JavaGenericServices ?? false; }
+            set { __pbn__JavaGenericServices = value; }
+        }
+        public bool ShouldSerializeJavaGenericServices() => __pbn__JavaGenericServices != null;
+        public void ResetJavaGenericServices() => __pbn__JavaGenericServices = null;
+        private bool? __pbn__JavaGenericServices;
+
+        [global::ProtoBuf.ProtoMember(18, Name = @"py_generic_services")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool PyGenericServices
+        {
+            get { return __pbn__PyGenericServices ?? false; }
+            set { __pbn__PyGenericServices = value; }
+        }
+        public bool ShouldSerializePyGenericServices() => __pbn__PyGenericServices != null;
+        public void ResetPyGenericServices() => __pbn__PyGenericServices = null;
+        private bool? __pbn__PyGenericServices;
+
+        [global::ProtoBuf.ProtoMember(23, Name = @"deprecated")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool Deprecated
+        {
+            get { return __pbn__Deprecated ?? false; }
+            set { __pbn__Deprecated = value; }
+        }
+        public bool ShouldSerializeDeprecated() => __pbn__Deprecated != null;
+        public void ResetDeprecated() => __pbn__Deprecated = null;
+        private bool? __pbn__Deprecated;
+
+        [global::ProtoBuf.ProtoMember(31, Name = @"cc_enable_arenas")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool CcEnableArenas
+        {
+            get { return __pbn__CcEnableArenas ?? false; }
+            set { __pbn__CcEnableArenas = value; }
+        }
+        public bool ShouldSerializeCcEnableArenas() => __pbn__CcEnableArenas != null;
+        public void ResetCcEnableArenas() => __pbn__CcEnableArenas = null;
+        private bool? __pbn__CcEnableArenas;
+
+        [global::ProtoBuf.ProtoMember(36, Name = @"objc_class_prefix")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string ObjcClassPrefix
+        {
+            get { return __pbn__ObjcClassPrefix ?? ""; }
+            set { __pbn__ObjcClassPrefix = value; }
+        }
+        public bool ShouldSerializeObjcClassPrefix() => __pbn__ObjcClassPrefix != null;
+        public void ResetObjcClassPrefix() => __pbn__ObjcClassPrefix = null;
+        private string __pbn__ObjcClassPrefix;
+
+        [global::ProtoBuf.ProtoMember(37, Name = @"csharp_namespace")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string CsharpNamespace
+        {
+            get { return __pbn__CsharpNamespace ?? ""; }
+            set { __pbn__CsharpNamespace = value; }
+        }
+        public bool ShouldSerializeCsharpNamespace() => __pbn__CsharpNamespace != null;
+        public void ResetCsharpNamespace() => __pbn__CsharpNamespace = null;
+        private string __pbn__CsharpNamespace;
+
+        [global::ProtoBuf.ProtoMember(39, Name = @"swift_prefix")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string SwiftPrefix
+        {
+            get { return __pbn__SwiftPrefix ?? ""; }
+            set { __pbn__SwiftPrefix = value; }
+        }
+        public bool ShouldSerializeSwiftPrefix() => __pbn__SwiftPrefix != null;
+        public void ResetSwiftPrefix() => __pbn__SwiftPrefix = null;
+        private string __pbn__SwiftPrefix;
+
+        [global::ProtoBuf.ProtoMember(40, Name = @"php_class_prefix")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string PhpClassPrefix
+        {
+            get { return __pbn__PhpClassPrefix ?? ""; }
+            set { __pbn__PhpClassPrefix = value; }
+        }
+        public bool ShouldSerializePhpClassPrefix() => __pbn__PhpClassPrefix != null;
+        public void ResetPhpClassPrefix() => __pbn__PhpClassPrefix = null;
+        private string __pbn__PhpClassPrefix;
+
+        [global::ProtoBuf.ProtoMember(999, Name = @"uninterpreted_option")]
+        public global::System.Collections.Generic.List<UninterpretedOption> UninterpretedOptions { get; } = new global::System.Collections.Generic.List<UninterpretedOption>();
+
+        [global::ProtoBuf.ProtoContract()]
+        public enum OptimizeMode
+        {
+            [global::ProtoBuf.ProtoEnum(Name = @"SPEED")]
+            Speed = 1,
+            [global::ProtoBuf.ProtoEnum(Name = @"CODE_SIZE")]
+            CodeSize = 2,
+            [global::ProtoBuf.ProtoEnum(Name = @"LITE_RUNTIME")]
+            LiteRuntime = 3,
+        }
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class MessageOptions : global::ProtoBuf.IExtensible
+    {
+        private global::ProtoBuf.IExtension __pbn__extensionData;
+        global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
+            => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing);
+
+        [global::ProtoBuf.ProtoMember(1, Name = @"message_set_wire_format")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool MessageSetWireFormat
+        {
+            get { return __pbn__MessageSetWireFormat ?? false; }
+            set { __pbn__MessageSetWireFormat = value; }
+        }
+        public bool ShouldSerializeMessageSetWireFormat() => __pbn__MessageSetWireFormat != null;
+        public void ResetMessageSetWireFormat() => __pbn__MessageSetWireFormat = null;
+        private bool? __pbn__MessageSetWireFormat;
+
+        [global::ProtoBuf.ProtoMember(2, Name = @"no_standard_descriptor_accessor")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool NoStandardDescriptorAccessor
+        {
+            get { return __pbn__NoStandardDescriptorAccessor ?? false; }
+            set { __pbn__NoStandardDescriptorAccessor = value; }
+        }
+        public bool ShouldSerializeNoStandardDescriptorAccessor() => __pbn__NoStandardDescriptorAccessor != null;
+        public void ResetNoStandardDescriptorAccessor() => __pbn__NoStandardDescriptorAccessor = null;
+        private bool? __pbn__NoStandardDescriptorAccessor;
+
+        [global::ProtoBuf.ProtoMember(3, Name = @"deprecated")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool Deprecated
+        {
+            get { return __pbn__Deprecated ?? false; }
+            set { __pbn__Deprecated = value; }
+        }
+        public bool ShouldSerializeDeprecated() => __pbn__Deprecated != null;
+        public void ResetDeprecated() => __pbn__Deprecated = null;
+        private bool? __pbn__Deprecated;
+
+        [global::ProtoBuf.ProtoMember(7, Name = @"map_entry")]
+        public bool MapEntry
+        {
+            get { return __pbn__MapEntry.GetValueOrDefault(); }
+            set { __pbn__MapEntry = value; }
+        }
+        public bool ShouldSerializeMapEntry() => __pbn__MapEntry != null;
+        public void ResetMapEntry() => __pbn__MapEntry = null;
+        private bool? __pbn__MapEntry;
+
+        [global::ProtoBuf.ProtoMember(999, Name = @"uninterpreted_option")]
+        public global::System.Collections.Generic.List<UninterpretedOption> UninterpretedOptions { get; } = new global::System.Collections.Generic.List<UninterpretedOption>();
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class FieldOptions : global::ProtoBuf.IExtensible
+    {
+        private global::ProtoBuf.IExtension __pbn__extensionData;
+        global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
+            => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing);
+
+        [global::ProtoBuf.ProtoMember(1, Name = @"ctype")]
+        [global::System.ComponentModel.DefaultValue(CType.String)]
+        public CType Ctype
+        {
+            get { return __pbn__Ctype ?? CType.String; }
+            set { __pbn__Ctype = value; }
+        }
+        public bool ShouldSerializeCtype() => __pbn__Ctype != null;
+        public void ResetCtype() => __pbn__Ctype = null;
+        private CType? __pbn__Ctype;
+
+        [global::ProtoBuf.ProtoMember(2, Name = @"packed")]
+        public bool Packed
+        {
+            get { return __pbn__Packed.GetValueOrDefault(); }
+            set { __pbn__Packed = value; }
+        }
+        public bool ShouldSerializePacked() => __pbn__Packed != null;
+        public void ResetPacked() => __pbn__Packed = null;
+        private bool? __pbn__Packed;
+
+        [global::ProtoBuf.ProtoMember(6, Name = @"jstype")]
+        [global::System.ComponentModel.DefaultValue(JSType.JsNormal)]
+        public JSType Jstype
+        {
+            get { return __pbn__Jstype ?? JSType.JsNormal; }
+            set { __pbn__Jstype = value; }
+        }
+        public bool ShouldSerializeJstype() => __pbn__Jstype != null;
+        public void ResetJstype() => __pbn__Jstype = null;
+        private JSType? __pbn__Jstype;
+
+        [global::ProtoBuf.ProtoMember(5, Name = @"lazy")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool Lazy
+        {
+            get { return __pbn__Lazy ?? false; }
+            set { __pbn__Lazy = value; }
+        }
+        public bool ShouldSerializeLazy() => __pbn__Lazy != null;
+        public void ResetLazy() => __pbn__Lazy = null;
+        private bool? __pbn__Lazy;
+
+        [global::ProtoBuf.ProtoMember(3, Name = @"deprecated")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool Deprecated
+        {
+            get { return __pbn__Deprecated ?? false; }
+            set { __pbn__Deprecated = value; }
+        }
+        public bool ShouldSerializeDeprecated() => __pbn__Deprecated != null;
+        public void ResetDeprecated() => __pbn__Deprecated = null;
+        private bool? __pbn__Deprecated;
+
+        [global::ProtoBuf.ProtoMember(10, Name = @"weak")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool Weak
+        {
+            get { return __pbn__Weak ?? false; }
+            set { __pbn__Weak = value; }
+        }
+        public bool ShouldSerializeWeak() => __pbn__Weak != null;
+        public void ResetWeak() => __pbn__Weak = null;
+        private bool? __pbn__Weak;
+
+        [global::ProtoBuf.ProtoMember(999, Name = @"uninterpreted_option")]
+        public global::System.Collections.Generic.List<UninterpretedOption> UninterpretedOptions { get; } = new global::System.Collections.Generic.List<UninterpretedOption>();
+
+        [global::ProtoBuf.ProtoContract()]
+        public enum CType
+        {
+            [global::ProtoBuf.ProtoEnum(Name = @"STRING")]
+            String = 0,
+            [global::ProtoBuf.ProtoEnum(Name = @"CORD")]
+            Cord = 1,
+            [global::ProtoBuf.ProtoEnum(Name = @"STRING_PIECE")]
+            StringPiece = 2,
+        }
+
+        [global::ProtoBuf.ProtoContract()]
+        public enum JSType
+        {
+            [global::ProtoBuf.ProtoEnum(Name = @"JS_NORMAL")]
+            JsNormal = 0,
+            [global::ProtoBuf.ProtoEnum(Name = @"JS_STRING")]
+            JsString = 1,
+            [global::ProtoBuf.ProtoEnum(Name = @"JS_NUMBER")]
+            JsNumber = 2,
+        }
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class OneofOptions : global::ProtoBuf.IExtensible
+    {
+        private global::ProtoBuf.IExtension __pbn__extensionData;
+        global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
+            => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing);
+
+        [global::ProtoBuf.ProtoMember(999, Name = @"uninterpreted_option")]
+        public global::System.Collections.Generic.List<UninterpretedOption> UninterpretedOptions { get; } = new global::System.Collections.Generic.List<UninterpretedOption>();
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class EnumOptions : global::ProtoBuf.IExtensible
+    {
+        private global::ProtoBuf.IExtension __pbn__extensionData;
+        global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
+            => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing);
+
+        [global::ProtoBuf.ProtoMember(2, Name = @"allow_alias")]
+        public bool AllowAlias
+        {
+            get { return __pbn__AllowAlias.GetValueOrDefault(); }
+            set { __pbn__AllowAlias = value; }
+        }
+        public bool ShouldSerializeAllowAlias() => __pbn__AllowAlias != null;
+        public void ResetAllowAlias() => __pbn__AllowAlias = null;
+        private bool? __pbn__AllowAlias;
+
+        [global::ProtoBuf.ProtoMember(3, Name = @"deprecated")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool Deprecated
+        {
+            get { return __pbn__Deprecated ?? false; }
+            set { __pbn__Deprecated = value; }
+        }
+        public bool ShouldSerializeDeprecated() => __pbn__Deprecated != null;
+        public void ResetDeprecated() => __pbn__Deprecated = null;
+        private bool? __pbn__Deprecated;
+
+        [global::ProtoBuf.ProtoMember(999, Name = @"uninterpreted_option")]
+        public global::System.Collections.Generic.List<UninterpretedOption> UninterpretedOptions { get; } = new global::System.Collections.Generic.List<UninterpretedOption>();
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class EnumValueOptions : global::ProtoBuf.IExtensible
+    {
+        private global::ProtoBuf.IExtension __pbn__extensionData;
+        global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
+            => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing);
+
+        [global::ProtoBuf.ProtoMember(1, Name = @"deprecated")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool Deprecated
+        {
+            get { return __pbn__Deprecated ?? false; }
+            set { __pbn__Deprecated = value; }
+        }
+        public bool ShouldSerializeDeprecated() => __pbn__Deprecated != null;
+        public void ResetDeprecated() => __pbn__Deprecated = null;
+        private bool? __pbn__Deprecated;
+
+        [global::ProtoBuf.ProtoMember(999, Name = @"uninterpreted_option")]
+        public global::System.Collections.Generic.List<UninterpretedOption> UninterpretedOptions { get; } = new global::System.Collections.Generic.List<UninterpretedOption>();
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class ServiceOptions : global::ProtoBuf.IExtensible
+    {
+        private global::ProtoBuf.IExtension __pbn__extensionData;
+        global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
+            => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing);
+
+        [global::ProtoBuf.ProtoMember(33, Name = @"deprecated")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool Deprecated
+        {
+            get { return __pbn__Deprecated ?? false; }
+            set { __pbn__Deprecated = value; }
+        }
+        public bool ShouldSerializeDeprecated() => __pbn__Deprecated != null;
+        public void ResetDeprecated() => __pbn__Deprecated = null;
+        private bool? __pbn__Deprecated;
+
+        [global::ProtoBuf.ProtoMember(999, Name = @"uninterpreted_option")]
+        public global::System.Collections.Generic.List<UninterpretedOption> UninterpretedOptions { get; } = new global::System.Collections.Generic.List<UninterpretedOption>();
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class MethodOptions : global::ProtoBuf.IExtensible
+    {
+        private global::ProtoBuf.IExtension __pbn__extensionData;
+        global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
+            => global::ProtoBuf.Extensible.GetExtensionObject(ref __pbn__extensionData, createIfMissing);
+
+        [global::ProtoBuf.ProtoMember(33, Name = @"deprecated")]
+        [global::System.ComponentModel.DefaultValue(false)]
+        public bool Deprecated
+        {
+            get { return __pbn__Deprecated ?? false; }
+            set { __pbn__Deprecated = value; }
+        }
+        public bool ShouldSerializeDeprecated() => __pbn__Deprecated != null;
+        public void ResetDeprecated() => __pbn__Deprecated = null;
+        private bool? __pbn__Deprecated;
+
+        [global::ProtoBuf.ProtoMember(34)]
+        [global::System.ComponentModel.DefaultValue(IdempotencyLevel.IdempotencyUnknown)]
+        public IdempotencyLevel idempotency_level
+        {
+            get { return __pbn__idempotency_level ?? IdempotencyLevel.IdempotencyUnknown; }
+            set { __pbn__idempotency_level = value; }
+        }
+        public bool ShouldSerializeidempotency_level() => __pbn__idempotency_level != null;
+        public void Resetidempotency_level() => __pbn__idempotency_level = null;
+        private IdempotencyLevel? __pbn__idempotency_level;
+
+        [global::ProtoBuf.ProtoMember(999, Name = @"uninterpreted_option")]
+        public global::System.Collections.Generic.List<UninterpretedOption> UninterpretedOptions { get; } = new global::System.Collections.Generic.List<UninterpretedOption>();
+
+        [global::ProtoBuf.ProtoContract()]
+        public enum IdempotencyLevel
+        {
+            [global::ProtoBuf.ProtoEnum(Name = @"IDEMPOTENCY_UNKNOWN")]
+            IdempotencyUnknown = 0,
+            [global::ProtoBuf.ProtoEnum(Name = @"NO_SIDE_EFFECTS")]
+            NoSideEffects = 1,
+            [global::ProtoBuf.ProtoEnum(Name = @"IDEMPOTENT")]
+            Idempotent = 2,
+        }
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class UninterpretedOption
+    {
+        [global::ProtoBuf.ProtoMember(2, Name = @"name")]
+        public global::System.Collections.Generic.List<NamePart> Names { get; } = new global::System.Collections.Generic.List<NamePart>();
+
+        [global::ProtoBuf.ProtoMember(3, Name = @"identifier_value")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string IdentifierValue
+        {
+            get { return __pbn__IdentifierValue ?? ""; }
+            set { __pbn__IdentifierValue = value; }
+        }
+        public bool ShouldSerializeIdentifierValue() => __pbn__IdentifierValue != null;
+        public void ResetIdentifierValue() => __pbn__IdentifierValue = null;
+        private string __pbn__IdentifierValue;
+
+        [global::ProtoBuf.ProtoMember(4, Name = @"positive_int_value")]
+        public ulong PositiveIntValue
+        {
+            get { return __pbn__PositiveIntValue.GetValueOrDefault(); }
+            set { __pbn__PositiveIntValue = value; }
+        }
+        public bool ShouldSerializePositiveIntValue() => __pbn__PositiveIntValue != null;
+        public void ResetPositiveIntValue() => __pbn__PositiveIntValue = null;
+        private ulong? __pbn__PositiveIntValue;
+
+        [global::ProtoBuf.ProtoMember(5, Name = @"negative_int_value")]
+        public long NegativeIntValue
+        {
+            get { return __pbn__NegativeIntValue.GetValueOrDefault(); }
+            set { __pbn__NegativeIntValue = value; }
+        }
+        public bool ShouldSerializeNegativeIntValue() => __pbn__NegativeIntValue != null;
+        public void ResetNegativeIntValue() => __pbn__NegativeIntValue = null;
+        private long? __pbn__NegativeIntValue;
+
+        [global::ProtoBuf.ProtoMember(6, Name = @"double_value")]
+        public double DoubleValue
+        {
+            get { return __pbn__DoubleValue.GetValueOrDefault(); }
+            set { __pbn__DoubleValue = value; }
+        }
+        public bool ShouldSerializeDoubleValue() => __pbn__DoubleValue != null;
+        public void ResetDoubleValue() => __pbn__DoubleValue = null;
+        private double? __pbn__DoubleValue;
+
+        [global::ProtoBuf.ProtoMember(7, Name = @"string_value")]
+        public byte[] StringValue
+        {
+            get { return __pbn__StringValue; }
+            set { __pbn__StringValue = value; }
+        }
+        public bool ShouldSerializeStringValue() => __pbn__StringValue != null;
+        public void ResetStringValue() => __pbn__StringValue = null;
+        private byte[] __pbn__StringValue;
+
+        [global::ProtoBuf.ProtoMember(8, Name = @"aggregate_value")]
+        [global::System.ComponentModel.DefaultValue("")]
+        public string AggregateValue
+        {
+            get { return __pbn__AggregateValue ?? ""; }
+            set { __pbn__AggregateValue = value; }
+        }
+        public bool ShouldSerializeAggregateValue() => __pbn__AggregateValue != null;
+        public void ResetAggregateValue() => __pbn__AggregateValue = null;
+        private string __pbn__AggregateValue;
+
+        [global::ProtoBuf.ProtoContract()]
+        public partial class NamePart
+        {
+            [global::ProtoBuf.ProtoMember(1, IsRequired = true)]
+            public string name_part { get; set; }
+
+            [global::ProtoBuf.ProtoMember(2, Name = @"is_extension", IsRequired = true)]
+            public bool IsExtension { get; set; }
+
+        }
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class SourceCodeInfo
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"location")]
+        public global::System.Collections.Generic.List<Location> Locations { get; } = new global::System.Collections.Generic.List<Location>();
+
+        [global::ProtoBuf.ProtoContract()]
+        public partial class Location
+        {
+            [global::ProtoBuf.ProtoMember(1, Name = @"path", IsPacked = true)]
+            public int[] Paths { get; set; }
+
+            [global::ProtoBuf.ProtoMember(2, Name = @"span", IsPacked = true)]
+            public int[] Spans { get; set; }
+
+            [global::ProtoBuf.ProtoMember(3, Name = @"leading_comments")]
+            [global::System.ComponentModel.DefaultValue("")]
+            public string LeadingComments
+            {
+                get { return __pbn__LeadingComments ?? ""; }
+                set { __pbn__LeadingComments = value; }
+            }
+            public bool ShouldSerializeLeadingComments() => __pbn__LeadingComments != null;
+            public void ResetLeadingComments() => __pbn__LeadingComments = null;
+            private string __pbn__LeadingComments;
+
+            [global::ProtoBuf.ProtoMember(4, Name = @"trailing_comments")]
+            [global::System.ComponentModel.DefaultValue("")]
+            public string TrailingComments
+            {
+                get { return __pbn__TrailingComments ?? ""; }
+                set { __pbn__TrailingComments = value; }
+            }
+            public bool ShouldSerializeTrailingComments() => __pbn__TrailingComments != null;
+            public void ResetTrailingComments() => __pbn__TrailingComments = null;
+            private string __pbn__TrailingComments;
+
+            [global::ProtoBuf.ProtoMember(6, Name = @"leading_detached_comments")]
+            public global::System.Collections.Generic.List<string> LeadingDetachedComments { get; } = new global::System.Collections.Generic.List<string>();
+
+        }
+
+    }
+
+    [global::ProtoBuf.ProtoContract()]
+    public partial class GeneratedCodeInfo
+    {
+        [global::ProtoBuf.ProtoMember(1, Name = @"annotation")]
+        public global::System.Collections.Generic.List<Annotation> Annotations { get; } = new global::System.Collections.Generic.List<Annotation>();
+
+        [global::ProtoBuf.ProtoContract()]
+        public partial class Annotation
+        {
+            [global::ProtoBuf.ProtoMember(1, Name = @"path", IsPacked = true)]
+            public int[] Paths { get; set; }
+
+            [global::ProtoBuf.ProtoMember(2, Name = @"source_file")]
+            [global::System.ComponentModel.DefaultValue("")]
+            public string SourceFile
+            {
+                get { return __pbn__SourceFile ?? ""; }
+                set { __pbn__SourceFile = value; }
+            }
+            public bool ShouldSerializeSourceFile() => __pbn__SourceFile != null;
+            public void ResetSourceFile() => __pbn__SourceFile = null;
+            private string __pbn__SourceFile;
+
+            [global::ProtoBuf.ProtoMember(3, Name = @"begin")]
+            public int Begin
+            {
+                get { return __pbn__Begin.GetValueOrDefault(); }
+                set { __pbn__Begin = value; }
+            }
+            public bool ShouldSerializeBegin() => __pbn__Begin != null;
+            public void ResetBegin() => __pbn__Begin = null;
+            private int? __pbn__Begin;
+
+            [global::ProtoBuf.ProtoMember(4, Name = @"end")]
+            public int End
+            {
+                get { return __pbn__End.GetValueOrDefault(); }
+                set { __pbn__End = value; }
+            }
+            public bool ShouldSerializeEnd() => __pbn__End != null;
+            public void ResetEnd() => __pbn__End = null;
+            private int? __pbn__End;
+
+        }
+
+    }
+
+}
+
+#pragma warning restore CS1591, CS0612, CS3021

+ 12 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/Descriptor.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 55155b31a4bfd564eb8257e320385434
+timeCreated: 1517401476
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 221 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/NameNormalizer.cs

@@ -0,0 +1,221 @@
+using Google.Protobuf.Reflection;
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+
+namespace ProtoBuf.Reflection
+{
+
+    internal class ParserException : Exception
+    {
+        public int ColumnNumber { get; }
+        public int LineNumber { get; }
+        public string File { get; }
+        public string Text { get; }
+        public string LineContents { get; }
+        public bool IsError { get; }
+        internal ParserException(Token token, string message, bool isError)
+            : base(message ?? "error")
+        {
+            ColumnNumber = token.ColumnNumber;
+            LineNumber = token.LineNumber;
+            File = token.File;
+            LineContents = token.LineContents;
+            Text = token.Value ?? "";
+            IsError = isError;
+        }
+    }
+    /// <summary>
+    /// Provides general purpose name suggestions
+    /// </summary>
+    public abstract class NameNormalizer
+    {
+        private class NullNormalizer : NameNormalizer
+        {
+            protected override string GetName(string identifier) => identifier;
+            /// <summary>
+            /// Suggest a name with idiomatic pluralization
+            /// </summary>
+            public override string Pluralize(string identifier) => identifier;
+        }
+        private class DefaultNormalizer : NameNormalizer
+        {
+            protected override string GetName(string identifier) => AutoCapitalize(identifier);
+            /// <summary>
+            /// Suggest a name with idiomatic pluralization
+            /// </summary>
+            public override string Pluralize(string identifier) => AutoPluralize(identifier);
+        }
+        /// <summary>
+        /// Suggest a name with idiomatic name capitalization
+        /// </summary>
+        protected static string AutoCapitalize(string identifier)
+        {
+            //if (string.IsNullOrEmpty(identifier)) return identifier;
+            //// if all upper-case, make proper-case
+            //if (Regex.IsMatch(identifier, @"^[_A-Z0-9]*$"))
+            //{
+            //    return Regex.Replace(identifier, @"(^|_)([A-Z0-9])([A-Z0-9]*)",
+            //        match => match.Groups[2].Value.ToUpperInvariant() + match.Groups[3].Value.ToLowerInvariant());
+            //}
+            //// if all lower-case, make proper case
+            //if (Regex.IsMatch(identifier, @"^[_a-z0-9]*$"))
+            //{
+            //    return Regex.Replace(identifier, @"(^|_)([a-z0-9])([a-z0-9]*)",
+            //        match => match.Groups[2].Value.ToUpperInvariant() + match.Groups[3].Value.ToLowerInvariant());
+            //}
+            //// just remove underscores - leave their chosen casing alone
+            //return identifier.Replace("_", "");
+            return identifier;
+        }
+        /// <summary>
+        /// Suggest a name with idiomatic pluralization
+        /// </summary>
+        protected static string AutoPluralize(string identifier)
+        {
+            // horribly Anglo-centric and only covers common cases; but: is swappable
+
+            //if (string.IsNullOrEmpty(identifier) || identifier.Length == 1) return identifier;
+
+            //if (identifier.EndsWith("ss") || identifier.EndsWith("o")) return identifier + "es";
+            //if (identifier.EndsWith("is") && identifier.Length > 2) return identifier.Substring(0, identifier.Length - 2) + "es";
+
+            //if (identifier.EndsWith("s")) return identifier; // misses some things (bus => buses), but: might already be pluralized
+
+            //if (identifier.EndsWith("y") && identifier.Length > 2)
+            //{   // identity => identities etc
+            //    switch (identifier[identifier.Length - 2])
+            //    {
+            //        case 'a':
+            //        case 'e':
+            //        case 'i':
+            //        case 'o':
+            //        case 'u':
+            //            break; // only for consonant prefix
+            //        default:
+            //            return identifier.Substring(0, identifier.Length - 1) + "ies";
+            //    }
+            //}
+            //return identifier + "s";
+            return identifier;
+        }
+        /// <summary>
+        /// Name normalizer with default protobuf-net behaviour, using .NET idioms
+        /// </summary>
+        public static NameNormalizer Default { get; } = new DefaultNormalizer();
+        /// <summary>
+        /// Name normalizer that passes through all identifiers without any changes
+        /// </summary>
+        public static NameNormalizer Null { get; } = new NullNormalizer();
+        /// <summary>
+        /// Suggest a normalized identifier
+        /// </summary>
+        protected abstract string GetName(string identifier);
+        /// <summary>
+        /// Suggest a name with idiomatic pluralization
+        /// </summary>
+        public abstract string Pluralize(string identifier);
+
+        /// <summary>
+        /// Suggest a normalized identifier
+        /// </summary>
+        public virtual string GetName(FileDescriptorProto definition)
+        {
+            var ns = definition?.Options?.GetOptions()?.Namespace;
+            if (!string.IsNullOrWhiteSpace(ns)) return ns;
+            ns = definition.Options?.CsharpNamespace;
+            if (string.IsNullOrWhiteSpace(ns)) ns = GetName(definition.Package);
+
+            return string.IsNullOrWhiteSpace(ns) ? null : ns;
+        }
+        /// <summary>
+        /// Suggest a normalized identifier
+        /// </summary>
+        public virtual string GetName(DescriptorProto definition)
+        {
+            var name = definition?.Options?.GetOptions()?.Name;
+            if (!string.IsNullOrWhiteSpace(name)) return name;
+            return GetName(definition.Parent as DescriptorProto, GetName(definition.Name), definition.Name, false);
+        }
+        /// <summary>
+        /// Suggest a normalized identifier
+        /// </summary>
+        public virtual string GetName(EnumDescriptorProto definition)
+        {
+            var name = definition?.Options?.GetOptions()?.Name;
+            if (!string.IsNullOrWhiteSpace(name)) return name;
+            return GetName(definition.Parent as DescriptorProto, GetName(definition.Name), definition.Name, false);
+        }
+        /// <summary>
+        /// Suggest a normalized identifier
+        /// </summary>
+        public virtual string GetName(EnumValueDescriptorProto definition)
+        {
+            var name = definition?.Options?.GetOptions()?.Name;
+            if (!string.IsNullOrWhiteSpace(name)) return name;
+            return AutoCapitalize(definition.Name);
+        }
+        /// <summary>
+        /// Suggest a normalized identifier
+        /// </summary>
+        public virtual string GetName(FieldDescriptorProto definition)
+        {
+            var name = definition?.Options?.GetOptions()?.Name;
+            if (!string.IsNullOrWhiteSpace(name)) return name;
+            var preferred = GetName(definition.Name);
+            if (definition.label == FieldDescriptorProto.Label.LabelRepeated)
+            {
+                preferred = Pluralize(preferred);
+            }
+            return GetName(definition.Parent as DescriptorProto, preferred, definition.Name, true);
+        }
+        /// <summary>
+        /// Obtain a set of all names defined for a message
+        /// </summary>
+        protected HashSet<string> BuildConflicts(DescriptorProto parent, bool includeDescendents)
+        {
+            var conflicts = new HashSet<string>();
+            if (parent != null)
+            {
+                conflicts.Add(GetName(parent));
+                if (includeDescendents)
+                {
+                    foreach (var type in parent.NestedTypes)
+                    {
+                        conflicts.Add(GetName(type));
+                    }
+                    foreach (var type in parent.EnumTypes)
+                    {
+                        conflicts.Add(GetName(type));
+                    }
+                }
+            }
+            return conflicts;
+        }
+        /// <summary>
+        /// Get the preferred name for an element
+        /// </summary>
+        protected virtual string GetName(DescriptorProto parent, string preferred, string fallback, bool includeDescendents)
+        {
+            var conflicts = BuildConflicts(parent, includeDescendents);
+
+            if (!conflicts.Contains(preferred)) return preferred;
+            if (!conflicts.Contains(fallback)) return fallback;
+
+            var attempt = preferred + "Value";
+            if (!conflicts.Contains(attempt)) return attempt;
+
+            attempt = fallback + "Value";
+            if (!conflicts.Contains(attempt)) return attempt;
+
+            int i = 1;
+            while (true)
+            {
+                attempt = preferred + i.ToString();
+                if (!conflicts.Contains(attempt)) return attempt;
+            }
+        }
+    }
+
+}

+ 12 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/NameNormalizer.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 0527d2da92d6e8d49addd37edd55e8de
+timeCreated: 1517401476
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 2841 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/Parsers.cs

@@ -0,0 +1,2841 @@
+using Google.Protobuf.Reflection;
+using ProtoBuf;
+using ProtoBuf.Reflection;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Google.Protobuf.Reflection
+{
+#pragma warning disable CS1591
+
+    interface IType
+    {
+        IType Parent { get; }
+        string FullyQualifiedName { get; }
+
+        IType Find(string name);
+    }
+    partial class FileDescriptorSet
+    {
+        internal const string Namespace = ".google.protobuf.";
+        public Func<string, bool> ImportValidator { get; set; }
+
+        internal List<string> importPaths = new List<string>();
+        public void AddImportPath(string path)
+        {
+            importPaths.Add(path);
+        }
+        public Error[] GetErrors() => Error.GetArray(Errors);
+        internal List<Error> Errors { get; } = new List<Error>();
+
+        public bool Add(string name, bool includeInOutput, TextReader source = null)
+        {
+            if (string.IsNullOrWhiteSpace(name))
+                throw new ArgumentNullException(nameof(name));
+            if (Path.IsPathRooted(name) || name.Contains(".."))
+                throw new ArgumentException("Paths should be relative to the import paths, not rooted", nameof(name));
+            FileDescriptorProto descriptor;
+            if (TryResolve(name, out descriptor))
+            {
+                if (includeInOutput) descriptor.IncludeInOutput = true;
+                return true; // already exists, that counts as success
+            }
+
+            using (var reader = source ?? Open(name))
+            {
+                if (reader == null) return false; // not found
+
+                descriptor = new FileDescriptorProto
+                {
+                    Name = name,
+                    IncludeInOutput = includeInOutput
+                };
+                Files.Add(descriptor);
+
+                descriptor.Parse(reader, Errors, name);
+                return true;
+            }
+        }
+
+        private TextReader Open(string name)
+        {
+            var found = FindFile(name);
+            if (found == null) return null;
+            return File.OpenText(found);
+        }
+        string FindFile(string file)
+        {
+            foreach (var path in importPaths)
+            {
+                var rel = Path.Combine(path, file);
+                if (File.Exists(rel)) return rel;
+            }
+            return null;
+        }
+
+        bool TryResolve(string name, out FileDescriptorProto descriptor)
+        {
+            descriptor = Files.FirstOrDefault(x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase));
+            return descriptor != null;
+        }
+
+        private void ApplyImports()
+        {
+            bool didSomething;
+            do
+            {
+                didSomething = false;
+                var file = Files.FirstOrDefault(x => x.HasPendingImports);
+                if (file != null)
+                {
+                    // note that GetImports clears the flag
+                    foreach (var import in file.GetImports(true))
+                    {
+                        if (!(ImportValidator?.Invoke(import.Path) ?? true))
+                        {
+                            Errors.Error(import.Token, $"import of {import.Path} is disallowed");
+                        }
+                        else if (Add(import.Path, false))
+                        {
+                            didSomething = true;
+                        }
+                        else
+                        {
+                            Errors.Error(import.Token, $"unable to find: '{import.Path}'");
+                        }
+                    }
+                }
+            } while (didSomething);
+        }
+
+        public void Process()
+        {
+            ApplyImports();
+            foreach (var file in Files)
+            {
+                using (var ctx = new ParserContext(file, null, Errors))
+                {
+                    file.BuildTypeHierarchy(this, ctx);
+                }
+            }
+            foreach (var file in Files)
+            {
+                using (var ctx = new ParserContext(file, null, Errors))
+                {
+                    file.ResolveTypes(ctx, false);
+                }
+            }
+            foreach (var file in Files)
+            {
+                using (var ctx = new ParserContext(file, null, Errors))
+                {
+                    file.ResolveTypes(ctx, true);
+                }
+            }
+        }
+
+        public T Serialize<T>(Func<FileDescriptorSet,object,T> customSerializer, bool includeImports, object state = null)
+        {
+            T result;
+            if (includeImports || Files.All(x => x.IncludeInOutput))
+            {
+                result = customSerializer(this, state);
+            }
+            else
+            {
+                var snapshort = Files.ToArray();
+                Files.RemoveAll(x => !x.IncludeInOutput);
+                result = customSerializer(this, state);
+                Files.Clear();
+                Files.AddRange(snapshort);
+            }
+            return result;
+        }
+
+        public void Serialize(Stream destination, bool includeImports)
+        {
+            Serialize((s,o) => { Serializer.Serialize((Stream)o, s); return true; }, includeImports, destination);
+        }
+
+        internal FileDescriptorProto GetFile(string path)
+            // try full match first, then name-only match
+            => Files.FirstOrDefault(x => string.Equals(x.Name, path, StringComparison.OrdinalIgnoreCase));
+    }
+    partial class DescriptorProto : ISchemaObject, IType, IMessage
+    {
+        public static byte[] GetExtensionData(IExtensible obj)
+        {
+            var ext = obj?.GetExtensionObject(false);
+            int len;
+            if (ext == null || (len = ext.GetLength()) == 0) return null;
+            var s = ext.BeginQuery();
+            try
+            {
+                if (s is MemoryStream) return ((MemoryStream)s).ToArray();
+
+                byte[] buffer = new byte[len];
+                int offset = 0, read;
+                while ((read = s.Read(buffer, offset, len)) > 0)
+                {
+                    offset += read;
+                    len -= read;
+                }
+                if (len != 0) throw new EndOfStreamException();
+                return buffer;
+            }
+            finally
+            {
+                ext.EndQuery(s);
+            }
+        }
+        public static void SetExtensionData(IExtensible obj, byte[] data)
+        {
+            if (obj == null || data == null || data.Length == 0) return;
+            var ext = obj.GetExtensionObject(true);
+            (ext as IExtensionResettable)?.Reset();
+            var s = ext.BeginAppend();
+            try
+            {
+                s.Write(data, 0, data.Length);
+                ext.EndAppend(s, true);
+            }
+            catch
+            {
+                ext.EndAppend(s, false);
+                throw;
+            }
+        }
+
+        public override string ToString() => Name;
+        internal IType Parent { get; set; }
+        IType IType.Parent => Parent;
+        string IType.FullyQualifiedName => FullyQualifiedName;
+        IType IType.Find(string name)
+        {
+            return (IType)NestedTypes.FirstOrDefault(x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase))
+                ?? (IType)EnumTypes.FirstOrDefault(x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase));
+        }
+        internal string FullyQualifiedName { get; set; }
+
+        List<DescriptorProto> IMessage.Types => NestedTypes;
+
+        internal int MaxField => (Options?.MessageSetWireFormat == true) ? int.MaxValue : FieldDescriptorProto.DefaultMaxField;
+        int IMessage.MaxField => MaxField;
+
+
+        internal static bool TryParse(ParserContext ctx, IHazNames parent, out DescriptorProto obj)
+        {
+            var name = ctx.Tokens.Consume(TokenType.AlphaNumeric);
+            ctx.CheckNames(parent, name, ctx.Tokens.Previous);
+            if (ctx.TryReadObject(out obj))
+            {
+                obj.Name = name;
+                return true;
+            }
+            return false;
+        }
+        void ISchemaObject.ReadOne(ParserContext ctx)
+        {
+            var tokens = ctx.Tokens;
+            if (tokens.ConsumeIf(TokenType.AlphaNumeric, "message"))
+            {
+                DescriptorProto obj;
+                if (DescriptorProto.TryParse(ctx, this, out obj))
+                {
+                    NestedTypes.Add(obj);
+                }
+            }
+            else if (tokens.ConsumeIf(TokenType.AlphaNumeric, "enum"))
+            {
+                EnumDescriptorProto obj;
+                if (EnumDescriptorProto.TryParse(ctx, this, out obj))
+                    EnumTypes.Add(obj);
+            }
+            else if (tokens.ConsumeIf(TokenType.AlphaNumeric, "option"))
+            {
+                Options = ctx.ParseOptionStatement(Options, this);
+            }
+            else if (tokens.ConsumeIf(TokenType.AlphaNumeric, "reserved"))
+            {
+                ParseReservedRanges(ctx);
+            }
+            else if (tokens.ConsumeIf(TokenType.AlphaNumeric, "extensions"))
+            {
+                ParseExtensionRange(ctx);
+            }
+            else if (tokens.ConsumeIf(TokenType.AlphaNumeric, "extend"))
+            {
+                FieldDescriptorProto.ParseExtensions(ctx, this);
+            }
+            else if (tokens.ConsumeIf(TokenType.AlphaNumeric, "oneof"))
+            {
+                OneofDescriptorProto.Parse(ctx, this);
+            }
+            else if (tokens.ConsumeIf(TokenType.AlphaNumeric, "map"))
+            {
+                ParseMap(ctx);
+            }
+            else
+            {
+                FieldDescriptorProto obj;
+                if (FieldDescriptorProto.TryParse(ctx, this, false, out obj))
+                    Fields.Add(obj);
+            }
+        }
+
+
+        private void ParseMap(ParserContext ctx)
+        {
+            ctx.AbortState = AbortState.Statement;
+            var tokens = ctx.Tokens;
+            tokens.Consume(TokenType.Symbol, "<");
+            var keyName = tokens.Consume(TokenType.AlphaNumeric);
+            var keyToken = tokens.Previous;
+            FieldDescriptorProto.Type keyType;
+            if (FieldDescriptorProto.TryIdentifyType(keyName, out keyType))
+            {
+                keyName = null;
+            }
+            switch (keyType)
+            {
+                case 0:
+                case FieldDescriptorProto.Type.TypeBytes:
+                case FieldDescriptorProto.Type.TypeMessage:
+                case FieldDescriptorProto.Type.TypeGroup:
+                case FieldDescriptorProto.Type.TypeFloat:
+                case FieldDescriptorProto.Type.TypeDouble:
+                    ctx.Errors.Error(tokens.Previous, "invalid map key type (only integral and string types are allowed)");
+                    break;
+            }
+            tokens.Consume(TokenType.Symbol, ",");
+            var valueName = tokens.Consume(TokenType.AlphaNumeric);
+            var valueToken = tokens.Previous;
+            FieldDescriptorProto.Type valueType;
+            if (FieldDescriptorProto.TryIdentifyType(valueName, out valueType))
+            {
+                valueName = null;
+            }
+            tokens.Consume(TokenType.Symbol, ">");
+
+            var name = tokens.Consume(TokenType.AlphaNumeric);
+            var nameToken = tokens.Previous;
+            ctx.CheckNames(this, name, nameToken);
+
+            tokens.Consume(TokenType.Symbol, "=");
+            int number = tokens.ConsumeInt32();
+
+            var jsonName = FieldDescriptorProto.GetJsonName(name);
+            var typeName = jsonName.Substring(0, 1).ToUpperInvariant() + jsonName.Substring(1) + "Entry";
+            ctx.CheckNames(this, typeName, nameToken);
+
+            var field = new FieldDescriptorProto
+            {
+                type = FieldDescriptorProto.Type.TypeMessage,
+                TypeName = typeName,
+                Name = name,
+                JsonName = jsonName,
+                Number = number,
+                label = FieldDescriptorProto.Label.LabelRepeated,
+                TypeToken = nameToken
+            };
+
+            if (tokens.ConsumeIf(TokenType.Symbol, "["))
+            {
+                field.Options = ctx.ParseOptionBlock(field.Options, field);
+            }
+            Fields.Add(field);
+
+            var msgType = new DescriptorProto
+            {
+                Name = typeName,
+                Fields =
+                {
+                    new FieldDescriptorProto
+                    {
+                        label = FieldDescriptorProto.Label.LabelOptional,
+                        Name = "key",
+                        JsonName = "key",
+                        Number = 1,
+                        type = keyType,
+                        TypeName = keyName,
+                        TypeToken = keyToken,
+                    },
+                    new FieldDescriptorProto
+                    {
+                        label = FieldDescriptorProto.Label.LabelOptional,
+                        Name = "value",
+                        JsonName = "value",
+                        Number = 2,
+                        type = valueType,
+                        TypeName = valueName,
+                        TypeToken = valueToken,
+                    }
+                }
+            };
+            if (msgType.Options == null) msgType.Options = new MessageOptions();
+            msgType.Options.MapEntry = true;
+            NestedTypes.Add(msgType);
+
+            ctx.AbortState = AbortState.None;
+        }
+
+        private void ParseExtensionRange(ParserContext ctx)
+        {
+            ctx.AbortState = AbortState.Statement;
+            var tokens = ctx.Tokens;
+            tokens.Previous.RequireProto2(ctx);
+
+            while (true)
+            {
+                int from = tokens.ConsumeInt32(MaxField), to = from;
+                if (tokens.Read().Is(TokenType.AlphaNumeric, "to"))
+                {
+                    tokens.Consume();
+                    to = tokens.ConsumeInt32(MaxField);
+                }
+                // the end is off by one
+                if (to != int.MaxValue) to++;
+                ExtensionRanges.Add(new ExtensionRange { Start = from, End = to });
+
+                if (tokens.ConsumeIf(TokenType.Symbol, ","))
+                {
+                    tokens.Consume();
+                }
+                else if (tokens.ConsumeIf(TokenType.Symbol, ";"))
+                {
+                    break;
+                }
+                else
+                {
+                    tokens.Read().Throw("unable to parse extension range");
+                }
+            }
+            ctx.AbortState = AbortState.None;
+        }
+
+
+
+        private void ParseReservedRanges(ParserContext ctx)
+        {
+            ctx.AbortState = AbortState.Statement;
+            var tokens = ctx.Tokens;
+            var token = tokens.Read(); // test the first one to determine what we're doing
+            switch (token.Type)
+            {
+                case TokenType.StringLiteral:
+                    while (true)
+                    {
+                        var name = tokens.Consume(TokenType.StringLiteral);
+                        var conflict = Fields.FirstOrDefault(x => x.Name == name);
+                        if (conflict != null)
+                        {
+                            ctx.Errors.Error(tokens.Previous, $"'{conflict.Name}' is already in use by field {conflict.Number}");
+                        }
+                        ReservedNames.Add(name);
+
+                        if (tokens.ConsumeIf(TokenType.Symbol, ","))
+                        {
+                        }
+                        else if (tokens.ConsumeIf(TokenType.Symbol, ";"))
+                        {
+                            break;
+                        }
+                        else
+                        {
+                            tokens.Read().Throw("unable to parse reserved range");
+                        }
+                    }
+                    break;
+                case TokenType.AlphaNumeric:
+                    while (true)
+                    {
+                        int from = tokens.ConsumeInt32(), to = from;
+                        if (tokens.Read().Is(TokenType.AlphaNumeric, "to"))
+                        {
+                            tokens.Consume();
+                            to = tokens.ConsumeInt32();
+                        }
+                        var conflict = Fields.FirstOrDefault(x => x.Number >= from && x.Number <= to);
+                        if (conflict != null)
+                        {
+                            ctx.Errors.Error(tokens.Previous, $"field {conflict.Number} is already in use by '{conflict.Name}'");
+                        }
+                        ReservedRanges.Add(new ReservedRange { Start = from, End = to + 1 });
+
+                        token = tokens.Read();
+                        if (token.Is(TokenType.Symbol, ","))
+                        {
+                            tokens.Consume();
+                        }
+                        else if (token.Is(TokenType.Symbol, ";"))
+                        {
+                            tokens.Consume();
+                            break;
+                        }
+                        else
+                        {
+                            token.Throw();
+                        }
+                    }
+                    break;
+                default:
+                    throw token.Throw();
+            }
+            ctx.AbortState = AbortState.None;
+        }
+
+        IEnumerable<string> IHazNames.GetNames()
+        {
+            foreach (var field in Fields) yield return field.Name;
+            foreach (var type in NestedTypes) yield return type.Name;
+            foreach (var type in EnumTypes) yield return type.Name;
+            foreach (var name in ReservedNames) yield return name;
+        }
+    }
+
+    partial class OneofDescriptorProto : ISchemaObject
+    {
+        internal DescriptorProto Parent { get; set; }
+        internal static void Parse(ParserContext ctx, DescriptorProto parent)
+        {
+            ctx.AbortState = AbortState.Object;
+            var oneOf = new OneofDescriptorProto
+            {
+                Name = ctx.Tokens.Consume(TokenType.AlphaNumeric)
+            };
+            parent.OneofDecls.Add(oneOf);
+            oneOf.Parent = parent;
+
+            if (ctx.TryReadObjectImpl(oneOf))
+            {
+                ctx.AbortState = AbortState.None;
+            }
+        }
+        void ISchemaObject.ReadOne(ParserContext ctx)
+        {
+            var tokens = ctx.Tokens;
+            if (tokens.ConsumeIf(TokenType.AlphaNumeric, "option"))
+            {
+                Options = ctx.ParseOptionStatement(Options, this);
+            }
+            else
+            {
+                FieldDescriptorProto field;
+                if (FieldDescriptorProto.TryParse(ctx, Parent, true, out field))
+                {
+                    field.OneofIndex = Parent.OneofDecls.Count() - 1;
+                    Parent.Fields.Add(field);
+                }
+            }
+        }
+    }
+    partial class OneofOptions : ISchemaOptions
+    {
+        string ISchemaOptions.Extendee => FileDescriptorSet.Namespace + nameof(OneofOptions);
+        public byte[] ExtensionData
+        {
+            get { return DescriptorProto.GetExtensionData(this); }
+            set { DescriptorProto.SetExtensionData(this, value); }
+        }
+        bool ISchemaOptions.Deprecated { get { return false; } set { } }
+        bool ISchemaOptions.ReadOne(ParserContext ctx, string key) => false;
+    }
+    partial class FileDescriptorProto : ISchemaObject, IMessage, IType
+    {
+        internal static FileDescriptorProto GetFile(IType type)
+        {
+            while (type != null)
+            {
+                if (type is FileDescriptorProto) return (FileDescriptorProto)type;
+                type = type.Parent;
+            }
+            return null;
+        }
+        int IMessage.MaxField => FieldDescriptorProto.DefaultMaxField;
+        List<FieldDescriptorProto> IMessage.Fields => null;
+        List<FieldDescriptorProto> IMessage.Extensions => Extensions;
+        List<DescriptorProto> IMessage.Types => MessageTypes;
+
+        public override string ToString() => Name;
+
+        string IType.FullyQualifiedName => null;
+        IType IType.Parent => null;
+        IType IType.Find(string name)
+        {
+            return (IType)MessageTypes.FirstOrDefault(x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase))
+                ?? (IType)EnumTypes.FirstOrDefault(x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase));
+        }
+        internal bool HasPendingImports { get; private set; }
+        internal FileDescriptorSet Parent { get; private set; }
+
+        internal bool IncludeInOutput { get; set; }
+
+        public bool HasImports() => _imports.Count != 0;
+        internal IEnumerable<Import> GetImports(bool resetPendingFlag = false)
+        {
+            if (resetPendingFlag)
+            {
+                HasPendingImports = false;
+            }
+            return _imports;
+        }
+        readonly List<Import> _imports = new List<Import>();
+        internal bool AddImport(string path, bool isPublic, Token token)
+        {
+            var existing = _imports.FirstOrDefault(x => string.Equals(x.Path, path, StringComparison.OrdinalIgnoreCase));
+            if (existing != null)
+            {
+                // we'll allow this to upgrade
+                if (isPublic) existing.IsPublic = true;
+                return false;
+            }
+            HasPendingImports = true;
+            _imports.Add(new Import { Path = path, IsPublic = isPublic, Token = token });
+            return true;
+        }
+
+        internal const string SyntaxProto2 = "proto2", SyntaxProto3 = "proto3";
+
+        void ISchemaObject.ReadOne(ParserContext ctx)
+        {
+            var tokens = ctx.Tokens;
+            Token token;
+            if (tokens.ConsumeIf(TokenType.AlphaNumeric, "message"))
+            {
+                DescriptorProto obj;
+                if (DescriptorProto.TryParse(ctx, this, out obj))
+                    MessageTypes.Add(obj);
+            }
+            else if (tokens.ConsumeIf(TokenType.AlphaNumeric, "enum"))
+            {
+                EnumDescriptorProto obj;
+                if (EnumDescriptorProto.TryParse(ctx, this, out obj))
+                    EnumTypes.Add(obj);
+            }
+            else if (tokens.ConsumeIf(TokenType.AlphaNumeric, "extend"))
+            {
+                FieldDescriptorProto.ParseExtensions(ctx, this);
+            }
+            else if (tokens.ConsumeIf(TokenType.AlphaNumeric, "service"))
+            {
+                ServiceDescriptorProto obj;
+                if (ServiceDescriptorProto.TryParse(ctx, out obj))
+                    Services.Add(obj);
+            }
+            else if (tokens.ConsumeIf(TokenType.AlphaNumeric, "import"))
+            {
+                ctx.AbortState = AbortState.Statement;
+                bool isPublic = tokens.ConsumeIf(TokenType.AlphaNumeric, "public");
+                string path = tokens.Consume(TokenType.StringLiteral);
+
+                if (!AddImport(path, isPublic, tokens.Previous))
+                {
+                    ctx.Errors.Warn(tokens.Previous, $"duplicate import: '{path}'");
+                }
+                tokens.Consume(TokenType.Symbol, ";");
+                ctx.AbortState = AbortState.None;
+
+
+            }
+            else if (tokens.ConsumeIf(TokenType.AlphaNumeric, "syntax"))
+            {
+                ctx.AbortState = AbortState.Statement;
+                if (MessageTypes.Any() || EnumTypes.Any() || Extensions.Any())
+                {
+                    ctx.Errors.Error(tokens.Previous, "syntax must be set before types are defined");
+                }
+                tokens.Consume(TokenType.Symbol, "=");
+                Syntax = tokens.Consume(TokenType.StringLiteral);
+                switch (Syntax)
+                {
+                    case SyntaxProto2:
+                    case SyntaxProto3:
+                        break;
+                    default:
+                        ctx.Errors.Error(tokens.Previous, $"unknown syntax '{Syntax}'");
+                        break;
+                }
+                tokens.Consume(TokenType.Symbol, ";");
+                ctx.AbortState = AbortState.None;
+            }
+            else if (tokens.ConsumeIf(TokenType.AlphaNumeric, "package"))
+            {
+                ctx.AbortState = AbortState.Statement;
+                Package = tokens.Consume(TokenType.AlphaNumeric);
+                ctx.AbortState = AbortState.None;
+            }
+            else if (tokens.ConsumeIf(TokenType.AlphaNumeric, "option"))
+            {
+                Options = ctx.ParseOptionStatement(Options, this);
+            }
+            else if (tokens.Peek(out token))
+            {
+                token.Throw();
+            } // else EOF
+        }
+
+        public void Parse(TextReader schema, List<Error> errors, string file)
+        {
+            Syntax = "";
+            using (var ctx = new ParserContext(this, new Peekable<Token>(schema.Tokenize(file).RemoveCommentsAndWhitespace()), errors))
+            {
+                var tokens = ctx.Tokens;
+                Token startOfFile;
+                tokens.Peek(out startOfFile); // want this for "stuff you didn't do" warnings
+
+                // read the file into the object
+                ctx.Fill(this);
+
+                // finish up
+                if (string.IsNullOrWhiteSpace(Syntax))
+                {
+                    ctx.Errors.Warn(startOfFile, "no syntax specified; it is strongly recommended to specify 'syntax=\"proto2\";' or 'syntax=\"proto3\";'");
+                }
+                if (Syntax == "" || Syntax == SyntaxProto2)
+                {
+                    Syntax = null; // for output compatibility; is blank even if set to proto2 explicitly
+                }
+            }
+        }
+
+
+        internal bool TryResolveEnum(string typeName, IType parent, out EnumDescriptorProto @enum, bool allowImports, bool treatAllAsPublic = false)
+        {
+            IType type;
+            if (TryResolveType(typeName, parent, out type, allowImports, true, treatAllAsPublic))
+            {
+                @enum = type as EnumDescriptorProto;
+                return @enum != null;
+            }
+            @enum = null;
+            return false;
+        }
+        internal bool TryResolveMessage(string typeName, IType parent, out DescriptorProto message, bool allowImports, bool treatAllAsPublic = false)
+        {
+            IType type;
+            if (TryResolveType(typeName, parent, out type, allowImports, true, treatAllAsPublic))
+            {
+                message = type as DescriptorProto;
+                return message != null;
+            }
+            message = null;
+            return false;
+        }
+        internal static bool TrySplit(string input, out string left, out string right)
+        {
+            var split = input.IndexOf('.');
+            if (split < 0)
+            {
+                left = right = null;
+                return false;
+            }
+            left = input.Substring(0, split).Trim();
+            right = input.Substring(split + 1).Trim();
+            return true;
+        }
+        internal static bool TrySplitLast(string input, out string left, out string right)
+        {
+            var split = input.LastIndexOf('.');
+            if (split < 0)
+            {
+                left = right = null;
+                return false;
+            }
+            left = input.Substring(0, split).Trim();
+            right = input.Substring(split + 1).Trim();
+            return true;
+        }
+		bool TryResolveFromFile(FileDescriptorProto file, string ee, string ion, out FieldDescriptorProto fld, bool withPackageName, bool ai)
+		{
+			fld = null;
+			if (file == null) return false;
+
+			if (withPackageName)
+			{
+				var pkg = file.Package;
+				if (string.IsNullOrWhiteSpace(pkg)) return false; // we're only looking *with* packages right now
+
+				if (!ion.StartsWith(pkg + ".")) return false; // wrong file
+
+				ion = ion.Substring(pkg.Length + 1); // and fully qualified (non-qualified is a second pass)
+			}
+
+			return file.TryResolveExtension(ee, ion, out fld, ai, false);
+		}
+        private bool TryResolveExtension(string extendee, string extension, out FieldDescriptorProto field, bool allowImports = true, bool checkOwnPackage = true)
+        {
+            bool isRooted = extension.StartsWith(".");
+            if (isRooted)
+            {
+                // rooted
+                extension = extension.Substring(1); // remove the root
+            }
+            string left;
+            string right;
+            if (TrySplitLast(extension, out left, out right))
+            {
+                IType type;
+                if (TryResolveType(left, null, out type, true, true))
+                {
+                    field = (type as DescriptorProto)?.Extensions?.FirstOrDefault(x => x.Extendee == extendee
+                        && x.Name == right);
+                    if (field != null) return true;
+                }
+            }
+            else
+            {
+                field = Extensions?.FirstOrDefault(x => x.Extendee == extendee && x.Name == extension);
+                if (field != null) return true;
+            }
+
+            if (checkOwnPackage)
+            {
+                if (TryResolveFromFile(this, extendee, extension, out field, true, false)) return true;
+                if (TryResolveFromFile(this, extendee, extension, out field, false, false)) return true;
+            }
+            if (allowImports)
+            {
+                foreach (var import in _imports)
+                {
+                    var file = Parent?.GetFile(import.Path);
+                    if (file != null)
+                    {
+                        if (TryResolveFromFile(file, extendee, extension, out field, true, import.IsPublic))
+                        {
+                            import.Used = true;
+                            return true;
+                        }
+                    }
+                }
+                foreach (var import in _imports)
+                {
+                    var file = Parent?.GetFile(import.Path);
+                    if (file != null)
+                    {
+                        if (TryResolveFromFile(file, extendee, extension, out field, false, import.IsPublic))
+                        {
+                            import.Used = true;
+                            return true;
+                        }
+                    }
+                }
+            }
+            field = null;
+            return false;
+        }
+		bool TryResolveFromFile(FileDescriptorProto file, string tn, bool ai, out IType tp, bool withPackageName, bool treatAllAsPublic)
+		{
+			tp = null;
+			if (file == null) return false;
+
+			if (withPackageName)
+			{
+				var pkg = file.Package;
+				if (string.IsNullOrWhiteSpace(pkg)) return false; // we're only looking *with* packages right now
+
+				if (!tn.StartsWith(pkg + ".")) return false; // wrong file
+
+				tn = tn.Substring(pkg.Length + 1); // and fully qualified (non-qualified is a second pass)
+			}
+
+			return file.TryResolveType(tn, file, out tp, ai, false, treatAllAsPublic);
+		}
+        internal bool TryResolveType(string typeName, IType parent, out IType type, bool allowImports, bool checkOwnPackage = true, bool treatAllAsPublic = false)
+        {
+            bool isRooted = typeName.StartsWith(".");
+            string left;
+            string right;
+            if (isRooted)
+            {
+                // rooted
+                typeName = typeName.Substring(1); // remove the root
+            }
+            else if (TrySplit(typeName, out left, out right))
+            {
+                while (parent != null)
+                {
+                    var next = parent?.Find(left);
+                    if (next != null && TryResolveType(right, next, out type, false, treatAllAsPublic)) return true;
+
+                    parent = parent.Parent;
+                }
+            }
+            else
+            {
+                // simple name
+                while (parent != null)
+                {
+                    type = parent.Find(typeName);
+                    if (type != null)
+                    {
+                        return true;
+                    }
+                    parent = parent.Parent;
+                }
+            }
+
+            if (checkOwnPackage && TryResolveFromFile(this, typeName, false, out type, true, treatAllAsPublic)) return true;
+            if (checkOwnPackage && TryResolveFromFile(this, typeName, false, out type, false, treatAllAsPublic)) return true;
+
+            // look at imports
+            // check for the name including the package prefix
+            foreach (var import in _imports)
+            {
+                if (allowImports || import.IsPublic || treatAllAsPublic)
+                {
+                    var file = Parent?.GetFile(import.Path);
+                    if (TryResolveFromFile(file, typeName, false, out type, true, treatAllAsPublic))
+                    {
+                        import.Used = true;
+                        return true;
+                    }
+                }
+            }
+
+            // now look without package prefix
+            foreach (var import in _imports)
+            {
+                if (allowImports || import.IsPublic || treatAllAsPublic)
+                {
+                    var file = Parent?.GetFile(import.Path);
+                    if (TryResolveFromFile(file, typeName, false, out type, false, treatAllAsPublic))
+                    {
+                        import.Used = true;
+                        return true;
+                    }
+                }
+            }
+
+            type = null;
+            return false;
+
+        }
+
+        static void SetParents(string prefix, EnumDescriptorProto parent)
+        {
+            parent.FullyQualifiedName = prefix + "." + parent.Name;
+            foreach (var val in parent.Values)
+            {
+                val.Parent = parent;
+            }
+        }
+        static void SetParents(string prefix, DescriptorProto parent)
+        {
+            var fqn = parent.FullyQualifiedName = prefix + "." + parent.Name;
+            foreach (var field in parent.Fields)
+            {
+                field.Parent = parent;
+            }
+            foreach (var @enum in parent.EnumTypes)
+            {
+                @enum.Parent = parent;
+                SetParents(fqn, @enum);
+            }
+            foreach (var child in parent.NestedTypes)
+            {
+                child.Parent = parent;
+                SetParents(fqn, child);
+            }
+            foreach (var ext in parent.Extensions)
+            {
+                ext.Parent = parent;
+            }
+        }
+        internal void BuildTypeHierarchy(FileDescriptorSet set, ParserContext ctx)
+        {
+            // build the tree starting at the root
+            Parent = set;
+            var prefix = string.IsNullOrWhiteSpace(Package) ? "" : ("." + Package);
+            foreach (var type in EnumTypes)
+            {
+                type.Parent = this;
+                SetParents(prefix, type);
+            }
+            foreach (var type in MessageTypes)
+            {
+                type.Parent = this;
+                SetParents(prefix, type);
+            }
+            foreach (var type in Extensions)
+            {
+                type.Parent = this;
+            }
+        }
+
+        static bool ShouldResolveType(FieldDescriptorProto.Type type)
+        {
+            switch (type)
+            {
+                case 0:
+                case FieldDescriptorProto.Type.TypeMessage:
+                case FieldDescriptorProto.Type.TypeEnum:
+                case FieldDescriptorProto.Type.TypeGroup:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+        private void ResolveTypes(ParserContext ctx, List<FieldDescriptorProto> fields, IType parent, bool options)
+        {
+            foreach (var field in fields)
+            {
+                if (options) ResolveOptions(ctx, field.Options);
+                else
+                {
+                    if (!string.IsNullOrEmpty(field.TypeName) && ShouldResolveType(field.type))
+                    {
+                        // TODO: use TryResolveType once rather than twice
+                        string fqn;
+                        DescriptorProto msg;
+                        EnumDescriptorProto @enum;
+                        if (TryResolveMessage(field.TypeName, parent, out msg, true))
+                        {
+                            if (field.type != FieldDescriptorProto.Type.TypeGroup)
+                            {
+                                field.type = FieldDescriptorProto.Type.TypeMessage;
+                            }
+                            fqn = msg?.FullyQualifiedName;
+                        }
+                        else if (TryResolveEnum(field.TypeName, parent, out @enum, true))
+                        {
+                            field.type = FieldDescriptorProto.Type.TypeEnum;
+                            if (!string.IsNullOrWhiteSpace(field.DefaultValue)
+                                & !@enum.Values.Any(x => x.Name == field.DefaultValue))
+                            {
+                                ctx.Errors.Error(field.TypeToken, $"enum {@enum.Name} does not contain value '{field.DefaultValue}'");
+                            }
+                            fqn = @enum?.FullyQualifiedName;
+                        }
+                        else
+                        {
+                            ctx.Errors.Add(field.TypeToken.TypeNotFound(field.TypeName));
+                            fqn = field.TypeName;
+                            field.type = FieldDescriptorProto.Type.TypeMessage; // just an assumption
+                        }
+                        field.TypeName = fqn;
+                    }
+
+                    if (!string.IsNullOrEmpty(field.Extendee))
+                    {
+                        string fqn;
+                        DescriptorProto msg;
+                        if (TryResolveMessage(field.Extendee, parent, out msg, true))
+                        {
+                            fqn = msg?.FullyQualifiedName;
+                        }
+                        else
+                        {
+                            ctx.Errors.Add(field.TypeToken.TypeNotFound(field.Extendee));
+                            fqn = field.Extendee;
+                        }
+                        field.Extendee = fqn;
+                    }
+
+                    if (field.Options?.Packed ?? false)
+                    {
+                        bool canPack = FieldDescriptorProto.CanPack(field.type);
+                        if (!canPack)
+                        {
+                            ctx.Errors.Error(field.TypeToken, $"field of type {field.type} cannot be packed");
+                            field.Options.Packed = false;
+                        }
+                    }
+                }
+            }
+        }
+
+        private void ResolveTypes(ParserContext ctx, ServiceDescriptorProto service, bool options)
+        {
+            if (options) ResolveOptions(ctx, service.Options);
+            foreach (var method in service.Methods)
+            {
+                if (options) ResolveOptions(ctx, method.Options);
+                else
+                {
+                    DescriptorProto msg;
+                    if (!TryResolveMessage(method.InputType, this, out msg, true))
+                    {
+                        ctx.Errors.Add(method.InputTypeToken.TypeNotFound(method.InputType));
+                    }
+                    method.InputType = msg?.FullyQualifiedName;
+                    if (!TryResolveMessage(method.OutputType, this, out msg, true))
+                    {
+                        ctx.Errors.Add(method.OutputTypeToken.TypeNotFound(method.OutputType));
+                    }
+                    method.OutputType = msg?.FullyQualifiedName;
+                }
+            }
+        }
+
+        private void ResolveTypes(ParserContext ctx, DescriptorProto type, bool options)
+        {
+            if (options)
+            {
+                ResolveOptions(ctx, type.Options);
+                foreach (var decl in type.OneofDecls)
+                    ResolveOptions(ctx, decl.Options);
+            }
+
+            ResolveTypes(ctx, type.Fields, type, options);
+            ResolveTypes(ctx, type.Extensions, type, options);
+            foreach (var nested in type.NestedTypes)
+            {
+                ResolveTypes(ctx, nested, options);
+            }
+            foreach (var nested in type.EnumTypes)
+            {
+                ResolveTypes(ctx, nested, options);
+            }
+        }
+
+
+        IEnumerable<string> IHazNames.GetNames()
+        {
+            foreach (var type in MessageTypes) yield return type.Name;
+            foreach (var type in EnumTypes) yield return type.Name;
+        }
+        internal void ResolveTypes(ParserContext ctx, bool options)
+        {
+            if (options) ResolveOptions(ctx, Options);
+            foreach (var type in MessageTypes)
+            {
+                ResolveTypes(ctx, type, options);
+            }
+            foreach (var type in EnumTypes)
+            {
+                ResolveTypes(ctx, type, options);
+            }
+            foreach (var service in Services)
+            {
+                ResolveTypes(ctx, service, options);
+            }
+            ResolveTypes(ctx, Extensions, this, options);
+
+            if (options) // can only process deps on the second pass, once options have been resolved
+            {
+                HashSet<string> publicDependencies = null;
+                foreach (var import in _imports)
+                {
+                    if (!Dependencies.Contains(import.Path))
+                        Dependencies.Add(import.Path);
+                    if (import.IsPublic)
+                    {
+                        (publicDependencies ?? (publicDependencies = new HashSet<string>())).Add(import.Path);
+                    }
+                    if (IncludeInOutput && !import.Used)
+                    {
+                        ctx.Errors.Warn(import.Token, $"import not used: '{import.Path}'");
+                    }
+                }
+                // note that Dependencies should stay in declaration order to be consistent with protoc
+                if (publicDependencies != null)
+                {
+                    var arr = publicDependencies.Select(path => Dependencies.IndexOf(path)).ToArray();
+                    Array.Sort(arr);
+                    PublicDependencies = arr;
+                }
+            }
+        }
+
+        private void ResolveTypes(ParserContext ctx, EnumDescriptorProto type, bool options)
+        {
+            if (options)
+            {
+                ResolveOptions(ctx, type.Options);
+                foreach (var val in type.Values)
+                {
+                    ResolveOptions(ctx, val.Options);
+                }
+            }
+        }
+
+        private void ResolveOptions(ParserContext ctx, ISchemaOptions options)
+        {
+            if (options == null || options.UninterpretedOptions.Count == 0) return;
+
+            var extension = ((IExtensible)options).GetExtensionObject(true);
+            var target = extension.BeginAppend();
+            try
+            {
+                using (var writer = new ProtoWriter(target, null, null))
+                {
+                    var hive = OptionHive.Build(options.UninterpretedOptions);
+
+                    // first pass is used to sort the fields so we write them in the right order
+                    AppendOptions(this, writer, ctx, options.Extendee, hive.Children, true, 0, false);
+                    // second pass applies the data
+                    AppendOptions(this, writer, ctx, options.Extendee, hive.Children, false, 0, false);
+                }
+                options.UninterpretedOptions.RemoveAll(x => x.Applied);
+            }
+            finally
+            {
+                extension.EndAppend(target, true);
+            }
+
+        }
+
+        class OptionHive
+        {
+            public OptionHive(string name, bool isExtension, Token token)
+            {
+                Name = name;
+                IsExtension = isExtension;
+                Token = token;
+            }
+            public override string ToString()
+            {
+                var sb = new StringBuilder();
+                Concat(sb);
+                return sb.ToString();
+            }
+            private void Concat(StringBuilder sb)
+            {
+                bool isFirst = true;
+                foreach (var value in Options)
+                {
+                    if (!isFirst) sb.Append(", ");
+                    isFirst = false;
+                    sb.Append(value);
+                }
+                foreach (var child in Children)
+                {
+                    if (!isFirst) sb.Append(", ");
+                    sb.Append(child.Name).Append("={");
+                    child.Concat(sb);
+                    sb.Append("}");
+                }
+            }
+            public bool IsExtension { get; }
+            public string Name { get; }
+            public Token Token { get; }
+            public List<UninterpretedOption> Options { get; } = new List<UninterpretedOption>();
+            public List<OptionHive> Children { get; } = new List<OptionHive>();
+            public FieldDescriptorProto Field { get; set; }
+
+            public static OptionHive Build(List<UninterpretedOption> options)
+            {
+                if (options == null || options.Count == 0) return null;
+
+                var root = new OptionHive(null, false, default(Token));
+                foreach (var option in options)
+                {
+                    var level = root;
+                    OptionHive nextLevel = null;
+                    foreach (var name in option.Names)
+                    {
+                        nextLevel = level.Children.FirstOrDefault(x => x.Name == name.name_part && x.IsExtension == name.IsExtension);
+                        if (nextLevel == null)
+                        {
+                            nextLevel = new OptionHive(name.name_part, name.IsExtension, name.Token);
+                            level.Children.Add(nextLevel);
+                        }
+                        level = nextLevel;
+                    }
+                    level.Options.Add(option);
+                }
+                return root;
+            }
+        }
+        private static void AppendOptions(FileDescriptorProto file, ProtoWriter writer, ParserContext ctx, string extendee, List<OptionHive> options, bool resolveOnly, int depth, bool messageSet)
+        {
+            foreach (var option in options)
+                AppendOption(file, writer, ctx, extendee, option, resolveOnly, depth, messageSet);
+
+            if (resolveOnly && depth != 0) // fun fact: proto writes root fields in *file* order, but sub-fields in *field* order
+            {
+                // ascending field order
+                options.Sort((x, y) => (x.Field?.Number ?? 0).CompareTo(y.Field?.Number ?? 0));
+            }
+        }
+        private static bool ShouldWrite(FieldDescriptorProto f, string v, string d){
+            return f.label != FieldDescriptorProto.Label.LabelOptional || v != (f.DefaultValue ?? d);
+        }
+        private static void AppendOption(FileDescriptorProto file, ProtoWriter writer, ParserContext ctx, string extendee, OptionHive option, bool resolveOnly, int depth, bool messageSet)
+        {
+            // resolve the field for this level
+            FieldDescriptorProto field = option.Field;
+            DescriptorProto msg;
+            if (field != null)
+            {
+                // already resolved
+            }
+            else if (option.IsExtension)
+            {
+                if (!file.TryResolveExtension(extendee, option.Name, out field)) field = null;
+            }
+            else if (file.TryResolveMessage(extendee, null, out msg, true))
+            {
+                field = msg.Fields.FirstOrDefault(x => x.Name == option.Name);
+            }
+            else
+            {
+                field = null;
+            }
+
+            if (field == null)
+            {
+                if (!resolveOnly)
+                {
+                    ctx.Errors.Error(option.Token, $"unable to resolve custom option '{option.Name}' for '{extendee}'");
+                }
+                return;
+            }
+            option.Field = field;
+
+            switch (field.type)
+            {
+                case FieldDescriptorProto.Type.TypeMessage:
+                case FieldDescriptorProto.Type.TypeGroup:
+                    var nextFile = GetFile(field.Parent as IType);
+                    DescriptorProto fieldType;
+                    var nextMessageSet = !resolveOnly && nextFile.TryResolveMessage(field.TypeName, null, out fieldType, true)
+                        && (fieldType.Options?.MessageSetWireFormat ?? false);
+
+                    if (option.Children.Count != 0)
+                    {
+                        if (resolveOnly)
+                        {
+                            AppendOptions(nextFile, writer, ctx, field.TypeName, option.Children, resolveOnly, depth + 1, nextMessageSet);
+                        }
+                        else if (messageSet)
+                        {
+                            ProtoWriter.WriteFieldHeader(1, WireType.StartGroup, writer);
+                            var grp = ProtoWriter.StartSubItem(null, writer);
+
+                            ProtoWriter.WriteFieldHeader(2, WireType.Variant, writer);
+                            ProtoWriter.WriteInt32(field.Number, writer);
+
+                            ProtoWriter.WriteFieldHeader(3, WireType.String, writer);
+                            var payload = ProtoWriter.StartSubItem(null, writer);
+
+                            AppendOptions(nextFile, writer, ctx, field.TypeName, option.Children, resolveOnly, depth + 1, nextMessageSet);
+
+                            ProtoWriter.EndSubItem(payload, writer);
+                            ProtoWriter.EndSubItem(grp, writer);
+                        }
+                        else
+                        {
+                            ProtoWriter.WriteFieldHeader(field.Number,
+                                field.type == FieldDescriptorProto.Type.TypeGroup ? WireType.StartGroup : WireType.String, writer);
+                            var tok = ProtoWriter.StartSubItem(null, writer);
+
+                            AppendOptions(nextFile, writer, ctx, field.TypeName, option.Children, resolveOnly, depth + 1, nextMessageSet);
+
+                            ProtoWriter.EndSubItem(tok, writer);
+                        }
+                    }
+                    if (resolveOnly) return; // nothing more to do
+
+                    if (option.Options.Count == 1 && !option.Options.Single().ShouldSerializeAggregateValue())
+                    {
+                        // need to write an empty object to match protoc
+                        if (messageSet)
+                        {
+                            ProtoWriter.WriteFieldHeader(1, WireType.StartGroup, writer);
+                            var grp = ProtoWriter.StartSubItem(null, writer);
+
+                            ProtoWriter.WriteFieldHeader(2, WireType.Variant, writer);
+                            ProtoWriter.WriteInt32(field.Number, writer);
+
+                            ProtoWriter.WriteFieldHeader(3, WireType.String, writer);
+                            var payload = ProtoWriter.StartSubItem(null, writer);
+                            ProtoWriter.EndSubItem(payload, writer);
+                            ProtoWriter.EndSubItem(grp, writer);
+                        }
+                        else
+                        {
+                            ProtoWriter.WriteFieldHeader(field.Number,
+                                   field.type == FieldDescriptorProto.Type.TypeGroup ? WireType.StartGroup : WireType.String, writer);
+                            var payload = ProtoWriter.StartSubItem(null, writer);
+                            ProtoWriter.EndSubItem(payload, writer);
+                        }
+                        option.Options.Single().Applied = true;
+                    }
+                    else
+                    {
+                        foreach (var values in option.Options)
+                        {
+                            ctx.Errors.Error(option.Token, $"unable to assign custom option '{option.Name}' for '{extendee}'");
+                        }
+                    }
+                    break;
+                default:
+                    if (resolveOnly) return; // nothing more to do
+
+                    foreach (var child in option.Children)
+                    {
+                        ctx.Errors.Error(option.Token, $"unable to assign custom option '{child.Name}' for '{extendee}'");
+                    }
+                    foreach (var value in option.Options)
+                    {
+                        int i32;
+                        switch (field.type)
+                        {
+                            case FieldDescriptorProto.Type.TypeFloat:
+                                float f32;
+                                if (!TokenExtensions.TryParseSingle(value.AggregateValue, out f32))
+                                {
+                                    ctx.Errors.Error(option.Token, $"invalid value for floating point '{field.TypeName}': '{option.Name}' = '{value.AggregateValue}'");
+                                    continue;
+                                }
+                                if (ShouldWrite(field, value.AggregateValue, "0"))
+                                {
+                                    ProtoWriter.WriteFieldHeader(field.Number, WireType.Fixed32, writer);
+                                    ProtoWriter.WriteSingle(f32, writer);
+                                }
+                                break;
+                            case FieldDescriptorProto.Type.TypeDouble:
+                                double f64;
+                                if (!TokenExtensions.TryParseDouble(value.AggregateValue, out f64))
+                                {
+                                    ctx.Errors.Error(option.Token, $"invalid value for floating point '{field.TypeName}': '{option.Name}' = '{value.AggregateValue}'");
+                                    continue;
+                                }
+                                if (ShouldWrite(field, value.AggregateValue, "0"))
+                                {
+                                    ProtoWriter.WriteFieldHeader(field.Number, WireType.Fixed64, writer);
+                                    ProtoWriter.WriteDouble(f64, writer);
+                                }
+                                break;
+                            case FieldDescriptorProto.Type.TypeBool:
+                                switch (value.AggregateValue)
+                                {
+                                    case "true":
+                                        i32 = 1;
+                                        break;
+                                    case "false":
+                                        i32 = 0;
+                                        break;
+                                    default:
+                                        ctx.Errors.Error(option.Token, $"invalid value for boolean '{field.TypeName}': '{option.Name}' = '{value.AggregateValue}'");
+                                        continue;
+                                }
+                                if (ShouldWrite(field, value.AggregateValue, "false"))
+                                {
+                                    ProtoWriter.WriteFieldHeader(field.Number, WireType.Variant, writer);
+                                    ProtoWriter.WriteInt32(i32, writer);
+                                }
+                                break;
+                            case FieldDescriptorProto.Type.TypeUint32:
+                            case FieldDescriptorProto.Type.TypeFixed32:
+                                {
+                                    uint ui32;
+                                    if (!TokenExtensions.TryParseUInt32(value.AggregateValue, out ui32))
+                                    {
+                                        ctx.Errors.Error(option.Token, $"invalid value for unsigned integer '{field.TypeName}': '{option.Name}' = '{value.AggregateValue}'");
+                                        continue;
+                                    }
+                                    if (ShouldWrite(field, value.AggregateValue, "0"))
+                                    {
+                                        switch (field.type)
+                                        {
+                                            case FieldDescriptorProto.Type.TypeUint32:
+                                                ProtoWriter.WriteFieldHeader(field.Number, WireType.Variant, writer);
+                                                break;
+                                            case FieldDescriptorProto.Type.TypeFixed32:
+                                                ProtoWriter.WriteFieldHeader(field.Number, WireType.Fixed32, writer);
+                                                break;
+                                        }
+                                        ProtoWriter.WriteUInt32(ui32, writer);
+                                    }
+                                }
+                                break;
+                            case FieldDescriptorProto.Type.TypeUint64:
+                            case FieldDescriptorProto.Type.TypeFixed64:
+                                {
+                                    ulong ui64;
+                                    if (!TokenExtensions.TryParseUInt64(value.AggregateValue, out ui64))
+                                    {
+                                        ctx.Errors.Error(option.Token, $"invalid value for unsigned integer '{field.TypeName}': '{option.Name}' = '{value.AggregateValue}'");
+                                        continue;
+                                    }
+                                    if (ShouldWrite(field, value.AggregateValue, "0"))
+                                    {
+                                        switch (field.type)
+                                        {
+                                            case FieldDescriptorProto.Type.TypeUint64:
+                                                ProtoWriter.WriteFieldHeader(field.Number, WireType.Variant, writer);
+                                                break;
+                                            case FieldDescriptorProto.Type.TypeFixed64:
+                                                ProtoWriter.WriteFieldHeader(field.Number, WireType.Fixed64, writer);
+                                                break;
+                                        }
+                                        ProtoWriter.WriteUInt64(ui64, writer);
+                                    }
+                                }
+                                break;
+                            case FieldDescriptorProto.Type.TypeInt32:
+                            case FieldDescriptorProto.Type.TypeSint32:
+                            case FieldDescriptorProto.Type.TypeSfixed32:
+                                if (!TokenExtensions.TryParseInt32(value.AggregateValue, out i32))
+                                {
+                                    ctx.Errors.Error(option.Token, $"invalid value for integer '{field.TypeName}': '{option.Name}' = '{value.AggregateValue}'");
+                                    continue;
+                                }
+                                if (ShouldWrite(field, value.AggregateValue, "0"))
+                                {
+                                    switch (field.type)
+                                    {
+                                        case FieldDescriptorProto.Type.TypeInt32:
+                                            ProtoWriter.WriteFieldHeader(field.Number, WireType.Variant, writer);
+                                            break;
+                                        case FieldDescriptorProto.Type.TypeSint32:
+                                            ProtoWriter.WriteFieldHeader(field.Number, WireType.SignedVariant, writer);
+                                            break;
+                                        case FieldDescriptorProto.Type.TypeSfixed32:
+                                            ProtoWriter.WriteFieldHeader(field.Number, WireType.Fixed32, writer);
+                                            break;
+                                    }
+                                    ProtoWriter.WriteInt32(i32, writer);
+                                }
+                                break;
+                            case FieldDescriptorProto.Type.TypeInt64:
+                            case FieldDescriptorProto.Type.TypeSint64:
+                            case FieldDescriptorProto.Type.TypeSfixed64:
+                                {
+                                    long i64;
+                                    if (!TokenExtensions.TryParseInt64(value.AggregateValue, out i64))
+                                    {
+                                        ctx.Errors.Error(option.Token, $"invalid value for integer '{field.TypeName}': '{option.Name}' = '{value.AggregateValue}'");
+                                        continue;
+                                    }
+                                    if (ShouldWrite(field, value.AggregateValue, "0"))
+                                    {
+                                        switch (field.type)
+                                        {
+                                            case FieldDescriptorProto.Type.TypeInt64:
+                                                ProtoWriter.WriteFieldHeader(field.Number, WireType.Variant, writer);
+                                                break;
+                                            case FieldDescriptorProto.Type.TypeSint64:
+                                                ProtoWriter.WriteFieldHeader(field.Number, WireType.SignedVariant, writer);
+                                                break;
+                                            case FieldDescriptorProto.Type.TypeSfixed64:
+                                                ProtoWriter.WriteFieldHeader(field.Number, WireType.Fixed64, writer);
+                                                break;
+                                        }
+                                        ProtoWriter.WriteInt64(i64, writer);
+                                    }
+                                }
+                                break;
+                            case FieldDescriptorProto.Type.TypeEnum:
+                                EnumDescriptorProto @enum;
+                                if (file.TryResolveEnum(field.TypeName, null, out @enum, true, true))
+                                {
+                                    var found = @enum.Values.FirstOrDefault(x => x.Name == value.AggregateValue);
+                                    if (found == null)
+                                    {
+                                        ctx.Errors.Error(option.Token, $"invalid value for enum '{field.TypeName}': '{option.Name}' = '{value.AggregateValue}'");
+                                        continue;
+                                    }
+                                    else
+                                    {
+                                        if (ShouldWrite(field, value.AggregateValue, @enum.Values.FirstOrDefault()?.Name))
+                                        {
+                                            ProtoWriter.WriteFieldHeader(field.Number, WireType.Variant, writer);
+                                            ProtoWriter.WriteInt32(found.Number, writer);
+                                        }
+                                    }
+                                }
+                                else
+                                {
+                                    ctx.Errors.Error(option.Token, $"unable to resolve enum '{field.TypeName}': '{option.Name}' = '{value.AggregateValue}'");
+                                    continue;
+                                }
+                                break;
+                            case FieldDescriptorProto.Type.TypeString:
+                            case FieldDescriptorProto.Type.TypeBytes:
+                                if (ShouldWrite(field, value.AggregateValue, ""))
+                                {
+                                    ProtoWriter.WriteFieldHeader(field.Number, WireType.String, writer);
+                                    if (value.AggregateValue == null || value.AggregateValue.IndexOf('\\') < 0)
+                                        ProtoWriter.WriteString(value.AggregateValue ?? "", writer);
+                                    else
+                                    {
+                                        using (var ms = new MemoryStream(value.AggregateValue.Length))
+                                        {
+                                            if (!LoadBytes(ms, value.AggregateValue))
+                                            {
+                                                ctx.Errors.Error(option.Token, $"invalid escape sequence '{field.TypeName}': '{option.Name}' = '{value.AggregateValue}'");
+                                                continue;
+                                            }
+#if NETSTANDARD1_3
+                                            if (ms.TryGetBuffer(out var seg))
+                                                ProtoWriter.WriteBytes(seg.Array, seg.Offset, seg.Count, writer);
+                                            else
+                                                ProtoWriter.WriteBytes(ms.ToArray(), writer);
+#else
+                                            ProtoWriter.WriteBytes(ms.GetBuffer(), 0, (int)ms.Length, writer);
+#endif
+                                        }
+                                    }
+                                }
+                                break;
+                            default:
+                                ctx.Errors.Error(option.Token, $"{field.type} options not yet implemented: '{option.Name}' = '{value.AggregateValue}'");
+                                continue;
+                        }
+                        value.Applied = true;
+                    }
+                    break;
+            }
+        }
+
+        private static unsafe bool LoadBytes(Stream ms, string value)
+        {
+            bool isEscaped = false;
+            byte* b = stackalloc byte[10];
+            foreach (char c in value)
+            {
+                if (isEscaped)
+                {
+                    isEscaped = false;
+                    // only a few things remain escaped after ConsumeString:
+                    switch (c)
+                    {
+                        case '\\': ms.WriteByte((byte)'\\'); break;
+                        case '\'': ms.WriteByte((byte)'\''); break;
+                        case '"': ms.WriteByte((byte)'"'); break;
+                        case 'r': ms.WriteByte((byte)'\r'); break;
+                        case 'n': ms.WriteByte((byte)'\n'); break;
+                        case 't': ms.WriteByte((byte)'\t'); break;
+                        default: return false;
+                    }
+                }
+                else if (c == '\\')
+                {
+                    isEscaped = true;
+                }
+                else
+                {
+                    var x = c; // can't take address of readonly local
+                    int bytes = Encoding.UTF8.GetBytes(&x, 1, b, 10);
+                    for (int i = 0; i < bytes; i++)
+                    {
+                        ms.WriteByte(b[i]);
+                    }
+                }
+            }
+            return !isEscaped;
+        }
+    }
+
+    partial class EnumDescriptorProto : ISchemaObject, IType
+    {
+        public override string ToString() => Name;
+        internal IType Parent { get; set; }
+        string IType.FullyQualifiedName => FullyQualifiedName;
+        IType IType.Parent => Parent;
+        IType IType.Find(string name) => null;
+        internal string FullyQualifiedName { get; set; }
+
+        internal static bool TryParse(ParserContext ctx, IHazNames parent, out EnumDescriptorProto obj)
+        {
+            var name = ctx.Tokens.Consume(TokenType.AlphaNumeric);
+            ctx.CheckNames(parent, name, ctx.Tokens.Previous);
+            if (ctx.TryReadObject(out obj))
+            {
+                obj.Name = name;
+                return true;
+            }
+            return false;
+        }
+
+        void ISchemaObject.ReadOne(ParserContext ctx)
+        {
+            ctx.AbortState = AbortState.Statement;
+            var tokens = ctx.Tokens;
+            if (tokens.ConsumeIf(TokenType.AlphaNumeric, "option"))
+            {
+                Options = ctx.ParseOptionStatement(Options, this);
+            }
+            else
+            {
+                Values.Add(EnumValueDescriptorProto.Parse(ctx));
+            }
+            ctx.AbortState = AbortState.None;
+        }
+
+    }
+    partial class FieldDescriptorProto : ISchemaObject
+    {
+
+        public bool IsPacked(string syntax)
+        {
+            if (label != Label.LabelRepeated) return false;
+
+            var exp = Options?.Packed;
+            if (exp.HasValue) return exp.GetValueOrDefault();
+
+            if (syntax != FileDescriptorProto.SyntaxProto2 && FieldDescriptorProto.CanPack(type))
+            {
+                return true;
+            }
+
+            return false;
+        }
+        public override string ToString() => Name;
+        internal const int DefaultMaxField = 536870911;
+        internal const int FirstReservedField = 19000;
+        internal const int LastReservedField = 19999;
+
+        internal IMessage Parent { get; set; }
+        internal Token TypeToken { get; set; }
+
+        internal int MaxField => Parent?.MaxField ?? DefaultMaxField;
+
+		internal static void NotAllowedOneOf(ParserContext ctx)
+		{
+			var token = ctx.Tokens.Previous;
+			ctx.Errors.Error(token, $"'{token.Value}' not allowed with 'oneof'");
+		}
+
+        internal static bool TryParse(ParserContext ctx, IMessage parent, bool isOneOf, out FieldDescriptorProto field)
+        {
+            var tokens = ctx.Tokens;
+            ctx.AbortState = AbortState.Statement;
+            Label label = Label.LabelOptional; // default
+
+            if (tokens.ConsumeIf(TokenType.AlphaNumeric, "repeated"))
+            {
+                if (isOneOf) NotAllowedOneOf(ctx);
+                label = Label.LabelRepeated;
+            }
+            else if (tokens.ConsumeIf(TokenType.AlphaNumeric, "required"))
+            {
+                if (isOneOf) NotAllowedOneOf(ctx);
+                else tokens.Previous.RequireProto2(ctx);
+                label = Label.LabelRequired;
+            }
+            else if (tokens.ConsumeIf(TokenType.AlphaNumeric, "optional"))
+            {
+                if (isOneOf) NotAllowedOneOf(ctx);
+                else tokens.Previous.RequireProto2(ctx);
+                label = Label.LabelOptional;
+            }
+            else if (ctx.Syntax == FileDescriptorProto.SyntaxProto2 && !isOneOf)
+            {
+                // required in proto2
+                throw tokens.Read().Throw("expected 'repeated' / 'required' / 'optional'");
+            }
+
+            var typeToken = tokens.Read();
+            if (typeToken.Is(TokenType.AlphaNumeric, "map"))
+            {
+                tokens.Previous.Throw($"'{tokens.Previous.Value}' can not be used with 'map'");
+            }
+            string typeName = tokens.Consume(TokenType.AlphaNumeric);
+
+            var isGroup = typeName == "group";
+            if (isGroup)
+            {
+                //if (isOneOf) NotAllowedOneOf(ctx);
+                //else if (parentTyped == null)
+                //{
+                //    ctx.Errors.Error(tokens.Previous, "group not allowed in this context");
+                //}
+                ctx.AbortState = AbortState.Object;
+            }
+
+            string name = tokens.Consume(TokenType.AlphaNumeric);
+            var nameToken = tokens.Previous;
+            tokens.Consume(TokenType.Symbol, "=");
+            var number = tokens.ConsumeInt32();
+            var numberToken = tokens.Previous;
+
+            if (number < 1 || number > parent.MaxField)
+            {
+                ctx.Errors.Error(numberToken, $"field numbers must be in the range 1-{parent.MaxField}");
+            }
+            else if (number >= FirstReservedField && number <= LastReservedField)
+            {
+                ctx.Errors.Warn(numberToken, $"field numbers in the range {FirstReservedField}-{LastReservedField} are reserved; this may cause problems on many implementations");
+            }
+            ctx.CheckNames(parent, name, nameToken);
+            if (parent is DescriptorProto)
+            {
+                var parentTyped = parent as DescriptorProto;
+                var conflict = parentTyped.Fields.FirstOrDefault(x => x.Number == number);
+                if (conflict != null)
+                {
+                    ctx.Errors.Error(numberToken, $"field {number} is already in use by '{conflict.Name}'");
+                }
+                if (parentTyped.ReservedNames.Contains(name))
+                {
+                    ctx.Errors.Error(nameToken, $"field '{name}' is reserved");
+                }
+                if (parentTyped.ReservedRanges.Any(x => x.Start <= number && x.End > number))
+                {
+                    ctx.Errors.Error(numberToken, $"field {number} is reserved");
+                }
+            }
+
+            Type type;
+            if (isGroup)
+            {
+                type = Type.TypeGroup;
+                typeName = name;
+
+                typeToken.RequireProto2(ctx);
+
+                var firstChar = typeName[0].ToString();
+                if (firstChar.ToLowerInvariant() == firstChar)
+                {
+                    ctx.Errors.Error(nameToken, "group names must start with an upper-case letter");
+                }
+                name = typeName.ToLowerInvariant();
+                DescriptorProto grpType;
+                if (ctx.TryReadObject<DescriptorProto>(out grpType))
+                {
+                    grpType.Name = typeName;
+                    ctx.CheckNames(parent, typeName, nameToken);
+                    parent?.Types?.Add(grpType);
+                }
+            }
+            else if (TryIdentifyType(typeName, out type))
+            {
+                typeName = null;
+            }
+
+            field = new FieldDescriptorProto
+            {
+                type = type,
+                TypeName = typeName,
+                Name = name,
+                JsonName = GetJsonName(name),
+                Number = number,
+                label = label,
+                TypeToken = typeToken // internal property that helps give useful error messages
+            };
+
+            if (!isGroup)
+            {
+                if (tokens.ConsumeIf(TokenType.Symbol, "["))
+                {
+                    field.Options = ctx.ParseOptionBlock(field.Options, field);
+                }
+
+                tokens.Consume(TokenType.Symbol, ";");
+            }
+            ctx.AbortState = AbortState.None;
+            return true;
+        }
+        static readonly char[] Underscores = { '_' };
+        internal static string GetJsonName(string name)
+            => Regex.Replace(name, "_+([0-9a-zA-Z])", match => match.Groups[1].Value.ToUpperInvariant()).TrimEnd(Underscores);
+
+
+        internal static bool CanPack(Type type)
+        {
+            switch (type)
+            {
+                case Type.TypeBool:
+                case Type.TypeDouble:
+                case Type.TypeEnum:
+                case Type.TypeFixed32:
+                case Type.TypeFixed64:
+                case Type.TypeFloat:
+                case Type.TypeInt32:
+                case Type.TypeInt64:
+                case Type.TypeSfixed32:
+                case Type.TypeSfixed64:
+                case Type.TypeSint32:
+                case Type.TypeSint64:
+                case Type.TypeUint32:
+                case Type.TypeUint64:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+		internal static bool Assign(Type @in, out Type @out)
+		{
+			@out = @in;
+			return true;
+		}
+        internal static bool TryIdentifyType(string typeName, out Type type)
+        {
+            switch (typeName)
+            {
+                case "bool": return Assign(Type.TypeBool, out @type);
+                case "bytes": return Assign(Type.TypeBytes, out @type);
+                case "double": return Assign(Type.TypeDouble, out @type);
+                case "fixed32": return Assign(Type.TypeFixed32, out @type);
+                case "fixed64": return Assign(Type.TypeFixed64, out @type);
+                case "float": return Assign(Type.TypeFloat, out @type);
+                case "int32": return Assign(Type.TypeInt32, out @type);
+                case "int64": return Assign(Type.TypeInt64, out @type);
+                case "sfixed32": return Assign(Type.TypeSfixed32, out @type);
+                case "sfixed64": return Assign(Type.TypeSfixed64, out @type);
+                case "sint32": return Assign(Type.TypeSint32, out @type);
+                case "sint64": return Assign(Type.TypeSint64, out @type);
+                case "string": return Assign(Type.TypeString, out @type);
+                case "uint32": return Assign(Type.TypeUint32, out @type);
+                case "uint64": return Assign(Type.TypeUint64, out @type);
+                default:
+                    type = default(Type);
+                    return false;
+            }
+        }
+
+        internal static void ParseExtensions(ParserContext ctx, IMessage message)
+        {
+            var extendee = ctx.Tokens.Consume(TokenType.AlphaNumeric);
+            var dummy = new DummyExtensions(extendee, message);
+            ctx.TryReadObjectImpl(dummy);
+        }
+
+        void ISchemaObject.ReadOne(ParserContext ctx)
+        {
+            throw new InvalidOperationException();
+        }
+
+        class DummyExtensions : ISchemaObject, IHazNames, IMessage
+        {
+            int IMessage.MaxField => message.MaxField;
+            List<DescriptorProto> IMessage.Types => message.Types;
+            List<FieldDescriptorProto> IMessage.Extensions => message.Extensions;
+            List<FieldDescriptorProto> IMessage.Fields => message.Fields;
+            public byte[] ExtensionData
+            {
+                get { return null; }
+                set { }
+            }
+            IEnumerable<string> IHazNames.GetNames()
+            {
+                var fields = message.Fields;
+                if (fields != null)
+                {
+                    foreach (var field in fields) yield return field.Name;
+                }
+                foreach (var field in message.Extensions) yield return field.Name;
+                foreach (var type in message.Types) yield return type.Name;
+            }
+
+            void ISchemaObject.ReadOne(ParserContext ctx)
+            {
+                ctx.AbortState = AbortState.Statement;
+                FieldDescriptorProto field;
+                if (TryParse(ctx, this, false, out field))
+                {
+                    field.Extendee = extendee;
+                    message.Extensions.Add(field);
+                }
+                ctx.AbortState = AbortState.None;
+            }
+
+            private IMessage message;
+            private string extendee;
+
+            public DummyExtensions(string extendee, IMessage message)
+            {
+                this.extendee = extendee;
+                this.message = message;
+            }
+        }
+    }
+
+    internal interface IMessage : IHazNames
+    {
+        int MaxField { get; }
+        List<DescriptorProto> Types { get; }
+        List<FieldDescriptorProto> Extensions { get; }
+        List<FieldDescriptorProto> Fields { get; }
+    }
+
+    partial class ServiceDescriptorProto : ISchemaObject
+    {
+        internal static bool TryParse(ParserContext ctx, out ServiceDescriptorProto obj)
+        {
+            var name = ctx.Tokens.Consume(TokenType.AlphaNumeric);
+            if (ctx.TryReadObject(out obj))
+            {
+                obj.Name = name;
+                return true;
+            }
+            return false;
+        }
+        void ISchemaObject.ReadOne(ParserContext ctx)
+        {
+            ctx.AbortState = AbortState.Statement;
+            var tokens = ctx.Tokens;
+
+            if (tokens.ConsumeIf(TokenType.AlphaNumeric, "option"))
+            {
+                Options = ctx.ParseOptionStatement(Options, this);
+            }
+            else
+            {
+                // is a method
+                Methods.Add(MethodDescriptorProto.Parse(ctx));
+            }
+            ctx.AbortState = AbortState.None;
+        }
+    }
+
+    partial class MethodDescriptorProto : ISchemaObject
+    {
+        internal Token InputTypeToken { get; set; }
+        internal Token OutputTypeToken { get; set; }
+
+        internal static MethodDescriptorProto Parse(ParserContext ctx)
+        {
+            var tokens = ctx.Tokens;
+            tokens.Consume(TokenType.AlphaNumeric, "rpc");
+            var name = tokens.Consume(TokenType.AlphaNumeric);
+            tokens.Consume(TokenType.Symbol, "(");
+            bool isInputStream = tokens.ConsumeIf(TokenType.AlphaNumeric, "stream");
+            var inputTypeToken = tokens.Read();
+            var inputType = tokens.Consume(TokenType.AlphaNumeric);
+            tokens.Consume(TokenType.Symbol, ")");
+            tokens.Consume(TokenType.AlphaNumeric, "returns");
+            tokens.Consume(TokenType.Symbol, "(");
+            bool isOutputStream = tokens.ConsumeIf(TokenType.AlphaNumeric, "stream");
+            var outputTypeToken = tokens.Read();
+            var outputType = tokens.Consume(TokenType.AlphaNumeric);
+            tokens.Consume(TokenType.Symbol, ")");
+
+            var method = new MethodDescriptorProto
+            {
+                Name = name,
+                InputType = inputType,
+                OutputType = outputType,
+                InputTypeToken = inputTypeToken,
+                OutputTypeToken = outputTypeToken
+            };
+            if (isInputStream) method.ClientStreaming = true;
+            if (isOutputStream) method.ServerStreaming = true;
+            Token token;
+            if (tokens.Peek(out token) && token.Is(TokenType.Symbol, "{"))
+            {
+                ctx.AbortState = AbortState.Object;
+                ctx.TryReadObjectImpl(method);
+            }
+            else
+            {
+                tokens.Consume(TokenType.Symbol, ";");
+            }
+            return method;
+        }
+
+        void ISchemaObject.ReadOne(ParserContext ctx)
+        {
+            ctx.Tokens.Consume(TokenType.AlphaNumeric, "option");
+            Options = ctx.ParseOptionStatement(Options, this);
+        }
+    }
+
+    partial class EnumValueDescriptorProto
+    {
+        internal static EnumValueDescriptorProto Parse(ParserContext ctx)
+        {
+            var tokens = ctx.Tokens;
+            string name = tokens.Consume(TokenType.AlphaNumeric);
+            tokens.Consume(TokenType.Symbol, "=");
+            var value = tokens.ConsumeInt32();
+
+            var obj = new EnumValueDescriptorProto { Name = name, Number = value };
+            if (tokens.ConsumeIf(TokenType.Symbol, "["))
+            {
+                obj.Options = ctx.ParseOptionBlock(obj.Options);
+            }
+            tokens.Consume(TokenType.Symbol, ";");
+            return obj;
+        }
+        internal EnumDescriptorProto Parent { get; set; }
+
+    }
+    partial class MessageOptions : ISchemaOptions
+    {
+        string ISchemaOptions.Extendee => FileDescriptorSet.Namespace + nameof(MessageOptions);
+        bool ISchemaOptions.ReadOne(ParserContext ctx, string key)
+        {
+            switch (key)
+            {
+                case "map_entry":
+                    MapEntry = ctx.Tokens.ConsumeBoolean();
+                    ctx.Errors.Error(ctx.Tokens.Previous, "'map_entry' should not be set explicitly; use 'map<TKey,TValue>' instead");
+                    return true;
+                case "message_set_wire_format": MessageSetWireFormat = ctx.Tokens.ConsumeBoolean(); return true;
+                case "no_standard_descriptor_accessor": NoStandardDescriptorAccessor = ctx.Tokens.ConsumeBoolean(); return true;
+                default: return false;
+            }
+        }
+        public byte[] ExtensionData
+        {
+            get { return DescriptorProto.GetExtensionData(this); }
+            set { DescriptorProto.SetExtensionData(this, value); }
+        }
+    }
+    partial class MethodOptions : ISchemaOptions
+    {
+        string ISchemaOptions.Extendee => FileDescriptorSet.Namespace + nameof(MethodOptions);
+        bool ISchemaOptions.ReadOne(ParserContext ctx, string key)
+        {
+            switch (key)
+            {
+                case "idempotency_level": idempotency_level = ctx.Tokens.ConsumeEnum<IdempotencyLevel>(); return true;
+                default: return false;
+            }
+        }
+        public byte[] ExtensionData
+        {
+            get { return DescriptorProto.GetExtensionData(this); }
+            set { DescriptorProto.SetExtensionData(this, value); }
+        }
+    }
+    partial class ServiceOptions : ISchemaOptions
+    {
+        string ISchemaOptions.Extendee => FileDescriptorSet.Namespace + nameof(ServiceOptions);
+        bool ISchemaOptions.ReadOne(ParserContext ctx, string key) => false;
+
+        public byte[] ExtensionData
+        {
+            get { return DescriptorProto.GetExtensionData(this); }
+            set { DescriptorProto.SetExtensionData(this, value); }
+        }
+    }
+
+    partial class UninterpretedOption
+    {
+        partial class NamePart
+        {
+            public override string ToString() => IsExtension ? ("(" + name_part + ")") : name_part;
+            internal Token Token { get; set; }
+        }
+        internal bool Applied { get; set; }
+        internal Token Token { get; set; }
+    }
+    partial class EnumOptions : ISchemaOptions
+    {
+        string ISchemaOptions.Extendee => FileDescriptorSet.Namespace + nameof(EnumOptions);
+        bool ISchemaOptions.ReadOne(ParserContext ctx, string key)
+        {
+            switch (key)
+            {
+                case "allow_alias": AllowAlias = ctx.Tokens.ConsumeBoolean(); return true;
+                default: return false;
+            }
+        }
+        public byte[] ExtensionData
+        {
+            get { return DescriptorProto.GetExtensionData(this); }
+            set { DescriptorProto.SetExtensionData(this, value); }
+        }
+    }
+    partial class EnumValueOptions : ISchemaOptions
+    {
+        string ISchemaOptions.Extendee => FileDescriptorSet.Namespace + nameof(EnumValueOptions);
+        bool ISchemaOptions.ReadOne(ParserContext ctx, string key) => false;
+
+        public byte[] ExtensionData
+        {
+            get { return DescriptorProto.GetExtensionData(this); }
+            set { DescriptorProto.SetExtensionData(this, value); }
+        }
+    }
+    partial class FieldOptions : ISchemaOptions
+    {
+        string ISchemaOptions.Extendee => FileDescriptorSet.Namespace + nameof(FieldOptions);
+        bool ISchemaOptions.ReadOne(ParserContext ctx, string key)
+        {
+            switch (key)
+            {
+                case "jstype": Jstype = ctx.Tokens.ConsumeEnum<JSType>(); return true;
+                case "ctype": Ctype = ctx.Tokens.ConsumeEnum<CType>(); return true;
+                case "lazy": Lazy = ctx.Tokens.ConsumeBoolean(); return true;
+                case "packed": Packed = ctx.Tokens.ConsumeBoolean(); return true;
+                case "weak": Weak = ctx.Tokens.ConsumeBoolean(); return true;
+                default: return false;
+            }
+        }
+
+        public byte[] ExtensionData
+        {
+            get { return DescriptorProto.GetExtensionData(this); }
+            set { DescriptorProto.SetExtensionData(this, value); }
+        }
+    }
+    partial class FileOptions : ISchemaOptions
+    {
+        string ISchemaOptions.Extendee => FileDescriptorSet.Namespace + nameof(FileOptions);
+        bool ISchemaOptions.ReadOne(ParserContext ctx, string key)
+        {
+            switch (key)
+            {
+                case "optimize_for": OptimizeFor = ctx.Tokens.ConsumeEnum<OptimizeMode>(); return true;
+                case "cc_enable_arenas": CcEnableArenas = ctx.Tokens.ConsumeBoolean(); return true;
+                case "cc_generic_services": CcGenericServices = ctx.Tokens.ConsumeBoolean(); return true;
+#pragma warning disable 0612
+                case "java_generate_equals_and_hash": JavaGenerateEqualsAndHash = ctx.Tokens.ConsumeBoolean(); return true;
+#pragma warning restore 0612
+                case "java_generic_services": JavaGenericServices = ctx.Tokens.ConsumeBoolean(); return true;
+                case "java_multiple_files": JavaMultipleFiles = ctx.Tokens.ConsumeBoolean(); return true;
+                case "java_string_check_utf8": JavaStringCheckUtf8 = ctx.Tokens.ConsumeBoolean(); return true;
+                case "py_generic_services": PyGenericServices = ctx.Tokens.ConsumeBoolean(); return true;
+
+                case "csharp_namespace": CsharpNamespace = ctx.Tokens.ConsumeString(); return true;
+                case "go_package": GoPackage = ctx.Tokens.ConsumeString(); return true;
+                case "java_outer_classname": JavaOuterClassname = ctx.Tokens.ConsumeString(); return true;
+                case "java_package": JavaPackage = ctx.Tokens.ConsumeString(); return true;
+                case "objc_class_prefix": ObjcClassPrefix = ctx.Tokens.ConsumeString(); return true;
+                case "php_class_prefix": PhpClassPrefix = ctx.Tokens.ConsumeString(); return true;
+                case "swift_prefix": SwiftPrefix = ctx.Tokens.ConsumeString(); return true;
+
+                default: return false;
+            }
+        }
+        public byte[] ExtensionData
+        {
+            get { return DescriptorProto.GetExtensionData(this); }
+            set { DescriptorProto.SetExtensionData(this, value); }
+        }
+    }
+
+#pragma warning restore CS1591
+}
+namespace ProtoBuf.Reflection
+{
+    internal static class ErrorExtensions
+    {
+        public static void Warn(this List<Error> errors, Token token, string message)
+            => errors.Add(new Error(token, message, false));
+        public static void Error(this List<Error> errors, Token token, string message)
+            => errors.Add(new Error(token, message, true));
+        public static void Error(this List<Error> errors, ParserException ex)
+            => errors.Add(new Error(ex));
+    }
+
+    /// <summary>
+    /// Describes a generated file
+    /// </summary>
+    public class CodeFile
+    {
+        /// <summary>
+        /// Get a string representation of this instance
+        /// </summary>
+        /// <returns></returns>
+        public override string ToString() => Name;
+        /// <summary>
+        /// Create a new CodeFile instance
+        /// </summary>
+        public CodeFile(string name, string text)
+        {
+            Name = name;
+            Text = text;
+        }
+        /// <summary>
+        /// The name (including path if necessary) of this file
+        /// </summary>
+        public string Name { get; }
+        /// <summary>
+        /// The contents of this file
+        /// </summary>
+        public string Text { get; }
+    }
+
+    /// <summary>
+    /// Represents the overall result of a compilation process
+    /// </summary>
+    public class CompilerResult
+    {
+        internal CompilerResult(Error[] errors, CodeFile[] files)
+        {
+            Errors = errors;
+            Files = files;
+        }
+        /// <summary>
+        /// The errors from this execution
+        /// </summary>
+        public Error[] Errors { get; }
+        /// <summary>
+        /// The output files from this execution
+        /// </summary>
+        public CodeFile[] Files { get; }
+    }
+
+    internal class Import
+    {
+        public override string ToString() => Path;
+        public string Path { get; set; }
+        public bool IsPublic { get; set; }
+        public Token Token { get; set; }
+        public bool Used { get; set; }
+    }
+    /// <summary>
+    /// Describes an error that occurred during processing
+    /// </summary>
+    public class Error
+    {
+        /// <summary>
+        /// Parse an error from a PROTOC error message
+        /// </summary>
+        public static Error[] Parse(string stdout, string stderr)
+        {
+            if (string.IsNullOrWhiteSpace(stdout) && string.IsNullOrWhiteSpace(stderr))
+                return noErrors;
+
+            List<Error> errors = new List<Error>();
+            using (var reader = new StringReader(stdout))
+            {
+                Add(reader, errors);
+            }
+            using (var reader = new StringReader(stderr))
+            {
+                Add(reader, errors);
+            }
+            return errors.ToArray();
+        }
+        static void Add(TextReader lines, List<Error> errors)
+        {
+            string line;
+            while ((line = lines.ReadLine()) != null)
+            {
+                var s = line;
+                bool isError = true;
+                int lineNumber = 1, columnNumber = 1;
+                if (s[0] == '[')
+                {
+                    int i = s.IndexOf(']');
+                    if (i > 0)
+                    {
+                        var prefix = line.Substring(1, i).Trim();
+                        s = line.Substring(i + 1).Trim();
+                        if (prefix.IndexOf("WARNING", StringComparison.OrdinalIgnoreCase) >= 0
+                            && prefix.IndexOf("ERROR", StringComparison.OrdinalIgnoreCase) < 0)
+                        {
+                            isError = false;
+                        }
+                    }
+                }
+                var match = Regex.Match(s, @"^([^:]+):([0-9]+):([0-9]+):\s+");
+                string file = "";
+                if (match.Success)
+                {
+                    file = match.Groups[1].Value;
+                    if (!int.TryParse(match.Groups[2].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out lineNumber))
+                        lineNumber = 1;
+                    if (!int.TryParse(match.Groups[3].Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out columnNumber))
+                        columnNumber = 1;
+                    s = s.Substring(match.Length).Trim();
+                }
+                errors.Add(new Error(new Token(" ", lineNumber, columnNumber, TokenType.None, "", 0, file), s, isError));
+            }
+        }
+        internal string ToString(bool includeType) => Text.Length == 0
+                ? $"{File}({LineNumber},{ColumnNumber}): {(includeType ? (IsError ? "error: " : "warning: ") : "")}{Message}"
+                : $"{File}({LineNumber},{ColumnNumber},{LineNumber},{ColumnNumber + Text.Length}): {(includeType ? (IsError ? "error: " : "warning: ") : "")}{Message}";
+        /// <summary>
+        /// Get a text representation of this instance
+        /// </summary>
+        /// <returns></returns>
+        public override string ToString() => ToString(true);
+
+        internal static Error[] GetArray(List<Error> errors)
+            => errors.Count == 0 ? noErrors : errors.ToArray();
+
+        private static readonly Error[] noErrors = new Error[0];
+
+        internal Error(Token token, string message, bool isError)
+        {
+            ColumnNumber = token.ColumnNumber;
+            LineNumber = token.LineNumber;
+            File = token.File;
+            LineContents = token.LineContents;
+            Message = message;
+            IsError = isError;
+            Text = token.Value;
+        }
+        internal Error(ParserException ex)
+        {
+            ColumnNumber = ex.ColumnNumber;
+            LineNumber = ex.LineNumber;
+            File = ex.File;
+            LineContents = ex.LineContents;
+            Message = ex.Message;
+            IsError = ex.IsError;
+            Text = ex.Text ?? "";
+        }
+        /// <summary>
+        /// True if this instance represents a non-fatal warning
+        /// </summary>
+        public bool IsWarning => !IsError;
+        /// <summary>
+        /// True if this instance represents a fatal error
+        /// </summary>
+        public bool IsError { get; }
+        /// <summary>
+        /// The file in which this error was identified
+        /// </summary>
+        public string File { get; }
+        /// <summary>
+        /// The source text relating to this error
+        /// </summary>
+        public string Text { get; }
+        /// <summary>
+        /// The error message
+        /// </summary>
+        public string Message { get; }
+        /// <summary>
+        /// The entire line contents in the source in which this error was located
+        /// </summary>
+        public string LineContents { get; }
+        /// <summary>
+        /// The line number in which this error was located
+        /// </summary>
+        public int LineNumber { get; }
+        /// <summary>
+        /// The column number in which this error was located
+        /// </summary>
+        public int ColumnNumber { get; }
+    }
+    enum AbortState
+    {
+        None, Statement, Object
+    }
+    interface ISchemaOptions
+    {
+        List<UninterpretedOption> UninterpretedOptions { get; }
+        bool Deprecated { get; set; }
+        bool ReadOne(ParserContext ctx, string key);
+        byte[] ExtensionData { get; set; }
+        string Extendee { get; }
+    }
+
+    interface IHazNames
+    {
+        IEnumerable<string> GetNames();
+    }
+
+    interface ISchemaObject
+    {
+        void ReadOne(ParserContext ctx);
+    }
+    internal class ParserContext : IDisposable
+    {
+        public AbortState AbortState { get; set; }
+        private void ReadOne<T>(T obj) where T : class, ISchemaObject
+        {
+            AbortState oldState = AbortState;
+            AbortState = AbortState.None;
+            Token stateBefore;
+            if (!Tokens.Peek(out stateBefore)) return;
+
+            try
+            {
+                obj.ReadOne(this);
+            }
+            catch (ParserException ex)
+            {
+                Errors.Error(ex);
+            }
+            finally
+            {
+                var state = AbortState;
+                Token stateAfter;
+                if (Tokens.Peek(out stateAfter) && stateBefore == stateAfter)
+                {
+                    // we didn't move! avoid looping forever failing to do the same thing
+                    Errors.Error(stateAfter, "unknown error");
+                    state = stateAfter.Is(TokenType.Symbol, "}")
+                        ? AbortState.Object : AbortState.Statement;
+                }
+                AbortState = oldState;
+                switch (state)
+                {
+                    case AbortState.Object:
+                        Tokens.SkipToEndObject();
+                        break;
+                    case AbortState.Statement:
+                        Tokens.SkipToEndStatement();
+                        break;
+                }
+            }
+        }
+        public void Fill<T>(T obj) where T : class, ISchemaObject
+        {
+            var tokens = Tokens;
+            Token token;
+            while (tokens.Peek(out token))
+            {
+                if (tokens.ConsumeIf(TokenType.Symbol, ";"))
+                { }
+                else
+                {
+                    ReadOne(obj);
+                }
+            }
+        }
+        static readonly char[] Period = { '.' };
+        private void ReadOption<T>(ref T obj, ISchemaObject parent, List<UninterpretedOption.NamePart> existingNameParts = null) where T : class, ISchemaOptions, new()
+        {
+            var tokens = Tokens;
+            bool isBlock = existingNameParts != null;
+            var nameParts = isBlock
+                ? new List<UninterpretedOption.NamePart>(existingNameParts) // create a clone we can append to
+                : new List<UninterpretedOption.NamePart>();
+
+            do
+            {
+                if (nameParts.Count != 0) tokens.ConsumeIf(TokenType.AlphaNumeric, ".");
+
+                bool isExtension = tokens.ConsumeIf(TokenType.Symbol, isBlock ? "[" : "(");
+                string key = tokens.Consume(TokenType.AlphaNumeric);
+                var keyToken = tokens.Previous;
+                if (isExtension) tokens.Consume(TokenType.Symbol, isBlock ? "]" : ")");
+
+                if (!isExtension && key.StartsWith("."))
+                {
+                    key = key.TrimStart(Period);
+                }
+
+                key = key.Trim();
+                if (isExtension || nameParts.Count == 0 || key.IndexOf('.') < 0)
+                {
+                    var name = new UninterpretedOption.NamePart { IsExtension = isExtension, name_part = key, Token = keyToken };
+                    nameParts.Add(name);
+                }
+                else
+                {
+                    foreach (var part in key.Split(Period, StringSplitOptions.RemoveEmptyEntries))
+                    {
+                        var name = new UninterpretedOption.NamePart { IsExtension = false, name_part = part, Token = keyToken };
+                        nameParts.Add(name);
+                    }
+                }
+            } while (!(
+            (isBlock && tokens.Is(TokenType.Symbol, "{"))
+            || tokens.ConsumeIf(TokenType.Symbol, isBlock ? ":" : "=")));
+
+            if (tokens.ConsumeIf(TokenType.Symbol, "{"))
+            {
+                if (obj == null) obj = new T();
+                bool any = false;
+                while (!tokens.ConsumeIf(TokenType.Symbol, "}"))
+                {
+                    ReadOption(ref obj, parent, nameParts);
+                    any = true;
+                }
+                if (!any)
+                {
+                    var newOption = new UninterpretedOption();
+                    newOption.Names.AddRange(nameParts);
+                    obj.UninterpretedOptions.Add(newOption);
+                }
+            }
+            else
+            {
+
+                var field = parent as FieldDescriptorProto;
+                bool isField = typeof(T) == typeof(FieldOptions) && field != null;
+                var singleKey = (nameParts.Count == 1 && !nameParts[0].IsExtension) ? nameParts[0].name_part : null;
+                if (singleKey == "default" && isField)
+                {
+                    string defaultValue = tokens.ConsumeString(field.type == FieldDescriptorProto.Type.TypeBytes);
+                    nameParts[0].Token.RequireProto2(this);
+                    ParseDefault(tokens.Previous, field.type, ref defaultValue);
+                    if (defaultValue != null)
+                    {
+                        field.DefaultValue = defaultValue;
+                    }
+                }
+                else if (singleKey == "json_name" && isField)
+                {
+                    string jsonName = tokens.ConsumeString();
+                    field.JsonName = jsonName;
+                }
+                else
+                {
+                    if (obj == null) obj = new T();
+                    if (singleKey == "deprecated")
+                    {
+                        obj.Deprecated = tokens.ConsumeBoolean();
+                    }
+                    else if (singleKey == null || !obj.ReadOne(this, singleKey))
+                    {
+                        var newOption = new UninterpretedOption
+                        {
+                            AggregateValue = tokens.ConsumeString(),
+                            Token = tokens.Previous
+                        };
+                        newOption.Names.AddRange(nameParts);
+                        obj.UninterpretedOptions.Add(newOption);
+                    }
+                }
+            }
+        }
+
+        private void ParseDefault(Token token, FieldDescriptorProto.Type type, ref string defaultValue)
+        {
+            switch (type)
+            {
+                case FieldDescriptorProto.Type.TypeBool:
+                    switch (defaultValue)
+                    {
+                        case "true":
+                        case "false":
+                            break;
+                        default:
+                            Errors.Error(token, "expected 'true' or 'false'");
+                            break;
+                    }
+                    break;
+                case FieldDescriptorProto.Type.TypeDouble:
+                    switch (defaultValue)
+                    {
+                        case "inf":
+                        case "-inf":
+                        case "nan":
+                            break;
+                        default:
+                            double val;
+                            if (TokenExtensions.TryParseDouble(defaultValue, out val))
+                            {
+                                defaultValue = Format(val);
+                            }
+                            else
+                            {
+                                Errors.Error(token, "invalid floating-point number");
+                            }
+                            break;
+                    }
+                    break;
+                case FieldDescriptorProto.Type.TypeFloat:
+                    switch (defaultValue)
+                    {
+                        case "inf":
+                        case "-inf":
+                        case "nan":
+                            break;
+                        default:
+                            float val;
+                            if (TokenExtensions.TryParseSingle(defaultValue, out val))
+                            {
+                                defaultValue = Format(val);
+                            }
+                            else
+                            {
+                                Errors.Error(token, "invalid floating-point number");
+                            }
+                            break;
+                    }
+                    break;
+                case FieldDescriptorProto.Type.TypeSfixed32:
+                case FieldDescriptorProto.Type.TypeInt32:
+                case FieldDescriptorProto.Type.TypeSint32:
+                    {
+                        int val;
+                        if (TokenExtensions.TryParseInt32(defaultValue, out val))
+                        {
+                            defaultValue = val.ToString(CultureInfo.InvariantCulture);
+                        }
+                        else
+                        {
+                            Errors.Error(token, "invalid integer");
+                        }
+                    }
+                    break;
+                case FieldDescriptorProto.Type.TypeFixed32:
+                case FieldDescriptorProto.Type.TypeUint32:
+                    {
+                        uint val;
+                        if (TokenExtensions.TryParseUInt32(defaultValue, out val))
+                        {
+                            defaultValue = val.ToString(CultureInfo.InvariantCulture);
+                        }
+                        else
+                        {
+                            Errors.Error(token, "invalid unsigned integer");
+                        }
+                    }
+                    break;
+                case FieldDescriptorProto.Type.TypeSfixed64:
+                case FieldDescriptorProto.Type.TypeInt64:
+                case FieldDescriptorProto.Type.TypeSint64:
+                    {
+                        long val;
+                        if (TokenExtensions.TryParseInt64(defaultValue, out val))
+                        {
+                            defaultValue = val.ToString(CultureInfo.InvariantCulture);
+                        }
+                        else
+                        {
+                            Errors.Error(token, "invalid integer");
+                        }
+                    }
+                    break;
+                case FieldDescriptorProto.Type.TypeFixed64:
+                case FieldDescriptorProto.Type.TypeUint64:
+                    {
+                        ulong val;
+                        if (TokenExtensions.TryParseUInt64(defaultValue, out val))
+                        {
+                            defaultValue = val.ToString(CultureInfo.InvariantCulture);
+                        }
+                        else
+                        {
+                            Errors.Error(token, "invalid unsigned integer");
+                        }
+                    }
+                    break;
+                case 0:
+                case FieldDescriptorProto.Type.TypeBytes:
+                case FieldDescriptorProto.Type.TypeString:
+                case FieldDescriptorProto.Type.TypeEnum:
+                    break;
+                default:
+                    Errors.Error(token, $"default value not handled: {type}={defaultValue}");
+                    break;
+            }
+        }
+
+        static readonly char[] ExponentChars = { 'e', 'E' };
+        static readonly string[] ExponentFormats = { "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "e10" };
+        static string Format(float val)
+        {
+            string s = val.ToString(CultureInfo.InvariantCulture);
+            if (s.IndexOfAny(ExponentChars) < 0) return s;
+
+            foreach (var format in ExponentFormats)
+            {
+                var tmp = val.ToString(format, CultureInfo.InvariantCulture);
+                float x;
+                if (float.TryParse(tmp, NumberStyles.Any, CultureInfo.InvariantCulture, out x) && x == val) return tmp;
+            }
+            return val.ToString("e", CultureInfo.InvariantCulture);
+
+        }
+
+        static string Format(double val)
+        {
+            string s = val.ToString(CultureInfo.InvariantCulture).ToUpperInvariant();
+            if (s.IndexOfAny(ExponentChars) < 0) return s;
+
+            foreach (var format in ExponentFormats)
+            {
+                var tmp = val.ToString(format, CultureInfo.InvariantCulture);
+                double x;
+                if (double.TryParse(tmp, NumberStyles.Any, CultureInfo.InvariantCulture, out x) && x == val) return tmp;
+            }
+            return val.ToString("e", CultureInfo.InvariantCulture);
+        }
+
+        public T ParseOptionBlock<T>(T obj, ISchemaObject parent = null) where T : class, ISchemaOptions, new()
+        {
+            var tokens = Tokens;
+            try
+            {
+                while (true)
+                {
+                    if (tokens.ConsumeIf(TokenType.Symbol, "]"))
+                    {
+                        break;
+                    }
+                    else if (tokens.ConsumeIf(TokenType.Symbol, ","))
+                    {
+                    }
+                    else
+                    {
+                        ReadOption(ref obj, parent);
+                    }
+                }
+            }
+            catch (ParserException ex)
+            {
+                Errors.Error(ex);
+                tokens.SkipToEndOptions();
+            }
+            return obj;
+        }
+        public T ParseOptionStatement<T>(T obj, ISchemaObject parent) where T : class, ISchemaOptions, new()
+        {
+            var tokens = Tokens;
+            try
+            {
+                ReadOption(ref obj, parent);
+                tokens.Consume(TokenType.Symbol, ";");
+            }
+            catch (ParserException ex)
+            {
+                Errors.Error(ex);
+                tokens.SkipToEndStatement();
+            }
+            return obj;
+        }
+        public bool TryReadObject<T>(out T obj) where T : class, ISchemaObject, new()
+        {
+            obj = new T();
+            return TryReadObjectImpl(obj);
+        }
+        internal bool TryReadObjectImpl<T>(T obj) where T : class, ISchemaObject
+        {
+            var tokens = Tokens;
+
+            try
+            {
+                tokens.Consume(TokenType.Symbol, "{");
+                Token token;
+                while (tokens.Peek(out token) && !token.Is(TokenType.Symbol, "}"))
+                {
+                    if (tokens.ConsumeIf(TokenType.Symbol, ";"))
+                    { }
+                    else
+                    {
+                        ReadOne(obj);
+                    }
+                }
+                tokens.Consume(TokenType.Symbol, "}");
+                return true;
+            }
+            catch (ParserException ex)
+            {
+                Errors.Error(ex);
+                tokens.SkipToEndObject();
+            }
+            obj = null;
+            return false;
+        }
+        public ParserContext(FileDescriptorProto file, Peekable<Token> tokens, List<Error> errors)
+        {
+            Tokens = tokens;
+            Errors = errors;
+            _file = file;
+        }
+
+        public string Syntax
+        {
+            get
+            {
+                var syntax = _file.Syntax;
+                return string.IsNullOrEmpty(syntax) ? FileDescriptorProto.SyntaxProto2 : syntax;
+            }
+        }
+
+        private readonly FileDescriptorProto _file;
+        public Peekable<Token> Tokens { get; }
+        public List<Error> Errors { get; }
+
+        public void Dispose() { Tokens?.Dispose(); }
+
+        internal void CheckNames(IHazNames parent, string name, Token token
+#if DEBUG && NETSTANDARD1_3
+            , [System.Runtime.CompilerServices.CallerMemberName] string caller = null
+#endif
+            )
+        {
+            if (parent != null && parent.GetNames().Contains(name))
+            {
+                Errors.Error(token, $"name '{name}' is already in use"
+#if DEBUG && NETSTANDARD1_3
+             + $" ({caller})"
+#endif
+                    );
+            }
+        }
+    }
+}

+ 12 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/Parsers.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 3ebfae42955ead84eb07b8d228c44dc8
+timeCreated: 1517401476
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 55 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/Peekable.cs

@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+
+namespace ProtoBuf.Reflection
+{
+    internal sealed class Peekable<T> : IDisposable
+    {
+        public override string ToString()
+        {
+            T val;
+            return Peek(out val) ? (val?.ToString() ?? "(null)") : "(EOF)";
+        }
+        private readonly IEnumerator<T> _iter;
+        private T _peek, _prev;
+        private bool _havePeek, _eof;
+        public Peekable(IEnumerable<T> sequence)
+        {
+            _iter = sequence.GetEnumerator();
+        }
+        public T Previous => _prev;
+        public bool Consume()
+        {
+            T val;
+            bool haveData = _havePeek || Peek(out val);
+            _prev = _peek;
+            _havePeek = false;            
+            return haveData;
+        }
+        public bool Peek(out T next)
+        {
+            if (!_havePeek)
+            {
+                if (_iter.MoveNext())
+                {
+                    _prev = _peek;
+                    _peek = _iter.Current;
+                    _havePeek = true;
+                }
+                else
+                {
+                    _eof = true;
+                    _havePeek = false;
+                }
+            }
+            if (_eof)
+            {
+                next = default(T);
+                return false;
+            }
+            next = _peek;
+            return true;
+        }
+        public void Dispose() => _iter?.Dispose();
+    }
+}

+ 12 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/Peekable.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: f074942646acd7147abc5c31ce5991bd
+timeCreated: 1517401477
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 83 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/Token.cs

@@ -0,0 +1,83 @@
+using Google.Protobuf.Reflection;
+using System;
+
+namespace ProtoBuf.Reflection
+{
+    internal struct Token
+    {
+
+        public static bool operator ==(Token x, Token y)
+        {
+            return x.Offset == y.Offset && x.File == y.File;
+        }
+        public static bool operator !=(Token x, Token y)
+        {
+            return x.Offset != y.Offset || x.File != y.File;
+        }
+        public override int GetHashCode() => Offset;
+        public override bool Equals(object obj) => (obj is Token) && ((Token)obj).Offset == this.Offset;
+        public bool Equals(Token token) => token.Offset == this.Offset;
+        public int Offset { get; }
+        public int LineNumber { get; }
+        public string File { get; }
+        public int ColumnNumber { get; }
+        public TokenType Type { get; }
+        public string Value { get; }
+        public string LineContents { get; }
+        internal Token(string value, int lineNumber, int columnNumber, TokenType type, string lineContents, int offset, string file)
+        {
+            Value = value;
+            LineNumber = lineNumber;
+            ColumnNumber = columnNumber;
+            File = file;
+            Type = type;
+            LineContents = lineContents;
+            Offset = offset;
+        }
+        public override string ToString() => $"({LineNumber},{ColumnNumber}) '{Value}'";
+
+
+        internal Exception Throw(string error = null, bool isError = true)
+        {
+            throw new ParserException(this, string.IsNullOrWhiteSpace(error) ? $"syntax error: '{Value}'" : error, isError);
+        }
+
+        internal void Assert(TokenType type, string value = null)
+        {
+            if (value != null)
+            {
+                if (type != Type || value != Value)
+                {
+                    Throw($"expected {type} '{value}'");
+                }
+
+            }
+            else
+            {
+                if (type != Type)
+                {
+                    Throw($"expected {type}");
+                }
+            }
+        }
+
+        internal bool Is(TokenType type, string value = null)
+        {
+            if (type != Type) return false;
+            if (value != null && value != Value) return false;
+            return true;
+        }
+
+        internal void RequireProto2(ParserContext ctx)
+        {
+            if(ctx.Syntax != FileDescriptorProto.SyntaxProto2)
+            {
+                var msg = "'" + Value + "' requires " + FileDescriptorProto.SyntaxProto2 + " syntax";
+                ctx.Errors.Error(this, msg);
+            }
+        }
+
+        internal Error TypeNotFound(string typeName = null) => new Error(this,
+            $"type not found: '{(string.IsNullOrWhiteSpace(typeName) ? Value : typeName)}'", true);
+    }
+}

+ 12 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/Token.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 4db473beaf44e034eae65fa8ac6c9d2d
+timeCreated: 1517401476
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 643 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/TokenExtensions.cs

@@ -0,0 +1,643 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+namespace ProtoBuf.Reflection
+{
+    internal static class TokenExtensions
+    {
+        public static bool Is(this Peekable<Token> tokens, TokenType type, string value = null)
+        {
+            Token val; 
+            return tokens.Peek(out val) && val.Is(type, value);
+        }
+
+        public static void Consume(this Peekable<Token> tokens, TokenType type, string value)
+        {
+            var token = tokens.Read();
+            token.Assert(type, value);
+            tokens.Consume();
+        }
+        public static bool ConsumeIf(this Peekable<Token> tokens, TokenType type, string value)
+        {
+            Token token;
+            if (tokens.Peek(out token) && token.Is(type, value))
+            {
+                tokens.Consume();
+                return true;
+            }
+            return false;
+        }
+
+        public static Token Read(this Peekable<Token> tokens)
+        {
+            Token val;
+            if (!tokens.Peek(out val))
+            {
+                throw new ParserException(tokens.Previous, "Unexpected end of file", true);
+            }
+            return val;
+        }
+        public static bool SkipToEndOptions(this Peekable<Token> tokens)
+        {
+            Token token;
+            while (tokens.Peek(out token))
+            {
+                if (token.Is(TokenType.Symbol, ";") || token.Is(TokenType.Symbol, "}"))
+                    return true; // but don't consume
+
+                tokens.Consume();
+                if (token.Is(TokenType.Symbol, "]"))
+                    return true;
+            }
+            return false;
+        }
+        public static bool SkipToEndStatement(this Peekable<Token> tokens)
+        {
+            Token token; 
+            while (tokens.Peek(out token))
+            {
+                if (token.Is(TokenType.Symbol, "}"))
+                    return true; // but don't consume
+
+                tokens.Consume();
+                if (token.Is(TokenType.Symbol, ";"))
+                    return true;
+            }
+            return false;
+        }
+        public static bool SkipToEndObject(this Peekable<Token> tokens) => SkipToSymbol(tokens, "}");
+        private static bool SkipToSymbol(this Peekable<Token> tokens, string symbol)
+        {
+            Token token;
+            while (tokens.Peek(out token))
+            {
+                tokens.Consume();
+                if (token.Is(TokenType.Symbol, symbol))
+                    return true;
+            }
+            return false;
+        }
+        public static bool SkipToEndStatementOrObject(this Peekable<Token> tokens)
+        {
+            Token token;
+            while (tokens.Peek(out token))
+            {
+                tokens.Consume();
+                if (token.Is(TokenType.Symbol, "}") || token.Is(TokenType.Symbol, ";"))
+                    return true;
+            }
+            return false;
+        }
+        public static string Consume(this Peekable<Token> tokens, TokenType type)
+        {
+            var token = tokens.Read();
+            token.Assert(type);
+            string s = token.Value;
+            tokens.Consume();
+            return s;
+        }
+
+        static class EnumCache<T>
+        {
+            private static readonly Dictionary<string, T> lookup;
+            public static bool TryGet(string name, out T value) => lookup.TryGetValue(name, out value);
+            static EnumCache()
+            {
+                var fields = typeof(T).GetFields(BindingFlags.Static | BindingFlags.Public);
+                var tmp = new Dictionary<string, T>(StringComparer.OrdinalIgnoreCase);
+                foreach (var field in fields)
+                {
+                    string name = field.Name;
+                    var attrib = (ProtoEnumAttribute)field.GetCustomAttributes(false).FirstOrDefault();
+                    if (!string.IsNullOrWhiteSpace(attrib?.Name)) name = attrib.Name;
+                    var val = (T)field.GetValue(null);
+                    tmp.Add(name, val);
+                }
+                lookup = tmp;
+            }
+        }
+        internal static T ConsumeEnum<T>(this Peekable<Token> tokens, bool ignoreCase = true) where T : struct
+        {
+            var token = tokens.Read();
+            //var value = 
+                tokens.ConsumeString();
+
+            T val;
+            if (!EnumCache<T>.TryGet(token.Value, out val))
+                token.Throw("Unable to parse " + typeof(T).Name);
+            return val;
+        }
+        internal static bool TryParseUInt32(string token, out uint val, uint? max = null)
+        {
+            if (max.HasValue && token == "max")
+            {
+                val = max.GetValueOrDefault();
+                return true;
+            }
+
+            if (token.StartsWith("0x", StringComparison.OrdinalIgnoreCase) && uint.TryParse(token.Substring(2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out val))
+            {
+                return true;
+            }
+
+            return uint.TryParse(token, NumberStyles.Integer | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out val);
+        }
+        internal static bool TryParseUInt64(string token, out ulong val, ulong? max = null)
+        {
+            if (max.HasValue && token == "max")
+            {
+                val = max.GetValueOrDefault();
+                return true;
+            }
+
+            if (token.StartsWith("0x", StringComparison.OrdinalIgnoreCase) && ulong.TryParse(token.Substring(2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out val))
+            {
+                return true;
+            }
+
+            return ulong.TryParse(token, NumberStyles.Integer | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out val);
+        }
+        internal static bool TryParseInt32(string token, out int val, int? max = null)
+        {
+            if (max.HasValue && token == "max")
+            {
+                val = max.GetValueOrDefault();
+                return true;
+            }
+
+            if (token.StartsWith("-0x", StringComparison.OrdinalIgnoreCase) && int.TryParse(token.Substring(3), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out val))
+            {
+                val = -val;
+                return true;
+            }
+
+            if (token.StartsWith("0x", StringComparison.OrdinalIgnoreCase) && int.TryParse(token.Substring(2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out val))
+            {
+                return true;
+            }
+
+            return int.TryParse(token, NumberStyles.Integer | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out val);
+        }
+        internal static bool TryParseInt64(string token, out long val, long? max = null)
+        {
+            if (max.HasValue && token == "max")
+            {
+                val = max.GetValueOrDefault();
+                return true;
+            }
+
+            if (token.StartsWith("-0x", StringComparison.OrdinalIgnoreCase) && long.TryParse(token.Substring(3), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out val))
+            {
+                val = -val;
+                return true;
+            }
+
+            if (token.StartsWith("0x", StringComparison.OrdinalIgnoreCase) && long.TryParse(token.Substring(2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out val))
+            {
+                return true;
+            }
+
+            return long.TryParse(token, NumberStyles.Integer | NumberStyles.AllowLeadingSign | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out val);
+        }
+        internal static int ConsumeInt32(this Peekable<Token> tokens, int? max = null)
+        {
+            var token = tokens.Read();
+            token.Assert(TokenType.AlphaNumeric);
+            tokens.Consume();
+            int val;
+            if (TryParseInt32(token.Value, out val, max)) return val;
+            throw token.Throw("Unable to parse integer");
+        }
+
+        internal static string ConsumeString(this Peekable<Token> tokens, bool asBytes = false)
+        {
+            var token = tokens.Read();
+            switch (token.Type)
+            {
+                case TokenType.StringLiteral:
+                    MemoryStream ms = null;
+                    do
+                    {
+                        ReadStringBytes(ref ms, token.Value);
+                        tokens.Consume();
+                    } while (tokens.Peek(out token) && token.Type == TokenType.StringLiteral); // literal concat is a thing
+                    if (ms == null) return "";
+
+                    if (!asBytes)
+                    {
+#if NETSTANDARD1_3
+                        string s = ms.TryGetBuffer(out var segment)
+                            ? Encoding.UTF8.GetString(segment.Array, segment.Offset, segment.Count)
+                            : Encoding.UTF8.GetString(ms.ToArray());
+
+#else
+                        string s = Encoding.UTF8.GetString(ms.GetBuffer(), 0, (int)ms.Length);
+#endif
+                        return s.Replace("\\", @"\\")
+                            .Replace("\'", @"\'")
+                            .Replace("\"", @"\""")
+                            .Replace("\r", @"\r")
+                            .Replace("\n", @"\n")
+                            .Replace("\t", @"\t");
+                    }
+
+                    var sb = new StringBuilder((int)ms.Length);
+                    int b;
+                    ms.Position = 0;
+                    while ((b = ms.ReadByte()) >= 0)
+                    {
+                        switch (b)
+                        {
+                            case '\n': sb.Append(@"\n"); break;
+                            case '\r': sb.Append(@"\r"); break;
+                            case '\t': sb.Append(@"\t"); break;
+                            case '\'': sb.Append(@"\'"); break;
+                            case '\"': sb.Append(@"\"""); break;
+                            case '\\': sb.Append(@"\\"); break;
+                            default:
+                                if (b >= 32 && b < 127)
+                                {
+                                    sb.Append((char)b);
+                                }
+                                else
+                                {
+                                    // encode as 3-part octal
+                                    sb.Append('\\')
+                                          .Append((char)(((b >> 6) & 7) + (int)'0'))
+                                          .Append((char)(((b >> 3) & 7) + (int)'0'))
+                                          .Append((char)(((b >> 0) & 7) + (int)'0'));
+                                }
+                                break;
+                        }
+                    }
+                    return sb.ToString();
+                case TokenType.AlphaNumeric:
+                    tokens.Consume();
+                    return token.Value;
+                default:
+                    throw token.Throw();
+            }
+        }
+		internal static void AppendAscii(MemoryStream target, string ascii)
+		{
+			foreach (char c in ascii)
+				target.WriteByte(checked((byte)c));
+		}
+		internal static void AppendByte(MemoryStream target, ref uint codePoint, ref int len)
+		{
+			if (len != 0)
+			{
+				target.WriteByte(checked((byte)codePoint));
+			}
+			codePoint = 0;
+			len = 0;
+		}
+		internal static unsafe void AppendNormalized(MemoryStream target, ref uint codePoint, ref int len)
+		{
+			if (len == 0)
+			{
+				codePoint = 0;
+				return;
+			}
+			byte* b = stackalloc byte[10];
+			char c = checked((char)codePoint);
+			int count = Encoding.UTF8.GetBytes(&c, 1, b, 10);
+			for (int i = 0; i < count; i++)
+			{
+				target.WriteByte(b[i]);
+			}
+		}
+		internal static void AppendEscaped(MemoryStream target, char c)
+		{
+			uint codePoint;
+			switch (c)
+			{
+				// encoded as octal
+				case 'a': codePoint = '\a'; break;
+				case 'b': codePoint = '\b'; break;
+				case 'f': codePoint = '\f'; break;
+				case 'v': codePoint = '\v'; break;
+				case 't': codePoint = '\t'; break;
+				case 'n': codePoint = '\n'; break;
+				case 'r': codePoint = '\r'; break;
+
+				case '\\':
+				case '?':
+				case '\'':
+				case '\"':
+					codePoint = c;
+					break;
+				default:
+					codePoint = '?';
+					break;
+			}
+			int len = 1;
+			AppendNormalized(target, ref codePoint, ref len);
+		}
+		internal static bool GetHexValue(char c, out uint val, ref int len)
+		{
+			len++;
+			if (c >= '0' && c <= '9')
+			{
+				val = (uint)c - (uint)'0';
+				return true;
+			}
+			if (c >= 'a' && c <= 'f')
+			{
+				val = 10 + (uint)c - (uint)'a';
+				return true;
+			}
+			if (c >= 'A' && c <= 'F')
+			{
+				val = 10 + (uint)c - (uint)'A';
+				return true;
+			}
+			len--;
+			val = 0;
+			return false;
+		}
+        // the normalized output *includes* the slashes, but expands octal to 3 places;
+        // it is the job of codegen to change this normalized form to the target language form
+        internal static void ReadStringBytes(ref MemoryStream ms, string value)
+        {
+            const int STATE_NORMAL = 0, STATE_ESCAPE = 1, STATE_OCTAL = 2, STATE_HEX = 3;
+            int state = STATE_NORMAL;
+            if (value == null || value.Length == 0) return;
+
+            if (ms == null) ms = new MemoryStream(value.Length);
+            uint escapedCodePoint = 0;
+            int escapeLength = 0;
+            foreach (char c in value)
+            {
+                switch (state)
+                {
+                    case STATE_ESCAPE:
+                        if (c >= '0' && c <= '7')
+                        {
+                            state = STATE_OCTAL;
+                            GetHexValue(c, out escapedCodePoint, ref escapeLength); // not a typo; all 1-char octal values are also the same in hex
+                        }
+                        else if (c == 'x')
+                        {
+                            state = STATE_HEX;
+                        }
+                        else if (c == 'u' || c == 'U')
+                        {
+                            throw new NotSupportedException("Unicode escape points: on my todo list");
+                        }
+                        else
+                        {
+                            state = STATE_NORMAL;
+                            AppendEscaped(ms, c);
+                        }
+                        break;
+                    case STATE_OCTAL:
+                        if (c >= '0' && c <= '7')
+                        {
+                            uint x;
+                            GetHexValue(c, out x, ref escapeLength);
+                            escapedCodePoint = (escapedCodePoint << 3) | x;
+                            if (escapeLength == 3)
+                            {
+                                AppendByte(ms, ref escapedCodePoint, ref escapeLength);
+                                state = STATE_NORMAL;
+                            }
+                        }
+                        else
+                        {
+                            // not an octal char - regular append
+                            if (escapeLength == 0)
+                            {
+                                // include the malformed \x
+                                AppendAscii(ms, @"\x");
+                            }
+                            else
+                            {
+                                AppendByte(ms, ref escapedCodePoint, ref escapeLength);
+                            }
+                            state = STATE_NORMAL;
+                            goto case STATE_NORMAL;
+                        }
+                        break;
+                    case STATE_HEX:
+                        {
+                            uint x;
+                            if (GetHexValue(c, out x, ref escapeLength))
+                            {
+                                escapedCodePoint = (escapedCodePoint << 4) | x;
+                                if (escapeLength == 2)
+                                {
+                                    AppendByte(ms, ref escapedCodePoint, ref escapeLength);
+                                    state = STATE_NORMAL;
+                                }
+                            }
+                            else
+                            {
+                                // not a hex char - regular append
+                                AppendByte(ms, ref escapedCodePoint, ref escapeLength);
+                                state = STATE_NORMAL;
+                                goto case STATE_NORMAL;
+                            }
+                        }
+                        break;
+                    case STATE_NORMAL:
+                        if (c == '\\')
+                        {
+                            state = STATE_ESCAPE;
+                        }
+                        else
+                        {
+                            uint codePoint = (uint)c;
+                            int len = 1;
+                            AppendNormalized(ms, ref codePoint, ref len);
+                        }
+                        break;
+                    default:
+                        throw new InvalidOperationException();
+                }
+            }
+            // append any trailing escaped data
+            AppendByte(ms, ref escapedCodePoint, ref escapeLength);
+        }
+
+        internal static bool ConsumeBoolean(this Peekable<Token> tokens)
+        {
+            var token = tokens.Read();
+            token.Assert(TokenType.AlphaNumeric);
+            tokens.Consume();
+            if (string.Equals("true", token.Value, StringComparison.OrdinalIgnoreCase)) return true;
+            if (string.Equals("false", token.Value, StringComparison.OrdinalIgnoreCase)) return false;
+            throw token.Throw("Unable to parse boolean");
+        }
+
+        static TokenType Identify(char c)
+        {
+            if (c == '"' || c == '\'') return TokenType.StringLiteral;
+            if (char.IsWhiteSpace(c)) return TokenType.Whitespace;
+            if (char.IsLetterOrDigit(c)) return TokenType.AlphaNumeric;
+            switch (c)
+            {
+                case '_':
+                case '.':
+                case '-':
+                    return TokenType.AlphaNumeric;
+            }
+            return TokenType.Symbol;
+        }
+
+        public static IEnumerable<Token> RemoveCommentsAndWhitespace(this IEnumerable<Token> tokens)
+        {
+            int commentLineNumber = -1;
+            bool isBlockComment = false;
+            foreach (var token in tokens)
+            {
+                if (isBlockComment)
+                {
+                    // swallow everything until the end of the block comment
+                    if (token.Is(TokenType.Symbol, "*/"))
+                        isBlockComment = false;
+                }
+                else if (commentLineNumber == token.LineNumber)
+                {
+                    // swallow everything else on that line
+                }
+                else if (token.Is(TokenType.Whitespace))
+                {
+                    continue;
+                }
+                else if (token.Is(TokenType.Symbol, "//"))
+                {
+                    commentLineNumber = token.LineNumber;
+                }
+                else if (token.Is(TokenType.Symbol, "/*"))
+                {
+                    isBlockComment = true;
+                }
+                else
+                {
+                    yield return token;
+                }
+            }
+        }
+
+        static bool CanCombine(TokenType type, int len, char prev, char next)
+            => type != TokenType.Symbol
+            || (len == 1 && prev == '/' && (next == '/' || next == '*'))
+            || (len == 1 && prev == '*' && next == '/');
+
+
+        public static IEnumerable<Token> Tokenize(this TextReader reader, string file)
+        {
+            var buffer = new StringBuilder();
+
+            int lineNumber = 0, offset = 0;
+            string line;
+            string lastLine = null;
+            while ((line = reader.ReadLine()) != null)
+            {
+                lastLine = line;
+                lineNumber++;
+                int columnNumber = 0, tokenStart = 1;
+                char lastChar = '\0', stringType = '\0';
+                TokenType type = TokenType.None;
+                bool isEscaped = false;
+                foreach (char c in line)
+                {
+                    columnNumber++;
+                    if (type == TokenType.StringLiteral)
+                    {
+                        if (c == stringType && !isEscaped)
+                        {
+                            yield return new Token(buffer.ToString(), lineNumber, tokenStart, type, line, offset++, file);
+                            buffer.Clear();
+                            type = TokenType.None;
+                        }
+                        else
+                        {
+                            buffer.Append(c);
+                            isEscaped = !isEscaped && c == '\\'; // ends an existing escape or starts a new one
+                        }
+                    }
+                    else
+                    {
+                        var newType = Identify(c);
+                        if (newType == type && CanCombine(type, buffer.Length, lastChar, c))
+                        {
+                            buffer.Append(c);
+                        }
+                        else
+                        {
+                            if (buffer.Length != 0)
+                            {
+                                yield return new Token(buffer.ToString(), lineNumber, tokenStart, type, line, offset++, file);
+                                buffer.Clear();
+                            }
+                            type = newType;
+                            tokenStart = columnNumber;
+                            if (newType == TokenType.StringLiteral)
+                            {
+                                stringType = c;
+                            }
+                            else
+                            {
+                                buffer.Append(c);
+                            }
+                        }
+                    }
+                    lastChar = c;
+                }
+
+                if (buffer.Length != 0)
+                {
+                    yield return new Token(buffer.ToString(), lineNumber, tokenStart, type, lastLine, offset++, file);
+                    buffer.Clear();
+                }
+            }
+
+        }
+        internal static bool TryParseSingle(string token, out float val)
+        {
+            if (token == "nan")
+            {
+                val = float.NaN;
+                return true;
+            }
+            if (token == "inf")
+            {
+                val = float.PositiveInfinity;
+                return true;
+            }
+            if (token == "-inf")
+            {
+                val = float.NegativeInfinity;
+                return true;
+            }
+            return float.TryParse(token, NumberStyles.Number | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out val);
+        }
+        internal static bool TryParseDouble(string token, out double val)
+        {
+            if(token == "nan")
+            {
+                val = double.NaN;
+                return true;
+            }
+            if(token == "inf")
+            {
+                val = double.PositiveInfinity;
+                return true;
+            }
+            if(token == "-inf")
+            {
+                val = double.NegativeInfinity;
+                return true;
+            }
+            return double.TryParse(token, NumberStyles.Number | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out val);
+        }
+    }
+}
+

+ 12 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/TokenExtensions.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 976194549766e5246a08024fee47bf05
+timeCreated: 1517401477
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 11 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/TokenType.cs

@@ -0,0 +1,11 @@
+namespace ProtoBuf.Reflection
+{
+    internal enum TokenType
+    {
+        None,
+        Whitespace,
+        StringLiteral,
+        AlphaNumeric,
+        Symbol
+    }
+}

+ 12 - 0
Unity/Assets/ThirdParty/Protobuf/Editor/protobuf-net.Reflection/TokenType.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 08d254e5562c1da4697c61fdd75c708d
+timeCreated: 1517401476
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 68 - 0
Unity/Assets/ThirdParty/Protobuf/IExtensibleAdapter.cs

@@ -0,0 +1,68 @@
+using UnityEngine;
+using System.Collections.Generic;
+using ILRuntime.Other;
+using System;
+using System.Collections;
+using ILRuntime.Runtime.Enviorment;
+using ILRuntime.Runtime.Intepreter;
+using ILRuntime.CLR.Method;
+using ProtoBuf;
+
+namespace ProtoBuf
+{
+    public sealed class IExtensibleAdapter : CrossBindingAdaptor
+    {
+        public override Type BaseCLRType
+        {
+            get
+            {
+                return typeof(IExtensible);
+            }
+        }
+
+        public override Type AdaptorType
+        {
+            get
+            {
+                return typeof(Adaptor);
+            }
+        }
+
+        public override object CreateCLRInstance(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance)
+        {
+            return new Adaptor(appdomain, instance);
+        }
+
+        internal class Adaptor : IExtensible, CrossBindingAdaptorType
+        {
+            ILTypeInstance instance;
+            ILRuntime.Runtime.Enviorment.AppDomain appdomain;
+
+            public Adaptor():base()
+            {
+
+            }
+
+            public Adaptor(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance)
+            {
+                this.appdomain = appdomain;
+                this.instance = instance;
+                Init();
+            }
+
+            public ILTypeInstance ILInstance { get { return instance; } }
+
+            public IExtension GetExtensionObject(bool createIfMissing)
+            {
+                return appdomain.Invoke(mMethoGetExObject, instance, createIfMissing) as IExtension;
+            }
+
+            IMethod mMethoGetExObject;
+
+            void Init()
+            {
+                mMethoGetExObject = instance.Type.GetMethod("GetExtensionObject",0);
+            }
+        }
+    }
+}

+ 12 - 0
Unity/Assets/ThirdParty/Protobuf/IExtensibleAdapter.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: deb7df5df8979fc41b9d1f55b5029958
+timeCreated: 1517401477
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 2 - 2
Unity/Assets/Plugins/protobuf-net.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 1955d356bbec05042969173ba13e7ce0
+guid: 7e3f7b5d5d9676f41a4e50538fcade57
 folderAsset: yes
-timeCreated: 1513686875
+timeCreated: 1517401476
 licenseType: Free
 DefaultImporter:
   userData: 

+ 186 - 14
Unity/Assets/Plugins/protobuf-net/BclHelpers.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/BclHelpers.cs

@@ -34,23 +34,63 @@ namespace ProtoBuf
         /// <exception cref="NotSupportedException">If the platform does not support constructor-skipping</exception>
         public static object GetUninitializedObject(Type type)
         {
-#if PLAT_BINARYFORMATTER && !(WINRT || PHONE8)
+#if COREFX
+            object obj = TryGetUninitializedObjectWithFormatterServices(type);
+            if (obj != null) return obj;
+#endif
+#if PLAT_BINARYFORMATTER && !(WINRT || PHONE8 || COREFX)
             return System.Runtime.Serialization.FormatterServices.GetUninitializedObject(type);
 #else
             throw new NotSupportedException("Constructor-skipping is not supported on this platform");
 #endif
         }
+
+#if COREFX // this is inspired by DCS: https://github.com/dotnet/corefx/blob/c02d33b18398199f6acc17d375dab154e9a1df66/src/System.Private.DataContractSerialization/src/System/Runtime/Serialization/XmlFormatReaderGenerator.cs#L854-L894
+        static Func<Type, object> getUninitializedObject;
+        static internal object TryGetUninitializedObjectWithFormatterServices(Type type)
+        {
+            if (getUninitializedObject == null)
+            {
+                try {
+                    var formatterServiceType = typeof(string).GetTypeInfo().Assembly.GetType("System.Runtime.Serialization.FormatterServices");
+                    MethodInfo method = formatterServiceType?.GetMethod("GetUninitializedObject", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
+                    if (method != null)
+                    {
+                        getUninitializedObject = (Func<Type, object>)method.CreateDelegate(typeof(Func<Type, object>));
+                    }
+                }
+                catch  { /* best efforts only */ }
+                if(getUninitializedObject == null) getUninitializedObject = x => null;
+            }
+            return getUninitializedObject(type);
+        }
+#endif
+
 #if FX11
         private BclHelpers() { } // not a static class for C# 1.2 reasons
 #endif
-        const int FieldTimeSpanValue = 0x01, FieldTimeSpanScale = 0x02;
-        
-        internal static readonly DateTime EpochOrigin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
+        const int FieldTimeSpanValue = 0x01, FieldTimeSpanScale = 0x02, FieldTimeSpanKind = 0x03;
+
+        internal static readonly DateTime[] EpochOrigin = {
+            new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified),
+            new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc),
+            new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Local)
+        };
+
+        /// <summary>
+        /// The default value for dates that are following google.protobuf.Timestamp semantics
+        /// </summary>
+        private static readonly DateTime TimestampEpoch = EpochOrigin[(int)DateTimeKind.Utc];
+
 
         /// <summary>
-        /// Writes a TimeSpan to a protobuf stream
+        /// Writes a TimeSpan to a protobuf stream using protobuf-net's own representation, bcl.TimeSpan
         /// </summary>
         public static void WriteTimeSpan(TimeSpan timeSpan, ProtoWriter dest)
+        {
+            WriteTimeSpanImpl(timeSpan, dest, DateTimeKind.Unspecified);
+        }
+        private static void WriteTimeSpanImpl(TimeSpan timeSpan, ProtoWriter dest, DateTimeKind kind)
         {
             if (dest == null) throw new ArgumentNullException("dest");
             long value;
@@ -110,6 +150,11 @@ namespace ProtoBuf
                         ProtoWriter.WriteFieldHeader(FieldTimeSpanScale, WireType.Variant, dest);
                         ProtoWriter.WriteInt32((int)scale, dest);
                     }
+                    if(kind != DateTimeKind.Unspecified)
+                    {
+                        ProtoWriter.WriteFieldHeader(FieldTimeSpanKind, WireType.Variant, dest);
+                        ProtoWriter.WriteInt32((int)kind, dest);
+                    }
                     ProtoWriter.EndSubItem(token, dest);
                     break;
                 case WireType.Fixed64:
@@ -120,29 +165,141 @@ namespace ProtoBuf
             }
         }
         /// <summary>
-        /// Parses a TimeSpan from a protobuf stream
+        /// Parses a TimeSpan from a protobuf stream using protobuf-net's own representation, bcl.TimeSpan
         /// </summary>        
         public static TimeSpan ReadTimeSpan(ProtoReader source)
         {
-            long ticks = ReadTimeSpanTicks(source);
+            DateTimeKind kind;
+            long ticks = ReadTimeSpanTicks(source, out kind);
             if (ticks == long.MinValue) return TimeSpan.MinValue;
             if (ticks == long.MaxValue) return TimeSpan.MaxValue;
             return TimeSpan.FromTicks(ticks);
         }
+
+        /// <summary>
+        /// Parses a TimeSpan from a protobuf stream using the standardized format, google.protobuf.Duration
+        /// </summary>
+        public static TimeSpan ReadDuration(ProtoReader source)
+        {
+            long seconds = 0;
+            int nanos = 0;
+            SubItemToken token = ProtoReader.StartSubItem(source);
+            int fieldNumber;
+            while ((fieldNumber = source.ReadFieldHeader()) > 0)
+            {
+                switch (fieldNumber)
+                {
+                    case 1:
+                        seconds = source.ReadInt64();
+                        break;
+                    case 2:
+                        nanos = source.ReadInt32();
+                        break;
+                    default:
+                        source.SkipField();
+                        break;
+                }
+            }
+            ProtoReader.EndSubItem(token, source);
+            return FromDurationSeconds(seconds, nanos);
+        }
+
+        /// <summary>
+        /// Writes a TimeSpan to a protobuf stream using the standardized format, google.protobuf.Duration
+        /// </summary>
+        public static void WriteDuration(TimeSpan value, ProtoWriter dest)
+        {
+			int nanos;
+            var seconds = ToDurationSeconds(value, out nanos);
+            WriteSecondsNanos(seconds, nanos, dest);
+        }
+        private static void WriteSecondsNanos(long seconds, int nanos, ProtoWriter dest)
+        {
+            SubItemToken token = ProtoWriter.StartSubItem(null, dest);
+            if (seconds != 0)
+            {
+                ProtoWriter.WriteFieldHeader(1, WireType.Variant, dest);
+                ProtoWriter.WriteInt64(seconds, dest);
+            }
+            if (nanos != 0)
+            {
+                ProtoWriter.WriteFieldHeader(2, WireType.Variant, dest);
+                ProtoWriter.WriteInt32(nanos, dest);
+            }
+            ProtoWriter.EndSubItem(token, dest);
+        }
+
+        /// <summary>
+        /// Parses a DateTime from a protobuf stream using the standardized format, google.protobuf.Timestamp
+        /// </summary>
+        public static DateTime ReadTimestamp(ProtoReader source)
+        {
+            // note: DateTime is only defined for just over 0000 to just below 10000;
+            // TimeSpan has a range of +/- 10,675,199 days === 29k years;
+            // so we can just use epoch time delta
+            return TimestampEpoch + ReadDuration(source);
+        }
+
+        /// <summary>
+        /// Writes a DateTime to a protobuf stream using the standardized format, google.protobuf.Timestamp
+        /// </summary>
+        public static void WriteTimestamp(DateTime value, ProtoWriter dest)
+        {
+			int nanos;
+            var seconds = ToDurationSeconds(value - TimestampEpoch, out nanos);
+            
+            if (nanos < 0)
+            {   // from Timestamp.proto:
+                // "Negative second values with fractions must still have
+                // non -negative nanos values that count forward in time."
+                seconds--;
+                nanos += 1000000000;
+            }
+            WriteSecondsNanos(seconds, nanos, dest);
+        }
+        
+        static TimeSpan FromDurationSeconds(long seconds, int nanos)
+        {
+            
+            long ticks = checked((seconds * TimeSpan.TicksPerSecond)
+                + (nanos * TimeSpan.TicksPerMillisecond) / 1000000);
+            return TimeSpan.FromTicks(ticks);
+        }
+        static long ToDurationSeconds(TimeSpan value, out int nanos)
+        {
+            nanos = (int)(((value.Ticks % TimeSpan.TicksPerSecond) * 1000000)
+                / TimeSpan.TicksPerMillisecond);
+            return value.Ticks / TimeSpan.TicksPerSecond;
+        }
+
         /// <summary>
         /// Parses a DateTime from a protobuf stream
         /// </summary>
         public static DateTime ReadDateTime(ProtoReader source)
         {
-            long ticks = ReadTimeSpanTicks(source);
+            DateTimeKind kind;
+            long ticks = ReadTimeSpanTicks(source, out kind);
             if (ticks == long.MinValue) return DateTime.MinValue;
             if (ticks == long.MaxValue) return DateTime.MaxValue;
-            return EpochOrigin.AddTicks(ticks);
+            return EpochOrigin[(int)kind].AddTicks(ticks);
         }
+
         /// <summary>
-        /// Writes a DateTime to a protobuf stream
+        /// Writes a DateTime to a protobuf stream, excluding the <c>Kind</c>
         /// </summary>
         public static void WriteDateTime(DateTime value, ProtoWriter dest)
+        {
+            WriteDateTimeImpl(value, dest, false);
+        }
+        /// <summary>
+        /// Writes a DateTime to a protobuf stream, including the <c>Kind</c>
+        /// </summary>
+        public static void WriteDateTimeWithKind(DateTime value, ProtoWriter dest)
+        {
+            WriteDateTimeImpl(value, dest, true);
+        }
+
+        private static void WriteDateTimeImpl(DateTime value, ProtoWriter dest, bool includeKind)
         {
             if (dest == null) throw new ArgumentNullException("dest");
             TimeSpan delta;
@@ -153,24 +310,27 @@ namespace ProtoBuf
                     if (value == DateTime.MaxValue)
                     {
                         delta = TimeSpan.MaxValue;
+                        includeKind = false;
                     }
                     else if (value == DateTime.MinValue)
                     {
                         delta = TimeSpan.MinValue;
+                        includeKind = false;
                     }
                     else
                     {
-                        delta = value - EpochOrigin;
+                        delta = value - EpochOrigin[0];
                     }
                     break;
                 default:
-                    delta = value - EpochOrigin;
+                    delta = value - EpochOrigin[0];
                     break;
             }
-            WriteTimeSpan(delta, dest);
+            WriteTimeSpanImpl(delta, dest, includeKind ? value.Kind : DateTimeKind.Unspecified);
         }
 
-        private static long ReadTimeSpanTicks(ProtoReader source) {
+        private static long ReadTimeSpanTicks(ProtoReader source, out DateTimeKind kind) {
+            kind = DateTimeKind.Unspecified;
             switch (source.WireType)
             {
                 case WireType.String:
@@ -190,6 +350,18 @@ namespace ProtoBuf
                                 source.Assert(WireType.SignedVariant);
                                 value = source.ReadInt64();
                                 break;
+                            case FieldTimeSpanKind:
+                                kind = (DateTimeKind)source.ReadInt32();
+                                switch(kind)
+                                {
+                                    case DateTimeKind.Unspecified:
+                                    case DateTimeKind.Utc:
+                                    case DateTimeKind.Local:
+                                        break; // fine
+                                    default:
+                                        throw new ProtoException("Invalid date/time kind: " + kind.ToString());
+                                }
+                                break;
                             default:
                                 source.SkipField();
                                 break;

+ 3 - 3
Unity/Assets/Plugins/protobuf-net/BclHelpers.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/BclHelpers.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 69695e052455cac449470837a9e61a5d
-timeCreated: 1515899113
-licenseType: Pro
+guid: 117bb096fd64caf4b857526ec7fb5180
+timeCreated: 1517401476
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 8 - 2
Unity/Assets/Plugins/protobuf-net/BufferExtension.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/BufferExtension.cs

@@ -6,10 +6,16 @@ namespace ProtoBuf
     /// <summary>
     /// Provides a simple buffer-based implementation of an <see cref="IExtension">extension</see> object.
     /// </summary>
-    public sealed class BufferExtension : IExtension
+    public sealed class BufferExtension : IExtension, IExtensionResettable
     {
         private byte[] buffer;
 
+
+        void IExtensionResettable.Reset()
+        {
+            buffer = null;
+        }
+
         int IExtension.GetLength()
         {
             return buffer == null ? 0 : buffer.Length;
@@ -52,7 +58,7 @@ namespace ProtoBuf
                         if(len != 0) throw new EndOfStreamException();
                         ms.Position = oldPos;
 #else
-                        Helpers.BlockCopy(ms.GetBuffer(), 0, tmp, offset, len);
+                        Helpers.BlockCopy(Helpers.GetBuffer(ms), 0, tmp, offset, len);
 #endif
                         buffer = tmp;
                     }

+ 3 - 3
Unity/Assets/Plugins/protobuf-net/BufferExtension.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/BufferExtension.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 35d4c37b88b78c74b9028da5eca9152b
-timeCreated: 1515899112
-licenseType: Pro
+guid: 3132d0d6b75fda64989c6c6641f7efce
+timeCreated: 1517401476
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 0 - 0
Unity/Assets/Plugins/protobuf-net/BufferPool.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/BufferPool.cs


+ 3 - 3
Unity/Assets/Plugins/protobuf-net/BufferPool.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/BufferPool.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 0af08889f498edd47ae2a63d9852bb97
-timeCreated: 1515899112
-licenseType: Pro
+guid: ef21c7976ac381a44949e10d6781c16f
+timeCreated: 1517401477
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 4 - 4
Unity/Assets/Plugins/protobuf-net/CallbackAttributes.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/CallbackAttributes.cs

@@ -5,28 +5,28 @@ namespace ProtoBuf
 {
     /// <summary>Specifies a method on the root-contract in an hierarchy to be invoked before serialization.</summary>
     [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
-#if !CF && !SILVERLIGHT && !MONODROID && !WINRT && !IOS && !PORTABLE
+#if !CF && !SILVERLIGHT && !MONODROID && !WINRT && !IOS && !PORTABLE && !COREFX
     [ImmutableObject(true)]
 #endif
     public sealed class ProtoBeforeSerializationAttribute : Attribute { }
 
     /// <summary>Specifies a method on the root-contract in an hierarchy to be invoked after serialization.</summary>
     [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
-#if !CF && !SILVERLIGHT && !MONODROID && !WINRT && !IOS && !PORTABLE
+#if !CF && !SILVERLIGHT && !MONODROID && !WINRT && !IOS && !PORTABLE && !COREFX
     [ImmutableObject(true)]
 #endif
     public sealed class ProtoAfterSerializationAttribute : Attribute { }
 
     /// <summary>Specifies a method on the root-contract in an hierarchy to be invoked before deserialization.</summary>
     [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
-#if !CF && !SILVERLIGHT && !MONODROID && !WINRT && !IOS && !PORTABLE
+#if !CF && !SILVERLIGHT && !MONODROID && !WINRT && !IOS && !PORTABLE && !COREFX
     [ImmutableObject(true)]
 #endif
     public sealed class ProtoBeforeDeserializationAttribute : Attribute { }
 
     /// <summary>Specifies a method on the root-contract in an hierarchy to be invoked after deserialization.</summary>
     [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
-#if !CF && !SILVERLIGHT && !MONODROID && !WINRT && !IOS && !PORTABLE
+#if !CF && !SILVERLIGHT && !MONODROID && !WINRT && !IOS && !PORTABLE && !COREFX
     [ImmutableObject(true)]
 #endif
     public sealed class ProtoAfterDeserializationAttribute : Attribute { }

+ 3 - 3
Unity/Assets/Plugins/protobuf-net/CallbackAttributes.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/CallbackAttributes.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: d9062a6e5fc89b34e83029c618bd923f
-timeCreated: 1515899114
-licenseType: Pro
+guid: 5e39176d147cadf4ea7851f529ad0c02
+timeCreated: 1517401476
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 3 - 3
Unity/Assets/Plugins/protobuf-net/Compiler.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Compiler.meta

@@ -1,8 +1,8 @@
 fileFormatVersion: 2
-guid: aaa90da5f976d9847b630b506f37fe57
+guid: 438ec840d2d93ce4caaa7c4dc525845f
 folderAsset: yes
-timeCreated: 1515899111
-licenseType: Pro
+timeCreated: 1517401476
+licenseType: Free
 DefaultImporter:
   userData: 
   assetBundleName: 

+ 224 - 167
Unity/Assets/Plugins/protobuf-net/Compiler/CompilerContext.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Compiler/CompilerContext.cs

@@ -41,13 +41,33 @@ namespace ProtoBuf.Compiler
             CodeLabel result = new CodeLabel(il.DefineLabel(), nextLabel++);
             return result;
         }
-        internal void MarkLabel(CodeLabel label)
+#if DEBUG_COMPILE
+        static readonly string traceCompilePath;
+        static CompilerContext()
+        {
+            traceCompilePath = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(),
+                "TraceCompile.txt");
+            Console.WriteLine("DEBUG_COMPILE enabled; writing to " + traceCompilePath);
+        }
+#endif
+        [System.Diagnostics.Conditional("DEBUG_COMPILE")]
+        private void TraceCompile(string value)
         {
-            il.MarkLabel(label.Value);
 #if DEBUG_COMPILE
-            Helpers.DebugWriteLine("#: " + label.Index);
+            if (!string.IsNullOrWhiteSpace(value))
+            {
+                using (System.IO.StreamWriter sw = System.IO.File.AppendText(traceCompilePath))
+                {
+                    sw.WriteLine(value);
+                }
+            }
 #endif
         }
+        internal void MarkLabel(CodeLabel label)
+        {
+            il.MarkLabel(label.Value);
+            TraceCompile("#: " + label.Index);
+        }
 
 #if !(FX11 || FEAT_IKVM)
         public static ProtoSerializer BuildSerializer(IProtoSerializer head, TypeModel model)
@@ -107,7 +127,7 @@ namespace ProtoBuf.Compiler
             
             using (Local typedVal = new Local(ctx, type))
             {
-                if (!type.IsValueType)
+                if (!Helpers.IsValueType(type))
                 {
                     ctx.LoadValue(ctx.InputValue);
                     ctx.CastFromObject(type);
@@ -161,19 +181,15 @@ namespace ProtoBuf.Compiler
         {
             if(IsObject(type))
             { }
-            else if (type.IsValueType)
+            else if (Helpers.IsValueType(type))
             {
                 il.Emit(OpCodes.Box, type);
-#if DEBUG_COMPILE
-                Helpers.DebugWriteLine(OpCodes.Box + ": " + type);
-#endif
+                TraceCompile(OpCodes.Box + ": " + type);
             }
             else
             {
                 il.Emit(OpCodes.Castclass, MapType(typeof(object)));
-#if DEBUG_COMPILE
-                Helpers.DebugWriteLine(OpCodes.Castclass + ": " + type);
-#endif
+                TraceCompile(OpCodes.Castclass + ": " + type);
             }
         }
 
@@ -181,26 +197,22 @@ namespace ProtoBuf.Compiler
         {
             if (IsObject(type))
             { }
-            else if (type.IsValueType)
+            else if (Helpers.IsValueType(type))
             {
                 switch (MetadataVersion)
                 {
                     case ILVersion.Net1:
                         il.Emit(OpCodes.Unbox, type);
                         il.Emit(OpCodes.Ldobj, type);
-#if DEBUG_COMPILE
-                        Helpers.DebugWriteLine(OpCodes.Unbox + ": " + type);
-                        Helpers.DebugWriteLine(OpCodes.Ldobj + ": " + type);
-#endif
+                        TraceCompile(OpCodes.Unbox + ": " + type);
+                        TraceCompile(OpCodes.Ldobj + ": " + type);
                         break;
                     default:
 #if FX11
                         throw new NotSupportedException();
 #else
                         il.Emit(OpCodes.Unbox_Any, type);
-#if DEBUG_COMPILE
-                        Helpers.DebugWriteLine(OpCodes.Unbox_Any + ": " + type);
-#endif
+                        TraceCompile(OpCodes.Unbox_Any + ": " + type);
                         break;
 #endif
                 }
@@ -208,9 +220,7 @@ namespace ProtoBuf.Compiler
             else
             {
                 il.Emit(OpCodes.Castclass, type);
-#if DEBUG_COMPILE
-                Helpers.DebugWriteLine(OpCodes.Castclass + ": " + type);
-#endif
+                TraceCompile(OpCodes.Castclass + ": " + type);
             }
         }
         private readonly bool isStatic;
@@ -258,7 +268,7 @@ namespace ProtoBuf.Compiler
         public Local InputValue { get { return inputValue; } }
 #if !(SILVERLIGHT || PHONE8)
         private readonly string assemblyName;
-        internal CompilerContext(ILGenerator il, bool isStatic, bool isWriter, RuntimeTypeModel.SerializerPair[] methodPairs, TypeModel model, ILVersion metadataVersion, string assemblyName, Type inputType)
+        internal CompilerContext(ILGenerator il, bool isStatic, bool isWriter, RuntimeTypeModel.SerializerPair[] methodPairs, TypeModel model, ILVersion metadataVersion, string assemblyName, Type inputType, string traceName)
         {
             if (il == null) throw new ArgumentNullException("il");
             if (methodPairs == null) throw new ArgumentNullException("methodPairs");
@@ -273,6 +283,7 @@ namespace ProtoBuf.Compiler
             this.model = model;
             this.metadataVersion = metadataVersion;
             if (inputType != null) this.inputValue = new Local(null, inputType);
+            TraceCompile(">> " + traceName);
         }
 #endif
 #if !(FX11 || FEAT_IKVM)
@@ -306,9 +317,14 @@ namespace ProtoBuf.Compiler
 #else
             uniqueIdentifier = Interlocked.Increment(ref next);
 #endif
-            method = new DynamicMethod("proto_" + uniqueIdentifier.ToString(), returnType, paramTypes, associatedType.IsInterface ? typeof(object) : associatedType, true);
+            method = new DynamicMethod("proto_" + uniqueIdentifier.ToString(), returnType, paramTypes, associatedType
+#if COREFX
+                .GetTypeInfo()
+#endif
+                .IsInterface ? typeof(object) : associatedType, true);
             this.il = method.GetILGenerator();
             if (inputType != null) this.inputValue = new Local(null, inputType);
+            TraceCompile(">> " + method.Name);
         }
 
 #endif
@@ -317,9 +333,7 @@ namespace ProtoBuf.Compiler
         private void Emit(OpCode opcode)
         {
             il.Emit(opcode);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(opcode.ToString());
-#endif
+            TraceCompile(opcode.ToString());
         }
         public void LoadValue(string value)
         {
@@ -330,31 +344,23 @@ namespace ProtoBuf.Compiler
             else
             {
                 il.Emit(OpCodes.Ldstr, value);
-#if DEBUG_COMPILE
-                Helpers.DebugWriteLine(OpCodes.Ldstr + ": " + value);
-#endif
+                TraceCompile(OpCodes.Ldstr + ": " + value);
             }
         }
         public void LoadValue(float value)
         {
             il.Emit(OpCodes.Ldc_R4, value);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(OpCodes.Ldc_R4 + ": " + value);
-#endif
+            TraceCompile(OpCodes.Ldc_R4 + ": " + value);
         }
         public void LoadValue(double value)
         {
             il.Emit(OpCodes.Ldc_R8, value);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(OpCodes.Ldc_R8 + ": " + value);
-#endif
+            TraceCompile(OpCodes.Ldc_R8 + ": " + value);
         }
         public void LoadValue(long value)
         {
             il.Emit(OpCodes.Ldc_I8, value);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(OpCodes.Ldc_I8 + ": " + value);
-#endif
+            TraceCompile(OpCodes.Ldc_I8 + ": " + value);
         }
         public void LoadValue(int value)
         {
@@ -374,16 +380,12 @@ namespace ProtoBuf.Compiler
                     if (value >= -128 && value <= 127)
                     {
                         il.Emit(OpCodes.Ldc_I4_S, (sbyte)value);
-#if DEBUG_COMPILE
-                        Helpers.DebugWriteLine(OpCodes.Ldc_I4_S + ": " + value);
-#endif
+                        TraceCompile(OpCodes.Ldc_I4_S + ": " + value);
                     }
                     else
                     {
                         il.Emit(OpCodes.Ldc_I4, value);
-#if DEBUG_COMPILE
-                        Helpers.DebugWriteLine(OpCodes.Ldc_I4 + ": " + value);
-#endif
+                        TraceCompile(OpCodes.Ldc_I4 + ": " + value);
                     }
                     break;
 
@@ -404,9 +406,7 @@ namespace ProtoBuf.Compiler
                 }
             }
             LocalBuilder result = il.DeclareLocal(type);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine("$ " + result + ": " + type);
-#endif
+            TraceCompile("$ " + result + ": " + type);
             return result;
         }
         //
@@ -433,9 +433,7 @@ namespace ProtoBuf.Compiler
             {
                 byte b = isStatic ? (byte) 0 : (byte)1;
                 il.Emit(OpCodes.Starg_S, b);
-#if DEBUG_COMPILE
-                Helpers.DebugWriteLine(OpCodes.Starg_S + ": $" + b);
-#endif                
+                TraceCompile(OpCodes.Starg_S + ": $" + b);
             }
             else
             {
@@ -450,9 +448,7 @@ namespace ProtoBuf.Compiler
 #endif
                         OpCode code = UseShortForm(local) ? OpCodes.Stloc_S : OpCodes.Stloc;
                         il.Emit(code, local.Value);
-#if DEBUG_COMPILE
-                        Helpers.DebugWriteLine(code + ": $" + local.Value);
-#endif
+                        TraceCompile(code + ": $" + local.Value);
 #if !FX11
                         break;
                 }
@@ -479,9 +475,7 @@ namespace ProtoBuf.Compiler
 #endif             
                         OpCode code = UseShortForm(local) ? OpCodes.Ldloc_S :  OpCodes.Ldloc;
                         il.Emit(code, local.Value);
-#if DEBUG_COMPILE
-                        Helpers.DebugWriteLine(code + ": $" + local.Value);
-#endif
+                        TraceCompile(code + ": $" + local.Value);
 #if !FX11
                         break;
                 }
@@ -495,7 +489,7 @@ namespace ProtoBuf.Compiler
                 if (fromValue.Type == type) return fromValue.AsCopy();
                 // otherwise, load onto the stack and let the default handling (below) deal with it
                 LoadValue(fromValue);
-                if (!type.IsValueType && (fromValue.Type == null || !type.IsAssignableFrom(fromValue.Type)))
+                if (!Helpers.IsValueType(type) && (fromValue.Type == null || !type.IsAssignableFrom(fromValue.Type)))
                 { // need to cast
                     Cast(type);
                 }
@@ -552,15 +546,27 @@ namespace ProtoBuf.Compiler
             LoadReaderWriter();
             EmitCall(method);
         }
-        public void EmitCall(MethodInfo method)
+        public void EmitCall(MethodInfo method) { EmitCall(method, null); }
+        public void EmitCall(MethodInfo method, Type targetType)
         {
             Helpers.DebugAssert(method != null);
-            CheckAccessibility(method);
-            OpCode opcode = (method.IsStatic || method.DeclaringType.IsValueType) ? OpCodes.Call : OpCodes.Callvirt;
+            MemberInfo member = method;
+            CheckAccessibility(ref member);
+            OpCode opcode;
+            if (method.IsStatic || Helpers.IsValueType(method.DeclaringType))
+            {
+                opcode = OpCodes.Call; 
+            }
+            else
+            {
+                opcode = OpCodes.Callvirt;
+                if (targetType != null && Helpers.IsValueType(targetType) && !Helpers.IsValueType(method.DeclaringType))
+                {
+                    Constrain(targetType);
+                }
+            }
             il.EmitCall(opcode, method, null);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(opcode + ": " + method + " on " + method.DeclaringType);
-#endif
+            TraceCompile(opcode + ": " + method + " on " + method.DeclaringType + (targetType == null ? "" : (" via " + targetType)));
         }
         /// <summary>
         /// Pushes a null reference onto the stack. Note that this should only
@@ -576,7 +582,7 @@ namespace ProtoBuf.Compiler
 
         internal void WriteNullCheckedTail(Type type, IProtoSerializer tail, Compiler.Local valueFrom)
         {
-            if (type.IsValueType)
+            if (Helpers.IsValueType(type))
             {
                 Type underlyingType = null;
 #if !FX11
@@ -620,7 +626,7 @@ namespace ProtoBuf.Compiler
 #if !FX11
             Type underlyingType;
             
-            if (type.IsValueType && (underlyingType = Helpers.GetUnderlyingType(type)) != null)
+            if (Helpers.IsValueType(type) && (underlyingType = Helpers.GetUnderlyingType(type)) != null)
             {
                 if(tail.RequiresOldValue)
                 {
@@ -658,27 +664,34 @@ namespace ProtoBuf.Compiler
         public void EmitCtor(ConstructorInfo ctor)
         {
             if (ctor == null) throw new ArgumentNullException("ctor");
-            CheckAccessibility(ctor);
+            MemberInfo ctorMember = ctor;
+            CheckAccessibility(ref ctorMember);
             il.Emit(OpCodes.Newobj, ctor);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(OpCodes.Newobj + ": " + ctor.DeclaringType);
-#endif
+            TraceCompile(OpCodes.Newobj + ": " + ctor.DeclaringType);
         }
 
+        public void InitLocal(Type type, Compiler.Local target)
+        {
+            LoadAddress(target, type, evenIfClass: true); // for class, initobj is a load-null, store-indirect
+            il.Emit(OpCodes.Initobj, type);
+            TraceCompile(OpCodes.Initobj + ": " + type);
+        }
         public void EmitCtor(Type type, params Type[] parameterTypes)
         {
             Helpers.DebugAssert(type != null);
             Helpers.DebugAssert(parameterTypes != null);
-            if (type.IsValueType && parameterTypes.Length == 0)
+            if (Helpers.IsValueType(type) && parameterTypes.Length == 0)
             {
                 il.Emit(OpCodes.Initobj, type);
-#if DEBUG_COMPILE
-                Helpers.DebugWriteLine(OpCodes.Initobj + ": " + type);
-#endif
+                TraceCompile(OpCodes.Initobj + ": " + type);
             }
             else
             {
-                ConstructorInfo ctor =  Helpers.GetConstructor(type, parameterTypes, true);
+                ConstructorInfo ctor =  Helpers.GetConstructor(type
+#if COREFX
+                .GetTypeInfo()
+#endif
+                    , parameterTypes, true);
                 if (ctor == null) throw new InvalidOperationException("No suitable constructor found for " + type.FullName);
                 EmitCtor(ctor);
             }
@@ -723,7 +736,12 @@ namespace ProtoBuf.Compiler
                 }
             }
 #else
+
+#if COREFX
+            foreach (System.Runtime.CompilerServices.InternalsVisibleToAttribute attrib in assembly.GetCustomAttributes(attributeType))
+#else
             foreach (System.Runtime.CompilerServices.InternalsVisibleToAttribute attrib in assembly.GetCustomAttributes(attributeType, false))
+#endif
             {
                 if (attrib.AssemblyName == assemblyName || attrib.AssemblyName.StartsWith(assemblyName + ","))
                 {
@@ -745,18 +763,66 @@ namespace ProtoBuf.Compiler
             return isTrusted;
 #endif
         }
-        internal void CheckAccessibility(MemberInfo member)
+        internal void CheckAccessibility(ref MemberInfo member)
         {
             if (member == null)
             {
                 throw new ArgumentNullException("member");
             }
-
-            MemberTypes memberType = member.MemberType;
+#if ! COREFX
             Type type;
+#endif
             if (!NonPublic)
             {
+                if(member is FieldInfo && member.Name.StartsWith("<") & member.Name.EndsWith(">k__BackingField"))
+                {
+                    var propName = member.Name.Substring(1, member.Name.Length - 17);
+                    var prop = member.DeclaringType.GetProperty(propName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static);
+                    if (prop != null) member = prop;
+                }
                 bool isPublic;
+#if COREFX
+                if (member is TypeInfo)
+                {
+                    TypeInfo ti = (TypeInfo)member;
+                    do
+                    {
+                        isPublic = ti.IsNestedPublic || ti.IsPublic || ((ti.IsNested || ti.IsNestedAssembly || ti.IsNestedFamORAssem) && InternalsVisible(ti.Assembly));
+                    } while (isPublic && ti.IsNested && (ti = ti.DeclaringType.GetTypeInfo()) != null);
+                }
+                else if (member is FieldInfo)
+                {
+                    FieldInfo field = ((FieldInfo)member);
+                    isPublic = field.IsPublic || ((field.IsAssembly || field.IsFamilyOrAssembly) && InternalsVisible(Helpers.GetAssembly(field.DeclaringType)));
+                }
+                else if (member is PropertyInfo)
+                {
+                    isPublic = true; // defer to get/set
+                }
+                else if (member is ConstructorInfo)
+                {
+                    ConstructorInfo ctor = ((ConstructorInfo)member);
+                    isPublic = ctor.IsPublic || ((ctor.IsAssembly || ctor.IsFamilyOrAssembly) && InternalsVisible(Helpers.GetAssembly(ctor.DeclaringType)));
+                }
+                else if (member is MethodInfo)
+                {
+                    MethodInfo method = ((MethodInfo)member);
+                    isPublic = method.IsPublic || ((method.IsAssembly || method.IsFamilyOrAssembly) && InternalsVisible(Helpers.GetAssembly(method.DeclaringType)));
+                    if (!isPublic)
+                    {
+                        // allow calls to TypeModel protected methods, and methods we are in the process of creating
+                        if (
+                                member is MethodBuilder ||
+                                member.DeclaringType == MapType(typeof(TypeModel)))
+                            isPublic = true;
+                    }
+                }
+                else
+                {
+                    throw new NotSupportedException(member.GetType().Name);
+                }
+#else
+                MemberTypes memberType = member.MemberType;
                 switch (memberType)
                 {
                     case MemberTypes.TypeInfo:
@@ -788,7 +854,7 @@ namespace ProtoBuf.Compiler
                             if(
 #if !SILVERLIGHT
                                 member is MethodBuilder ||
-#endif                
+#endif
                                 member.DeclaringType == MapType(typeof(TypeModel))) isPublic = true; 
                         }
                         break;
@@ -798,8 +864,22 @@ namespace ProtoBuf.Compiler
                     default:
                         throw new NotSupportedException(memberType.ToString());
                 }
+#endif
                 if (!isPublic)
                 {
+#if COREFX
+                    if (member is TypeInfo)
+                    {
+                        throw new InvalidOperationException("Non-public type cannot be used with full dll compilation: " +
+                                ((TypeInfo)member).FullName);
+                    }
+                    else
+                    {
+                        throw new InvalidOperationException("Non-public member cannot be used with full dll compilation: " +
+                                member.DeclaringType.FullName + "." + member.Name);
+                    }
+
+#else
                     switch (memberType)
                     {
                         case MemberTypes.TypeInfo:
@@ -810,19 +890,26 @@ namespace ProtoBuf.Compiler
                             throw new InvalidOperationException("Non-public member cannot be used with full dll compilation: " +
                                 member.DeclaringType.FullName + "." + member.Name);
                     }
-                    
+#endif
+
                 }
             }
         }
 
         public void LoadValue(FieldInfo field)
         {
-            CheckAccessibility(field);
-            OpCode code = field.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld;
-            il.Emit(code, field);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(code + ": " + field + " on " + field.DeclaringType);
-#endif
+            MemberInfo member = field;
+            CheckAccessibility(ref member);
+            if (member is PropertyInfo)
+            {
+                LoadValue((PropertyInfo)member);
+            }
+            else
+            {
+                OpCode code = field.IsStatic ? OpCodes.Ldsfld : OpCodes.Ldfld;
+                il.Emit(code, field);
+                TraceCompile(code + ": " + field + " on " + field.DeclaringType);
+            }
         }
 #if FEAT_IKVM
         public void StoreValue(System.Reflection.FieldInfo field)
@@ -844,21 +931,30 @@ namespace ProtoBuf.Compiler
 #endif
         public void StoreValue(FieldInfo field)
         {
-            CheckAccessibility(field);
-            OpCode code = field.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld;
-            il.Emit(code, field);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(code + ": " + field + " on " + field.DeclaringType);
-#endif
+            MemberInfo member = field;
+            CheckAccessibility(ref member);
+            if (member is PropertyInfo)
+            {
+                StoreValue((PropertyInfo)member);
+            }
+            else
+            {
+                OpCode code = field.IsStatic ? OpCodes.Stsfld : OpCodes.Stfld;
+                il.Emit(code, field);
+                TraceCompile(code + ": " + field + " on " + field.DeclaringType);
+            }
         }
+        
         public void LoadValue(PropertyInfo property)
         {
-            CheckAccessibility(property);
+            MemberInfo member = property;
+            CheckAccessibility(ref member);
             EmitCall(Helpers.GetGetMethod(property, true, true));
         }
         public void StoreValue(PropertyInfo property)
         {
-            CheckAccessibility(property);
+            MemberInfo member = property;
+            CheckAccessibility(ref member);
             EmitCall(Helpers.GetSetMethod(property, true, true));
         }
 
@@ -900,29 +996,25 @@ namespace ProtoBuf.Compiler
             LoadAddress(local, MapType(type));
         }
 #endif
-        internal void LoadAddress(Local local, Type type)
+        internal void LoadAddress(Local local, Type type, bool evenIfClass = false)
         {
-            if (type.IsValueType)
+            if (evenIfClass || Helpers.IsValueType(type))
             {
                 if (local == null)
                 {
-                    throw new InvalidOperationException("Cannot load the address of a struct at the head of the stack");
+                    throw new InvalidOperationException("Cannot load the address of the head of the stack");
                 }
 
                 if (local == this.InputValue)
                 {
                     il.Emit(OpCodes.Ldarga_S, (isStatic ? (byte)0 : (byte)1));
-#if DEBUG_COMPILE
-                    Helpers.DebugWriteLine(OpCodes.Ldarga_S + ": $" + (isStatic ? 0 : 1));
-#endif
+                    TraceCompile(OpCodes.Ldarga_S + ": $" + (isStatic ? 0 : 1));
                 }
                 else
                 {
                     OpCode code = UseShortForm(local) ? OpCodes.Ldloca_S : OpCodes.Ldloca;
                     il.Emit(code, local.Value);
-#if DEBUG_COMPILE
-                    Helpers.DebugWriteLine(code + ": $" + local.Value);
-#endif
+                    TraceCompile(code + ": $" + local.Value);
                 }
 
             }
@@ -935,17 +1027,13 @@ namespace ProtoBuf.Compiler
         {
             OpCode code = @short ? OpCodes.Br_S : OpCodes.Br;
             il.Emit(code, label.Value);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(code + ": " + label.Index);
-#endif
+            TraceCompile(code + ": " + label.Index);
         }
         internal void BranchIfFalse(CodeLabel label, bool @short)
         {
             OpCode code = @short ? OpCodes.Brfalse_S :  OpCodes.Brfalse;
             il.Emit(code, label.Value);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(code + ": " + label.Index);
-#endif
+            TraceCompile(code + ": " + label.Index);
         }
 
 
@@ -953,17 +1041,13 @@ namespace ProtoBuf.Compiler
         {
             OpCode code = @short ? OpCodes.Brtrue_S : OpCodes.Brtrue;
             il.Emit(code, label.Value);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(code + ": " + label.Index);
-#endif
+            TraceCompile(code + ": " + label.Index);
         }
         internal void BranchIfEqual(CodeLabel label, bool @short)
         {
             OpCode code = @short ? OpCodes.Beq_S : OpCodes.Beq;
             il.Emit(code, label.Value);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(code + ": " + label.Index);
-#endif
+            TraceCompile(code + ": " + label.Index);
         }
         //internal void TestEqual()
         //{
@@ -980,18 +1064,14 @@ namespace ProtoBuf.Compiler
         {
             OpCode code = @short ? OpCodes.Bgt_S : OpCodes.Bgt;
             il.Emit(code, label.Value);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(code + ": " + label.Index);
-#endif
+            TraceCompile(code + ": " + label.Index);
         }
 
         internal void BranchIfLess(CodeLabel label, bool @short)
         {
             OpCode code = @short ? OpCodes.Blt_S : OpCodes.Blt;
             il.Emit(code, label.Value);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(code + ": " + label.Index);
-#endif
+            TraceCompile(code + ": " + label.Index);
         }
 
         internal void DiscardValue()
@@ -1018,9 +1098,7 @@ namespace ProtoBuf.Compiler
                 {
                     labels[i] = jumpTable[i].Value;
                 }
-#if DEBUG_COMPILE
-                Helpers.DebugWriteLine(OpCodes.Switch.ToString());
-#endif
+                TraceCompile(OpCodes.Switch.ToString());
                 il.Emit(OpCodes.Switch, labels);
             }
             else
@@ -1042,9 +1120,7 @@ namespace ProtoBuf.Compiler
                     LoadValue(val);
                     LoadValue(MAX_JUMPS);
                     Emit(OpCodes.Div);
-#if DEBUG_COMPILE
-                Helpers.DebugWriteLine(OpCodes.Switch.ToString());
-#endif
+                    TraceCompile(OpCodes.Switch.ToString());
                     il.Emit(OpCodes.Switch, blockLabels);
                     Branch(endOfSwitch, false);
 
@@ -1068,9 +1144,7 @@ namespace ProtoBuf.Compiler
                             LoadValue(subtract);
                             Emit(OpCodes.Sub);
                         }
-#if DEBUG_COMPILE
-                        Helpers.DebugWriteLine(OpCodes.Switch.ToString());
-#endif
+                        TraceCompile(OpCodes.Switch.ToString());
                         il.Emit(OpCodes.Switch, innerLabels);
                         if (count != 0)
                         { // force default to the very bottom
@@ -1086,60 +1160,50 @@ namespace ProtoBuf.Compiler
         internal void EndFinally()
         {
             il.EndExceptionBlock();
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine("EndExceptionBlock");
-#endif
+            TraceCompile("EndExceptionBlock");
         }
 
         internal void BeginFinally()
         {
             il.BeginFinallyBlock();
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine("BeginFinallyBlock");
-#endif
+            TraceCompile("BeginFinallyBlock");
         }
 
         internal void EndTry(CodeLabel label, bool @short)
         {
             OpCode code = @short ? OpCodes.Leave_S : OpCodes.Leave;
             il.Emit(code, label.Value);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(code + ": " + label.Index);
-#endif
+            TraceCompile(code + ": " + label.Index);
         }
 
         internal CodeLabel BeginTry()
         {
             CodeLabel label = new CodeLabel(il.BeginExceptionBlock(), nextLabel++);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine("BeginExceptionBlock: " + label.Index);
-#endif
+            TraceCompile("BeginExceptionBlock: " + label.Index);
             return label;
         }
-#if !FX11
+
         internal void Constrain(Type type)
         {
+#if FX11
+            throw new NotSupportedException("This operation requires a constrained call, which is not available on this platform");
+#else
             il.Emit(OpCodes.Constrained, type);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(OpCodes.Constrained + ": " + type);
+            TraceCompile(OpCodes.Constrained + ": " + type);
 #endif
         }
-#endif
+
 
         internal void TryCast(Type type)
         {
             il.Emit(OpCodes.Isinst, type);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(OpCodes.Isinst + ": " + type);
-#endif
+            TraceCompile(OpCodes.Isinst + ": " + type);
         }
 
         internal void Cast(Type type)
         {
             il.Emit(OpCodes.Castclass, type);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(OpCodes.Castclass + ": " + type);
-#endif
+            TraceCompile(OpCodes.Castclass + ": " + type);
         }
         public IDisposable Using(Local local)
         {
@@ -1166,7 +1230,7 @@ namespace ProtoBuf.Compiler
 
                 Type type = local.Type;
                 // check if **never** disposable
-                if ((type.IsValueType || type.IsSealed) &&
+                if ((Helpers.IsValueType(type) || Helpers.IsSealed(type)) &&
                     !ctx.MapType(typeof(IDisposable)).IsAssignableFrom(type))
                 {
                     return; // nothing to do! easiest "using" block ever
@@ -1189,7 +1253,7 @@ namespace ProtoBuf.Compiler
                 Type type = local.Type;
                 // remember that we've already (in the .ctor) excluded the case
                 // where it *cannot* be disposable
-                if (type.IsValueType)
+                if (Helpers.IsValueType(type))
                 {
                     ctx.LoadAddress(local, type);
                     switch (ctx.MetadataVersion)
@@ -1274,10 +1338,7 @@ namespace ProtoBuf.Compiler
         {
             LoadValue(length);
             il.Emit(OpCodes.Newarr, elementType);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(OpCodes.Newarr + ": " + elementType);
-#endif
-
+            TraceCompile(OpCodes.Newarr + ": " + elementType);
         }
 
         internal void LoadArrayValue(Local arr, Local i)
@@ -1302,14 +1363,12 @@ namespace ProtoBuf.Compiler
                 case ProtoTypeCode.Single: Emit(OpCodes.Ldelem_R4); break;
                 case ProtoTypeCode.Double: Emit(OpCodes.Ldelem_R8); break;
                 default:
-                    if (type.IsValueType)
+                    if (Helpers.IsValueType(type))
                     {
                         il.Emit(OpCodes.Ldelema, type);
                         il.Emit(OpCodes.Ldobj, type);
-#if DEBUG_COMPILE
-                        Helpers.DebugWriteLine(OpCodes.Ldelema + ": " + type);
-                        Helpers.DebugWriteLine(OpCodes.Ldobj + ": " + type);
-#endif
+                        TraceCompile(OpCodes.Ldelema + ": " + type);
+                        TraceCompile(OpCodes.Ldobj + ": " + type);
                     }
                     else
                     {
@@ -1326,9 +1385,7 @@ namespace ProtoBuf.Compiler
         internal void LoadValue(Type type)
         {
             il.Emit(OpCodes.Ldtoken, type);
-#if DEBUG_COMPILE
-            Helpers.DebugWriteLine(OpCodes.Ldtoken + ": " + type);
-#endif
+            TraceCompile(OpCodes.Ldtoken + ": " + type);
             EmitCall(MapType(typeof(System.Type)).GetMethod("GetTypeFromHandle"));
         }
 
@@ -1444,7 +1501,7 @@ namespace ProtoBuf.Compiler
 
         internal bool AllowInternal(PropertyInfo property)
         {
-            return NonPublic ? true : InternalsVisible(property.DeclaringType.Assembly);
+            return NonPublic ? true : InternalsVisible(Helpers.GetAssembly(property.DeclaringType));
         }
     }
 }

+ 3 - 3
Unity/Assets/Plugins/protobuf-net/Compiler/CompilerContext.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Compiler/CompilerContext.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 3fa3f54def85eb4488cf2cbd8d118e66
-timeCreated: 1515899112
-licenseType: Pro
+guid: 7a955d0c37551a040aeedd194546aa47
+timeCreated: 1517401476
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 0 - 0
Unity/Assets/Plugins/protobuf-net/Compiler/CompilerDelegates.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Compiler/CompilerDelegates.cs


+ 3 - 3
Unity/Assets/Plugins/protobuf-net/Compiler/CompilerDelegates.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Compiler/CompilerDelegates.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 0f76001f4592d5d498e2ef4c6c5bf1a8
-timeCreated: 1515899112
-licenseType: Pro
+guid: ace60611b4c2a614e97280c9d2fc43d2
+timeCreated: 1517401477
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 0 - 0
Unity/Assets/Plugins/protobuf-net/Compiler/Local.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Compiler/Local.cs


+ 3 - 3
Unity/Assets/Plugins/protobuf-net/Compiler/Local.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Compiler/Local.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 0dcacd88e875d944b82e41d2a0902f79
-timeCreated: 1515899112
-licenseType: Pro
+guid: 13c2a3cacaefae945a24375d1136154c
+timeCreated: 1517401476
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 8 - 1
Unity/Assets/Plugins/protobuf-net/DataFormat.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/DataFormat.cs

@@ -37,6 +37,13 @@ namespace ProtoBuf
         /// When applied to a sub-message, indicates that the value should be treated
         /// as group-delimited.
         /// </summary>
-        Group
+        Group,
+
+        /// <summary>
+        /// When applied to members of types such as DateTime or TimeSpan, specifies
+        /// that the "well known" standardized representation should be use; DateTime uses Timestamp,
+        /// 
+        /// </summary>
+        WellKnown
     }
 }

+ 3 - 3
Unity/Assets/Plugins/protobuf-net/DataFormat.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/DataFormat.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: aab300bfaae2b4849838362e1a0fa44b
-timeCreated: 1515899114
-licenseType: Pro
+guid: 12599bcc666828644aecc5f11c54c426
+timeCreated: 1517401476
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 395 - 0
Unity/Assets/ThirdParty/Protobuf/protobuf-net/DiscriminatedUnion.cs

@@ -0,0 +1,395 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace ProtoBuf
+{
+    /// <summary>Represent multiple types as a union; this is used as part of OneOf -
+    /// note that it is the caller's responsbility to only read/write the value as the same type</summary>
+    public struct DiscriminatedUnionObject
+    {
+        private readonly int _discriminator;
+
+        /// <summary>The value typed as Object</summary>
+        public readonly object Object;
+
+        /// <summary>Indicates whether the specified discriminator is assigned</summary>
+        public bool Is(int discriminator) => _discriminator == ~discriminator;
+
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnionObject(int discriminator, object value)
+        {
+            _discriminator = ~discriminator; // avoids issues with default value / 0
+            Object = value;
+        }
+
+        /// <summary>Reset a value if the specified discriminator is assigned</summary>
+        public static void Reset(ref DiscriminatedUnionObject value, int discriminator)
+        {
+            if (value.Is(discriminator)) value = default(DiscriminatedUnionObject);
+        }
+    }
+
+    /// <summary>Represent multiple types as a union; this is used as part of OneOf -
+    /// note that it is the caller's responsbility to only read/write the value as the same type</summary>
+    [StructLayout(LayoutKind.Explicit)]
+    public struct DiscriminatedUnion64
+    {
+        unsafe static DiscriminatedUnion64()
+        {
+            if (sizeof(DateTime) > 8) throw new InvalidOperationException(nameof(DateTime) + " was unexpectedly too big for " + nameof(DiscriminatedUnion64));
+            if (sizeof(TimeSpan) > 8) throw new InvalidOperationException(nameof(TimeSpan) + " was unexpectedly too big for " + nameof(DiscriminatedUnion64));
+        }
+        [FieldOffset(0)] private readonly int _discriminator;  // note that we can't pack further because Object needs x8 alignment/padding on x64
+
+        /// <summary>The value typed as Int64</summary>
+        [FieldOffset(8)] public readonly long Int64;
+        /// <summary>The value typed as UInt64</summary>
+        [FieldOffset(8)] public readonly ulong UInt64;
+        /// <summary>The value typed as Int32</summary>
+        [FieldOffset(8)] public readonly int Int32;
+        /// <summary>The value typed as UInt32</summary>
+        [FieldOffset(8)] public readonly uint UInt32;
+        /// <summary>The value typed as Boolean</summary>
+        [FieldOffset(8)] public readonly bool Boolean;
+        /// <summary>The value typed as Single</summary>
+        [FieldOffset(8)] public readonly float Single;
+        /// <summary>The value typed as Double</summary>
+        [FieldOffset(8)] public readonly double Double;
+        /// <summary>The value typed as DateTime</summary>
+        [FieldOffset(8)] public readonly DateTime DateTime;
+        /// <summary>The value typed as TimeSpan</summary>
+        [FieldOffset(8)] public readonly TimeSpan TimeSpan;
+
+        private DiscriminatedUnion64(int discriminator) : this()
+        {
+            _discriminator = ~discriminator; // avoids issues with default value / 0
+        }
+
+        /// <summary>Indicates whether the specified discriminator is assigned</summary>
+        public bool Is(int discriminator) => _discriminator == ~discriminator;
+
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64(int discriminator, long value) : this(discriminator) { Int64 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64(int discriminator, int value) : this(discriminator) { Int32 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64(int discriminator, ulong value) : this(discriminator) { UInt64 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64(int discriminator, uint value) : this(discriminator) { UInt32 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64(int discriminator, float value) : this(discriminator) { Single = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64(int discriminator, double value) : this(discriminator) { Double = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64(int discriminator, bool value) : this(discriminator) { Boolean = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64(int discriminator, DateTime? value) : this(value.HasValue ? discriminator: ~0) { DateTime = value.GetValueOrDefault(); }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64(int discriminator, TimeSpan? value) : this(value.HasValue ? discriminator : ~0) { TimeSpan = value.GetValueOrDefault(); }
+
+        /// <summary>Reset a value if the specified discriminator is assigned</summary>
+        public static void Reset(ref DiscriminatedUnion64 value, int discriminator)
+        {
+            if (value.Is(discriminator)) value = default(DiscriminatedUnion64);
+        }
+    }
+
+    /// <summary>Represent multiple types as a union; this is used as part of OneOf -
+    /// note that it is the caller's responsbility to only read/write the value as the same type</summary>
+    [StructLayout(LayoutKind.Explicit)]
+    public struct DiscriminatedUnion128Object
+    {
+        unsafe static DiscriminatedUnion128Object()
+        {
+            if (sizeof(DateTime) > 16) throw new InvalidOperationException(nameof(DateTime) + " was unexpectedly too big for " + nameof(DiscriminatedUnion128Object));
+            if (sizeof(TimeSpan) > 16) throw new InvalidOperationException(nameof(TimeSpan) + " was unexpectedly too big for " + nameof(DiscriminatedUnion128Object));
+            if (sizeof(Guid) > 16) throw new InvalidOperationException(nameof(Guid) + " was unexpectedly too big for " + nameof(DiscriminatedUnion128Object));
+        }
+
+        [FieldOffset(0)] private readonly int _discriminator;  // note that we can't pack further because Object needs x8 alignment/padding on x64
+
+        /// <summary>The value typed as Int64</summary>
+        [FieldOffset(8)] public readonly long Int64;
+        /// <summary>The value typed as UInt64</summary>
+        [FieldOffset(8)] public readonly ulong UInt64;
+        /// <summary>The value typed as Int32</summary>
+        [FieldOffset(8)] public readonly int Int32;
+        /// <summary>The value typed as UInt32</summary>
+        [FieldOffset(8)] public readonly uint UInt32;
+        /// <summary>The value typed as Boolean</summary>
+        [FieldOffset(8)] public readonly bool Boolean;
+        /// <summary>The value typed as Single</summary>
+        [FieldOffset(8)] public readonly float Single;
+        /// <summary>The value typed as Double</summary>
+        [FieldOffset(8)] public readonly double Double;
+        /// <summary>The value typed as DateTime</summary>
+        [FieldOffset(8)] public readonly DateTime DateTime;
+        /// <summary>The value typed as TimeSpan</summary>
+        [FieldOffset(8)] public readonly TimeSpan TimeSpan;
+        /// <summary>The value typed as Guid</summary>
+        [FieldOffset(8)] public readonly Guid Guid;
+        /// <summary>The value typed as Double</summary>
+        [FieldOffset(24)] public readonly object Object;
+
+        private DiscriminatedUnion128Object(int discriminator) : this()
+        {
+            _discriminator = ~discriminator; // avoids issues with default value / 0
+        }
+
+        /// <summary>Indicates whether the specified discriminator is assigned</summary>
+        public bool Is(int discriminator) => _discriminator == ~discriminator;
+
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128Object(int discriminator, long value) : this(discriminator) { Int64 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128Object(int discriminator, int value) : this(discriminator) { Int32 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128Object(int discriminator, ulong value) : this(discriminator) { UInt64 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128Object(int discriminator, uint value) : this(discriminator) { UInt32 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128Object(int discriminator, float value) : this(discriminator) { Single = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128Object(int discriminator, double value) : this(discriminator) { Double = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128Object(int discriminator, bool value) : this(discriminator) { Boolean = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128Object(int discriminator, object value) : this(value != null ? discriminator : ~0) { Object = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128Object(int discriminator, DateTime? value) : this(value.HasValue ? discriminator: ~0) { DateTime = value.GetValueOrDefault(); }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128Object(int discriminator, TimeSpan? value) : this(value.HasValue ? discriminator : ~0) { TimeSpan = value.GetValueOrDefault(); }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128Object(int discriminator, Guid? value) : this(value.HasValue ? discriminator : ~0) { Guid = value.GetValueOrDefault(); }
+
+        /// <summary>Reset a value if the specified discriminator is assigned</summary>
+        public static void Reset(ref DiscriminatedUnion128Object value, int discriminator)
+        {
+            if (value.Is(discriminator)) value = default(DiscriminatedUnion128Object);
+        }
+    }
+
+    /// <summary>Represent multiple types as a union; this is used as part of OneOf -
+    /// note that it is the caller's responsbility to only read/write the value as the same type</summary>
+    [StructLayout(LayoutKind.Explicit)]
+    public struct DiscriminatedUnion128
+    {
+        unsafe static DiscriminatedUnion128()
+        {
+            if (sizeof(DateTime) > 16) throw new InvalidOperationException(nameof(DateTime) + " was unexpectedly too big for " + nameof(DiscriminatedUnion128));
+            if (sizeof(TimeSpan) > 16) throw new InvalidOperationException(nameof(TimeSpan) + " was unexpectedly too big for " + nameof(DiscriminatedUnion128));
+            if (sizeof(Guid) > 16) throw new InvalidOperationException(nameof(Guid) + " was unexpectedly too big for " + nameof(DiscriminatedUnion128));
+        }
+        [FieldOffset(0)] private readonly int _discriminator;  // note that we can't pack further because Object needs x8 alignment/padding on x64
+
+        /// <summary>The value typed as Int64</summary>
+        [FieldOffset(8)] public readonly long Int64;
+        /// <summary>The value typed as UInt64</summary>
+        [FieldOffset(8)] public readonly ulong UInt64;
+        /// <summary>The value typed as Int32</summary>
+        [FieldOffset(8)] public readonly int Int32;
+        /// <summary>The value typed as UInt32</summary>
+        [FieldOffset(8)] public readonly uint UInt32;
+        /// <summary>The value typed as Boolean</summary>
+        [FieldOffset(8)] public readonly bool Boolean;
+        /// <summary>The value typed as Single</summary>
+        [FieldOffset(8)] public readonly float Single;
+        /// <summary>The value typed as Double</summary>
+        [FieldOffset(8)] public readonly double Double;
+        /// <summary>The value typed as DateTime</summary>
+        [FieldOffset(8)] public readonly DateTime DateTime;
+        /// <summary>The value typed as TimeSpan</summary>
+        [FieldOffset(8)] public readonly TimeSpan TimeSpan;
+        /// <summary>The value typed as Guid</summary>
+        [FieldOffset(8)] public readonly Guid Guid;
+
+        private DiscriminatedUnion128(int discriminator) : this()
+        {
+            _discriminator = ~discriminator; // avoids issues with default value / 0
+        }
+
+        /// <summary>Indicates whether the specified discriminator is assigned</summary>
+        public bool Is(int discriminator) => _discriminator == ~discriminator;
+
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128(int discriminator, long value) : this(discriminator) { Int64 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128(int discriminator, int value) : this(discriminator) { Int32 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128(int discriminator, ulong value) : this(discriminator) { UInt64 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128(int discriminator, uint value) : this(discriminator) { UInt32 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128(int discriminator, float value) : this(discriminator) { Single = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128(int discriminator, double value) : this(discriminator) { Double = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128(int discriminator, bool value) : this(discriminator) { Boolean = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128(int discriminator, DateTime? value) : this(value.HasValue ? discriminator: ~0) { DateTime = value.GetValueOrDefault(); }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128(int discriminator, TimeSpan? value) : this(value.HasValue ? discriminator : ~0) { TimeSpan = value.GetValueOrDefault(); }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion128(int discriminator, Guid? value) : this(value.HasValue ? discriminator : ~0) { Guid = value.GetValueOrDefault(); }
+
+        /// <summary>Reset a value if the specified discriminator is assigned</summary>
+        public static void Reset(ref DiscriminatedUnion128 value, int discriminator)
+        {
+            if (value.Is(discriminator)) value = default(DiscriminatedUnion128);
+        }
+    }
+
+    /// <summary>Represent multiple types as a union; this is used as part of OneOf -
+    /// note that it is the caller's responsbility to only read/write the value as the same type</summary>
+    [StructLayout(LayoutKind.Explicit)]
+    public struct DiscriminatedUnion64Object
+    {
+        unsafe static DiscriminatedUnion64Object()
+        {
+            if (sizeof(DateTime) > 8) throw new InvalidOperationException(nameof(DateTime) + " was unexpectedly too big for " + nameof(DiscriminatedUnion64Object));
+            if (sizeof(TimeSpan) > 8) throw new InvalidOperationException(nameof(TimeSpan) + " was unexpectedly too big for " + nameof(DiscriminatedUnion64Object));
+        }
+
+        [FieldOffset(0)] private readonly int _discriminator;  // note that we can't pack further because Object needs x8 alignment/padding on x64
+
+        /// <summary>The value typed as Int64</summary>
+        [FieldOffset(8)] public readonly long Int64;
+        /// <summary>The value typed as UInt64</summary>
+        [FieldOffset(8)] public readonly ulong UInt64;
+        /// <summary>The value typed as Int32</summary>
+        [FieldOffset(8)] public readonly int Int32;
+        /// <summary>The value typed as UInt32</summary>
+        [FieldOffset(8)] public readonly uint UInt32;
+        /// <summary>The value typed as Boolean</summary>
+        [FieldOffset(8)] public readonly bool Boolean;
+        /// <summary>The value typed as Single</summary>
+        [FieldOffset(8)] public readonly float Single;
+        /// <summary>The value typed as Double</summary>
+        [FieldOffset(8)] public readonly double Double;
+        /// <summary>The value typed as DateTime</summary>
+        [FieldOffset(8)] public readonly DateTime DateTime;
+        /// <summary>The value typed as TimeSpan</summary>
+        [FieldOffset(8)] public readonly TimeSpan TimeSpan;
+        /// <summary>The value typed as Double</summary>
+        [FieldOffset(16)] public readonly object Object;
+
+        private DiscriminatedUnion64Object(int discriminator) : this()
+        {
+            _discriminator = ~discriminator; // avoids issues with default value / 0
+        }
+
+        /// <summary>Indicates whether the specified discriminator is assigned</summary>
+        public bool Is(int discriminator) => _discriminator == ~discriminator;
+
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64Object(int discriminator, long value) : this(discriminator) { Int64 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64Object(int discriminator, int value) : this(discriminator) { Int32 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64Object(int discriminator, ulong value) : this(discriminator) { UInt64 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64Object(int discriminator, uint value) : this(discriminator) { UInt32 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64Object(int discriminator, float value) : this(discriminator) { Single = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64Object(int discriminator, double value) : this(discriminator) { Double = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64Object(int discriminator, bool value) : this(discriminator) { Boolean = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64Object(int discriminator, object value) : this(value != null ? discriminator : ~0) { Object = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64Object(int discriminator, DateTime? value) : this(value.HasValue ? discriminator: ~0) { DateTime = value.GetValueOrDefault(); }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion64Object(int discriminator, TimeSpan? value) : this(value.HasValue ? discriminator : ~0) { TimeSpan = value.GetValueOrDefault(); }
+
+        /// <summary>Reset a value if the specified discriminator is assigned</summary>
+        public static void Reset(ref DiscriminatedUnion64Object value, int discriminator)
+        {
+            if (value.Is(discriminator)) value = default(DiscriminatedUnion64Object);
+        }
+    }
+
+    /// <summary>Represent multiple types as a union; this is used as part of OneOf -
+    /// note that it is the caller's responsbility to only read/write the value as the same type</summary>
+    [StructLayout(LayoutKind.Explicit)]
+    public struct DiscriminatedUnion32
+    {
+        [FieldOffset(0)] private readonly int _discriminator;
+
+        /// <summary>The value typed as Int32</summary>
+        [FieldOffset(4)] public readonly int Int32;
+        /// <summary>The value typed as UInt32</summary>
+        [FieldOffset(4)] public readonly uint UInt32;
+        /// <summary>The value typed as Boolean</summary>
+        [FieldOffset(4)] public readonly bool Boolean;
+        /// <summary>The value typed as Single</summary>
+        [FieldOffset(4)] public readonly float Single;
+
+        private DiscriminatedUnion32(int discriminator) : this()
+        {
+            _discriminator = ~discriminator; // avoids issues with default value / 0
+        }
+
+        /// <summary>Indicates whether the specified discriminator is assigned</summary>
+        public bool Is(int discriminator) => _discriminator == ~discriminator;
+
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion32(int discriminator, int value) : this(discriminator) { Int32 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion32(int discriminator, uint value) : this(discriminator) { UInt32 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion32(int discriminator, float value) : this(discriminator) { Single = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion32(int discriminator, bool value) : this(discriminator) { Boolean = value; }
+
+        /// <summary>Reset a value if the specified discriminator is assigned</summary>
+        public static void Reset(ref DiscriminatedUnion32 value, int discriminator)
+        {
+            if (value.Is(discriminator)) value = default(DiscriminatedUnion32);
+        }
+    }
+
+    /// <summary>Represent multiple types as a union; this is used as part of OneOf -
+    /// note that it is the caller's responsbility to only read/write the value as the same type</summary>
+    [StructLayout(LayoutKind.Explicit)]
+    public struct DiscriminatedUnion32Object
+    {
+        [FieldOffset(0)] private readonly int _discriminator;
+
+        /// <summary>The value typed as Int32</summary>
+        [FieldOffset(4)] public readonly int Int32;
+        /// <summary>The value typed as UInt32</summary>
+        [FieldOffset(4)] public readonly uint UInt32;
+        /// <summary>The value typed as Boolean</summary>
+        [FieldOffset(4)] public readonly bool Boolean;
+        /// <summary>The value typed as Single</summary>
+        [FieldOffset(4)] public readonly float Single;
+        /// <summary>The value typed as Double</summary>
+        [FieldOffset(8)] public readonly object Object;
+
+        private DiscriminatedUnion32Object(int discriminator) : this()
+        {
+            _discriminator = ~discriminator; // avoids issues with default value / 0
+        }
+
+        /// <summary>Indicates whether the specified discriminator is assigned</summary>
+        public bool Is(int discriminator) => _discriminator == ~discriminator;
+
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion32Object(int discriminator, int value) : this(discriminator) { Int32 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion32Object(int discriminator, uint value) : this(discriminator) { UInt32 = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion32Object(int discriminator, float value) : this(discriminator) { Single = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion32Object(int discriminator, bool value) : this(discriminator) { Boolean = value; }
+        /// <summary>Create a new discriminated union value</summary>
+        public DiscriminatedUnion32Object(int discriminator, object value) : this(value != null ? discriminator : ~0) { Object = value; }
+
+        /// <summary>Reset a value if the specified discriminator is assigned</summary>
+        public static void Reset(ref DiscriminatedUnion32Object value, int discriminator)
+        {
+            if (value.Is(discriminator)) value = default(DiscriminatedUnion32Object);
+        }
+    }
+}

+ 12 - 0
Unity/Assets/ThirdParty/Protobuf/protobuf-net/DiscriminatedUnion.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: 780cf5353636add4f830b307e08be3d5
+timeCreated: 1517401476
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 0 - 0
Unity/Assets/Plugins/protobuf-net/Extensible.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Extensible.cs


+ 3 - 3
Unity/Assets/Plugins/protobuf-net/Extensible.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Extensible.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 77c8983bf441b92468a08431a347d975
-timeCreated: 1515899113
-licenseType: Pro
+guid: 62c73bb4078005c41ba1edb13ed712c1
+timeCreated: 1517401476
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 2 - 2
Unity/Assets/Plugins/protobuf-net/ExtensibleUtil.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/ExtensibleUtil.cs

@@ -73,7 +73,7 @@ namespace ProtoBuf
             try {
                 SerializationContext ctx = new SerializationContext();
                 reader = ProtoReader.Create(stream, model, ctx, ProtoReader.TO_EOF);
-                while (model.TryDeserializeAuxiliaryType(reader, format, tag, type, ref value, true, false, false, false) && value != null)
+                while (model.TryDeserializeAuxiliaryType(reader, format, tag, type, ref value, true, false, false, false, null) && value != null)
                 {
                     if (!singleton)
                     {
@@ -123,7 +123,7 @@ namespace ProtoBuf
             Stream stream = extn.BeginAppend();
             try {
                 using(ProtoWriter writer = new ProtoWriter(stream, model, null)) {
-                    model.TrySerializeAuxiliaryType(writer, null, format, tag, value, false);
+                    model.TrySerializeAuxiliaryType(writer, null, format, tag, value, false, null);
                     writer.Close();
                 }
                 commit = true;

+ 3 - 3
Unity/Assets/Plugins/protobuf-net/ExtensibleUtil.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/ExtensibleUtil.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 211105008660eb04e95682d31cbb4430
-timeCreated: 1515899112
-licenseType: Pro
+guid: 9ff350175b9058648be612a2299cde4b
+timeCreated: 1517401477
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 0 - 0
Unity/Assets/Plugins/protobuf-net/GlobalSuppressions.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/GlobalSuppressions.cs


+ 3 - 3
Unity/Assets/Plugins/protobuf-net/GlobalSuppressions.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/GlobalSuppressions.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: e2c9fa3fac1ee3e4eba16c0ccc6d7794
-timeCreated: 1515899114
-licenseType: Pro
+guid: ca80ad59a05515845ae2a5711289d7b9
+timeCreated: 1517401477
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 134 - 59
Unity/Assets/Plugins/protobuf-net/Helpers.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Helpers.cs

@@ -1,7 +1,10 @@
 
 using System;
 using System.Collections;
-
+using System.IO;
+#if COREFX
+using System.Linq;
+#endif
 #if FEAT_IKVM
 using Type = IKVM.Reflection.Type;
 using IKVM.Reflection;
@@ -70,7 +73,7 @@ namespace ProtoBuf
 #if TRACE
 #if MF
             Microsoft.SPOT.Trace.Print(message);
-#elif SILVERLIGHT || MONODROID || CF2 || WINRT || IOS || PORTABLE
+#elif SILVERLIGHT || MONODROID || CF2 || WINRT || IOS || PORTABLE || COREFX
             System.Diagnostics.Debug.WriteLine(message);
 #else
             System.Diagnostics.Trace.WriteLine(message);
@@ -152,56 +155,62 @@ namespace ProtoBuf
             return float.IsInfinity(value);
 #endif
         }
-#if WINRT
+#if WINRT || COREFX
         internal static MemberInfo GetInstanceMember(TypeInfo declaringType, string name)
         {
-            PropertyInfo prop = declaringType.GetDeclaredProperty(name);
-            MethodInfo method;
-            if (prop != null && (method = Helpers.GetGetMethod(prop, true, true)) != null && !method.IsStatic) return prop;
-
-            FieldInfo field = declaringType.GetDeclaredField(name);
-            if (field != null && !field.IsStatic) return field;
-
+            var members = declaringType.AsType().GetMember(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+            switch(members.Length)
+            {
+                case 0: return null;
+                case 1: return members[0];
+                default: throw new AmbiguousMatchException(name);
+            }
+        }
+        internal static MethodInfo GetInstanceMethod(Type declaringType, string name)
+        {
+            foreach (MethodInfo method in declaringType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
+            {
+                if (method.Name == name) return method;
+            }
             return null;
         }
         internal static MethodInfo GetInstanceMethod(TypeInfo declaringType, string name)
         {
-            foreach (MethodInfo method in declaringType.DeclaredMethods)
+            return GetInstanceMethod(declaringType.AsType(), name); ;
+        }
+        internal static MethodInfo GetStaticMethod(Type declaringType, string name)
+        {
+            foreach (MethodInfo method in declaringType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
             {
-                if (!method.IsStatic && method.Name == name)
-                {
-                    return method;
-                }
+                if (method.Name == name) return method;
             }
             return null;
         }
+
         internal static MethodInfo GetStaticMethod(TypeInfo declaringType, string name)
         {
-            foreach (MethodInfo method in declaringType.DeclaredMethods)
+            return GetStaticMethod(declaringType.AsType(), name);
+        }
+        internal static MethodInfo GetStaticMethod(Type declaringType, string name, Type[] parameterTypes)
+        {
+            foreach(MethodInfo method in declaringType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
             {
-                if (method.IsStatic && method.Name == name)
-                {
-                    return method;
-                }
+                if (method.Name == name && IsMatch(method.GetParameters(), parameterTypes)) return method;
             }
             return null;
         }
-        internal static MethodInfo GetInstanceMethod(Type declaringType, string name, Type[] types)
-        {
-            return GetInstanceMethod(declaringType.GetTypeInfo(), name, types);
-        }
-        internal static MethodInfo GetInstanceMethod(TypeInfo declaringType, string name, Type[] types)
+        internal static MethodInfo GetInstanceMethod(Type declaringType, string name, Type[] parameterTypes)
         {
-            if (types == null) types = EmptyTypes;
-            foreach (MethodInfo method in declaringType.DeclaredMethods)
+            foreach (MethodInfo method in declaringType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
             {
-                if (!method.IsStatic && method.Name == name)
-                {
-                    if(IsMatch(method.GetParameters(), types)) return method;
-                }
+                if (method.Name == name && IsMatch(method.GetParameters(), parameterTypes)) return method;
             }
             return null;
         }
+        internal static MethodInfo GetInstanceMethod(TypeInfo declaringType, string name, Type[] types)
+        {
+            return GetInstanceMethod(declaringType.AsType(), name, types);
+        }
 #else
         internal static MethodInfo GetInstanceMethod(Type declaringType, string name)
         {
@@ -211,10 +220,22 @@ namespace ProtoBuf
         {
             return declaringType.GetMethod(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
         }
+        internal static MethodInfo GetStaticMethod(Type declaringType, string name, Type[] parameterTypes)
+        {
+#if PORTABLE
+            foreach (MethodInfo method in declaringType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))
+            {
+                if (method.Name == name && IsMatch(method.GetParameters(), parameterTypes)) return method;
+            }
+            return null;
+#else
+            return declaringType.GetMethod(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, parameterTypes, null);
+#endif
+        }
         internal static MethodInfo GetInstanceMethod(Type declaringType, string name, Type[] types)
         {
             if(types == null) types = EmptyTypes;
-#if PORTABLE
+#if PORTABLE || COREFX
             MethodInfo method = declaringType.GetMethod(name, types);
             if (method != null && method.IsStatic) method = null;
             return method;
@@ -225,9 +246,9 @@ namespace ProtoBuf
         }
 #endif
 
-        internal static bool IsSubclassOf(Type type, Type baseClass)
+            internal static bool IsSubclassOf(Type type, Type baseClass)
         {
-#if WINRT
+#if WINRT || COREFX
             return type.GetTypeInfo().IsSubclassOf(baseClass);
 #else
             return type.IsSubclassOf(baseClass);
@@ -250,7 +271,7 @@ namespace ProtoBuf
             Type.EmptyTypes;
 #endif
 
-#if WINRT
+#if WINRT || COREFX
         private static readonly Type[] knownTypes = new Type[] {
                 typeof(bool), typeof(char), typeof(sbyte), typeof(byte),
                 typeof(short), typeof(ushort), typeof(int), typeof(uint),
@@ -307,8 +328,11 @@ namespace ProtoBuf
 
         public static ProtoTypeCode GetTypeCode(System.Type type)
         {
-#if WINRT
-            
+#if WINRT || COREFX
+            if(IsEnum(type))
+            {
+                type = Enum.GetUnderlyingType(type);
+            }
             int idx = Array.IndexOf<Type>(knownTypes, type);
             if (idx >= 0) return knownCodes[idx];
             return type == null ? ProtoTypeCode.Empty : ProtoTypeCode.Unknown;
@@ -334,11 +358,16 @@ namespace ProtoBuf
                 case TypeCode.String:
                     return (ProtoTypeCode)code;
             }
-            if (type == typeof(TimeSpan)) return ProtoTypeCode.TimeSpan;
-            if (type == typeof(Guid)) return ProtoTypeCode.Guid;
-            if (type == typeof(Uri)) return ProtoTypeCode.Uri;
-            if (type == typeof(byte[])) return ProtoTypeCode.ByteArray;
-            if (type == typeof(System.Type)) return ProtoTypeCode.Type;
+
+            if (type.FullName == typeof(TimeSpan).FullName) return ProtoTypeCode.TimeSpan;
+            if (type.FullName == typeof(Guid).FullName) return ProtoTypeCode.Guid;
+            if (type.FullName == typeof(Uri).FullName) return ProtoTypeCode.Uri;
+#if PORTABLE
+            // In PCLs, the Uri type may not match (WinRT uses Internal/Uri, .Net uses System/Uri), so match on the full name instead
+            if (type.FullName == typeof(Uri).FullName) return ProtoTypeCode.Uri;
+#endif
+            if (type.FullName == typeof(byte[]).FullName) return ProtoTypeCode.ByteArray;
+            if (type.FullName == typeof(System.Type).FullName) return ProtoTypeCode.Type;
 
             return ProtoTypeCode.Unknown;
 #endif
@@ -367,16 +396,32 @@ namespace ProtoBuf
 
         internal static bool IsValueType(Type type)
         {
-#if WINRT
+#if WINRT || COREFX
             return type.GetTypeInfo().IsValueType;
 #else
             return type.IsValueType;
 #endif
         }
+        internal static bool IsSealed(Type type)
+        {
+#if WINRT || COREFX
+            return type.GetTypeInfo().IsSealed;
+#else
+            return type.IsSealed;
+#endif
+        }
+        internal static bool IsClass(Type type)
+        {
+#if WINRT || COREFX
+            return type.GetTypeInfo().IsClass;
+#else
+            return type.IsClass;
+#endif
+        }
 
         internal static bool IsEnum(Type type)
         {
-#if WINRT
+#if WINRT || COREFX
             return type.GetTypeInfo().IsEnum;
 #else
             return type.IsEnum;
@@ -386,7 +431,7 @@ namespace ProtoBuf
         internal static MethodInfo GetGetMethod(PropertyInfo property, bool nonPublic, bool allowInternal)
         {
             if (property == null) return null;
-#if WINRT
+#if WINRT || COREFX
             MethodInfo method = property.GetMethod;
             if (!nonPublic && method != null && !method.IsPublic) method = null;
             return method;
@@ -406,7 +451,7 @@ namespace ProtoBuf
         internal static MethodInfo GetSetMethod(PropertyInfo property, bool nonPublic, bool allowInternal)
         {
             if (property == null) return null;
-#if WINRT
+#if WINRT || COREFX
             MethodInfo method = property.SetMethod;
             if (!nonPublic && method != null && !method.IsPublic) method = null;
             return method;
@@ -436,7 +481,7 @@ namespace ProtoBuf
             return true;
         }
 #endif
-#if WINRT
+#if WINRT || COREFX || PORTABLE
         private static bool IsMatch(ParameterInfo[] parameters, Type[] parameterTypes)
         {
             if (parameterTypes == null) parameterTypes = EmptyTypes;
@@ -447,20 +492,23 @@ namespace ProtoBuf
             }
             return true;
         }
+#endif
+#if WINRT || COREFX
+        internal static ConstructorInfo GetConstructor(Type type, Type[] parameterTypes, bool nonPublic)
+        {
+            return GetConstructor(type.GetTypeInfo(), parameterTypes, nonPublic);
+        }
         internal static ConstructorInfo GetConstructor(TypeInfo type, Type[] parameterTypes, bool nonPublic)
         {
-            foreach (ConstructorInfo ctor in type.DeclaredConstructors)
-            {
-                if (!nonPublic && !ctor.IsPublic) continue;
-                if (IsMatch(ctor.GetParameters(), parameterTypes)) return ctor;
-            }
-            return null;
+            return GetConstructors(type, nonPublic).SingleOrDefault(ctor => IsMatch(ctor.GetParameters(), parameterTypes));
         }
         internal static ConstructorInfo[] GetConstructors(TypeInfo typeInfo, bool nonPublic)
         {
-            if (nonPublic) return System.Linq.Enumerable.ToArray(typeInfo.DeclaredConstructors);
-            return System.Linq.Enumerable.ToArray(
-                System.Linq.Enumerable.Where(typeInfo.DeclaredConstructors, x => x.IsPublic));
+            return typeInfo.DeclaredConstructors.Where(c => !c.IsStatic && (nonPublic || c.IsPublic)).ToArray();
+        }
+        internal static PropertyInfo GetProperty(Type type, string name, bool nonPublic)
+        {
+            return GetProperty(type.GetTypeInfo(), name, nonPublic);
         }
         internal static PropertyInfo GetProperty(TypeInfo type, string name, bool nonPublic)
         {
@@ -470,7 +518,7 @@ namespace ProtoBuf
 
         internal static ConstructorInfo GetConstructor(Type type, Type[] parameterTypes, bool nonPublic)
         {
-#if PORTABLE
+#if PORTABLE || COREFX
             // pretty sure this will only ever return public, but...
             ConstructorInfo ctor = type.GetConstructor(parameterTypes);
             return (ctor != null && (nonPublic || ctor.IsPublic)) ? ctor : null;
@@ -541,7 +589,7 @@ namespace ProtoBuf
 
         internal static Type GetMemberType(MemberInfo member)
         {
-#if WINRT || PORTABLE
+#if WINRT || PORTABLE || COREFX
             PropertyInfo prop = member as PropertyInfo;
             if (prop != null) return prop.PropertyType;
             FieldInfo fld = member as FieldInfo;
@@ -564,7 +612,34 @@ namespace ProtoBuf
             return target.IsAssignableFrom(type);
 #endif
         }
-
+        internal static Assembly GetAssembly(Type type)
+        {
+#if COREFX
+            return type.GetTypeInfo().Assembly;
+#else
+            return type.Assembly;
+#endif
+        }
+        internal static byte[] GetBuffer(MemoryStream ms)
+        {
+#if COREFX
+            ArraySegment<byte> segment;
+            if(!ms.TryGetBuffer(out segment))
+            {
+                throw new InvalidOperationException("Unable to obtain underlying MemoryStream buffer");
+            } else if(segment.Offset != 0)
+            {
+                throw new InvalidOperationException("Underlying MemoryStream buffer was not zero-offset");
+            } else
+            {
+                return segment.Array;
+            }
+#elif PORTABLE
+            return ms.ToArray();
+#else
+            return ms.GetBuffer();
+#endif
+        }
     }
     /// <summary>
     /// Intended to be a direct map to regular TypeCode, but:

+ 3 - 3
Unity/Assets/Plugins/protobuf-net/Helpers.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Helpers.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: de5f728a0785a6f4ea8ace112c87e3f4
-timeCreated: 1515899114
-licenseType: Pro
+guid: 1187cdbad0f6e53449ce1dccefa61e75
+timeCreated: 1517401476
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 0 - 0
Unity/Assets/Plugins/protobuf-net/IExtensible.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/IExtensible.cs


+ 3 - 3
Unity/Assets/Plugins/protobuf-net/IExtensible.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/IExtensible.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 894b4ee53fcbde940a50299693252ab8
-timeCreated: 1515899113
-licenseType: Pro
+guid: 7a187cd337ef0de4ca2878f54eff71d4
+timeCreated: 1517401476
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 11 - 0
Unity/Assets/Plugins/protobuf-net/IExtension.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/IExtension.cs

@@ -44,4 +44,15 @@ namespace ProtoBuf
         /// <returns>The length of the binary stream representing unexpected data.</returns>
         int GetLength();
     }
+
+    /// <summary>
+    /// Provides the ability to remove all existing extension data
+    /// </summary>
+    public interface IExtensionResettable : IExtension
+    {
+        /// <summary>
+        /// Remove all existing extension data
+        /// </summary>
+        void Reset();
+    }
 }

+ 3 - 3
Unity/Assets/Plugins/protobuf-net/IExtension.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/IExtension.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 862151bfca11b9b45b582315f7e87b60
-timeCreated: 1515899113
-licenseType: Pro
+guid: 50d75dac206571d4d898706bbf37e218
+timeCreated: 1517401476
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 0 - 0
Unity/Assets/Plugins/protobuf-net/ImplicitFields.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/ImplicitFields.cs


+ 3 - 3
Unity/Assets/Plugins/protobuf-net/ImplicitFields.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/ImplicitFields.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 8fab61a3c17d23f46ac0a6a4af26b42b
-timeCreated: 1515899113
-licenseType: Pro
+guid: 1e18c46bc2ab6a043a199b640a8a1721
+timeCreated: 1517401476
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 0 - 0
Unity/Assets/Plugins/protobuf-net/KeyValuePairProxy.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/KeyValuePairProxy.cs


+ 3 - 3
Unity/Assets/Plugins/protobuf-net/KeyValuePairProxy.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/KeyValuePairProxy.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 21371fef76d30f345973acb5a3b3bae9
-timeCreated: 1515899112
-licenseType: Pro
+guid: ca760a241fb06c94085ff1d139c97fca
+timeCreated: 1517401477
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 3 - 3
Unity/Assets/Plugins/protobuf-net/Meta.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta.meta

@@ -1,8 +1,8 @@
 fileFormatVersion: 2
-guid: 1473358c6161ad14889452b663dbe0d7
+guid: 43d81520489d261469de78eae27f4707
 folderAsset: yes
-timeCreated: 1515899111
-licenseType: Pro
+timeCreated: 1517401476
+licenseType: Free
 DefaultImporter:
   userData: 
   assetBundleName: 

+ 7 - 5
Unity/Assets/Plugins/protobuf-net/Meta/AttributeMap.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/AttributeMap.cs

@@ -15,6 +15,7 @@ namespace ProtoBuf.Meta
         [Obsolete("Please use AttributeType instead")]
         new public Type GetType() { return AttributeType; }
 #endif
+        public override string ToString() => AttributeType?.FullName ?? "";
         public abstract bool TryGet(string key, bool publicOnly, out object value);
         public bool TryGet(string key, out object value)
         {
@@ -34,7 +35,7 @@ namespace ProtoBuf.Meta
             }
             return result;
 #else
-#if WINRT
+#if WINRT || COREFX
             Attribute[] all = System.Linq.Enumerable.ToArray(type.GetTypeInfo().GetCustomAttributes(inherit));
 #else
             object[] all = type.GetCustomAttributes(inherit);
@@ -60,7 +61,7 @@ namespace ProtoBuf.Meta
             }
             return result;
 #else
-#if WINRT
+#if WINRT || COREFX
             Attribute[] all = System.Linq.Enumerable.ToArray(member.GetCustomAttributes(inherit));
 #else
             object[] all = member.GetCustomAttributes(inherit);
@@ -75,7 +76,7 @@ namespace ProtoBuf.Meta
         }
         public static AttributeMap[] Create(TypeModel model, Assembly assembly)
         {
-            
+
 #if FEAT_IKVM
             const bool inherit = false;
             System.Collections.Generic.IList<CustomAttributeData> all = assembly.__GetCustomAttributes(model.MapType(typeof(Attribute)), inherit);
@@ -87,7 +88,7 @@ namespace ProtoBuf.Meta
             }
             return result;
 #else
-#if WINRT
+#if WINRT || COREFX
             Attribute[] all = System.Linq.Enumerable.ToArray(assembly.GetCustomAttributes());
 #else
             const bool inherit = false;
@@ -164,7 +165,8 @@ namespace ProtoBuf.Meta
                     {
                         PropertyInfo prop = member as PropertyInfo;
                         if (prop != null) {
-                            value = prop.GetValue(attribute, null);
+                            //value = prop.GetValue(attribute, null);
+                            value = prop.GetGetMethod(true).Invoke(attribute, null);
                             return true;
                         }
                         FieldInfo field = member as FieldInfo;

+ 3 - 3
Unity/Assets/Plugins/protobuf-net/Meta/AttributeMap.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/AttributeMap.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 9d113bdb4bb5aa94fb27939b26628db3
-timeCreated: 1515899113
-licenseType: Pro
+guid: 355d494afaeb2cb4f84385f6fc44778b
+timeCreated: 1517401476
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 0 - 0
Unity/Assets/Plugins/protobuf-net/Meta/BasicList.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/BasicList.cs


+ 3 - 3
Unity/Assets/Plugins/protobuf-net/Meta/BasicList.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/BasicList.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 29a4c7082e074e34ca71d6dd7fde3eb9
-timeCreated: 1515899112
-licenseType: Pro
+guid: ef6d4524ae82c684e990451829f2c0ac
+timeCreated: 1517401477
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 0 - 0
Unity/Assets/Plugins/protobuf-net/Meta/CallbackSet.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/CallbackSet.cs


+ 3 - 3
Unity/Assets/Plugins/protobuf-net/Meta/CallbackSet.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/CallbackSet.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 0e13df364e5504540a1a196b64da7a48
-timeCreated: 1515899112
-licenseType: Pro
+guid: 81ffd608ce47c7c4b9599518a5354824
+timeCreated: 1517401477
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 400 - 134
Unity/Assets/Plugins/protobuf-net/Meta/MetaType.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/MetaType.cs

@@ -1,6 +1,7 @@
 #if !NO_RUNTIME
 using System;
 using System.Collections;
+using System.Collections.Generic;
 using System.Text;
 using ProtoBuf.Serializers;
 
@@ -15,6 +16,7 @@ using IKVM.Reflection.Emit;
 using System.Reflection;
 #if FEAT_COMPILER
 using System.Reflection.Emit;
+using System.Globalization;
 #endif
 #endif
 
@@ -88,7 +90,7 @@ namespace ProtoBuf.Meta
         private BasicList subTypes;
         private bool IsValidSubType(Type subType)
         {
-#if WINRT
+#if WINRT || COREFX
             return typeInfo.IsAssignableFrom(subType.GetTypeInfo());
 #else
             return type.IsAssignableFrom(subType);
@@ -108,7 +110,7 @@ namespace ProtoBuf.Meta
         {
             if (derivedType == null) throw new ArgumentNullException("derivedType");
             if (fieldNumber < 1) throw new ArgumentOutOfRangeException("fieldNumber");
-#if WINRT
+#if WINRT || COREFX || COREFX
             if (!(typeInfo.IsClass || typeInfo.IsInterface) || typeInfo.IsSealed) {
 #else
             if (!(type.IsClass || type.IsInterface) || type.IsSealed) {
@@ -130,7 +132,7 @@ namespace ProtoBuf.Meta
             subTypes.Add(subType);
             return this;
         }
-#if WINRT
+#if WINRT || COREFX
         internal static readonly TypeInfo ienumerable = typeof(IEnumerable).GetTypeInfo();
 #else
         internal static readonly System.Type ienumerable = typeof(IEnumerable);
@@ -183,7 +185,7 @@ namespace ProtoBuf.Meta
         {
             get
             {
-#if WINRT
+#if WINRT || COREFX
                 return typeInfo.IsValueType;
 #else
                 return type.IsValueType;
@@ -235,7 +237,7 @@ namespace ProtoBuf.Meta
             string typeName = type.Name;
 #if !NO_GENERICS
             if (type
-#if WINRT
+#if WINRT || COREFX
                 .GetTypeInfo()
 #endif       
                 .IsGenericType)
@@ -244,7 +246,7 @@ namespace ProtoBuf.Meta
                 int split = typeName.IndexOf('`');
                 if (split >= 0) sb.Length = split;
                 foreach (Type arg in type
-#if WINRT
+#if WINRT || COREFX
                     .GetTypeInfo().GenericTypeArguments
 #else               
                     .GetGenericArguments()
@@ -313,7 +315,7 @@ namespace ProtoBuf.Meta
         private MethodInfo ResolveMethod(string name, bool instance)
         {
             if (Helpers.IsNullOrEmpty(name)) return null;
-#if WINRT
+#if WINRT || COREFX
             return instance ? Helpers.GetInstanceMethod(typeInfo, name) : Helpers.GetStaticMethod(typeInfo, name);
 #else
             return instance ? Helpers.GetInstanceMethod(type, name) : Helpers.GetStaticMethod(type, name);
@@ -329,7 +331,8 @@ namespace ProtoBuf.Meta
             this.factory = factory;
             if (model == null) throw new ArgumentNullException("model");
             if (type == null) throw new ArgumentNullException("type");
-            
+
+            if (type.IsArray) throw InbuiltType(type);
             IProtoSerializer coreSerializer = model.TryGetBasicTypeSerializer(type);
             if (coreSerializer != null)
             {
@@ -337,21 +340,21 @@ namespace ProtoBuf.Meta
             }
             
             this.type = type;
-#if WINRT
+#if WINRT || COREFX
             this.typeInfo = type.GetTypeInfo();
 #endif
             this.model = model;
             
             if (Helpers.IsEnum(type))
             {
-#if WINRT
+#if WINRT || COREFX
                 EnumPassthru = typeInfo.IsDefined(typeof(FlagsAttribute), false);
 #else
                 EnumPassthru = type.IsDefined(model.MapType(typeof(FlagsAttribute)), false);
 #endif
             }
         }
-#if WINRT
+#if WINRT || COREFX
         private readonly TypeInfo typeInfo;
 #endif
         /// <summary>
@@ -362,6 +365,14 @@ namespace ProtoBuf.Meta
             if ((flags & OPTIONS_Frozen)!=0) throw new InvalidOperationException("The type cannot be changed once a serializer has been generated for " + type.FullName);
         }
         //internal void Freeze() { flags |= OPTIONS_Frozen; }
+		public Type KVPKeyType {
+			get;
+			set;
+		}
+		public Type KVPValueType {
+			get;
+			set;
+		}
 
         private readonly Type type;
         /// <summary>
@@ -433,10 +444,10 @@ namespace ProtoBuf.Meta
             }
             if (IsAutoTuple)
             {
-                MemberInfo[] mapping;
+				MemberInfo[] mapping;
                 ConstructorInfo ctor = ResolveTupleConstructor(type, out mapping);
-                if(ctor == null) throw new InvalidOperationException();
-                return new TupleSerializer(model, ctor, mapping);
+                if (ctor == null) throw new InvalidOperationException();
+				return new TupleSerializer(model, ctor, mapping,new Type[]{KVPKeyType,KVPValueType});
             }
             
 
@@ -450,7 +461,7 @@ namespace ProtoBuf.Meta
             {
                 foreach (SubType subType in subTypes)
                 {
-#if WINRT
+#if WINRT || COREFX
                     if (!subType.DerivedType.IgnoreListHandling && ienumerable.IsAssignableFrom(subType.DerivedType.Type.GetTypeInfo()))
 #else
                     if (!subType.DerivedType.IgnoreListHandling && model.MapType(ienumerable).IsAssignableFrom(subType.DerivedType.Type))
@@ -501,7 +512,7 @@ namespace ProtoBuf.Meta
         }
         static Type GetBaseType(MetaType type)
         {
-#if WINRT
+#if WINRT || COREFX
             return type.typeInfo.BaseType;
 #else
             return type.type.BaseType;
@@ -516,7 +527,7 @@ namespace ProtoBuf.Meta
             {
                 if (typeAttribs[i].AttributeType.FullName == "ProtoBuf.ProtoContractAttribute")
                 {
-                    object tmp;
+					object tmp;
                     if (typeAttribs[i].TryGet("AsReferenceDefault", out tmp)) return (bool)tmp;
                 }
             }
@@ -539,6 +550,8 @@ namespace ProtoBuf.Meta
             }
             bool isEnum = !EnumPassthru && Helpers.IsEnum(type);
             if(family ==  AttributeFamily.None && !isEnum) return; // and you'd like me to do what, exactly?
+
+            bool enumShouldUseImplicitPassThru = isEnum;
             BasicList partialIgnores = null, partialMembers = null;
             int dataMemberOffset = 0, implicitFirstTag = 1;
             bool inferTagByName = model.InferTagFromNameDefault;
@@ -562,7 +575,7 @@ namespace ProtoBuf.Meta
                     try
                     {
                         if (item.TryGet("knownTypeName", out tmp)) knownType = model.GetType((string)tmp, type
-#if WINRT
+#if WINRT || COREFX
                             .GetTypeInfo()
 #endif       
                             .Assembly);
@@ -581,7 +594,7 @@ namespace ProtoBuf.Meta
 
                 if (fullAttributeTypeName == "ProtoBuf.ProtoPartialIgnoreAttribute")
                 {
-                    if (item.TryGet("MemberName", out tmp) && tmp != null)
+                    if (item.TryGet(nameof(ProtoPartialIgnoreAttribute.MemberName), out tmp) && tmp != null)
                     {
                         if (partialIgnores == null) partialIgnores = new BasicList();
                         partialIgnores.Add((string)tmp);
@@ -592,45 +605,48 @@ namespace ProtoBuf.Meta
                     if (partialMembers == null) partialMembers = new BasicList();
                     partialMembers.Add(item);
                 }
-
+                
                 if (fullAttributeTypeName == "ProtoBuf.ProtoContractAttribute")
                 {
-                    if (item.TryGet("Name", out tmp)) name = (string) tmp;
+                    if (item.TryGet(nameof(ProtoContractAttribute.Name), out tmp)) name = (string) tmp;
                     if (Helpers.IsEnum(type)) // note this is subtly different to isEnum; want to do this even if [Flags]
                     {
+
 #if !FEAT_IKVM
-                        // IKVM can't access EnumPassthruHasValue, but conveniently, InferTagFromName will only be returned if set via ctor or property
-                        if (item.TryGet("EnumPassthruHasValue", false, out tmp) && (bool)tmp)
+                        // IKVM can't access EnumPassthruHasValue, but conveniently, EnumPassthru will only be returned if set via ctor or property
+                        if (item.TryGet(nameof(ProtoContractAttribute.EnumPassthruHasValue), false, out tmp) && (bool)tmp)
 #endif
                         {
-                            if (item.TryGet("EnumPassthru", out tmp))
+                            if (item.TryGet(nameof(ProtoContractAttribute.EnumPassthru), out tmp))
                             {
                                 EnumPassthru = (bool)tmp;
+                                enumShouldUseImplicitPassThru = false;
                                 if (EnumPassthru) isEnum = false; // no longer treated as an enum
                             }
                         }
                     }
                     else
                     {
-                        if (item.TryGet("DataMemberOffset", out tmp)) dataMemberOffset = (int) tmp;
+                        if (item.TryGet(nameof(ProtoContractAttribute.DataMemberOffset), out tmp)) dataMemberOffset = (int) tmp;
 
 #if !FEAT_IKVM
                         // IKVM can't access InferTagFromNameHasValue, but conveniently, InferTagFromName will only be returned if set via ctor or property
-                        if (item.TryGet("InferTagFromNameHasValue", false, out tmp) && (bool) tmp)
+                        if (item.TryGet(nameof(ProtoContractAttribute.InferTagFromNameHasValue), false, out tmp) && (bool) tmp)
 #endif
                         {
-                            if (item.TryGet("InferTagFromName", out tmp)) inferTagByName = (bool) tmp;
+                            if (item.TryGet(nameof(ProtoContractAttribute.InferTagFromName), out tmp)) inferTagByName = (bool) tmp;
                         }
 
-                        if (item.TryGet("ImplicitFields", out tmp) && tmp != null)
+                        if (item.TryGet(nameof(ProtoContractAttribute.ImplicitFields), out tmp) && tmp != null)
                         {
                             implicitMode = (ImplicitFields) (int) tmp; // note that this uses the bizarre unboxing rules of enums/underlying-types
                         }
 
-                        if (item.TryGet("SkipConstructor", out tmp)) UseConstructor = !(bool) tmp;
-                        if (item.TryGet("IgnoreListHandling", out tmp)) IgnoreListHandling = (bool) tmp;
-                        if (item.TryGet("AsReferenceDefault", out tmp)) AsReferenceDefault = (bool) tmp;
-                        if (item.TryGet("ImplicitFirstTag", out tmp) && (int) tmp > 0) implicitFirstTag = (int) tmp;
+                        if (item.TryGet(nameof(ProtoContractAttribute.SkipConstructor), out tmp)) UseConstructor = !(bool) tmp;
+                        if (item.TryGet(nameof(ProtoContractAttribute.IgnoreListHandling), out tmp)) IgnoreListHandling = (bool) tmp;
+                        if (item.TryGet(nameof(ProtoContractAttribute.AsReferenceDefault), out tmp)) AsReferenceDefault = (bool) tmp;
+                        if (item.TryGet(nameof(ProtoContractAttribute.ImplicitFirstTag), out tmp) && (int) tmp > 0) implicitFirstTag = (int) tmp;
+                        if (item.TryGet(nameof(ProtoContractAttribute.IsGroup), out tmp)) IsGroup = (bool)tmp;
                     }
                 }
 
@@ -672,6 +688,7 @@ namespace ProtoBuf.Meta
             MemberInfo[] foundList = type.GetMembers(isEnum ? BindingFlags.Public | BindingFlags.Static
                 : BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
 #endif
+            bool hasConflictingEnumValue = false;
             foreach (MemberInfo member in foundList)
             {
                 if (member.DeclaringType != type) continue;
@@ -688,11 +705,24 @@ namespace ProtoBuf.Meta
                 if((property = member as PropertyInfo) != null)
                 {
                     if (isEnum) continue; // wasn't expecting any props!
-
+                    MemberInfo backingField = null;
+                    if (!property.CanWrite)
+                    {
+                        // roslyn automatically implemented properties, in particular for get-only properties: <{Name}>k__BackingField;
+                        var backingFieldName = $"<{property.Name}>k__BackingField";
+                        foreach (var fieldMemeber in foundList)
+                        {
+                            if ((fieldMemeber as FieldInfo != null) && fieldMemeber.Name == backingFieldName)
+                            {
+                                backingField = fieldMemeber;
+                                break;
+                            }
+                        }
+                    }
                     effectiveType = property.PropertyType;
                     isPublic = Helpers.GetGetMethod(property, false, false) != null;
                     isField = false;
-                    ApplyDefaultBehaviour_AddMembers(model, family, isEnum, partialMembers, dataMemberOffset, inferTagByName, implicitMode, members, member, ref forced, isPublic, isField, ref effectiveType);
+                    ApplyDefaultBehaviour_AddMembers(model, family, isEnum, partialMembers, dataMemberOffset, inferTagByName, implicitMode, members, member, ref forced, isPublic, isField, ref effectiveType, ref hasConflictingEnumValue, backingField);
                 } else if ((field = member as FieldInfo) != null)
                 {
                     effectiveType = field.FieldType;
@@ -702,7 +732,7 @@ namespace ProtoBuf.Meta
                     { // only care about static things on enums; WinRT has a __value instance field!
                         continue;
                     }
-                    ApplyDefaultBehaviour_AddMembers(model, family, isEnum, partialMembers, dataMemberOffset, inferTagByName, implicitMode, members, member, ref forced, isPublic, isField, ref effectiveType);
+                    ApplyDefaultBehaviour_AddMembers(model, family, isEnum, partialMembers, dataMemberOffset, inferTagByName, implicitMode, members, member, ref forced, isPublic, isField, ref effectiveType, ref hasConflictingEnumValue);
                 } else if ((method = member as MethodInfo) != null)
                 {
                     if (isEnum) continue;
@@ -720,6 +750,12 @@ namespace ProtoBuf.Meta
                     }
                 }
             }
+
+            if(isEnum && enumShouldUseImplicitPassThru && !hasConflictingEnumValue)
+            {
+                EnumPassthru = true;
+                // but leave isEnum alone
+            }
             ProtoMemberAttribute[] arr = new ProtoMemberAttribute[members.Count];
             members.CopyTo(arr, 0);
             
@@ -752,7 +788,7 @@ namespace ProtoBuf.Meta
             }
         }
 
-        private static void ApplyDefaultBehaviour_AddMembers(TypeModel model, AttributeFamily family, bool isEnum, BasicList partialMembers, int dataMemberOffset, bool inferTagByName, ImplicitFields implicitMode, BasicList members, MemberInfo member, ref bool forced, bool isPublic, bool isField, ref Type effectiveType)
+        private static void ApplyDefaultBehaviour_AddMembers(TypeModel model, AttributeFamily family, bool isEnum, BasicList partialMembers, int dataMemberOffset, bool inferTagByName, ImplicitFields implicitMode, BasicList members, MemberInfo member, ref bool forced, bool isPublic, bool isField, ref Type effectiveType, ref bool hasConflictingEnumValue, MemberInfo backingMember = null)
         {
             switch (implicitMode)
             {
@@ -765,14 +801,14 @@ namespace ProtoBuf.Meta
             }
 
             // we just don't like delegate types ;p
-#if WINRT
+#if WINRT || COREFX
             if (effectiveType.GetTypeInfo().IsSubclassOf(typeof(Delegate))) effectiveType = null;
 #else
             if (effectiveType.IsSubclassOf(model.MapType(typeof(Delegate)))) effectiveType = null;
 #endif
             if (effectiveType != null)
             {
-                ProtoMemberAttribute normalizedAttribute = NormalizeProtoMember(model, member, family, forced, isEnum, partialMembers, dataMemberOffset, inferTagByName);
+                ProtoMemberAttribute normalizedAttribute = NormalizeProtoMember(model, member, family, forced, isEnum, partialMembers, dataMemberOffset, inferTagByName, ref hasConflictingEnumValue, backingMember);
                 if (normalizedAttribute != null) members.Add(normalizedAttribute);
             }
         }
@@ -817,8 +853,8 @@ namespace ProtoBuf.Meta
             }
             if(family == AttributeFamily.None)
             { // check for obvious tuples
-                MemberInfo[] mapping;
-                if(ResolveTupleConstructor(type, out mapping) != null)
+				MemberInfo[] mapping;
+                if (ResolveTupleConstructor(type, out mapping) != null)
                 {
                     family |= AttributeFamily.AutoTuple;
                 }
@@ -829,7 +865,7 @@ namespace ProtoBuf.Meta
         {
             mappedMembers = null;
             if(type == null) throw new ArgumentNullException("type");
-#if WINRT
+#if WINRT || COREFX
             TypeInfo typeInfo = type.GetTypeInfo();
             if (typeInfo.IsAbstract) return null; // as if!
             ConstructorInfo[] ctors = Helpers.GetConstructors(typeInfo, false);
@@ -842,21 +878,25 @@ namespace ProtoBuf.Meta
 
             MemberInfo[] fieldsPropsUnfiltered = Helpers.GetInstanceFieldsAndProperties(type, true);
             BasicList memberList = new BasicList();
+            // for most types we'll enforce that you need readonly, because that is what protobuf-net
+            // always did historically; but: if you smell so much like a Tuple that it is *in your name*,
+            // we'll let you past that
+            bool demandReadOnly = type.Name.IndexOf("Tuple", StringComparison.OrdinalIgnoreCase) < 0;
             for (int i = 0; i < fieldsPropsUnfiltered.Length; i++)
             {
-                PropertyInfo prop = fieldsPropsUnfiltered[i] as PropertyInfo;
-                if (prop != null)
+                if (fieldsPropsUnfiltered[i] is PropertyInfo)
                 {
+					var prop = fieldsPropsUnfiltered [i] as PropertyInfo;
                     if (!prop.CanRead) return null; // no use if can't read
-                    if (prop.CanWrite && Helpers.GetSetMethod(prop, false, false) != null) return null; // don't allow a public set (need to allow non-public to handle Mono's KeyValuePair<,>)
+                    if (demandReadOnly && prop.CanWrite && Helpers.GetSetMethod(prop, false, false) != null) return null; // don't allow a public set (need to allow non-public to handle Mono's KeyValuePair<,>)
                     memberList.Add(prop);
                 }
                 else
                 {
-                    FieldInfo field = fieldsPropsUnfiltered[i] as FieldInfo;
-                    if (field != null)
+                    if (fieldsPropsUnfiltered[i] is FieldInfo)
                     {
-                        if (!field.IsInitOnly) return null; // all public fields must be readonly to be counted a tuple
+						var field = fieldsPropsUnfiltered [i] as FieldInfo;
+                        if (demandReadOnly && !field.IsInitOnly) return null; // all public fields must be readonly to be counted a tuple
                         memberList.Add(field);
                     }
                 }
@@ -884,10 +924,9 @@ namespace ProtoBuf.Meta
 
                 for(int j = 0 ; j < parameters.Length ; j++)
                 {
-                    string lower = parameters[j].Name.ToLower();
                     for(int k = 0 ; k < members.Length ; k++)
                     {
-                        if (members[k].Name.ToLower() != lower) continue;
+                        if (string.Compare(parameters[j].Name, members[k].Name, StringComparison.OrdinalIgnoreCase) != 0) continue;
                         Type memberType = Helpers.GetMemberType(members[k]);
                         if (memberType != parameters[j].ParameterType) continue;
 
@@ -922,7 +961,7 @@ namespace ProtoBuf.Meta
                     if (callbacks == null) { callbacks = new MethodInfo[8]; }
                     else if (callbacks[index] != null)
                     {
-#if WINRT || FEAT_IKVM
+#if WINRT || FEAT_IKVM || COREFX
                         Type reflected = method.DeclaringType;
 #else
                         Type reflected = method.ReflectedType;
@@ -938,13 +977,15 @@ namespace ProtoBuf.Meta
             return (value & required) == required;
         }
         
-        private static ProtoMemberAttribute NormalizeProtoMember(TypeModel model, MemberInfo member, AttributeFamily family, bool forced, bool isEnum, BasicList partialMembers, int dataMemberOffset, bool inferByTagName)
+        private static ProtoMemberAttribute NormalizeProtoMember(TypeModel model, MemberInfo member, AttributeFamily family, bool forced, bool isEnum, BasicList partialMembers, int dataMemberOffset, bool inferByTagName, ref bool hasConflictingEnumValue, MemberInfo backingMember = null)
         {
             if (member == null || (family == AttributeFamily.None && !isEnum)) return null; // nix
             int fieldNumber = int.MinValue, minAcceptFieldNumber = inferByTagName ? -1 : 1;
             string name = null;
             bool isPacked = false, ignore = false, done = false, isRequired = false, asReference = false, asReferenceHasValue = false, dynamicType = false, tagIsPinned = false, overwriteList = false;
             DataFormat dataFormat = DataFormat.Default;
+			string typeName = null;
+			string keyTypeName = null;
             if (isEnum) forced = true;
             AttributeMap[] attribs = AttributeMap.Create(model, member, true);
             AttributeMap attrib;
@@ -959,24 +1000,31 @@ namespace ProtoBuf.Meta
                 else
                 {
                     attrib = GetAttribute(attribs, "ProtoBuf.ProtoEnumAttribute");
-#if WINRT || PORTABLE || CF || FX11
+#if WINRT || PORTABLE || CF || FX11 || COREFX
                     fieldNumber = Convert.ToInt32(((FieldInfo)member).GetValue(null));
 #else
                     fieldNumber = Convert.ToInt32(((FieldInfo)member).GetRawConstantValue());
 #endif
                     if (attrib != null)
                     {
-                        GetFieldName(ref name, attrib, "Name");
+                        GetFieldName(ref name, attrib, nameof(ProtoEnumAttribute.Name));
 #if !FEAT_IKVM // IKVM can't access HasValue, but conveniently, Value will only be returned if set via ctor or property
                         if ((bool)Helpers.GetInstanceMethod(attrib.AttributeType
-#if WINRT
+#if WINRT || COREFX
                              .GetTypeInfo()
 #endif
-                            ,"HasValue").Invoke(attrib.Target, null))
+                            , nameof(ProtoEnumAttribute.HasValue)).Invoke(attrib.Target, null))
 #endif
                         {
-                            object tmp;
-                            if(attrib.TryGet("Value", out tmp)) fieldNumber = (int)tmp;
+							object tmp;
+                            if (attrib.TryGet(nameof(ProtoEnumAttribute.Value), out tmp))
+                            {
+                                if (fieldNumber != (int)tmp)
+                                {
+                                    hasConflictingEnumValue = true;
+                                }
+                                fieldNumber = (int)tmp;
+                            }
                         }
                     }
 
@@ -997,7 +1045,8 @@ namespace ProtoBuf.Meta
                     GetFieldBoolean(ref isPacked, attrib, "IsPacked");
                     GetFieldBoolean(ref overwriteList, attrib, "OverwriteList");
                     GetDataFormat(ref dataFormat, attrib, "DataFormat");
-
+					GetFieldTypeName(ref typeName, attrib, "TypeName");
+					GetFieldTypeName(ref keyTypeName, attrib, "KeyTypeName");
 #if !FEAT_IKVM
                     // IKVM can't access AsReferenceHasValue, but conveniently, AsReference will only be returned if set via ctor or property
                     GetFieldBoolean(ref asReferenceHasValue, attrib, "AsReferenceHasValue", false);
@@ -1014,8 +1063,8 @@ namespace ProtoBuf.Meta
                 {
                     foreach (AttributeMap ppma in partialMembers)
                     {
-                        object tmp;
-                        if(ppma.TryGet("MemberName", out tmp) && (string)tmp == member.Name)
+						object tmp;
+                        if (ppma.TryGet("MemberName", out tmp) && (string)tmp == member.Name)
                         {
                             GetFieldNumber(ref fieldNumber, ppma, "Tag");
                             GetFieldName(ref name, ppma, "Name");
@@ -1023,7 +1072,8 @@ namespace ProtoBuf.Meta
                             GetFieldBoolean(ref isPacked, ppma, "IsPacked");
                             GetFieldBoolean(ref overwriteList, attrib, "OverwriteList");
                             GetDataFormat(ref dataFormat, ppma, "DataFormat");
-
+							GetFieldTypeName(ref typeName, attrib, "TypeName");
+							GetFieldTypeName(ref keyTypeName, attrib, "KeyTypeName");
 #if !FEAT_IKVM
                             // IKVM can't access AsReferenceHasValue, but conveniently, AsReference will only be returned if set via ctor or property
                             GetFieldBoolean(ref asReferenceHasValue, attrib, "AsReferenceHasValue", false);
@@ -1068,17 +1118,22 @@ namespace ProtoBuf.Meta
                 if (GetAttribute(attribs, "System.NonSerializedAttribute") != null) ignore = true;
             }
             if (ignore || (fieldNumber < minAcceptFieldNumber && !forced)) return null;
-            ProtoMemberAttribute result = new ProtoMemberAttribute(fieldNumber, forced || inferByTagName);
-            result.AsReference = asReference;
-            result.AsReferenceHasValue = asReferenceHasValue;
-            result.DataFormat = dataFormat;
-            result.DynamicType = dynamicType;
-            result.IsPacked = isPacked;
-            result.OverwriteList = overwriteList;
-            result.IsRequired = isRequired;
-            result.Name = Helpers.IsNullOrEmpty(name) ? member.Name : name;
-            result.Member = member;
-            result.TagIsPinned = tagIsPinned;
+            ProtoMemberAttribute result = new ProtoMemberAttribute(fieldNumber, forced || inferByTagName)
+            {
+                AsReference = asReference,
+                AsReferenceHasValue = asReferenceHasValue,
+                DataFormat = dataFormat,
+                DynamicType = dynamicType,
+                IsPacked = isPacked,
+                OverwriteList = overwriteList,
+                IsRequired = isRequired,
+                Name = Helpers.IsNullOrEmpty(name) ? member.Name : name,
+                Member = member,
+                BackingMember = backingMember,
+                TagIsPinned = tagIsPinned,
+				TypeName = typeName,
+				KeyTypeName = keyTypeName,
+            };
             return result;
         }
         
@@ -1094,7 +1149,7 @@ namespace ProtoBuf.Meta
             Type defaultType = null;
 
             // check for list types
-            ResolveListTypes(model, effectiveType, ref itemType, ref defaultType);
+			ResolveListTypes(model, effectiveType, ref itemType, ref defaultType);
             // but take it back if it is explicitly excluded
             if(itemType != null)
             { // looks like a list, but double check for IgnoreListHandling
@@ -1133,15 +1188,27 @@ namespace ProtoBuf.Meta
             }
             if ((attrib = GetAttribute(attribs, "System.ComponentModel.DefaultValueAttribute")) != null)
             {
-                object tmp;
-                if(attrib.TryGet("Value", out tmp)) defaultValue = tmp;
-            }
+				object tmp;
+                if (attrib.TryGet("Value", out tmp)) defaultValue = tmp;
+            }
+			var typeName = normalizedAttribute.TypeName;
+			if (itemType != null && itemType.FullName == "ILRuntime.Runtime.Intepreter.ILTypeInstance") {
+				if (typeName == null)
+					throw new ProtoException ("TypeName Must Not Null For " + itemType);
+				itemType = PType.FindType (typeName);
+			}
+			if (defaultType != null && defaultType.FullName == "ILRuntime.Runtime.Intepreter.ILTypeInstance") {
+				if (typeName == null)
+					throw new ProtoException ("TypeName Must Not Null For " + itemType);
+				defaultType = PType.FindType (typeName);
+			}
             ValueMember vm = ((isEnum || normalizedAttribute.Tag > 0))
                 ? new ValueMember(model, type, normalizedAttribute.Tag, member, effectiveType, itemType, defaultType, normalizedAttribute.DataFormat, defaultValue)
                     : null;
             if (vm != null)
             {
-#if WINRT
+                vm.BackingMember = normalizedAttribute.BackingMember;
+#if WINRT || COREFX
                 TypeInfo finalType = typeInfo;
 #else
                 Type finalType = type;
@@ -1170,6 +1237,27 @@ namespace ProtoBuf.Meta
                     vm.AsReference = normalizedAttribute.AsReference;
                 }
                 vm.DynamicType = normalizedAttribute.DynamicType;
+				Type dictionaryType,keyType,valueType;
+				vm.IsMap = vm.ResolveMapTypes(out dictionaryType, out keyType, out valueType);
+                if (vm.IsMap) // is it even *allowed* to be a map?
+                {
+                    if ((attrib = GetAttribute(attribs, "ProtoBuf.ProtoMapAttribute")) != null)
+                    {
+						object tmp;
+                        if (attrib.TryGet(nameof(ProtoMapAttribute.DisableMap), out tmp) && (bool)tmp)
+                        {
+                            vm.IsMap = false;
+                        }
+                        else
+                        {
+                            if (attrib.TryGet(nameof(ProtoMapAttribute.KeyFormat), out tmp)) vm.MapKeyFormat = (DataFormat)tmp;
+                            if (attrib.TryGet(nameof(ProtoMapAttribute.ValueFormat), out tmp)) vm.MapValueFormat = (DataFormat)tmp;
+							vm.MapKeyTypeName = normalizedAttribute.KeyTypeName;
+							vm.MapValueTypeName = normalizedAttribute.TypeName;
+                        }
+                    }
+                }
+
             }
             return vm;
         }
@@ -1177,10 +1265,17 @@ namespace ProtoBuf.Meta
         private static void GetDataFormat(ref DataFormat value, AttributeMap attrib, string memberName)
         {
             if ((attrib == null) || (value != DataFormat.Default)) return;
-            object obj;
+			object obj;
             if (attrib.TryGet(memberName, out obj) && obj != null) value = (DataFormat)obj;
         }
 
+		private static void GetFieldTypeName(ref string typeName, AttributeMap attrib, string memberName)
+		{
+			if (attrib == null || !Helpers.IsNullOrEmpty(typeName)) return;
+			object obj;
+			if (attrib.TryGet(memberName, out obj) && obj != null) typeName = (string)obj;
+		}
+
         private static void GetIgnore(ref bool ignore, AttributeMap attrib, AttributeMap[] attribs, string fullName)
         {
             if (ignore || attrib == null) return;
@@ -1196,7 +1291,7 @@ namespace ProtoBuf.Meta
         {
             if (attrib == null) return false;
             if (value) return true;
-            object obj;
+			object obj;
             if (attrib.TryGet(memberName, publicOnly, out obj) && obj != null)
             {
                 value = (bool)obj;
@@ -1208,13 +1303,13 @@ namespace ProtoBuf.Meta
         private static void GetFieldNumber(ref int value, AttributeMap attrib, string memberName)
         {
             if (attrib == null || value > 0) return;
-            object obj;
+			object obj;
             if (attrib.TryGet(memberName, out obj) && obj != null) value = (int)obj;
         }
         private static void GetFieldName(ref string name, AttributeMap attrib, string memberName)
         {
             if (attrib == null || !Helpers.IsNullOrEmpty(name)) return;
-            object obj;
+			object obj;
             if (attrib.TryGet(memberName, out obj) && obj != null) name = (string)obj;
         }
 
@@ -1393,7 +1488,7 @@ namespace ProtoBuf.Meta
             if (mi == null) throw new ArgumentException("Unable to determine member: " + memberName, "memberName");
 
             Type miType;
-#if WINRT || PORTABLE
+#if WINRT || PORTABLE || COREFX
             PropertyInfo pi = mi as PropertyInfo;
             if (pi == null)
             {
@@ -1423,7 +1518,17 @@ namespace ProtoBuf.Meta
             }
 #endif
             ResolveListTypes(model, miType, ref itemType, ref defaultType);
-            ValueMember newField = new ValueMember(model, type, fieldNumber, mi, miType, itemType, defaultType, DataFormat.Default, defaultValue);
+
+            MemberInfo backingField = null;
+            if ((mi as PropertyInfo)?.CanWrite == false)
+            {
+                var backingMembers = type.GetMember($"<{((PropertyInfo)mi).Name}>k__BackingField", Helpers.IsEnum(type) ? BindingFlags.Static | BindingFlags.Public : BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+                if (backingMembers!= null && backingMembers.Length == 1 && (backingMembers[0] as FieldInfo) != null)
+                    backingField = backingMembers[0];
+            }
+            ValueMember newField = new ValueMember(model, type, fieldNumber, backingField ?? mi, miType, itemType, defaultType, DataFormat.Default, defaultValue);
+            if (backingField != null)
+                newField.SetName(mi.Name);
             Add(newField);
             return newField;
         }
@@ -1434,10 +1539,10 @@ namespace ProtoBuf.Meta
             // handle arrays
             if (type.IsArray)
             {
-                if (type.GetArrayRank() != 1)
-                {
-                    throw new NotSupportedException("Multi-dimension arrays are supported");
-                }
+                //if (type.GetArrayRank() != 1)
+                //{
+                //    throw new NotSupportedException("Multi-dimensional arrays are not supported");
+                //}
                 itemType = type.GetElementType();
                 if (itemType == model.MapType(typeof(byte)))
                 {
@@ -1458,13 +1563,13 @@ namespace ProtoBuf.Meta
                 ResolveListTypes(model, itemType, ref nestedItemType, ref nestedDefaultType);
                 if (nestedItemType != null)
                 {
-                    throw TypeModel.CreateNestedListsNotSupported();
+                    throw TypeModel.CreateNestedListsNotSupported(type);
                 }
             }
 
             if (itemType != null && defaultType == null)
             {
-#if WINRT
+#if WINRT || COREFX
                 TypeInfo typeInfo = type.GetTypeInfo();
                 if (typeInfo.IsClass && !typeInfo.IsAbstract && Helpers.GetConstructor(typeInfo, Helpers.EmptyTypes, true) != null)
 #else
@@ -1475,7 +1580,7 @@ namespace ProtoBuf.Meta
                 }
                 if (defaultType == null)
                 {
-#if WINRT
+#if WINRT || COREFX
                     if (typeInfo.IsInterface)
 #else
                     if (type.IsInterface)
@@ -1485,7 +1590,7 @@ namespace ProtoBuf.Meta
                         defaultType = typeof(ArrayList);
 #else
                         Type[] genArgs;
-#if WINRT
+#if WINRT || COREFX
                         if (typeInfo.IsGenericType && type.GetGenericTypeDefinition() == typeof(System.Collections.Generic.IDictionary<,>)
                             && itemType == typeof(System.Collections.Generic.KeyValuePair<,>).MakeGenericType(genArgs = typeInfo.GenericTypeArguments))
 #else
@@ -1542,7 +1647,7 @@ namespace ProtoBuf.Meta
                 if (member == null) return null;
                 foreach (ValueMember x in fields)
                 {
-                    if (x.Member == member) return x;
+                    if (x.Member == member || x.BackingMember == member) return x;
                 }
                 return null;
             }
@@ -1646,7 +1751,7 @@ namespace ProtoBuf.Meta
             set { SetFlag(OPTIONS_Pending, value, false); }
         }
 
-        private const byte
+        private const ushort
             OPTIONS_Pending = 1,
             OPTIONS_EnumPassThru = 2,
             OPTIONS_Frozen = 4,
@@ -1654,11 +1759,12 @@ namespace ProtoBuf.Meta
             OPTIONS_SkipConstructor = 16,
             OPTIONS_AsReferenceDefault = 32,
             OPTIONS_AutoTuple = 64,
-            OPTIONS_IgnoreListHandling = 128;
+            OPTIONS_IgnoreListHandling = 128,
+            OPTIONS_IsGroup = 256;
 
-        private volatile byte flags;
-        private bool HasFlag(byte flag) { return (flags & flag) == flag; }
-        private void SetFlag(byte flag, bool value, bool throwIfFrozen)
+        private volatile ushort flags;
+        private bool HasFlag(ushort flag) { return (flags & flag) == flag; }
+        private void SetFlag(ushort flag, bool value, bool throwIfFrozen)
         {
             if (throwIfFrozen && HasFlag(flag) != value)
             {
@@ -1667,7 +1773,7 @@ namespace ProtoBuf.Meta
             if (value)
                 flags |= flag;
             else
-                flags = (byte)(flags & ~flag);
+                flags = (ushort)(flags & ~flag);
         }
 
         internal static MetaType GetRootType(MetaType source)
@@ -1714,7 +1820,17 @@ namespace ProtoBuf.Meta
         {
             get { return HasFlag(OPTIONS_AutoTuple); }
         }
-        internal void WriteSchema(System.Text.StringBuilder builder, int indent, ref bool requiresBclImport)
+
+        /// <summary>
+        /// Indicates whether this type should always be treated as a "group" (rather than a string-prefixed sub-message)
+        /// </summary>
+        public bool IsGroup
+        {
+            get { return HasFlag(OPTIONS_IsGroup); }
+            set { SetFlag(OPTIONS_IsGroup, value, true); }
+        }
+
+        internal void WriteSchema(System.Text.StringBuilder builder, int indent, ref RuntimeTypeModel.CommonImports imports, ProtoSyntax syntax)
         {
             if (surrogate != null) return; // nothing to write
 
@@ -1725,31 +1841,33 @@ namespace ProtoBuf.Meta
 
             if (IsList)
             {
-                string itemTypeName = model.GetSchemaTypeName(TypeModel.GetListItemType(model, type), DataFormat.Default, false, false, ref requiresBclImport);
+                string itemTypeName = model.GetSchemaTypeName(TypeModel.GetListItemType(model, type), DataFormat.Default, false, false, ref imports);
                 NewLine(builder, indent).Append("message ").Append(GetSchemaTypeName()).Append(" {");
                 NewLine(builder, indent + 1).Append("repeated ").Append(itemTypeName).Append(" items = 1;");
                 NewLine(builder, indent).Append('}');
             }
             else if (IsAutoTuple)
             { // key-value-pair etc
-                MemberInfo[] mapping;
-                if(ResolveTupleConstructor(type, out mapping) != null)
+				MemberInfo[] mapping;
+                if (ResolveTupleConstructor(type, out mapping) != null)
                 {
                     NewLine(builder, indent).Append("message ").Append(GetSchemaTypeName()).Append(" {");
-                    for(int i = 0 ; i < mapping.Length ; i++)
+                    for (int i = 0; i < mapping.Length; i++)
                     {
                         Type effectiveType;
-                        if(mapping[i] is PropertyInfo)
+                        if (mapping[i] is PropertyInfo)
                         {
-                            effectiveType = ((PropertyInfo) mapping[i]).PropertyType;
-                        } else if (mapping[i] is FieldInfo)
+                            effectiveType = ((PropertyInfo)mapping[i]).PropertyType;
+                        }
+                        else if (mapping[i] is FieldInfo)
                         {
-                            effectiveType = ((FieldInfo) mapping[i]).FieldType;
-                        } else
+                            effectiveType = ((FieldInfo)mapping[i]).FieldType;
+                        }
+                        else
                         {
                             throw new NotSupportedException("Unknown member type: " + mapping[i].GetType().Name);
                         }
-                        NewLine(builder, indent + 1).Append("optional ").Append(model.GetSchemaTypeName(effectiveType, DataFormat.Default, false, false, ref requiresBclImport).Replace('.','_'))
+                        NewLine(builder, indent + 1).Append(syntax == ProtoSyntax.Proto2 ? "optional " : "").Append(model.GetSchemaTypeName(effectiveType, DataFormat.Default, false, false, ref imports).Replace('.', '_'))
                             .Append(' ').Append(mapping[i].Name).Append(" = ").Append(i + 1).Append(';');
                     }
                     NewLine(builder, indent).Append('}');
@@ -1760,7 +1878,7 @@ namespace ProtoBuf.Meta
                 NewLine(builder, indent).Append("enum ").Append(GetSchemaTypeName()).Append(" {");
                 if (fieldsArr.Length == 0 && EnumPassthru) {
                     if (type
-#if WINRT
+#if WINRT || COREFX
                     .GetTypeInfo()
 #endif
 .IsDefined(model.MapType(typeof(FlagsAttribute)), false))
@@ -1783,8 +1901,8 @@ namespace ProtoBuf.Meta
                         if(field.IsStatic && field.IsLiteral)
                         {
                             object enumVal;
-#if WINRT || PORTABLE || CF || FX11
-                            enumVal = field.GetValue(null);
+#if WINRT || PORTABLE || CF || FX11 || NETSTANDARD1_3 || NETSTANDARD1_4
+                            enumVal = Convert.ChangeType(field.GetValue(null), Enum.GetUnderlyingType(field.FieldType), System.Globalization.CultureInfo.InvariantCulture);
 #else
                             enumVal = field.GetRawConstantValue();
 #endif
@@ -1795,8 +1913,40 @@ namespace ProtoBuf.Meta
                 }
                 else
                 {
+                    Dictionary<int, int> countByField = new Dictionary<int, int>(fieldsArr.Length);
+                    bool needsAlias = false;
+                    foreach(var field in fieldsArr)
+                    {
+                        if(countByField.ContainsKey(field.FieldNumber))
+                        {  // no point actually counting; that's enough to know we have a problem
+                            needsAlias = true;
+                            break;
+                        }
+                        countByField.Add(field.FieldNumber, 1);
+                    }
+                    if (needsAlias)
+                    {   // duplicated value requires allow_alias
+                        NewLine(builder, indent + 1).Append("option allow_alias = true;");
+                    }
+
+                    bool haveWrittenZero = false;
+                    // write zero values **first**
+                    foreach (ValueMember member in fieldsArr)
+                    {
+                        if(member.FieldNumber == 0)
+                        {
+                            NewLine(builder, indent + 1).Append(member.Name).Append(" = ").Append(member.FieldNumber).Append(';');
+                            haveWrittenZero = true;
+                        }
+                    }
+                    if (syntax == ProtoSyntax.Proto3 && !haveWrittenZero)
+                    {
+                        NewLine(builder, indent + 1).Append("ZERO = 0; // proto3 requires a zero value as the first item (it can be named anything)");   
+                    }
+                    // note array is already sorted, so zero would already be first
                     foreach (ValueMember member in fieldsArr)
                     {
+                        if (member.FieldNumber == 0) continue;
                         NewLine(builder, indent + 1).Append(member.Name).Append(" = ").Append(member.FieldNumber).Append(';');
                     }
                 }
@@ -1806,35 +1956,83 @@ namespace ProtoBuf.Meta
                 NewLine(builder, indent).Append("message ").Append(GetSchemaTypeName()).Append(" {");
                 foreach (ValueMember member in fieldsArr)
                 {
-                    string ordinality = member.ItemType != null ? "repeated" : member.IsRequired ? "required" : "optional";
-                    NewLine(builder, indent + 1).Append(ordinality).Append(' ');
-                    if (member.DataFormat == DataFormat.Group) builder.Append("group ");
-                    string schemaTypeName = member.GetSchemaTypeName(true, ref requiresBclImport);
-                    builder.Append(schemaTypeName).Append(" ")
-                         .Append(member.Name).Append(" = ").Append(member.FieldNumber);
-                    if(member.DefaultValue != null)
+                    string schemaTypeName;
+                    bool hasOption = false;
+                    if (member.IsMap)
                     {
-                        if (member.DefaultValue is string)
+						Type dictionaryType, keyType,valueType;
+						member.ResolveMapTypes(out dictionaryType, out keyType, out valueType);
+
+                        var keyTypeName = model.GetSchemaTypeName(keyType, member.MapKeyFormat, false, false, ref imports);
+                        schemaTypeName = model.GetSchemaTypeName(valueType, member.MapKeyFormat, member.AsReference, member.DynamicType, ref imports);
+                        NewLine(builder, indent + 1).Append("map<").Append(keyTypeName).Append(",").Append(schemaTypeName).Append("> ")
+                            .Append(member.Name).Append(" = ").Append(member.FieldNumber).Append(";");
+                    }
+                    else
+                    {
+                        string ordinality = member.ItemType != null ? "repeated " : (syntax == ProtoSyntax.Proto2 ? (member.IsRequired ? "required " : "optional ") : "");
+                        NewLine(builder, indent + 1).Append(ordinality);
+                        if (member.DataFormat == DataFormat.Group) builder.Append("group ");
+                        schemaTypeName = member.GetSchemaTypeName(true, ref imports);
+                        builder.Append(schemaTypeName).Append(" ")
+                             .Append(member.Name).Append(" = ").Append(member.FieldNumber);
+
+                        if (syntax == ProtoSyntax.Proto2 && member.DefaultValue != null && member.IsRequired == false)
+                        {
+                            if (member.DefaultValue is string)
+                            {
+                                AddOption(builder, ref hasOption).Append("default = \"").Append(member.DefaultValue).Append("\"");
+                            }
+                            else if (member.DefaultValue is TimeSpan)
+                            {
+                                // ignore
+                            }
+                            else if (member.DefaultValue is bool)
+                            {   // need to be lower case (issue 304)
+                                AddOption(builder, ref hasOption).Append((bool)member.DefaultValue ? "default = true" : "default = false");
+                            }
+                            else
+                            {
+                                AddOption(builder, ref hasOption).Append("default = ").Append(member.DefaultValue);
+                            }
+                        }
+                        if (CanPack(member.ItemType))
+                        {
+                            if(syntax == ProtoSyntax.Proto2)
+                            {
+                                if (member.IsPacked) AddOption(builder, ref hasOption).Append("packed = true"); // disabled by default
+                            }
+                            else
+                            {
+                                if (!member.IsPacked) AddOption(builder, ref hasOption).Append("packed = false"); // enabled by default
+                            }
+                        }
+                        if (member.AsReference)
                         {
-                            builder.Append(" [default = \"").Append(member.DefaultValue).Append("\"]");
+                            imports |= RuntimeTypeModel.CommonImports.Protogen;
+                            AddOption(builder, ref hasOption).Append("(.protobuf_net.fieldopt).asRef = true");
                         }
-                        else if(member.DefaultValue is bool)
-                        {   // need to be lower case (issue 304)
-                            builder.Append((bool)member.DefaultValue ? " [default = true]" : " [default = false]");
+                        if (member.DynamicType)
+                        {
+                            imports |= RuntimeTypeModel.CommonImports.Protogen;
+                            AddOption(builder, ref hasOption).Append("(.protobuf_net.fieldopt).dynamicType = true");
                         }
-                        else
+                        CloseOption(builder, ref hasOption).Append(';');
+                        if (syntax != ProtoSyntax.Proto2 && member.DefaultValue != null && !member.IsRequired)
                         {
-                            builder.Append(" [default = ").Append(member.DefaultValue).Append(']');
+                            if (IsImplicitDefault(member.DefaultValue))
+                            {
+                                // don't emit; we're good
+                            }
+                            else 
+                            {
+                                builder.Append(" // default value could not be applied: ").Append(member.DefaultValue);
+                            }
                         }
                     }
-                    if(member.ItemType != null && member.IsPacked)
-                    {
-                        builder.Append(" [packed=true]");
-                    }
-                    builder.Append(';');
-                    if (schemaTypeName == "bcl.NetObjectProxy" && member.AsReference && !member.DynamicType) // we know what it is; tell the user
+                    if (schemaTypeName == ".bcl.NetObjectProxy" && member.AsReference && !member.DynamicType) // we know what it is; tell the user
                     {
-                        builder.Append(" // reference-tracked ").Append(member.GetSchemaTypeName(false, ref requiresBclImport));
+                        builder.Append(" // reference-tracked ").Append(member.GetSchemaTypeName(false, ref imports));
                     }
                 }
                 if (subTypes != null && subTypes.Count != 0)
@@ -1846,13 +2044,81 @@ namespace ProtoBuf.Meta
                     foreach (SubType subType in subTypeArr)
                     {
                         string subTypeName = subType.DerivedType.GetSchemaTypeName();
-                        NewLine(builder, indent + 1).Append("optional ").Append(subTypeName)
+                        NewLine(builder, indent + 1).Append((syntax == ProtoSyntax.Proto2 ? "optional " : "")).Append(subTypeName)
                             .Append(" ").Append(subTypeName).Append(" = ").Append(subType.FieldNumber).Append(';');
                     }
                 }
                 NewLine(builder, indent).Append('}');
             }
         }
+
+        private static StringBuilder AddOption(StringBuilder builder, ref bool hasOption)
+        {
+            if (hasOption)
+                return builder.Append(", ");
+            hasOption = true;
+            return builder.Append(" [");
+        }
+        private static StringBuilder CloseOption(StringBuilder builder, ref bool hasOption)
+        {
+            if(hasOption)
+            {
+                hasOption = false;
+                return builder.Append("]");
+            }
+            return builder;
+        }
+
+        private static bool IsImplicitDefault(object value)
+        {
+            try
+            {
+                if (value == null) return false;
+                switch (Helpers.GetTypeCode(value.GetType()))
+                {
+                    case ProtoTypeCode.Boolean: return ((bool)value) == false;
+                    case ProtoTypeCode.Byte: return ((byte)value) == (byte)0;
+                    case ProtoTypeCode.Char: return ((char)value) == (char)0;
+                    case ProtoTypeCode.DateTime: return ((DateTime)value) == default(DateTime);
+                    case ProtoTypeCode.Decimal: return ((decimal)value) == 0M;
+                    case ProtoTypeCode.Double: return ((double)value) == (double)0;
+                    case ProtoTypeCode.Int16: return ((short)value) == (short)0;
+                    case ProtoTypeCode.Int32: return ((int)value) == (int)0;
+                    case ProtoTypeCode.Int64: return ((long)value) == (long)0;
+                    case ProtoTypeCode.SByte: return ((sbyte)value) == (sbyte)0;
+                    case ProtoTypeCode.Single: return ((float)value) == (float)0;
+                    case ProtoTypeCode.String: return ((string)value) == "";
+                    case ProtoTypeCode.TimeSpan: return ((TimeSpan)value) == TimeSpan.Zero;
+                    case ProtoTypeCode.UInt16: return ((ushort)value) == (ushort)0;
+                    case ProtoTypeCode.UInt32: return ((uint)value) == (uint)0;
+                    case ProtoTypeCode.UInt64: return ((ulong)value) == (ulong)0;
+                }
+            }
+            catch { }
+            return false;
+        }
+
+        private static bool CanPack(Type type)
+        {
+            if (type == null) return false;
+            switch(Helpers.GetTypeCode(type))
+            {
+                case ProtoTypeCode.Boolean:
+                case ProtoTypeCode.Byte:
+                case ProtoTypeCode.Char:
+                case ProtoTypeCode.Double:
+                case ProtoTypeCode.Int16:
+                case ProtoTypeCode.Int32:
+                case ProtoTypeCode.Int64:
+                case ProtoTypeCode.SByte:
+                case ProtoTypeCode.Single:
+                case ProtoTypeCode.UInt16:
+                case ProtoTypeCode.UInt32:
+                case ProtoTypeCode.UInt64:
+                    return true;
+            }
+            return false;
+        }
     }
 }
 #endif

+ 3 - 3
Unity/Assets/Plugins/protobuf-net/Meta/MetaType.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/MetaType.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 853a227c3b0c9514aad6a5386f422cc2
-timeCreated: 1515899113
-licenseType: Pro
+guid: 8077fe676716aab4c9cc968c5e7ad6ef
+timeCreated: 1517401477
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 17 - 0
Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/ProtoSyntax.cs

@@ -0,0 +1,17 @@
+namespace ProtoBuf.Meta
+{
+    /// <summary>
+    /// Indiate the variant of the protobuf .proto DSL syntax to use
+    /// </summary>
+    public enum ProtoSyntax
+    {
+        /// <summary>
+        /// https://developers.google.com/protocol-buffers/docs/proto
+        /// </summary>
+        Proto2 = 0,
+        /// <summary>
+        /// https://developers.google.com/protocol-buffers/docs/proto3
+        /// </summary>
+        Proto3 = 1,
+    }
+}

+ 12 - 0
Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/ProtoSyntax.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: e4f88f5312bc6d74fbb674a293fe3b37
+timeCreated: 1517401477
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 204 - 61
Unity/Assets/Plugins/protobuf-net/Meta/RuntimeTypeModel.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/RuntimeTypeModel.cs

@@ -26,8 +26,8 @@ namespace ProtoBuf.Meta
     /// </summary>
     public sealed class RuntimeTypeModel : TypeModel
     {
-        private byte options;
-        private const byte
+        private ushort options;
+        private const ushort
            OPTIONS_InferTagFromNameDefault = 1,
            OPTIONS_IsDefaultModel = 2,
            OPTIONS_Frozen = 4,
@@ -37,15 +37,16 @@ namespace ProtoBuf.Meta
 #endif
            OPTIONS_UseImplicitZeroDefaults = 32,
            OPTIONS_AllowParseableTypes = 64,
-           OPTIONS_AutoAddProtoContractTypesOnly = 128;
-        private bool GetOption(byte option)
+           OPTIONS_AutoAddProtoContractTypesOnly = 128,
+           OPTIONS_IncludeDateTimeKind = 256;
+        private bool GetOption(ushort option)
         {
             return (options & option) == option;
         }
-        private void SetOption(byte option, bool value)
+        private void SetOption(ushort option, bool value)
         {
             if (value) options |= option;
-            else options &= (byte)~option;
+            else options &= (ushort)~option;
         }
         /// <summary>
         /// Global default that
@@ -102,6 +103,22 @@ namespace ProtoBuf.Meta
             get { return GetOption(OPTIONS_AllowParseableTypes); }
             set { SetOption(OPTIONS_AllowParseableTypes, value); }
         }
+        /// <summary>
+        /// Global switch that determines whether DateTime serialization should include the <c>Kind</c> of the date/time.
+        /// </summary>
+        public bool IncludeDateTimeKind
+        {
+            get { return GetOption(OPTIONS_IncludeDateTimeKind); }
+            set { SetOption(OPTIONS_IncludeDateTimeKind, value); }
+        }
+
+        /// <summary>
+        /// Should the <c>Kind</c> be included on date/time values?
+        /// </summary>
+        protected internal override bool SerializeDateTimeKind()
+        {
+            return GetOption(OPTIONS_IncludeDateTimeKind);
+        }
         
 
         private sealed class Singleton
@@ -127,7 +144,8 @@ namespace ProtoBuf.Meta
         /// </summary>
         /// <param name="type">The type to generate a .proto definition for, or <c>null</c> to generate a .proto that represents the entire model</param>
         /// <returns>The .proto definition as a string</returns>
-        public override string GetSchema(Type type)
+        /// <param name="syntax">The .proto syntax to use</param>
+        public override string GetSchema(Type type, ProtoSyntax syntax)
         {
             BasicList requiredTypes = new BasicList();
             MetaType primaryType = null;
@@ -193,14 +211,25 @@ namespace ProtoBuf.Meta
                     }
                 }
             }
-
+            switch(syntax)
+            {
+                case ProtoSyntax.Proto2:
+                    headerBuilder.AppendLine(@"syntax = ""proto2"";");
+                    break;
+                case ProtoSyntax.Proto3:
+                    headerBuilder.AppendLine(@"syntax = ""proto3"";");
+                    break;
+                default:
+                    throw new ArgumentOutOfRangeException(nameof(syntax));
+            }
+            
             if (!Helpers.IsNullOrEmpty(package))
             {
                 headerBuilder.Append("package ").Append(package).Append(';');
                 Helpers.AppendLine(headerBuilder);
             }
 
-            bool requiresBclImport = false;
+            var imports = CommonImports.None;
             StringBuilder bodyBuilder = new StringBuilder();
             // sort them by schema-name
             MetaType[] metaTypesArr = new MetaType[requiredTypes.Count];
@@ -211,7 +240,7 @@ namespace ProtoBuf.Meta
             if (isInbuiltType)
             {
                 Helpers.AppendLine(bodyBuilder).Append("message ").Append(type.Name).Append(" {");
-                MetaType.NewLine(bodyBuilder, 1).Append("optional ").Append(GetSchemaTypeName(type, DataFormat.Default, false, false, ref requiresBclImport))
+                MetaType.NewLine(bodyBuilder, 1).Append(syntax == ProtoSyntax.Proto2 ? "optional " : "").Append(GetSchemaTypeName(type, DataFormat.Default, false, false, ref imports))
                     .Append(" value = 1;");
                 Helpers.AppendLine(bodyBuilder).Append('}');
             }
@@ -221,16 +250,40 @@ namespace ProtoBuf.Meta
                 {
                     MetaType tmp = metaTypesArr[i];
                     if (tmp.IsList && tmp != primaryType) continue;
-                    tmp.WriteSchema(bodyBuilder, 0, ref requiresBclImport);
+                    tmp.WriteSchema(bodyBuilder, 0, ref imports, syntax);
                 }
             }
-            if (requiresBclImport)
+            if ((imports & CommonImports.Bcl) != 0)
+            {
+                headerBuilder.Append("import \"protobuf-net/bcl.proto\"; // schema for protobuf-net's handling of core .NET types");
+                Helpers.AppendLine(headerBuilder);
+            }
+            if ((imports & CommonImports.Protogen) != 0)
             {
-                headerBuilder.Append("import \"bcl.proto\"; // schema for protobuf-net's handling of core .NET types");
+                headerBuilder.Append("import \"protobuf-net/protogen.proto\"; // custom protobuf-net options");
+                Helpers.AppendLine(headerBuilder);
+            }
+            if ((imports & CommonImports.Timestamp) != 0)
+            {
+                headerBuilder.Append("import \"google/protobuf/timestamp.proto\";");
+                Helpers.AppendLine(headerBuilder);
+            }
+            if ((imports & CommonImports.Duration) != 0)
+            {
+                headerBuilder.Append("import \"google/protobuf/duration.proto\";");
                 Helpers.AppendLine(headerBuilder);
             }
             return Helpers.AppendLine(headerBuilder.Append(bodyBuilder)).ToString();
         }
+        [Flags]
+        internal enum CommonImports
+        {
+            None = 0,
+            Bcl = 1,
+            Timestamp = 2,
+            Duration = 4,
+            Protogen = 8
+        }
         private void CascadeDependents(BasicList list, MetaType metaType)
         {
             MetaType tmp;
@@ -289,6 +342,11 @@ namespace ProtoBuf.Meta
                     foreach (ValueMember member in metaType.Fields)
                     {
                         Type type = member.ItemType;
+                        if(member.IsMap)
+                        {
+							Type dictionaryType, keyType;
+							member.ResolveMapTypes(out dictionaryType, out keyType, out type); // don't need key-type
+                        }
                         if (type == null) type = member.MemberType;
                         WireType defaultWireType;
                         IProtoSerializer coreSerializer = ValueMember.TryGetCoreSerializer(this, DataFormat.Default, type, out defaultWireType, false, false, false, false);
@@ -361,7 +419,7 @@ namespace ProtoBuf.Meta
 
         /// <summary>
         /// Adds support for an additional type in this model, optionally
-        /// appplying inbuilt patterns. If the type is already known to the
+        /// applying inbuilt patterns. If the type is already known to the
         /// model, the existing type is returned **without** applying
         /// any additional behaviour.
         /// </summary>
@@ -372,7 +430,7 @@ namespace ProtoBuf.Meta
         }
         /// <summary>
         /// Adds support for an additional type in this model, optionally
-        /// appplying inbuilt patterns. If the type is already known to the
+        /// applying inbuilt patterns. If the type is already known to the
         /// model, the existing type is returned **without** applying
         /// any additional behaviour.
         /// </summary>
@@ -593,7 +651,7 @@ namespace ProtoBuf.Meta
 
         /// <summary>
         /// Adds support for an additional type in this model, optionally
-        /// appplying inbuilt patterns. If the type is already known to the
+        /// applying inbuilt patterns. If the type is already known to the
         /// model, the existing type is returned **without** applying
         /// any additional behaviour.
         /// </summary>
@@ -615,8 +673,8 @@ namespace ProtoBuf.Meta
             MetaType newType = FindWithoutAdd(type);
             if (newType != null) return newType; // return existing
             int opaqueToken = 0;
-            
-#if WINRT
+
+#if WINRT || COREFX
             System.Reflection.TypeInfo typeInfo = System.Reflection.IntrospectionExtensions.GetTypeInfo(type);
             if (typeInfo.IsInterface && MetaType.ienumerable.IsAssignableFrom(typeInfo)
 #else
@@ -749,6 +807,13 @@ namespace ProtoBuf.Meta
             throw new NotSupportedException();
 #else
             //Helpers.DebugWriteLine("Serialize", value);
+			var type = value.GetType();
+			if(type.IsGenericType && type.GetGenericTypeDefinition() == typeof(System.Collections.Generic.KeyValuePair<,>)){
+				var Key = type.GetProperty("Key");
+				var Value = type.GetProperty("Value");
+				((MetaType)types[key]).KVPKeyType = PType.GetPType(Key.GetValue(value));
+				((MetaType)types[key]).KVPValueType = PType.GetPType(Value.GetValue(value));
+			}
             ((MetaType)types[key]).Serializer.Write(value, dest);
 #endif
         }
@@ -769,7 +834,7 @@ namespace ProtoBuf.Meta
             //Helpers.DebugWriteLine("Deserialize", value);
             IProtoSerializer ser = ((MetaType)types[key]).Serializer;
             if (value == null && Helpers.IsValueType(ser.ExpectedType)) {
-                if(ser.RequiresOldValue) value = Activator.CreateInstance(ser.ExpectedType);
+				if(ser.RequiresOldValue) value = PType.CreateInstance(ser.ExpectedType);
                 return ser.Read(value, source);
             } else {
                 return ser.Read(value, source);
@@ -893,7 +958,8 @@ namespace ProtoBuf.Meta
         /// <returns>An instance of the newly created compiled type-model</returns>
         public TypeModel Compile()
         {
-            return Compile(null, null);
+            CompilerOptions options = new CompilerOptions();
+            return Compile(options);
         }
         static ILGenerator Override(TypeBuilder type, string name)
         {
@@ -963,7 +1029,7 @@ namespace ProtoBuf.Meta
             public void SetFrameworkOptions(MetaType from)
             {
                 if (from == null) throw new ArgumentNullException("from");
-                AttributeMap[] attribs = AttributeMap.Create(from.Model, from.Type.Assembly);
+                AttributeMap[] attribs = AttributeMap.Create(from.Model, Helpers.GetAssembly(from.Type));
                 foreach (AttributeMap attrib in attribs)
                 {
                     if (attrib.AttributeType.FullName == "System.Runtime.Versioning.TargetFrameworkAttribute")
@@ -991,9 +1057,16 @@ namespace ProtoBuf.Meta
             /// The name of the TypeModel class to create
             /// </summary>
             public string TypeName { get { return typeName; } set { typeName = value; } }
+
+#if COREFX
+            internal const string NoPersistence = "Assembly persistence not supported on this runtime";
+#endif
             /// <summary>
             /// The path for the new dll
             /// </summary>
+#if COREFX
+            [Obsolete(NoPersistence)]
+#endif
             public string OutputPath { get { return outputPath; } set { outputPath = value; } }
             /// <summary>
             /// The runtime version for the generated assembly
@@ -1041,6 +1114,8 @@ namespace ProtoBuf.Meta
             /// </summary>
             Internal
         }
+
+#if !COREFX
         /// <summary>
         /// Fully compiles the current model into a static-compiled serialization dll
         /// (the serialization dll still requires protobuf-net for support services).
@@ -1056,7 +1131,7 @@ namespace ProtoBuf.Meta
             options.OutputPath = path;
             return Compile(options);
         }
-
+#endif
         /// <summary>
         /// Fully compiles the current model into a static-compiled serialization dll
         /// (the serialization dll still requires protobuf-net for support services).
@@ -1067,7 +1142,9 @@ namespace ProtoBuf.Meta
         {
             if (options == null) throw new ArgumentNullException("options");
             string typeName = options.TypeName;
+#pragma warning disable 0618
             string path = options.OutputPath;
+#pragma warning restore 0618
             BuildAllSerializers();
             Freeze();
             bool save = !Helpers.IsNullOrEmpty(path);
@@ -1111,6 +1188,12 @@ namespace ProtoBuf.Meta
                 asm.__SetImageRuntimeVersion(options.ImageRuntimeVersion, options.MetaDataVersion);
             }
             ModuleBuilder module = asm.DefineDynamicModule(moduleName, path);
+#elif COREFX
+            AssemblyName an = new AssemblyName();
+            an.Name = assemblyName;
+            AssemblyBuilder asm = AssemblyBuilder.DefineDynamicAssembly(an,
+                AssemblyBuilderAccess.Run);
+            ModuleBuilder module = asm.DefineDynamicModule(moduleName);
 #else
             AssemblyName an = new AssemblyName();
             an.Name = assemblyName;
@@ -1137,17 +1220,37 @@ namespace ProtoBuf.Meta
             Type knownTypesLookupType;
             WriteGetKeyImpl(type, hasInheritance, methodPairs, ilVersion, assemblyName, out il, out knownTypesCategory, out knownTypes, out knownTypesLookupType);
 
+            // trivial flags
+            il = Override(type, "SerializeDateTimeKind");
+            il.Emit(IncludeDateTimeKind ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
+            il.Emit(OpCodes.Ret);
+            // end: trivial flags
+
             Compiler.CompilerContext ctx = WriteSerializeDeserialize(assemblyName, type, methodPairs, ilVersion, ref il);
 
             WriteConstructors(type, ref index, methodPairs, ref il, knownTypesCategory, knownTypes, knownTypesLookupType, ctx);
-            
 
 
+#if COREFX
+            Type finalType = type.CreateTypeInfo().AsType();
+#else
             Type finalType = type.CreateType();
-            if(!Helpers.IsNullOrEmpty(path))
+#endif
+            if (!Helpers.IsNullOrEmpty(path))
             {
-                asm.Save(path);
+#if COREFX
+                throw new NotSupportedException(CompilerOptions.NoPersistence);
+#else
+                try
+                {
+                    asm.Save(path);
+                } catch(IOException ex)
+                {
+                    // advertise the file info
+                    throw new IOException(path + ", " + ex.Message, ex);
+                }
                 Helpers.DebugWriteLine("Wrote dll:" + path);
+#endif
             }
 #if FEAT_IKVM
             return null;
@@ -1262,7 +1365,7 @@ namespace ProtoBuf.Meta
         private Compiler.CompilerContext WriteSerializeDeserialize(string assemblyName, TypeBuilder type, SerializerPair[] methodPairs, Compiler.CompilerContext.ILVersion ilVersion, ref ILGenerator il)
         {
             il = Override(type, "Serialize");
-            Compiler.CompilerContext ctx = new Compiler.CompilerContext(il, false, true, methodPairs, this, ilVersion, assemblyName, MapType(typeof(object)));
+            Compiler.CompilerContext ctx = new Compiler.CompilerContext(il, false, true, methodPairs, this, ilVersion, assemblyName, MapType(typeof(object)), "Serialize " + type.Name);
             // arg0 = this, arg1 = key, arg2=obj, arg3=dest
             Compiler.CodeLabel[] jumpTable = new Compiler.CodeLabel[types.Count];
             for (int i = 0; i < jumpTable.Length; i++)
@@ -1284,7 +1387,7 @@ namespace ProtoBuf.Meta
             }
 
             il = Override(type, "Deserialize");
-            ctx = new Compiler.CompilerContext(il, false, false, methodPairs, this, ilVersion, assemblyName, MapType(typeof(object)));
+            ctx = new Compiler.CompilerContext(il, false, false, methodPairs, this, ilVersion, assemblyName, MapType(typeof(object)), "Deserialize " + type.Name);
             // arg0 = this, arg1 = key, arg2=obj, arg3=source
             for (int i = 0; i < jumpTable.Length; i++)
             {
@@ -1299,7 +1402,7 @@ namespace ProtoBuf.Meta
                 SerializerPair pair = methodPairs[i];
                 ctx.MarkLabel(jumpTable[i]);
                 Type keyType = pair.Type.Type;
-                if (keyType.IsValueType)
+                if (Helpers.IsValueType(keyType))
                 {
                     il.Emit(OpCodes.Ldarg_2);
                     il.Emit(OpCodes.Ldarg_3);
@@ -1323,8 +1426,9 @@ namespace ProtoBuf.Meta
         {
 
             il = Override(type, "GetKeyImpl");
-            Compiler.CompilerContext ctx = new Compiler.CompilerContext(il, false, false, methodPairs, this, ilVersion, assemblyName, MapType(typeof(System.Type), true));
-            
+            Compiler.CompilerContext ctx = new Compiler.CompilerContext(il, false, false, methodPairs, this, ilVersion, assemblyName, MapType(typeof(System.Type), true), "GetKeyImpl");
+
+
             if (types.Count <= KnownTypes_ArrayCutoff)
             {
                 knownTypesCategory = KnownTypes_Array;
@@ -1337,12 +1441,15 @@ namespace ProtoBuf.Meta
 #else
                 knownTypesLookupType = MapType(typeof(System.Collections.Generic.Dictionary<System.Type, int>), false);
 #endif
+
+#if !COREFX
                 if (knownTypesLookupType == null)
                 {
                     knownTypesLookupType = MapType(typeof(Hashtable), true);
                     knownTypesCategory = KnownTypes_Hashtable;
                 }
                 else
+#endif
                 {
                     knownTypesCategory = KnownTypes_Dictionary;
                 }
@@ -1511,12 +1618,17 @@ namespace ProtoBuf.Meta
             for (index = 0; index < methodPairs.Length; index++)
             {
                 SerializerPair pair = methodPairs[index];
-                ctx = new Compiler.CompilerContext(pair.SerializeBody, true, true, methodPairs, this, ilVersion, assemblyName, pair.Type.Type);
-                ctx.CheckAccessibility(pair.Deserialize.ReturnType);
+                ctx = new Compiler.CompilerContext(pair.SerializeBody, true, true, methodPairs, this, ilVersion, assemblyName, pair.Type.Type, "SerializeImpl " + pair.Type.Type.Name);
+                MemberInfo returnType = pair.Deserialize.ReturnType
+#if COREFX
+                    .GetTypeInfo()
+#endif
+                    ;
+                ctx.CheckAccessibility(ref returnType);
                 pair.Type.Serializer.EmitWrite(ctx, ctx.InputValue);
                 ctx.Return();
 
-                ctx = new Compiler.CompilerContext(pair.DeserializeBody, true, false, methodPairs, this, ilVersion, assemblyName, pair.Type.Type);
+                ctx = new Compiler.CompilerContext(pair.DeserializeBody, true, false, methodPairs, this, ilVersion, assemblyName, pair.Type.Type, "DeserializeImpl " + pair.Type.Type.Name);
                 pair.Type.Serializer.EmitRead(ctx, ctx.InputValue);
                 if (!pair.Type.Serializer.ReturnsValue)
                 {
@@ -1529,7 +1641,11 @@ namespace ProtoBuf.Meta
         private TypeBuilder WriteBasicTypeModel(CompilerOptions options, string typeName, ModuleBuilder module)
         {
             Type baseType = MapType(typeof(TypeModel));
+#if COREFX
+            TypeAttributes typeAttributes = (baseType.GetTypeInfo().Attributes & ~TypeAttributes.Abstract) | TypeAttributes.Sealed;
+#else
             TypeAttributes typeAttributes = (baseType.Attributes & ~TypeAttributes.Abstract) | TypeAttributes.Sealed;
+#endif
             if (options.Accessibility == Accessibility.Internal)
             {
                 typeAttributes &= ~TypeAttributes.Public;
@@ -1547,7 +1663,7 @@ namespace ProtoBuf.Meta
                 Type versionAttribType = null;
                 try
                 { // this is best-endeavours only
-                    versionAttribType = GetType("System.Runtime.Versioning.TargetFrameworkAttribute", MapType(typeof(string)).Assembly);
+                    versionAttribType = GetType("System.Runtime.Versioning.TargetFrameworkAttribute", Helpers.GetAssembly(MapType(typeof(string))));
                 }
                 catch { /* don't stress */ }
                 if (versionAttribType != null)
@@ -1587,7 +1703,7 @@ namespace ProtoBuf.Meta
                 BasicList internalAssemblies = new BasicList(), consideredAssemblies = new BasicList();
                 foreach (MetaType metaType in types)
                 {
-                    Assembly assembly = metaType.Type.Assembly;
+                    Assembly assembly = Helpers.GetAssembly(metaType.Type);
                     if (consideredAssemblies.IndexOfReference(assembly) >= 0) continue;
                     consideredAssemblies.Add(assembly);
 
@@ -1619,7 +1735,7 @@ namespace ProtoBuf.Meta
             MethodInfo dedicated = methodPairs[i].Deserialize;
             MethodBuilder boxedSerializer = type.DefineMethod("_" + i.ToString(), MethodAttributes.Static, CallingConventions.Standard,
                 model.MapType(typeof(object)), new Type[] { model.MapType(typeof(object)), model.MapType(typeof(ProtoReader)) });
-            Compiler.CompilerContext ctx = new Compiler.CompilerContext(boxedSerializer.GetILGenerator(), true, false, methodPairs, model, ilVersion, assemblyName, model.MapType(typeof(object)));
+            Compiler.CompilerContext ctx = new Compiler.CompilerContext(boxedSerializer.GetILGenerator(), true, false, methodPairs, model, ilVersion, assemblyName, model.MapType(typeof(object)), "BoxedSerializer "  + valueType.Name);
             ctx.LoadValue(ctx.InputValue);
             Compiler.CodeLabel @null = ctx.DefineLabel();
             ctx.BranchIfFalse(@null, true);
@@ -1649,13 +1765,13 @@ namespace ProtoBuf.Meta
         
 #endif
 #endif
-        //internal bool IsDefined(Type type, int fieldNumber)
-        //{
-        //    return FindWithoutAdd(type).IsDefined(fieldNumber);
-        //}
+            //internal bool IsDefined(Type type, int fieldNumber)
+            //{
+            //    return FindWithoutAdd(type).IsDefined(fieldNumber);
+            //}
 
-        // note that this is used by some of the unit tests
-        internal bool IsPrepared(Type type)
+            // note that this is used by some of the unit tests
+            internal bool IsPrepared(Type type)
         {
             MetaType meta = FindWithoutAdd(type);
             return meta != null && meta.IsPrepared();
@@ -1693,7 +1809,7 @@ namespace ProtoBuf.Meta
             const string message = "Timeout while inspecting metadata; this may indicate a deadlock. This can often be avoided by preparing necessary serializers during application initialization, rather than allowing multiple threads to perform the initial metadata inspection; please also see the LockContended event";
             opaqueToken = 0;
 #if PORTABLE
-            if(!Monitor.TryEnter(types)) throw new TimeoutException(message); // yes, we have to do this immediately - I'm not creating a "hot" loop, just because Sleep() doesn't exist...
+            if(!Monitor.TryEnter(types, metadataTimeoutMilliseconds)) throw new TimeoutException(message);
             opaqueToken = Interlocked.CompareExchange(ref contentionCounter, 0, 0); // just fetch current value (starts at 1)
 #elif CF2 || CF35
             int remaining = metadataTimeoutMilliseconds;
@@ -1792,7 +1908,6 @@ namespace ProtoBuf.Meta
         {
             if (type == null) return;
             if(Helpers.GetTypeCode(type) != ProtoTypeCode.Unknown) return; // don't try this[type] for inbuilts
-            if(this[type].IgnoreListHandling) return;
 
             // handle arrays
             if (type.IsArray)
@@ -1811,7 +1926,13 @@ namespace ProtoBuf.Meta
                     defaultType = type;
                 }
             }
-            // handle lists
+            else
+            {
+                // if not an array, first check it isn't explicitly opted out
+                if (this[type].IgnoreListHandling) return;
+            }
+
+            // handle lists 
             if (itemType == null) { itemType = TypeModel.GetListItemType(this, type); }
 
             // check for nested data (not allowed)
@@ -1821,13 +1942,13 @@ namespace ProtoBuf.Meta
                 ResolveListTypes(itemType, ref nestedItemType, ref nestedDefaultType);
                 if (nestedItemType != null)
                 {
-                    throw TypeModel.CreateNestedListsNotSupported();
+                    throw TypeModel.CreateNestedListsNotSupported(type);
                 }
             }
 
             if (itemType != null && defaultType == null)
             {
-#if WINRT
+#if WINRT || COREFX
                 System.Reflection.TypeInfo typeInfo = System.Reflection.IntrospectionExtensions.GetTypeInfo(type);
                 if (typeInfo.IsClass && !typeInfo.IsAbstract && Helpers.GetConstructor(typeInfo, Helpers.EmptyTypes, true) != null)
 #else
@@ -1838,7 +1959,7 @@ namespace ProtoBuf.Meta
                 }
                 if (defaultType == null)
                 {
-#if WINRT
+#if WINRT || COREFX
                     if (typeInfo.IsInterface)
 #else
                     if (type.IsInterface)
@@ -1848,7 +1969,7 @@ namespace ProtoBuf.Meta
                         defaultType = typeof(ArrayList);
 #else
                         Type[] genArgs;
-#if WINRT
+#if WINRT || COREFX
                         if (typeInfo.IsGenericType && typeInfo.GetGenericTypeDefinition() == typeof(System.Collections.Generic.IDictionary<,>)
                             && itemType == typeof(System.Collections.Generic.KeyValuePair<,>).MakeGenericType(genArgs = typeInfo.GenericTypeArguments))
 #else
@@ -1883,7 +2004,7 @@ namespace ProtoBuf.Meta
         }
 #endif
 
-        internal string GetSchemaTypeName(Type effectiveType, DataFormat dataFormat, bool asReference, bool dynamicType, ref bool requiresBclImport)
+        internal string GetSchemaTypeName(Type effectiveType, DataFormat dataFormat, bool asReference, bool dynamicType, ref CommonImports imports)
         {
             Type tmp = Helpers.GetUnderlyingType(effectiveType);
             if (tmp != null) effectiveType = tmp;
@@ -1896,8 +2017,8 @@ namespace ProtoBuf.Meta
             {   // model type
                 if (asReference || dynamicType)
                 {
-                    requiresBclImport = true;
-                    return "bcl.NetObjectProxy";
+                    imports |= CommonImports.Bcl;
+                    return ".bcl.NetObjectProxy";
                 }
                 return this[effectiveType].GetSurrogateOrBaseOrSelf(true).GetSchemaTypeName();
             }
@@ -1905,8 +2026,8 @@ namespace ProtoBuf.Meta
             {
                 if (ser is ParseableSerializer)
                 {
-                    if (asReference) requiresBclImport = true;
-                    return asReference ? "bcl.NetObjectProxy" : "string";
+                    if (asReference) imports |= CommonImports.Bcl;
+                    return asReference ? ".bcl.NetObjectProxy" : "string";
                 }
 
                 switch (Helpers.GetTypeCode(effectiveType))
@@ -1915,8 +2036,8 @@ namespace ProtoBuf.Meta
                     case ProtoTypeCode.Single: return "float";
                     case ProtoTypeCode.Double: return "double";
                     case ProtoTypeCode.String:
-                        if (asReference) requiresBclImport = true;
-                        return asReference ? "bcl.NetObjectProxy" : "string";
+                        if (asReference) imports |= CommonImports.Bcl;
+                        return asReference ? ".bcl.NetObjectProxy" : "string";
                     case ProtoTypeCode.Byte:
                     case ProtoTypeCode.Char:
                     case ProtoTypeCode.UInt16:
@@ -1948,10 +2069,31 @@ namespace ProtoBuf.Meta
                             case DataFormat.FixedSize: return "sfixed64";
                             default: return "int64";
                         }
-                    case ProtoTypeCode.DateTime: requiresBclImport = true; return "bcl.DateTime";
-                    case ProtoTypeCode.TimeSpan: requiresBclImport = true; return "bcl.TimeSpan";
-                    case ProtoTypeCode.Decimal: requiresBclImport = true; return "bcl.Decimal";
-                    case ProtoTypeCode.Guid: requiresBclImport = true; return "bcl.Guid";
+                    case ProtoTypeCode.DateTime:
+                        switch (dataFormat)
+                        {
+                            case DataFormat.FixedSize: return "sint64";
+                            case DataFormat.WellKnown:
+                                imports |= CommonImports.Timestamp;
+                                return ".google.protobuf.Timestamp";
+                            default:
+                                imports |= CommonImports.Bcl;
+                                return ".bcl.DateTime";
+                        }
+                    case ProtoTypeCode.TimeSpan:
+                        switch(dataFormat)
+                        {
+                            case DataFormat.FixedSize: return "sint64";
+                            case DataFormat.WellKnown:
+                                imports |= CommonImports.Duration;
+                                return ".google.protobuf.Duration";
+                            default:
+                                imports |= CommonImports.Bcl;
+                                return ".bcl.TimeSpan";
+                        }
+                    case ProtoTypeCode.Decimal: imports |= CommonImports.Bcl; return ".bcl.Decimal";
+                    case ProtoTypeCode.Guid: imports |= CommonImports.Bcl; return ".bcl.Guid";
+                    case ProtoTypeCode.Type: return "string";
                     default: throw new NotSupportedException("No .proto map found for: " + effectiveType.FullName);
                 }
             }
@@ -1979,6 +2121,7 @@ namespace ProtoBuf.Meta
                 if (!CallbackSet.CheckCallbackParameters(this, factory)) throw new ArgumentException("Invalid factory signature in " + factory.DeclaringType.FullName + "." + factory.Name, "factory");
             }
         }
+
     }
     /// <summary>
     /// Contains the stack-trace of the owning code when a lock-contention scenario is detected
@@ -2002,4 +2145,4 @@ namespace ProtoBuf.Meta
 
 
 }
-#endif
+#endif

+ 3 - 3
Unity/Assets/Plugins/protobuf-net/Meta/RuntimeTypeModel.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/RuntimeTypeModel.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 5f9aa92f9aa952949ac0bba19f939b67
-timeCreated: 1515899112
-licenseType: Pro
+guid: f7181119b0e6c324ea5513e4694897fc
+timeCreated: 1517401477
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 0 - 0
Unity/Assets/Plugins/protobuf-net/Meta/SubType.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/SubType.cs


+ 3 - 3
Unity/Assets/Plugins/protobuf-net/Meta/SubType.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/SubType.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 41873650e7e427f45bc9cee494f6bc9c
-timeCreated: 1515899112
-licenseType: Pro
+guid: 3306624739dbb9d48b5e75981faf23b3
+timeCreated: 1517401476
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 0 - 0
Unity/Assets/Plugins/protobuf-net/Meta/TypeFormatEventArgs.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/TypeFormatEventArgs.cs


+ 3 - 3
Unity/Assets/Plugins/protobuf-net/Meta/TypeFormatEventArgs.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/TypeFormatEventArgs.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 97eec0d4199d7844b895963cf6132653
-timeCreated: 1515899113
-licenseType: Pro
+guid: ce090bf52a5036b45aab8359d3f5d2ae
+timeCreated: 1517401477
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 179 - 84
Unity/Assets/Plugins/protobuf-net/Meta/TypeModel.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/TypeModel.cs

@@ -16,12 +16,18 @@ namespace ProtoBuf.Meta
     /// </summary>
     public abstract class TypeModel
     {
-#if WINRT
+#if WINRT || COREFX
         internal TypeInfo MapType(TypeInfo type)
         {
             return type;
         }
 #endif
+
+        /// <summary>
+        /// Should the <c>Kind</c> be included on date/time values?
+        /// </summary>
+        protected internal virtual bool SerializeDateTimeKind() { return false; }
+
         /// <summary>
         /// Resolve a System.Type to the compiler-specific type
         /// </summary>
@@ -35,7 +41,7 @@ namespace ProtoBuf.Meta
         protected internal virtual Type MapType(System.Type type, bool demand)
         {
 #if FEAT_IKVM
-            throw new NotImplementedException(); // this should come from RuntimeTypeModel!
+            throw new NotSupportedException(); // this should come from RuntimeTypeModel!
 #else
             return type;
 #endif
@@ -93,13 +99,13 @@ namespace ProtoBuf.Meta
         ///  - IEnumerable sequences of any type handled by TrySerializeAuxiliaryType
         ///  
         /// </summary>
-        internal bool TrySerializeAuxiliaryType(ProtoWriter writer,  Type type, DataFormat format, int tag, object value, bool isInsideList)
+        internal bool TrySerializeAuxiliaryType(ProtoWriter writer,  Type type, DataFormat format, int tag, object value, bool isInsideList, object parentList)
         {
             if (type == null) { type = value.GetType(); }
 
             ProtoTypeCode typecode = Helpers.GetTypeCode(type);
-            int modelKey;
             // note the "ref type" here normalizes against proxies
+			int modelKey;
             WireType wireType = GetWireType(typecode, format, ref type, out modelKey);
 
 
@@ -147,13 +153,18 @@ namespace ProtoBuf.Meta
                 case ProtoTypeCode.Char: ProtoWriter.WriteUInt16((ushort)(char)value, writer); return true;
                 case ProtoTypeCode.Double: ProtoWriter.WriteDouble((double)value, writer); return true;
                 case ProtoTypeCode.Single: ProtoWriter.WriteSingle((float)value, writer); return true;
-                case ProtoTypeCode.DateTime: BclHelpers.WriteDateTime((DateTime)value, writer); return true;
+                case ProtoTypeCode.DateTime:
+                    if (SerializeDateTimeKind())
+                        BclHelpers.WriteDateTimeWithKind((DateTime)value, writer);
+                    else
+                        BclHelpers.WriteDateTime((DateTime)value, writer);
+                    return true;
                 case ProtoTypeCode.Decimal: BclHelpers.WriteDecimal((decimal)value, writer); return true;
                 case ProtoTypeCode.String: ProtoWriter.WriteString((string)value, writer); return true;
                 case ProtoTypeCode.ByteArray: ProtoWriter.WriteBytes((byte[])value, writer); return true;
                 case ProtoTypeCode.TimeSpan: BclHelpers.WriteTimeSpan((TimeSpan)value, writer); return true;
                 case ProtoTypeCode.Guid: BclHelpers.WriteGuid((Guid)value, writer); return true;
-                case ProtoTypeCode.Uri: ProtoWriter.WriteString(((Uri)value).AbsoluteUri, writer); return true;
+                case ProtoTypeCode.Uri: ProtoWriter.WriteString(((Uri)value).OriginalString, writer); return true;
             }
 
             // by now, we should have covered all the simple cases; if we wrote a field-header, we have
@@ -161,13 +172,14 @@ namespace ProtoBuf.Meta
             Helpers.DebugAssert(wireType == WireType.None);
 
             // now attempt to handle sequences (including arrays and lists)
-            IEnumerable sequence = value as IEnumerable;
-            if (sequence != null)
+            if (value is IEnumerable)
             {
-                if (isInsideList) throw CreateNestedListsNotSupported();
-                foreach (object item in sequence) {
+				var sequence = value as IEnumerable;
+                if (isInsideList) throw CreateNestedListsNotSupported(parentList?.GetType());
+                foreach (object item in sequence)
+                {
                     if (item == null) { throw new NullReferenceException(); }
-                    if (!TrySerializeAuxiliaryType(writer, null, format, tag, item, true))
+                    if (!TrySerializeAuxiliaryType(writer, null, format, tag, item, true, sequence))
                     {
                         ThrowUnexpectedType(item.GetType());
                     }
@@ -177,15 +189,19 @@ namespace ProtoBuf.Meta
             return false;
         }
         private void SerializeCore(ProtoWriter writer, object value)
+        {
+			SerializeCore(writer, PType.GetPType(value), value);
+        }
+
+        private void SerializeCore(ProtoWriter writer, Type type, object value)
         {
             if (value == null) throw new ArgumentNullException("value");
-            Type type = value.GetType();
             int key = GetKey(ref type);
             if (key >= 0)
             {
                 Serialize(key, value, writer);
             }
-            else if (!TrySerializeAuxiliaryType(writer, type, DataFormat.Default, Serializer.ListItemTag, value, false))
+            else if (!TrySerializeAuxiliaryType(writer, type, DataFormat.Default, Serializer.ListItemTag, value, false, null))
             {
                 ThrowUnexpectedType(type);
             }
@@ -200,6 +216,7 @@ namespace ProtoBuf.Meta
         {
             Serialize(dest, value, null);
         }
+
         /// <summary>
         /// Writes a protocol-buffer representation of the given instance to the supplied stream.
         /// </summary>
@@ -250,11 +267,10 @@ namespace ProtoBuf.Meta
         /// <returns>The updated instance; this may be different to the instance argument if
         /// either the original instance was null, or the stream defines a known sub-type of the
         /// original instance.</returns>
-        public object DeserializeWithLengthPrefix(Stream source, object value, Type type, PrefixStyle style, int fieldNumber)
-        {
-            int bytesRead;
-            return DeserializeWithLengthPrefix(source, value, type, style, fieldNumber, null, out bytesRead);
-        }
+		public object DeserializeWithLengthPrefix(Stream source, object value, Type type, PrefixStyle style, int fieldNumber){
+			long bytesRead;
+			return DeserializeWithLengthPrefix(source, value, type, style, fieldNumber, null, out bytesRead);
+		}
 
 
         /// <summary>
@@ -270,11 +286,10 @@ namespace ProtoBuf.Meta
         /// <returns>The updated instance; this may be different to the instance argument if
         /// either the original instance was null, or the stream defines a known sub-type of the
         /// original instance.</returns>
-        public object DeserializeWithLengthPrefix(Stream source, object value, Type type, PrefixStyle style, int expectedField, Serializer.TypeResolver resolver)
-        {
-            int bytesRead;
-            return DeserializeWithLengthPrefix(source, value, type, style, expectedField, resolver, out bytesRead);
-        }
+		public object DeserializeWithLengthPrefix(Stream source, object value, Type type, PrefixStyle style, int expectedField, Serializer.TypeResolver resolver){
+			long bytesRead;
+			return DeserializeWithLengthPrefix(source, value, type, style, expectedField, resolver, out bytesRead);
+		}
 
         /// <summary>
         /// Applies a protocol-buffer stream to an existing instance (or null), using length-prefixed
@@ -292,30 +307,52 @@ namespace ProtoBuf.Meta
         /// original instance.</returns>
         public object DeserializeWithLengthPrefix(Stream source, object value, Type type, PrefixStyle style, int expectedField, Serializer.TypeResolver resolver, out int bytesRead)
         {
-            bool haveObject;
-            return DeserializeWithLengthPrefix(source, value, type, style, expectedField, resolver, out bytesRead, out haveObject, null);
+			long bytesRead64;
+			bool haveObject;
+            object result = DeserializeWithLengthPrefix(source, value, type, style, expectedField, resolver, out bytesRead64, out haveObject, null);
+            bytesRead = checked((int)bytesRead64);
+            return result;
         }
+        /// <summary>
+        /// Applies a protocol-buffer stream to an existing instance (or null), using length-prefixed
+        /// data - useful with network IO.
+        /// </summary>
+        /// <param name="type">The type being merged.</param>
+        /// <param name="value">The existing instance to be modified (can be null).</param>
+        /// <param name="source">The binary stream to apply to the instance (cannot be null).</param>
+        /// <param name="style">How to encode the length prefix.</param>
+        /// <param name="expectedField">The tag used as a prefix to each record (only used with base-128 style prefixes).</param>
+        /// <param name="resolver">Used to resolve types on a per-field basis.</param>
+        /// <param name="bytesRead">Returns the number of bytes consumed by this operation (includes length-prefix overheads and any skipped data).</param>
+        /// <returns>The updated instance; this may be different to the instance argument if
+        /// either the original instance was null, or the stream defines a known sub-type of the
+        /// original instance.</returns>
+		public object DeserializeWithLengthPrefix(Stream source, object value, Type type, PrefixStyle style, int expectedField, Serializer.TypeResolver resolver, out long bytesRead) {
+			bool haveObject;
+			return DeserializeWithLengthPrefix(source, value, type, style, expectedField, resolver, out bytesRead, out haveObject, null);
+		}
+
 
-        private object DeserializeWithLengthPrefix(Stream source, object value, Type type, PrefixStyle style, int expectedField, Serializer.TypeResolver resolver, out int bytesRead, out bool haveObject, SerializationContext context)
+        private object DeserializeWithLengthPrefix(Stream source, object value, Type type, PrefixStyle style, int expectedField, Serializer.TypeResolver resolver, out long bytesRead, out bool haveObject, SerializationContext context)
         {
 #if FEAT_IKVM
             throw new NotSupportedException();
 #else
             haveObject = false;
             bool skip;
-            int len;
-            int tmpBytesRead;
+            long len;
             bytesRead = 0;
             if (type == null && (style != PrefixStyle.Base128 || resolver == null))
             {
                 throw new InvalidOperationException("A type must be provided unless base-128 prefixing is being used in combination with a resolver");
             }
-            int actualField;
             do
             {
-                
+
                 bool expectPrefix = expectedField > 0 || resolver != null;
-                len = ProtoReader.ReadLengthPrefix(source, expectPrefix, style, out actualField, out tmpBytesRead);
+				int actualField;
+				int tmpBytesRead;
+                len = ProtoReader.ReadLongLengthPrefix(source, expectPrefix, style, out actualField, out tmpBytesRead);
                 if (tmpBytesRead == 0) return value;
                 bytesRead += tmpBytesRead;
                 if (len < 0) return value;
@@ -337,7 +374,7 @@ namespace ProtoBuf.Meta
 
                 if (skip)
                 {
-                    if (len == int.MaxValue) throw new InvalidOperationException();
+                    if (len == long.MaxValue) throw new InvalidOperationException();
                     ProtoReader.Seek(source, len, null);
                     bytesRead += len;
                 }
@@ -354,12 +391,12 @@ namespace ProtoBuf.Meta
                 }
                 else
                 {
-                    if (!(TryDeserializeAuxiliaryType(reader, DataFormat.Default, Serializer.ListItemTag, type, ref value, true, false, true, false) || len == 0))
+                    if (!(TryDeserializeAuxiliaryType(reader, DataFormat.Default, Serializer.ListItemTag, type, ref value, true, false, true, false, null) || len == 0))
                     {
                         TypeModel.ThrowUnexpectedType(type); // throws
                     }
                 }
-                bytesRead += reader.Position;
+                bytesRead += reader.LongPosition;
                 haveObject = true;
                 return value;
             }
@@ -472,7 +509,7 @@ namespace ProtoBuf.Meta
             {
                 if (haveObject)
                 {
-                    int bytesRead;
+					long bytesRead;
                     current = model.DeserializeWithLengthPrefix(source, null, type, style, expectedField, resolver, out bytesRead, out haveObject, context);
                 }
                 return haveObject;
@@ -633,9 +670,21 @@ namespace ProtoBuf.Meta
         /// either the original instance was null, or the stream defines a known sub-type of the
         /// original instance.</returns>
         public object Deserialize(Stream source, object value, System.Type type, int length)
-        {
-            return Deserialize(source, value, type, length, null);
-        }
+            => Deserialize(source, value, type, length, null);
+        
+        /// <summary>
+        /// Applies a protocol-buffer stream to an existing instance (which may be null).
+        /// </summary>
+        /// <param name="type">The type (including inheritance) to consider.</param>
+        /// <param name="value">The existing instance to be modified (can be null).</param>
+        /// <param name="source">The binary stream to apply to the instance (cannot be null).</param>
+        /// <param name="length">The number of bytes to consume.</param>
+        /// <returns>The updated instance; this may be different to the instance argument if
+        /// either the original instance was null, or the stream defines a known sub-type of the
+        /// original instance.</returns>
+        public object Deserialize(Stream source, object value, System.Type type, long length)
+            => Deserialize(source, value, type, length, null);
+
         /// <summary>
         /// Applies a protocol-buffer stream to an existing instance (which may be null).
         /// </summary>
@@ -648,6 +697,20 @@ namespace ProtoBuf.Meta
         /// original instance.</returns>
         /// <param name="context">Additional information about this serialization operation.</param>
         public object Deserialize(Stream source, object value, System.Type type, int length, SerializationContext context)
+            => Deserialize(source, value, type, length == int.MaxValue ? long.MaxValue : (long)length, context);
+
+        /// <summary>
+        /// Applies a protocol-buffer stream to an existing instance (which may be null).
+        /// </summary>
+        /// <param name="type">The type (including inheritance) to consider.</param>
+        /// <param name="value">The existing instance to be modified (can be null).</param>
+        /// <param name="source">The binary stream to apply to the instance (cannot be null).</param>
+        /// <param name="length">The number of bytes to consume (or -1 to read to the end of the stream).</param>
+        /// <returns>The updated instance; this may be different to the instance argument if
+        /// either the original instance was null, or the stream defines a known sub-type of the
+        /// original instance.</returns>
+        /// <param name="context">Additional information about this serialization operation.</param>
+        public object Deserialize(Stream source, object value, System.Type type, long length, SerializationContext context)
         {
 #if FEAT_IKVM
             throw new NotSupportedException();
@@ -700,18 +763,18 @@ namespace ProtoBuf.Meta
                 return Deserialize(key, value, reader);
             }
             // this returns true to say we actively found something, but a value is assigned either way (or throws)
-            TryDeserializeAuxiliaryType(reader, DataFormat.Default, Serializer.ListItemTag, type, ref value, true, false, noAutoCreate, false);
+            TryDeserializeAuxiliaryType(reader, DataFormat.Default, Serializer.ListItemTag, type, ref value, true, false, noAutoCreate, false, null);
             return value;
         }
 #endif
-#if WINRT
+#if WINRT || COREFX
         private static readonly System.Reflection.TypeInfo ilist = typeof(IList).GetTypeInfo();
 #else
         private static readonly System.Type ilist = typeof(IList);
 #endif
         internal static MethodInfo ResolveListAdd(TypeModel model, Type listType, Type itemType, out bool isList)
         {
-#if WINRT
+#if WINRT || COREFX
             TypeInfo listTypeInfo = listType.GetTypeInfo();
 #else
             Type listTypeInfo = listType;
@@ -727,12 +790,12 @@ namespace ProtoBuf.Meta
 
                 bool forceList = listTypeInfo.IsInterface &&
                     listTypeInfo == model.MapType(typeof(System.Collections.Generic.IEnumerable<>)).MakeGenericType(types)
-#if WINRT
+#if WINRT || COREFX
                     .GetTypeInfo()
 #endif
                     ;
 
-#if WINRT
+#if WINRT || COREFX
                 TypeInfo constuctedListType = typeof(System.Collections.Generic.ICollection<>).MakeGenericType(types).GetTypeInfo();
 #else
                 Type constuctedListType = model.MapType(typeof(System.Collections.Generic.ICollection<>)).MakeGenericType(types);
@@ -745,14 +808,14 @@ namespace ProtoBuf.Meta
 
             if (add == null)
             {
-                
-#if WINRT
+
+#if WINRT || COREFX
                 foreach (Type tmpType in listTypeInfo.ImplementedInterfaces)
 #else
                 foreach (Type interfaceType in listTypeInfo.GetInterfaces())
 #endif
                 {
-#if WINRT
+#if WINRT || COREFX
                     TypeInfo interfaceType = tmpType.GetTypeInfo();
 #endif
                     if (interfaceType.Name == "IProducerConsumerCollection`1" && interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition().FullName == "System.Collections.Concurrent.IProducerConsumerCollection`1")
@@ -786,6 +849,7 @@ namespace ProtoBuf.Meta
 #else
             if (listType == model.MapType(typeof(string)) || listType.IsArray
                 || !model.MapType(typeof(IEnumerable)).IsAssignableFrom(listType)) return null;
+			if (listType.FullName == "System.String") return null;
 #endif
             
             BasicList candidates = new BasicList();
@@ -851,10 +915,11 @@ namespace ProtoBuf.Meta
                 case 0:
                     return null;
                 case 1:
+                    if ((Type)candidates[0] == listType) return null; // recursive
                     return (Type)candidates[0];
                 case 2:
-                    if (CheckDictionaryAccessors(model, (Type)candidates[0], (Type)candidates[1])) return (Type)candidates[0];
-                    if (CheckDictionaryAccessors(model, (Type)candidates[1], (Type)candidates[0])) return (Type)candidates[1];
+                    if ((Type)candidates[0] != listType && CheckDictionaryAccessors(model, (Type)candidates[0], (Type)candidates[1])) return (Type)candidates[0];
+                    if ((Type)candidates[1] != listType && CheckDictionaryAccessors(model, (Type)candidates[1], (Type)candidates[0])) return (Type)candidates[1];
                     break;
             }
 
@@ -864,12 +929,15 @@ namespace ProtoBuf.Meta
         private static void TestEnumerableListPatterns(TypeModel model, BasicList candidates, Type iType)
         {
 
-#if WINRT
+#if WINRT || COREFX
             TypeInfo iTypeInfo = iType.GetTypeInfo();
             if (iTypeInfo.IsGenericType)
             {
                 Type typeDef = iTypeInfo.GetGenericTypeDefinition();
-                if(typeDef == typeof(System.Collections.Generic.ICollection<>) || typeDef.GetTypeInfo().FullName == "System.Collections.Concurrent.IProducerConsumerCollection`1")
+                if(
+                   typeDef == model.MapType(typeof(System.Collections.Generic.IEnumerable<>))
+                || typeDef == model.MapType(typeof(System.Collections.Generic.ICollection<>))
+                || typeDef.GetTypeInfo().FullName == "System.Collections.Concurrent.IProducerConsumerCollection`1")
                 {
                         
                     Type[] iTypeArgs = iTypeInfo.GenericTypeArguments;
@@ -899,10 +967,10 @@ namespace ProtoBuf.Meta
 
         private static bool CheckDictionaryAccessors(TypeModel model, Type pair, Type value)
         {
-            
+
 #if NO_GENERICS
             return false;
-#elif WINRT
+#elif WINRT || COREFX
             TypeInfo finalType = pair.GetTypeInfo();
             return finalType.IsGenericType && finalType.GetGenericTypeDefinition() == typeof(System.Collections.Generic.KeyValuePair<,>)
                 && finalType.GenericTypeArguments[1] == value;
@@ -915,7 +983,7 @@ namespace ProtoBuf.Meta
 #if !FEAT_IKVM
         private bool TryDeserializeList(TypeModel model, ProtoReader reader, DataFormat format, int tag, Type listType, Type itemType, ref object value)
         {
-            bool isList;
+			bool isList;
             MethodInfo addMethod = TypeModel.ResolveListAdd(model, listType, itemType, out isList);
             if (addMethod == null) throw new NotSupportedException("Unknown list variant: " + listType.FullName);
             bool found = false;
@@ -924,7 +992,7 @@ namespace ProtoBuf.Meta
             object[] args = isList ? null : new object[1];
             BasicList arraySurrogate = listType.IsArray ? new BasicList() : null;
 
-            while (TryDeserializeAuxiliaryType(reader, format, tag, itemType, ref nextItem, true, true, true, true))
+            while (TryDeserializeAuxiliaryType(reader, format, tag, itemType, ref nextItem, true, true, true, true, value ?? listType))
             {
                 found = true;
                 if (value == null && arraySurrogate == null)
@@ -983,7 +1051,7 @@ namespace ProtoBuf.Meta
                 return Array.CreateInstance(itemType, 0);
             }
 
-#if WINRT
+#if WINRT || COREFX
             TypeInfo listTypeInfo = listType.GetTypeInfo();
             if (!listTypeInfo.IsClass || listTypeInfo.IsAbstract ||
                 Helpers.GetConstructor(listTypeInfo, Helpers.EmptyTypes, true) == null)
@@ -994,7 +1062,7 @@ namespace ProtoBuf.Meta
             {
                 string fullName;
                 bool handled = false;
-#if WINRT
+#if WINRT || COREFX
                 if (listTypeInfo.IsInterface &&
 #else
                 if (listType.IsInterface &&
@@ -1002,7 +1070,7 @@ namespace ProtoBuf.Meta
                     (fullName = listType.FullName) != null && fullName.IndexOf("Dictionary") >= 0) // have to try to be frugal here...
                 {
 #if !NO_GENERICS
-#if WINRT
+#if WINRT || COREFX
                     TypeInfo finalType = listType.GetTypeInfo();
                     if (finalType.IsGenericType && finalType.GetGenericTypeDefinition() == typeof(System.Collections.Generic.IDictionary<,>))
                     {
@@ -1019,7 +1087,7 @@ namespace ProtoBuf.Meta
                     }
 #endif
 #endif
-#if !SILVERLIGHT && !WINRT && !PORTABLE
+#if !SILVERLIGHT && !WINRT && !PORTABLE && ! COREFX
                     if (!handled && listType == typeof(IDictionary))
                     {
                         concreteListType = typeof(Hashtable);
@@ -1035,7 +1103,7 @@ namespace ProtoBuf.Meta
                 }
 #endif
 
-#if !SILVERLIGHT && !WINRT && !PORTABLE
+#if !SILVERLIGHT && !WINRT && !PORTABLE && ! COREFX
                 if (!handled)
                 {
                     concreteListType = typeof(ArrayList);
@@ -1055,12 +1123,12 @@ namespace ProtoBuf.Meta
         ///  - basic values; individual int / string / Guid / etc
         ///  - IList sets of any type handled by TryDeserializeAuxiliaryType
         /// </summary>
-        internal bool TryDeserializeAuxiliaryType(ProtoReader reader, DataFormat format, int tag, Type type, ref object value, bool skipOtherFields, bool asListItem, bool autoCreate, bool insideList)
+        internal bool TryDeserializeAuxiliaryType(ProtoReader reader, DataFormat format, int tag, Type type, ref object value, bool skipOtherFields, bool asListItem, bool autoCreate, bool insideList, object parentListOrType)
         {
             if (type == null) throw new ArgumentNullException("type");
             Type itemType = null;
             ProtoTypeCode typecode = Helpers.GetTypeCode(type);
-            int modelKey;
+			int modelKey;
             WireType wiretype = GetWireType(typecode, format, ref type, out modelKey);
 
             bool found = false;
@@ -1073,7 +1141,7 @@ namespace ProtoBuf.Meta
                 }
                 if (itemType != null)
                 {
-                    if (insideList) throw TypeModel.CreateNestedListsNotSupported();
+                    if (insideList) throw TypeModel.CreateNestedListsNotSupported((parentListOrType as Type) ?? (parentListOrType?.GetType()));
                     found = TryDeserializeList(this, reader, format, tag, type, itemType, ref value);
                     if (!found && autoCreate)
                     {
@@ -1146,7 +1214,7 @@ namespace ProtoBuf.Meta
                     case ProtoTypeCode.ByteArray: value = ProtoReader.AppendBytes((byte[])value, reader); continue;
                     case ProtoTypeCode.TimeSpan: value = BclHelpers.ReadTimeSpan(reader); continue;
                     case ProtoTypeCode.Guid: value = BclHelpers.ReadGuid(reader); continue;
-                    case ProtoTypeCode.Uri: value = new Uri(reader.ReadString()); continue; 
+                    case ProtoTypeCode.Uri: value = new Uri(reader.ReadString(), UriKind.RelativeOrAbsolute); continue; 
                 }
 
             }
@@ -1190,7 +1258,14 @@ namespace ProtoBuf.Meta
 #if !(WINRT || CF)
             // EF POCO
             string fullName = type.FullName;
-            if (fullName != null && fullName.StartsWith("System.Data.Entity.DynamicProxies.")) return type.BaseType;
+            if (fullName != null && fullName.StartsWith("System.Data.Entity.DynamicProxies."))
+            {
+#if  COREFX
+                return type.GetTypeInfo().BaseType;
+#else
+                return type.BaseType;
+#endif
+            }
 
             // NHibernate
             Type[] interfaces = type.GetInterfaces();
@@ -1201,11 +1276,15 @@ namespace ProtoBuf.Meta
                     case "NHibernate.Proxy.INHibernateProxy":
                     case "NHibernate.Proxy.DynamicProxy.IProxy":
                     case "NHibernate.Intercept.IFieldInterceptorAccessor":
+#if COREFX
+                        return type.GetTypeInfo().BaseType;
+#else
                         return type.BaseType;
+#endif
                 }
             }
 #endif
-            return null;
+                        return null;
         }
         /// <summary>
         /// Indicates whether the supplied type is explicitly modelled by the model
@@ -1318,8 +1397,9 @@ namespace ProtoBuf.Meta
                     }
                 }
             }
-            int modelKey;
-            if (type == typeof(byte[])) {
+			int modelKey;
+            if (type == typeof(byte[]))
+            {
                 byte[] orig = (byte[])value, clone = new byte[orig.Length];
                 Helpers.BlockCopy(orig, 0, clone, 0, orig.Length);
                 return clone;
@@ -1332,7 +1412,7 @@ namespace ProtoBuf.Meta
             {
                 using (ProtoWriter writer = new ProtoWriter(ms, this, null))
                 {
-                    if (!TrySerializeAuxiliaryType(writer, type, DataFormat.Default, Serializer.ListItemTag, value, false)) ThrowUnexpectedType(type);
+                    if (!TrySerializeAuxiliaryType(writer, type, DataFormat.Default, Serializer.ListItemTag, value, false, null)) ThrowUnexpectedType(type);
                     writer.Close();
                 }
                 ms.Position = 0;
@@ -1341,7 +1421,7 @@ namespace ProtoBuf.Meta
                 {
                     reader = ProtoReader.Create(ms, this, null, ProtoReader.TO_EOF);
                     value = null; // start from scratch!
-                    TryDeserializeAuxiliaryType(reader, DataFormat.Default, Serializer.ListItemTag, type, ref value, true, false, true, false);
+                    TryDeserializeAuxiliaryType(reader, DataFormat.Default, Serializer.ListItemTag, type, ref value, true, false, true, false, null);
                     return value;
                 }
                 finally
@@ -1374,8 +1454,16 @@ namespace ProtoBuf.Meta
 #if !NO_GENERICS && !WINRT
             if (type != null)
             {
-                Type baseType = type.BaseType;
-                if (baseType != null && baseType.IsGenericType && baseType.GetGenericTypeDefinition().Name == "GeneratedMessage`2")
+                Type baseType = type
+#if COREFX
+                    .GetTypeInfo()
+#endif
+                    .BaseType;
+                if (baseType != null && baseType
+#if COREFX
+                    .GetTypeInfo()
+#endif                    
+                    .IsGenericType && baseType.GetGenericTypeDefinition().Name == "GeneratedMessage`2")
                 {
                     throw new InvalidOperationException(
                         "Are you mixing protobuf-net and protobuf-csharp-port? See http://stackoverflow.com/q/11564914; type: " + fullName);
@@ -1384,9 +1472,9 @@ namespace ProtoBuf.Meta
 #endif
             throw new InvalidOperationException("Type is not expected, and no contract can be inferred: " + fullName);
         }
-        internal static Exception CreateNestedListsNotSupported()
+        internal static Exception CreateNestedListsNotSupported(Type type)
         {
-            return new NotSupportedException("Nested or jagged lists and arrays are not supported");
+            return new NotSupportedException("Nested or jagged lists and arrays are not supported: " + (type?.FullName ?? "(null)"));
         }
         /// <summary>
         /// Indicates that the given type cannot be constructed; it may still be possible to 
@@ -1394,7 +1482,7 @@ namespace ProtoBuf.Meta
         /// </summary>
         public static void ThrowCannotCreateInstance(Type type)
         {
-            throw new ProtoException("No parameterless constructor found for " + (type == null ? "(null)" : type.Name));
+            throw new ProtoException("No parameterless constructor found for " + (type?.FullName ?? "(null)"));
         }
 
         internal static string SerializeType(TypeModel model, System.Type type)
@@ -1498,18 +1586,27 @@ namespace ProtoBuf.Meta
         /// </summary>
         /// <param name="type">The type to generate a .proto definition for, or <c>null</c> to generate a .proto that represents the entire model</param>
         /// <returns>The .proto definition as a string</returns>
-        public virtual string GetSchema(Type type)
+        public virtual string GetSchema(Type type) => GetSchema(type, ProtoSyntax.Proto2);
+
+        /// <summary>
+        /// Suggest a .proto definition for the given type
+        /// </summary>
+        /// <param name="type">The type to generate a .proto definition for, or <c>null</c> to generate a .proto that represents the entire model</param>
+        /// <returns>The .proto definition as a string</returns>
+        /// <param name="syntax">The .proto syntax to use for the operation</param>
+        public virtual string GetSchema(Type type, ProtoSyntax syntax)
         {
             throw new NotSupportedException();
         }
 
+
         /// <summary>
         /// Used to provide custom services for writing and parsing type names when using dynamic types. Both parsing and formatting
         /// are provided on a single API as it is essential that both are mapped identically at all times.
         /// </summary>
         public event TypeFormatEventHandler DynamicTypeFormatting;
 
-#if PLAT_BINARYFORMATTER && !(WINRT || PHONE8)
+#if PLAT_BINARYFORMATTER && !(WINRT || PHONE8 || COREFX)
         /// <summary>
         /// Creates a new IFormatter that uses protocol-buffer [de]serialization.
         /// </summary>
@@ -1526,10 +1623,8 @@ namespace ProtoBuf.Meta
             private readonly Type type;
             internal Formatter(TypeModel model, Type type)
             {
-                if (model == null) throw new ArgumentNullException("model");
-                if (type == null) throw new ArgumentNullException("type");
-                this.model = model;
-                this.type = type;
+                this.model = model ?? throw new ArgumentNullException("model");
+                this.type = type ?? throw new ArgumentNullException("type");
             }
             private System.Runtime.Serialization.SerializationBinder binder;
             public System.Runtime.Serialization.SerializationBinder Binder
@@ -1550,7 +1645,7 @@ namespace ProtoBuf.Meta
 #if FEAT_IKVM
                 throw new NotSupportedException();
 #else
-                return model.Deserialize(source, null, type, -1, Context);
+                return model.Deserialize(source, null, type, (long)-1, Context);
 #endif
             }
 
@@ -1583,7 +1678,7 @@ namespace ProtoBuf.Meta
         internal virtual Type GetType(string fullName, Assembly context)
         {
 #if FEAT_IKVM
-            throw new NotImplementedException();
+            throw new NotSupportedException();
 #else
             return ResolveKnownType(fullName, this, context);
 #endif
@@ -1608,10 +1703,10 @@ namespace ProtoBuf.Meta
             {
                 int i = name.IndexOf(',');
                 string fullName = (i > 0 ? name.Substring(0, i) : name).Trim();
-#if !(WINRT || FEAT_IKVM)
+#if !(WINRT || FEAT_IKVM || COREFX)
                 if (assembly == null) assembly = Assembly.GetCallingAssembly();
 #endif
-                Type type = assembly == null ? null : assembly.GetType(fullName);
+                Type type = assembly?.GetType(fullName);
                 if (type != null) return type;
             }
             catch { }

+ 3 - 3
Unity/Assets/Plugins/protobuf-net/Meta/TypeModel.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/TypeModel.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: d78c4d24137b63147a6a76481b42aee8
-timeCreated: 1515899114
-licenseType: Pro
+guid: b5db3c918ee259e408db4969b973fe2e
+timeCreated: 1517401477
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 356 - 86
Unity/Assets/Plugins/protobuf-net/Meta/ValueMember.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/ValueMember.cs

@@ -3,6 +3,7 @@ using System;
 
 using ProtoBuf.Serializers;
 using System.Globalization;
+using System.Collections.Generic;
 
 #if FEAT_IKVM
 using Type = IKVM.Reflection.Type;
@@ -23,11 +24,29 @@ namespace ProtoBuf.Meta
         /// The number that identifies this member in a protobuf stream
         /// </summary>
         public int FieldNumber { get { return fieldNumber; } }
-        private readonly MemberInfo member;
+        private readonly MemberInfo originalMember;
+        private MemberInfo backingMember;
         /// <summary>
         /// Gets the member (field/property) which this member relates to.
         /// </summary>
-        public MemberInfo Member { get { return member; } }
+        public MemberInfo Member { get { return originalMember; } }
+        /// <summary>
+        /// Gets the backing member (field/property) which this member relates to
+        /// </summary>
+        public MemberInfo BackingMember
+        {
+            get { return backingMember; }
+            set
+            {
+                if(backingMember != value)
+                {
+                    ThrowIfFrozen();
+                    backingMember = value;
+                }
+            }
+        }
+
+
         private readonly Type parentType, itemType, defaultType, memberType;
         private object defaultValue;
         /// <summary>
@@ -54,8 +73,11 @@ namespace ProtoBuf.Meta
         {
             get { return defaultValue; }
             set {
-                ThrowIfFrozen();
-                defaultValue = value;
+                if (defaultValue != value)
+                {
+                    ThrowIfFrozen();
+                    defaultValue = value;
+                }
             }
         }
 
@@ -70,7 +92,7 @@ namespace ProtoBuf.Meta
             if (parentType == null) throw new ArgumentNullException("parentType");
             if (fieldNumber < 1 && !Helpers.IsEnum(parentType)) throw new ArgumentOutOfRangeException("fieldNumber");
 
-            this.member = member;
+            this.originalMember = member;
             this.parentType = parentType;
             if (fieldNumber < 1 && !Helpers.IsEnum(parentType)) throw new ArgumentOutOfRangeException("fieldNumber");
 //#if WINRT
@@ -86,11 +108,11 @@ namespace ProtoBuf.Meta
             MetaType type = model.FindWithoutAdd(memberType);
             if (type != null)
             {
-                this.asReference = type.AsReferenceDefault;
+                AsReference = type.AsReferenceDefault;
             }
             else
             { // we need to scan the hard way; can't risk recursion by fully walking it
-                this.asReference = MetaType.GetAsReferenceDefault(model, memberType);
+                AsReference = MetaType.GetAsReferenceDefault(model, memberType);
             }
         }
         /// <summary>
@@ -98,7 +120,6 @@ namespace ProtoBuf.Meta
         /// </summary>
         internal ValueMember(RuntimeTypeModel model, int fieldNumber, Type memberType, Type itemType, Type defaultType, DataFormat dataFormat) 
         {
-
             if (memberType == null) throw new ArgumentNullException("memberType");
             if (model == null) throw new ArgumentNullException("model");
             this.fieldNumber = fieldNumber;
@@ -111,9 +132,9 @@ namespace ProtoBuf.Meta
         }
         internal object GetRawEnumValue()
         {
-#if WINRT || PORTABLE || CF || FX11
-            object value = ((FieldInfo)member).GetValue(null);
-            switch(Helpers.GetTypeCode(Enum.GetUnderlyingType(((FieldInfo)member).FieldType)))
+#if WINRT || PORTABLE || CF || FX11 || COREFX
+            object value = ((FieldInfo)originalMember).GetValue(null);
+            switch(Helpers.GetTypeCode(Enum.GetUnderlyingType(((FieldInfo)originalMember).FieldType)))
             {
                 case ProtoTypeCode.SByte: return (sbyte)value;
                 case ProtoTypeCode.Byte: return (byte)value;
@@ -127,15 +148,41 @@ namespace ProtoBuf.Meta
                     throw new InvalidOperationException();
             }
 #else
-            return ((FieldInfo)member).GetRawConstantValue();
+            return ((FieldInfo)originalMember).GetRawConstantValue();
 #endif
         }
         private static object ParseDefaultValue(Type type, object value)
         {
+			if(true)
             {
                 Type tmp = Helpers.GetUnderlyingType(type);
                 if (tmp != null) type = tmp;
             }
+			switch (Helpers.GetTypeCode(type))
+			{
+			case ProtoTypeCode.Boolean: 
+			case ProtoTypeCode.Byte: 
+			case ProtoTypeCode.Char: // char.Parse missing on CF/phone7
+			case ProtoTypeCode.DateTime: 
+			case ProtoTypeCode.Decimal: 
+			case ProtoTypeCode.Double: 
+			case ProtoTypeCode.Int16: 
+			case ProtoTypeCode.Int32: 
+			case ProtoTypeCode.Int64: 
+			case ProtoTypeCode.SByte: 
+			case ProtoTypeCode.Single: 
+			case ProtoTypeCode.String:
+			case ProtoTypeCode.UInt16:
+			case ProtoTypeCode.UInt32:
+			case ProtoTypeCode.UInt64:
+			case ProtoTypeCode.TimeSpan:
+			case ProtoTypeCode.Uri:
+			case ProtoTypeCode.Guid:
+				{
+					value = value + "";
+				}
+				break;
+			}
             if (value is string)
             {
                 string s = (string)value;
@@ -207,7 +254,14 @@ namespace ProtoBuf.Meta
         /// </summary>
         public DataFormat DataFormat {
             get { return dataFormat; }
-            set { ThrowIfFrozen(); this.dataFormat = value; }
+            set
+            {
+                if (value != dataFormat)
+                {
+                    ThrowIfFrozen();
+                    this.dataFormat = value;
+                }
+            }
         }
 
         /// <summary>
@@ -250,26 +304,85 @@ namespace ProtoBuf.Meta
             set { SetFlag(OPTIONS_IsRequired, value, true); }
         }
 
-        private bool asReference;
         /// <summary>
         /// Enables full object-tracking/full-graph support.
         /// </summary>
         public bool AsReference
         {
-            get { return asReference; }
-            set { ThrowIfFrozen(); asReference = value; }
+            get { return HasFlag(OPTIONS_AsReference); }
+            set { SetFlag(OPTIONS_AsReference, value, true); }
         }
 
-        private bool dynamicType;
         /// <summary>
         /// Embeds the type information into the stream, allowing usage with types not known in advance.
         /// </summary>
         public bool DynamicType
         {
-            get { return dynamicType; }
-            set { ThrowIfFrozen(); dynamicType = value; }
+            get { return HasFlag(OPTIONS_DynamicType); }
+            set { SetFlag(OPTIONS_DynamicType, value, true); }
         }
 
+        /// <summary>
+        /// Indicates that the member should be treated as a protobuf Map
+        /// </summary>
+        public bool IsMap
+        {
+            get { return HasFlag(OPTIONS_IsMap); }
+            set { SetFlag(OPTIONS_IsMap, value, true); }
+        }
+
+        private DataFormat mapKeyFormat, mapValueFormat;
+        /// <summary>
+        /// Specifies the data-format that should be used for the key, when IsMap is enabled
+        /// </summary>
+        public DataFormat MapKeyFormat
+        {
+            get { return mapKeyFormat; }
+            set
+            {
+                if(mapKeyFormat != value)
+                {
+                    ThrowIfFrozen();
+                    mapKeyFormat = value;
+                }
+            }
+        }
+        /// <summary>
+        /// Specifies the data-format that should be used for the value, when IsMap is enabled
+        /// </summary>
+        public DataFormat MapValueFormat
+        {
+            get { return mapValueFormat; }
+            set
+            {
+                if (mapValueFormat != value)
+                {
+                    ThrowIfFrozen();
+                    mapValueFormat = value;
+                }
+            }
+        }
+
+		private string mapKeyTypeName;
+		public string MapKeyTypeName{
+			get{ 
+				return mapKeyTypeName;
+			}
+			set{
+				mapKeyTypeName = value;
+			}
+		}
+
+		private string mapValueTypeName;
+		public string MapValueTypeName{
+			get{ 
+				return mapValueTypeName;
+			}
+			set{
+				mapValueTypeName = value;
+			}
+		}
+
         private MethodInfo getSpecified, setSpecified;
         /// <summary>
         /// Specifies methods for working with optional data members.
@@ -282,90 +395,227 @@ namespace ProtoBuf.Meta
         /// when data is found.</param>
         public void SetSpecified(MethodInfo getSpecified, MethodInfo setSpecified)
         {
-            if (getSpecified != null)
+            if (this.getSpecified != getSpecified || this.setSpecified != setSpecified)
             {
-                if (getSpecified.ReturnType != model.MapType(typeof(bool))
-                    || getSpecified.IsStatic
-                    || getSpecified.GetParameters().Length != 0)
+                if (getSpecified != null)
                 {
-                    throw new ArgumentException("Invalid pattern for checking member-specified", "getSpecified");
+                    if (getSpecified.ReturnType != model.MapType(typeof(bool))
+                        || getSpecified.IsStatic
+                        || getSpecified.GetParameters().Length != 0)
+                    {
+                        throw new ArgumentException("Invalid pattern for checking member-specified", "getSpecified");
+                    }
                 }
-            }
-            if (setSpecified != null)
-            {
-                ParameterInfo[] args;
-                if (setSpecified.ReturnType != model.MapType(typeof(void))
-                    || setSpecified.IsStatic
-                    || (args = setSpecified.GetParameters()).Length != 1
-                    || args[0].ParameterType != model.MapType(typeof(bool)))
+                if (setSpecified != null)
                 {
-                    throw new ArgumentException("Invalid pattern for setting member-specified", "setSpecified");
+                    ParameterInfo[] args;
+                    if (setSpecified.ReturnType != model.MapType(typeof(void))
+                        || setSpecified.IsStatic
+                        || (args = setSpecified.GetParameters()).Length != 1
+                        || args[0].ParameterType != model.MapType(typeof(bool)))
+                    {
+                        throw new ArgumentException("Invalid pattern for setting member-specified", "setSpecified");
+                    }
                 }
+
+                ThrowIfFrozen();
+                this.getSpecified = getSpecified;
+                this.setSpecified = setSpecified;
             }
-            ThrowIfFrozen();
-            this.getSpecified = getSpecified;
-            this.setSpecified = setSpecified;
-            
         }
         private void ThrowIfFrozen()
         {
             if (serializer != null) throw new InvalidOperationException("The type cannot be changed once a serializer has been generated");
         }
+        internal bool ResolveMapTypes(out Type dictionaryType, out Type keyType, out Type valueType)
+        {
+            dictionaryType = keyType = valueType = null;
+
+#if WINRT || COREFX
+            var info = memberType.GetTypeInfo();
+#else
+            var info = memberType;
+#endif
+			MethodInfo b, a, ar, f;
+            if(ImmutableCollectionDecorator.IdentifyImmutable(model, MemberType, out b, out a, out ar, out f))
+            {
+                return false;
+            }
+            if (info.IsInterface && info.IsGenericType && info.GetGenericTypeDefinition() == typeof(IDictionary<,>))
+            {
+                var typeArgs = memberType.GetGenericArguments();
+
+                if (IsValidMapKeyType(typeArgs[0]))
+                {
+                    keyType = typeArgs[0];
+                    valueType = typeArgs[1];
+                    dictionaryType = memberType;
+                }
+                return false;
+            }
+
+            foreach (var iType in memberType.GetInterfaces())
+            {
+#if WINRT || COREFX
+                info = iType.GetTypeInfo();
+#else
+                info = iType;
+#endif
+                if (info.IsGenericType && info.GetGenericTypeDefinition() == typeof(IDictionary<,>))
+                {
+                    if (dictionaryType != null) throw new InvalidOperationException("Multiple dictionary interfaces implemented by type: " + memberType.FullName);
+                    var typeArgs = iType.GetGenericArguments();
+
+                    if (IsValidMapKeyType(typeArgs[0]))
+                    {
+                        keyType = typeArgs[0];
+                        valueType = typeArgs[1];
+                        dictionaryType = memberType;
+                    }
+                }
+            }
+            if (dictionaryType == null) return false;
+
+            // (note we checked the key type already)
+            // not a map if value is repeated
+            Type itemType = null, defaultType = null;
+            model.ResolveListTypes(valueType, ref itemType, ref defaultType);
+            if (itemType != null) return false;
+
+            return dictionaryType != null;
+        }
+
+        static bool IsValidMapKeyType(Type type)
+        {
+            if (type == null) return false;
+            switch(Helpers.GetTypeCode(type))
+            {
+                case ProtoTypeCode.Boolean:
+                case ProtoTypeCode.Byte:
+                case ProtoTypeCode.Char:
+                case ProtoTypeCode.Int16:
+                case ProtoTypeCode.Int32:
+                case ProtoTypeCode.Int64:
+                case ProtoTypeCode.String:
+
+                case ProtoTypeCode.SByte:
+                case ProtoTypeCode.UInt16:
+                case ProtoTypeCode.UInt32:
+                case ProtoTypeCode.UInt64:
+                    return true;
+            }
+            return false;
+        }
         private IProtoSerializer BuildSerializer()
         {
             int opaqueToken = 0;
             try
             {
                 model.TakeLock(ref opaqueToken);// check nobody is still adding this type
-                WireType wireType;
-                Type finalType = itemType == null ? memberType : itemType;
-                IProtoSerializer ser = TryGetCoreSerializer(model, dataFormat, finalType, out wireType, asReference, dynamicType, OverwriteList, true);
-                if (ser == null)
+                var member = backingMember ?? originalMember;
+                IProtoSerializer ser;
+                if (IsMap)
                 {
-                    throw new InvalidOperationException("No serializer defined for type: " + finalType.FullName);
-                }
+					Type dictionaryType,keyType,valueType;
+                    ResolveMapTypes(out dictionaryType, out keyType, out valueType);
 
-                // apply tags
-                if (itemType != null && SupportNull)
-                {
-                    if(IsPacked)
+					var keyType2 = keyType;
+					var valueType2 = valueType;
+					if (keyType2 != null && keyType2.FullName == "ILRuntime.Runtime.Intepreter.ILTypeInstance") {
+						keyType2 = PType.FindType (mapKeyTypeName);
+					}
+					if (valueType2 != null && valueType2.FullName == "ILRuntime.Runtime.Intepreter.ILTypeInstance") {
+						valueType2 = PType.FindType (mapValueTypeName);
+					}
+					if(dictionaryType != null){
+						dictionaryType = typeof(System.Collections.Generic.Dictionary<,>).MakeGenericType(new Type[]{ keyType, valueType});
+					}
+
+                    if (dictionaryType == null)
                     {
-                        throw new NotSupportedException("Packed encodings cannot support null values");
+                        throw new InvalidOperationException("Unable to resolve map type for type: " + memberType.FullName);
                     }
-                    ser = new TagDecorator(NullDecorator.Tag, wireType, IsStrict, ser);
-                    ser = new NullDecorator(model, ser);
-                    ser = new TagDecorator(fieldNumber, WireType.StartGroup, false, ser);
+                    var concreteType = defaultType;
+                    if(concreteType == null && Helpers.IsClass(memberType))
+                    {
+                        concreteType = memberType;
+                    }
+					WireType keyWireType;
+                    var keySer = TryGetCoreSerializer(model, MapKeyFormat, keyType2, out keyWireType, false, false, false, false);
+                    if(!AsReference)
+                    {
+                        AsReference = MetaType.GetAsReferenceDefault(model, valueType);
+                    }
+					WireType valueWireType;
+                    var valueSer = TryGetCoreSerializer(model, MapValueFormat, valueType2, out valueWireType, AsReference, DynamicType, false, true);
+
+                    var ctors = typeof(MapDecorator<,,>).MakeGenericType(new Type[] { dictionaryType, keyType, valueType }).GetConstructors(
+                        BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
+                    if (ctors.Length != 1) throw new InvalidOperationException("Unable to resolve MapDecorator constructor");
+                    ser = (IProtoSerializer)ctors[0].Invoke(new object[] {model, concreteType, keySer, valueSer, fieldNumber,
+                        DataFormat == DataFormat.Group ? WireType.StartGroup : WireType.String, keyWireType, valueWireType, OverwriteList });
                 }
                 else
                 {
-                    ser = new TagDecorator(fieldNumber, wireType, IsStrict, ser);
-                }
-                // apply lists if appropriate
-                if (itemType != null)
-                {                    
+                    WireType wireType;
+                    Type finalType = itemType == null ? memberType : itemType;
+                    ser = TryGetCoreSerializer(model, dataFormat, finalType, out wireType, AsReference, DynamicType, OverwriteList, true);
+                    if (ser == null)
+                    {
+                        throw new InvalidOperationException("No serializer defined for type: " + finalType.FullName);
+                    }
+
+                    // apply tags
+                    if (itemType != null && SupportNull)
+                    {
+                        if (IsPacked)
+                        {
+                            throw new NotSupportedException("Packed encodings cannot support null values");
+                        }
+                        ser = new TagDecorator(NullDecorator.Tag, wireType, IsStrict, ser);
+                        ser = new NullDecorator(model, ser);
+                        ser = new TagDecorator(fieldNumber, WireType.StartGroup, false, ser);
+                    }
+                    else
+                    {
+                        ser = new TagDecorator(fieldNumber, wireType, IsStrict, ser);
+                    }
+                    // apply lists if appropriate
+                    if (itemType != null)
+                    {
 #if NO_GENERICS
                     Type underlyingItemType = itemType;
 #else
-                    Type underlyingItemType = SupportNull ? itemType : Helpers.GetUnderlyingType(itemType) ?? itemType;
+                        Type underlyingItemType = SupportNull ? itemType : Helpers.GetUnderlyingType(itemType) ?? itemType;
 #endif
-                    Helpers.DebugAssert(underlyingItemType == ser.ExpectedType, "Wrong type in the tail; expected {0}, received {1}", ser.ExpectedType, underlyingItemType);
-                    if (memberType.IsArray)
+                        Helpers.DebugAssert(underlyingItemType == ser.ExpectedType
+                            || (ser.ExpectedType == model.MapType(typeof(object)) && !Helpers.IsValueType(underlyingItemType))
+                            , "Wrong type in the tail; expected {0}, received {1}", ser.ExpectedType, underlyingItemType);
+                        if (memberType.IsArray)
+                        {
+                            ser = new ArrayDecorator(model, ser, fieldNumber, IsPacked, wireType, memberType, OverwriteList, SupportNull);
+                        }
+                        else
+                        {
+                            ser = ListDecorator.Create(model, memberType, defaultType, ser, fieldNumber, IsPacked, wireType, member != null && PropertyDecorator.CanWrite(model, member), OverwriteList, SupportNull);
+                        }
+                    }
+                    else if (defaultValue != null && !IsRequired && getSpecified == null)
+                    {   // note: "ShouldSerialize*" / "*Specified" / etc ^^^^ take precedence over defaultValue,
+                        // as does "IsRequired"
+                        ser = new DefaultValueDecorator(model, defaultValue, ser);
+                    }
+                    if (memberType == model.MapType(typeof(Uri)))
                     {
-                        ser = new ArrayDecorator(model, ser, fieldNumber, IsPacked, wireType, memberType, OverwriteList, SupportNull);
+                        ser = new UriDecorator(model, ser);
                     }
-                    else
+#if PORTABLE
+                    else if(memberType.FullName == typeof(Uri).FullName)
                     {
-                        ser = ListDecorator.Create(model, memberType, defaultType, ser, fieldNumber, IsPacked, wireType, member != null && PropertyDecorator.CanWrite(model, member), OverwriteList, SupportNull);
+                        // In PCLs, the Uri type may not match (WinRT uses Internal/Uri, .Net uses System/Uri)
+                        ser = new ReflectedUriDecorator(memberType, model, ser);
                     }
-                }
-                else if (defaultValue != null && !IsRequired && getSpecified == null)
-                {   // note: "ShouldSerialize*" / "*Specified" / etc ^^^^ take precedence over defaultValue,
-                    // as does "IsRequired"
-                    ser = new DefaultValueDecorator(model, defaultValue, ser);
-                }
-                if (memberType == model.MapType(typeof(Uri)))
-                {
-                    ser = new UriDecorator(model, ser);
+#endif
                 }
                 if (member != null)
                 {
@@ -412,9 +662,12 @@ namespace ProtoBuf.Meta
         {
             switch (format)
             {
+                
                 case DataFormat.Group: return WireType.StartGroup;
                 case DataFormat.FixedSize: return WireType.Fixed64;
-                case DataFormat.Default: return WireType.String;
+                case DataFormat.WellKnown:
+                case DataFormat.Default:
+                    return WireType.String;
                 default: throw new InvalidOperationException();
             }
         }
@@ -475,7 +728,7 @@ namespace ProtoBuf.Meta
                     return new BooleanSerializer(model);
                 case ProtoTypeCode.DateTime:
                     defaultWireType = GetDateTimeWireType(dataFormat);
-                    return new DateTimeSerializer(model);
+                    return new DateTimeSerializer(dataFormat, model);
                 case ProtoTypeCode.Decimal:
                     defaultWireType = WireType.String;
                     return new DecimalSerializer(model);
@@ -496,13 +749,13 @@ namespace ProtoBuf.Meta
                     return new UInt16Serializer(model);
                 case ProtoTypeCode.TimeSpan:
                     defaultWireType = GetDateTimeWireType(dataFormat);
-                    return new TimeSpanSerializer(model);
+                    return new TimeSpanSerializer(dataFormat, model);
                 case ProtoTypeCode.Guid:
-                    defaultWireType = WireType.String;
+                    defaultWireType = dataFormat == DataFormat.Group ? WireType.StartGroup : WireType.String;
                     return new GuidSerializer(model);
                 case ProtoTypeCode.Uri:
                     defaultWireType = WireType.String;
-                    return new StringSerializer(model); // treat as string; wrapped in decorator later
+                    return new StringSerializer(model);
                 case ProtoTypeCode.ByteArray:
                     defaultWireType = WireType.String;
                     return new BlobSerializer(model, overwriteList);
@@ -519,13 +772,22 @@ namespace ProtoBuf.Meta
             if (allowComplexTypes && model != null)
             {
                 int key = model.GetKey(type, false, true);
+                MetaType meta = null;
+                if (key >= 0)
+                {
+                    meta = model[type];
+                    if(dataFormat == DataFormat.Default && meta.IsGroup)
+                    {
+                        dataFormat = DataFormat.Group;
+                    }
+                }
+
                 if (asReference || dynamicType)
                 {
-                    defaultWireType = dataFormat == DataFormat.Group ? WireType.StartGroup : WireType.String;
                     BclHelpers.NetObjectOptions options = BclHelpers.NetObjectOptions.None;
                     if (asReference) options |= BclHelpers.NetObjectOptions.AsReference;
                     if (dynamicType) options |= BclHelpers.NetObjectOptions.DynamicType;
-                    if (key >= 0)
+                    if (meta != null)
                     { // exists
                         if (asReference && Helpers.IsValueType(type))
                         {
@@ -541,16 +803,17 @@ namespace ProtoBuf.Meta
                             }
                             throw new InvalidOperationException(message);
                         }
-                        MetaType meta = model[type];
+                        
                         if (asReference && meta.IsAutoTuple) options |= BclHelpers.NetObjectOptions.LateSet;                        
                         if (meta.UseConstructor) options |= BclHelpers.NetObjectOptions.UseConstructor;
                     }
+                    defaultWireType = dataFormat == DataFormat.Group ? WireType.StartGroup : WireType.String;
                     return new NetObjectSerializer(model, type, key, options);
                 }
                 if (key >= 0)
                 {
                     defaultWireType = dataFormat == DataFormat.Group ? WireType.StartGroup : WireType.String;
-                    return new SubItemSerializer(type, key, model[type], true);
+                    return new SubItemSerializer(type, key, meta, true);
                 }
             }
             defaultWireType = WireType.None;
@@ -561,8 +824,11 @@ namespace ProtoBuf.Meta
         private string name;
         internal void SetName(string name)
         {
-            ThrowIfFrozen();
-            this.name = name;
+            if (name != this.name)
+            {
+                ThrowIfFrozen();
+                this.name = name;
+            }
         }
         /// <summary>
         /// Gets the logical name for this member in the schema (this is not critical for binary serialization, but may be used
@@ -570,7 +836,8 @@ namespace ProtoBuf.Meta
         /// </summary>
         public string Name
         {
-            get { return Helpers.IsNullOrEmpty(name) ? member.Name : name; }
+            get { return Helpers.IsNullOrEmpty(name) ? originalMember.Name : name; }
+            set { SetName(value); }
         }
 
         private const byte
@@ -578,7 +845,10 @@ namespace ProtoBuf.Meta
            OPTIONS_IsPacked = 2,
            OPTIONS_IsRequired = 4,
            OPTIONS_OverwriteList = 8,
-           OPTIONS_SupportNull = 16;
+           OPTIONS_SupportNull = 16,
+           OPTIONS_AsReference = 32,
+           OPTIONS_IsMap = 64,
+           OPTIONS_DynamicType = 128;
 
         private byte flags;
         private bool HasFlag(byte flag) { return (flags & flag) == flag; }
@@ -603,11 +873,11 @@ namespace ProtoBuf.Meta
             set { SetFlag(OPTIONS_SupportNull, value, true);}
         }
 
-        internal string GetSchemaTypeName(bool applyNetObjectProxy, ref bool requiresBclImport)
+        internal string GetSchemaTypeName(bool applyNetObjectProxy, ref RuntimeTypeModel.CommonImports imports)
         {
             Type effectiveType = ItemType;
             if (effectiveType == null) effectiveType = MemberType;
-            return model.GetSchemaTypeName(effectiveType, DataFormat, applyNetObjectProxy && asReference, applyNetObjectProxy && dynamicType, ref requiresBclImport);
+            return model.GetSchemaTypeName(effectiveType, DataFormat, applyNetObjectProxy && AsReference, applyNetObjectProxy && DynamicType, ref imports);
         }
 
         

+ 3 - 3
Unity/Assets/Plugins/protobuf-net/Meta/ValueMember.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/Meta/ValueMember.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 6d408a0bf9912c542980902a9c4dfe9b
-timeCreated: 1515899113
-licenseType: Pro
+guid: abd202ffd824a0a40a57805c3e082cf8
+timeCreated: 1517401477
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 0 - 0
Unity/Assets/Plugins/protobuf-net/NetObjectCache.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/NetObjectCache.cs


+ 3 - 3
Unity/Assets/Plugins/protobuf-net/NetObjectCache.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/NetObjectCache.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 71e939a48d063e846b0e2e78531059d1
-timeCreated: 1515899113
-licenseType: Pro
+guid: e2debd3d7e786f8428eb725cad8d9f23
+timeCreated: 1517401477
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 83 - 0
Unity/Assets/ThirdParty/Protobuf/protobuf-net/PType.cs

@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+
+namespace ProtoBuf{
+	public class PType
+	{
+		static PType m_Current;
+	    static PType Current
+	    {
+	        get
+	        { 
+				if (m_Current == null) {
+					m_Current = new PType ();
+				}
+	            return m_Current;
+	        }
+	    }
+		Dictionary<string, Type> m_Types = new Dictionary<string, Type>();
+		
+	    private PType() { }
+
+	    void RegisterTypeInternal(string metaName, Type type)
+	    {
+            m_Types[metaName] = type;
+			//if (!m_Types.ContainsKey(metaName))
+	   //     {
+				//m_Types.Add(metaName,type);
+	   //     }
+	   //     else
+				//throw new SystemException(string.Format("PropertyMeta : {0} is registered!",metaName));
+	    }
+
+		Type FindTypeInternal(string metaName)
+		{
+			Type type = null;
+			if (!m_Types.TryGetValue(metaName, out type))
+			{
+				throw new SystemException(string.Format("PropertyMeta : {0} is not registered!", metaName));
+			}
+			return type;
+		}
+
+		public static void RegisterType(string metaName, Type type)
+	    {
+			Current.RegisterTypeInternal(metaName, type);
+	    }
+
+		public delegate object DelegateFunctionCreateInstance(string typeName);
+		static DelegateFunctionCreateInstance CreateInstanceFunc;
+		public static void RegisterFunctionCreateInstance(DelegateFunctionCreateInstance func){
+			CreateInstanceFunc = func;
+		}
+		public delegate Type DelegateFunctionGetRealType(object o);
+		static DelegateFunctionGetRealType GetRealTypeFunc;
+		public static void RegisterFunctionGetRealType(DelegateFunctionGetRealType func){
+			GetRealTypeFunc = func;
+		}
+
+		public static Type FindType(string metaName)
+		{
+			return Current.FindTypeInternal(metaName);
+		}
+
+		public static object CreateInstance(Type type){
+			if (Type.GetType (type.FullName) == null) {
+				if (CreateInstanceFunc != null) {
+					return CreateInstanceFunc.Invoke(type.FullName);
+				}
+			}
+			return Activator.CreateInstance (type
+				#if !(CF || SILVERLIGHT || WINRT || PORTABLE || NETSTANDARD1_3 || NETSTANDARD1_4)
+				, nonPublic: true
+				#endif
+			);
+		}
+		public static Type GetPType(object o){
+			if (GetRealTypeFunc != null) {
+				return GetRealTypeFunc.Invoke (o);
+			}
+			return o.GetType ();
+		}
+	}
+}

+ 12 - 0
Unity/Assets/ThirdParty/Protobuf/protobuf-net/PType.cs.meta

@@ -0,0 +1,12 @@
+fileFormatVersion: 2
+guid: c0e47e21030b9964cbc66d6f7d9bdd7d
+timeCreated: 1517401477
+licenseType: Free
+MonoImporter:
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 0 - 0
Unity/Assets/Plugins/protobuf-net/PrefixStyle.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/PrefixStyle.cs


+ 3 - 3
Unity/Assets/Plugins/protobuf-net/PrefixStyle.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/PrefixStyle.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: ca4331de0cc111b45bd865cc72fb28ff
-timeCreated: 1515899114
-licenseType: Pro
+guid: b0a9e81143feb3549be264569898fdd5
+timeCreated: 1517401477
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 19 - 6
Unity/Assets/Plugins/protobuf-net/ProtoContractAttribute.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/ProtoContractAttribute.cs

@@ -122,16 +122,28 @@ namespace ProtoBuf
             }
         }
 
-        private bool HasFlag(byte flag) { return (flags & flag) == flag; }
-        private void SetFlag(byte flag, bool value)
+        /// <summary>
+        /// Indicates whether this type should always be treated as a "group" (rather than a string-prefixed sub-message)
+        /// </summary>
+        public bool IsGroup
+        {
+            get { return HasFlag(OPTIONS_IsGroup); }
+            set
+            {
+                SetFlag(OPTIONS_IsGroup, value);
+            }
+        }
+
+        private bool HasFlag(ushort flag) { return (flags & flag) == flag; }
+        private void SetFlag(ushort flag, bool value)
         {
             if (value) flags |= flag;
-            else flags = (byte)(flags & ~flag);
+            else flags = (ushort)(flags & ~flag);
         }
 
-        private byte flags;
+        private ushort flags;
 
-        private const byte
+        private const ushort
             OPTIONS_InferTagFromName = 1,
             OPTIONS_InferTagFromNameHasValue = 2,
             OPTIONS_UseProtoMembersOnly = 4,
@@ -139,7 +151,8 @@ namespace ProtoBuf
             OPTIONS_IgnoreListHandling = 16,
             OPTIONS_AsReferenceDefault = 32,
             OPTIONS_EnumPassthru = 64,
-            OPTIONS_EnumPassthruHasValue = 128;
+            OPTIONS_EnumPassthruHasValue = 128,
+            OPTIONS_IsGroup = 256;
 
         /// <summary>
         /// Applies only to enums (not to DTO classes themselves); gets or sets a value indicating that an enum should be treated directly as an int/short/etc, rather

+ 3 - 3
Unity/Assets/Plugins/protobuf-net/ProtoContractAttribute.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/ProtoContractAttribute.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 633c13e01b94f3547b29e7ea206404ef
-timeCreated: 1515899113
-licenseType: Pro
+guid: 5743f10a5565b684fa4bd1fb882669d8
+timeCreated: 1517401476
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

+ 0 - 0
Unity/Assets/Plugins/protobuf-net/ProtoConverterAttribute.cs → Unity/Assets/ThirdParty/Protobuf/protobuf-net/ProtoConverterAttribute.cs


+ 3 - 3
Unity/Assets/Plugins/protobuf-net/ProtoConverterAttribute.cs.meta → Unity/Assets/ThirdParty/Protobuf/protobuf-net/ProtoConverterAttribute.cs.meta

@@ -1,7 +1,7 @@
 fileFormatVersion: 2
-guid: 9b016ecf3f3483b4383b6c647ba4c258
-timeCreated: 1515899113
-licenseType: Pro
+guid: 43ddadd81587a9643be3f18119a6f02e
+timeCreated: 1517401476
+licenseType: Free
 MonoImporter:
   serializedVersion: 2
   defaultReferences: []

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно