788 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C#
		
	
	
		
		
			
		
	
	
			788 lines
		
	
	
		
			34 KiB
		
	
	
	
		
			C#
		
	
	
| 
								 | 
							
								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();
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            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)
							 | 
						|||
| 
								 | 
							
								        {
							 | 
						|||
| 
								 | 
							
								            string dataFormat;
							 | 
						|||
| 
								 | 
							
								            var typeName = GetTypeName(ctx, obj, out dataFormat, out var isMap);
							 | 
						|||
| 
								 | 
							
								            if (isMap)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                return;
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								            var name = ctx.NameNormalizer.GetName(obj);
							 | 
						|||
| 
								 | 
							
								            var tw = ctx.Write($@"[global::ProtoBuf.ProtoMember({obj.Number}");
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            if (!string.IsNullOrWhiteSpace(dataFormat))
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                tw.Write($", (int)global::ProtoBuf.DataFormat.{dataFormat}");
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								            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");
							 | 
						|||
| 
								 | 
							
								            }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								            bool isOptional = obj.label == FieldDescriptorProto.Label.LabelOptional;
							 | 
						|||
| 
								 | 
							
								            bool isRepeated = obj.label == FieldDescriptorProto.Label.LabelRepeated;
							 | 
						|||
| 
								 | 
							
								            // Only needed by ILRuntime
							 | 
						|||
| 
								 | 
							
								            /*if (isRepeated && obj.type == FieldDescriptorProto.Type.TypeMessage)
							 | 
						|||
| 
								 | 
							
								            {
							 | 
						|||
| 
								 | 
							
								                tw.Write($@", TypeName = ""{GetTypeName2(obj.TypeName)}""");
							 | 
						|||
| 
								 | 
							
								            }*/
							 | 
						|||
| 
								 | 
							
								            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 (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";
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								}
							 |