/// <summary> /// Write an extension /// </summary> protected override void WriteExtension(GeneratorContext ctx, FieldDescriptorProto field) { var type = GetTypeName(ctx, field, out string dataFormat, out bool 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 = field.Name; 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) } }
/// <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.Output; bool isOptional = obj.label == FieldDescriptorProto.Label.LabelOptional; bool isRepeated = obj.label == FieldDescriptorProto.Label.LabelRepeated; 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; var typeName = GetTypeName(ctx, obj, out var dataFormat, out var isMap); defaultValue = GetDefaltValue(ctx, obj, typeName); if (isRepeated) { var mapMsgType = isMap ? ctx.TryFind <DescriptorProto>(obj.TypeName) : null; if (mapMsgType != null) { var keyTypeName = GetTypeName(ctx, mapMsgType.Fields.Single(x => x.Number == 1), out var keyDataFormat, out var _); var valueTypeName = GetTypeName(ctx, mapMsgType.Fields.Single(x => x.Number == 2), out var valueDataFormat, out var _); ctx.WriteLine($"{GetAccess(GetAccess(obj))} System.Collections.Generic.Dictionary<{keyTypeName}, {valueTypeName}> {Escape(obj.Name)} = new System.Collections.Generic.Dictionary<{keyTypeName}, {valueTypeName}>();"); } // else if (UseArray(obj)) // { // ctx.WriteLine($"{GetAccess(GetAccess(obj))} {typeName}[] {Escape(name)} ;"); // } else { ctx.WriteLine($"{GetAccess(GetAccess(obj))} System.Collections.Generic.List<{typeName}> {Escape(obj.Name)} = new System.Collections.Generic.List<{typeName}>();"); } } else { if (!string.IsNullOrEmpty(defaultValue)) { ctx.WriteLine($"{GetAccess(GetAccess(obj))} {typeName} {obj.Name} = {defaultValue};"); } else { ctx.WriteLine($"{GetAccess(GetAccess(obj))} {typeName} {obj.Name} ;"); } } }
/// <summary> /// Emit code initializing field values inside a constructor, if one is required /// </summary> protected override void WriteInitField(GeneratorContext ctx, FieldDescriptorProto obj, ref object state, OneOfStub[] oneOfs) { var name = ctx.NameNormalizer.GetName(obj); bool isOptional = obj.label == FieldDescriptorProto.Label.LabelOptional; bool isRepeated = obj.label == FieldDescriptorProto.Label.LabelRepeated; string dataFormat; bool isMap; var typeName = GetTypeName(ctx, obj, out dataFormat, out isMap); OneOfStub oneOf = obj.ShouldSerializeOneofIndex() ? oneOfs?[obj.OneofIndex] : null; bool explicitValues = isOptional && oneOf == null && ctx.Syntax == FileDescriptorProto.SyntaxProto2 && obj.type != FieldDescriptorProto.Type.TypeMessage && obj.type != FieldDescriptorProto.Type.TypeGroup; string defaultValue = GetDefaultValue(ctx, obj, typeName); if (isRepeated) { var mapMsgType = isMap ? ctx.TryFind <DescriptorProto>(obj.TypeName) : null; if (mapMsgType != null) { string keyDataFormat; string valueDataFormat; bool _; var keyTypeName = GetTypeName(ctx, mapMsgType.Fields.Single(x => x.Number == 1), out keyDataFormat, out _); var valueTypeName = GetTypeName(ctx, mapMsgType.Fields.Single(x => x.Number == 2), out valueDataFormat, out _); ctx.WriteLine($"{Escape(name)} = new global::System.Collections.Generic.Dictionary<{keyTypeName}, {valueTypeName}>();"); } else if (UseArray(obj)) { } // nothing needed else { ctx.WriteLine($"{Escape(name)} = new global::System.Collections.Generic.List<{typeName}>();"); } } else if (oneOf != null) { } // nothing to do else if (explicitValues) { } // nothing to do else { if (!string.IsNullOrWhiteSpace(defaultValue)) { ctx.WriteLine($"{Escape(name)} = {defaultValue};"); } } }
/// <summary> /// Obtain a relative name from a type name /// </summary> protected string MakeRelativeName(GeneratorContext ctx, string typeName) { var target = ctx.TryFind <DescriptorProto>(typeName); if (target != null && target.Parent is IType type) { var name = FindNameFromCommonAncestor(type, target, ctx.NameNormalizer); if (!string.IsNullOrWhiteSpace(name)) { return(name); } } return(Escape(typeName)); }
private string GetTypeName(GeneratorContext ctx, FieldDescriptorProto field, string typeName, ref string dataFormat, ref bool isMap, bool nonNullable = false) { switch (typeName) { case WellKnownTypeTimestamp: dataFormat = "WellKnown"; return(nonNullable ? "global::System.DateTime" : "global::System.DateTime?"); case WellKnownTypeDuration: dataFormat = "WellKnown"; return(nonNullable ? "global::System.TimeSpan" : "global::System.TimeSpan?"); case WellKnownTypeEmpty: return("global::ProtoBuf.Empty"); case ".bcl.NetObjectProxy": return("object"); case ".bcl.DateTime": return(nonNullable ? "global::System.DateTime" : "global::System.DateTime?"); case ".bcl.TimeSpan": return(nonNullable ? "global::System.TimeSpan" : "global::System.TimeSpan?"); case ".bcl.Decimal": return(nonNullable ? "decimal" : "decimal?"); case ".bcl.Guid": return(nonNullable ? "global::System.Guid" : "global::System.Guid?"); } var msgType = ctx.TryFind <DescriptorProto>(typeName); if (field != null && field.type == FieldDescriptorProto.Type.TypeGroup) { dataFormat = nameof(DataFormat.Group); } isMap = msgType?.Options?.MapEntry ?? false; return(field == null?MakeRelativeName(ctx, typeName) : MakeRelativeName(field, msgType, ctx.NameNormalizer)); }
/// <summary> /// Write an extension /// </summary> protected override void WriteExtension(GeneratorContext ctx, FieldDescriptorProto field) { var type = GetTypeName(ctx, field, out string dataFormat, out bool isMap); if (isMap) { ctx.WriteLine("REM #error map extensions not yet implemented; please file an issue"); } else if (field.label == FieldDescriptorProto.Label.LabelRepeated) { ctx.WriteLine("REM #error repeated extensions not yet implemented; please file an issue"); } else { var msg = ctx.TryFind <DescriptorProto>(field.Extendee); var extendee = MakeRelativeName(field, msg, ctx.NameNormalizer); string name = ctx.NameNormalizer.GetName(field); string shared = ""; if (field.Parent is FileDescriptorProto) { ctx.WriteLine("<Global.System.Runtime.CompilerServices.Extension> _"); } else { shared = "Shared "; } ctx.WriteLine($"{GetAccess(GetAccess(field))} {shared}Function Get{name}(ByVal obj As {extendee}) As {type}"); var tw = ctx.Indent().Write($"Return If(obj Is Nothing, CType(Nothing, {type}), Global.ProtoBuf.Extensible.GetValue(Of {type})(obj, {field.Number}"); if (!string.IsNullOrEmpty(dataFormat)) { tw.Write($", Global.ProtoBuf.DataFormat.{dataFormat}"); } tw.WriteLine("))"); ctx.Outdent().WriteLine("End Function"); } }
/// <summary> /// Write a field /// </summary> protected override void WriteField(GeneratorContext ctx, FieldDescriptorProto field, ref object state, OneOfStub[] oneOfs) { var name = ctx.NameNormalizer.GetName(field); var tw = ctx.Write($"[global::ProtoBuf.ProtoMember({field.Number}"); if (name != field.Name) { tw.Write($@", Name = @""{field.Name}"""); } var options = field.Options?.GetOptions(); if (options?.AsReference == true) { tw.Write(", AsReference = true"); } if (options?.DynamicType == true) { tw.Write(", DynamicType = true"); } bool isOptional = field.label == FieldDescriptorProto.Label.LabelOptional; bool isRepeated = field.label == FieldDescriptorProto.Label.LabelRepeated; OneOfStub oneOf = field.ShouldSerializeOneofIndex() ? oneOfs?[field.OneofIndex] : null; if (oneOf != null && !ctx.OneOfEnums && oneOf.CountTotal == 1) { oneOf = null; // not really a one-of, then! } bool explicitValues = isOptional && oneOf == null && ctx.Syntax == FileDescriptorProto.SyntaxProto2 && field.type != FieldDescriptorProto.Type.TypeMessage && field.type != FieldDescriptorProto.Type.TypeGroup; bool suppressDefaultAttribute = !isOptional; var typeName = GetTypeName(ctx, field, out var dataFormat, out var isMap); string defaultValue = GetDefaultValue(ctx, field, typeName); if (!string.IsNullOrWhiteSpace(dataFormat)) { tw.Write($", DataFormat = global::ProtoBuf.DataFormat.{dataFormat}"); } if (field.IsPacked(ctx.Syntax)) { tw.Write($", IsPacked = true"); } if (field.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, field.Options); if (isRepeated) { var mapMsgType = isMap ? ctx.TryFind <DescriptorProto>(field.TypeName) : null; bool allowSet = ctx.EmitListSetters; if (mapMsgType != null) { var keyTypeName = GetTypeName(ctx, mapMsgType.Fields.Single(x => x.Number == 1), out var keyDataFormat, out var _); var valueTypeName = GetTypeName(ctx, mapMsgType.Fields.Single(x => x.Number == 2), out var valueDataFormat, out var _); 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 ? "]" : ")]"); if (ctx.Supports(CSharp6)) { ctx.WriteLine($"{GetAccess(GetAccess(field))} global::System.Collections.Generic.Dictionary<{keyTypeName}, {valueTypeName}> {Escape(name)} {{ get; {(allowSet ? "set; " : "")}}} = new global::System.Collections.Generic.Dictionary<{keyTypeName}, {valueTypeName}>();"); } else { ctx.WriteLine($"{GetAccess(GetAccess(field))} global::System.Collections.Generic.Dictionary<{keyTypeName}, {valueTypeName}> {Escape(name)} {{ get; {(allowSet ? "" : "private ")}set; }}"); } } else if (UseArray(field)) { ctx.WriteLine($"{GetAccess(GetAccess(field))} {typeName}[] {Escape(name)} {{ get; set; }}"); } else if (ctx.Supports(CSharp6)) { ctx.WriteLine($"{GetAccess(GetAccess(field))} global::System.Collections.Generic.List<{typeName}> {Escape(name)} {{ get; {(allowSet ? "set; " : "")}}} = new global::System.Collections.Generic.List<{typeName}>();"); } else { ctx.WriteLine($"{GetAccess(GetAccess(field))} global::System.Collections.Generic.List<{typeName}> {Escape(name)} {{ get; {(allowSet ? "" : "private ")}set; }}"); } } else if (oneOf != null) { var defValue = string.IsNullOrWhiteSpace(defaultValue) ? (ctx.Supports(CSharp7_1) ? "default" : $"default({typeName})") : defaultValue; var fieldName = GetOneOfFieldName(oneOf.OneOf); var storage = oneOf.GetStorage(field.type, field.TypeName); ctx.WriteLine($"{GetAccess(GetAccess(field))} {typeName} {Escape(name)}").WriteLine("{").Indent(); switch (field.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({field.Number}) ? (({typeName}){fieldName}.{storage}) : {defValue}; }}"); break; default: ctx.WriteLine($"get {{ return {fieldName}.Is({field.Number}) ? {fieldName}.{storage} : {defValue}; }}"); break; } var unionType = oneOf.GetUnionType(); var cast = field.type == FieldDescriptorProto.Type.TypeEnum ? "(int)" : ""; ctx.WriteLine($"set {{ {fieldName} = new global::ProtoBuf.{unionType}({field.Number}, {cast}value); }}") .Outdent().WriteLine("}"); if (ctx.Supports(CSharp6)) { ctx.WriteLine($"{GetAccess(GetAccess(field))} bool ShouldSerialize{name}() => {fieldName}.Is({field.Number});") .WriteLine($"{GetAccess(GetAccess(field))} void Reset{name}() => global::ProtoBuf.{unionType}.Reset(ref {fieldName}, {field.Number});"); } else { ctx.WriteLine($"{GetAccess(GetAccess(field))} bool ShouldSerialize{name}()").WriteLine("{").Indent() .WriteLine($"return {fieldName}.Is({field.Number});").Outdent().WriteLine("}") .WriteLine($"{GetAccess(GetAccess(field))} void Reset{name}()").WriteLine("{").Indent() .WriteLine($"global::ProtoBuf.{unionType}.Reset(ref {fieldName}, {field.Number});").Outdent().WriteLine("}"); } if (oneOf.IsFirst()) { ctx.WriteLine().WriteLine($"private global::ProtoBuf.{unionType} {fieldName};"); } } else if (explicitValues) { string fieldName = FieldPrefix + name, fieldType; bool isRef = false; switch (field.type) { case FieldDescriptorProto.Type.TypeString: case FieldDescriptorProto.Type.TypeBytes: fieldType = typeName; isRef = true; break; default: fieldType = typeName + "?"; break; } ctx.WriteLine($"{GetAccess(GetAccess(field))} {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("}"); if (ctx.Supports(CSharp6)) { ctx.WriteLine($"{GetAccess(GetAccess(field))} bool ShouldSerialize{name}() => {fieldName} != null;") .WriteLine($"{GetAccess(GetAccess(field))} void Reset{name}() => {fieldName} = null;"); } else { ctx.WriteLine($"{GetAccess(GetAccess(field))} bool ShouldSerialize{name}()").WriteLine("{").Indent() .WriteLine($"return {fieldName} != null;").Outdent().WriteLine("}") .WriteLine($"{GetAccess(GetAccess(field))} void Reset{name}()").WriteLine("{").Indent() .WriteLine($"{fieldName} = null;").Outdent().WriteLine("}"); } ctx.WriteLine($"private {fieldType} {fieldName};"); } else { tw = ctx.Write($"{GetAccess(GetAccess(field))} {typeName} {Escape(name)} {{ get; set; }}"); if (!string.IsNullOrWhiteSpace(defaultValue) && ctx.Supports(CSharp6)) { tw.Write($" = {defaultValue};"); } tw.WriteLine(); } ctx.WriteLine(); }
private string GetDefaultValue(GeneratorContext ctx, FieldDescriptorProto obj, string typeName) { string defaultValue = null; bool isOptional = obj.label == FieldDescriptorProto.Label.LabelOptional; if (isOptional || ctx.EmitRequiredDefaults || obj.type == FieldDescriptorProto.Type.TypeEnum) { 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.Find(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 = typeName + "." + defaultValue; } } } } return(defaultValue); }
protected string GetDefaltValue(GeneratorContext ctx, FieldDescriptorProto obj, string _typename) { string defaultValue = obj.DefaultValue; if (obj.type == FieldDescriptorProto.Type.TypeString) { if (!string.IsNullOrEmpty(defaultValue)) { defaultValue = '"' + defaultValue + '"'; } } 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; default: if (!string.IsNullOrEmpty(defaultValue) && !defaultValue.EndsWith("f")) { defaultValue += "f"; } 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; default: if (!string.IsNullOrEmpty(defaultValue) && !defaultValue.EndsWith("f")) { defaultValue += "f"; } break; } } else if (obj.type == FieldDescriptorProto.Type.TypeMessage) { defaultValue = $"new {_typename}()"; } 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) { found = enumType.Values.FirstOrDefault(); } if (found != null) { // defaultValue = ctx.NameNormalizer.GetName(found); defaultValue = found.Name; } if (!string.IsNullOrEmpty(defaultValue)) { var typeName = GetTypeName(ctx, obj, out var dataFormat, out var isMap); defaultValue = typeName + "." + defaultValue; } } } return(defaultValue); }
protected void WriteFieldWrite(GeneratorContext ctx, FieldDescriptorProto obj, OneOfStub[] oneOfs) { bool isOptional = obj.label == FieldDescriptorProto.Label.LabelOptional; bool isRepeated = obj.label == FieldDescriptorProto.Label.LabelRepeated; Google.Protobuf.WireFormat.WireType ttwtype = ProtoTool.ILHelper.GetWireType(obj.type); uint ttag = Google.Protobuf.WireFormat.MakeTag(obj.Number, ttwtype); string tagstr = $"output.WriteTag({ttag});"; var typeName = GetTypeName(ctx, obj, out var dataFormat, out var isMap); if (isOptional) { string tifvalue = ""; if (obj.type == FieldDescriptorProto.Type.TypeString) { tifvalue = $"if(!string.IsNullOrEmpty({obj.Name})){"{"}"; } else { tifvalue = $"if({obj.Name} != default({typeName})){"{"}"; } ctx.WriteLine(tifvalue).Indent(); //代码块 ctx.WriteLine(tagstr); ctx.WriteLine(WriteString(obj.type, obj.Name)); ctx.Outdent(); ctx.WriteLine($"{"}"}"); } else if (isRepeated) { var mapMsgType = isMap ? ctx.TryFind <DescriptorProto>(obj.TypeName) : null; if (mapMsgType != null) { var keyTypeName = GetTypeName(ctx, mapMsgType.Fields.Single(x => x.Number == 1), out var keyDataFormat, out var _); var valueTypeName = GetTypeName(ctx, mapMsgType.Fields.Single(x => x.Number == 2), out var valueDataFormat, out var _); // System.Collections.Generic.Dictionary<int, int> ttt = new Dictionary<int, int>(); // System.Collections.Generic.KeyValuePair<int,int> ttt ctx.WriteLine($"if({obj.Name}.Count > 0 ){"{"}").Indent(); ctx.WriteLine($"foreach (System.Collections.Generic.KeyValuePair<{keyTypeName}, {valueTypeName}> item in {obj.Name}){"{"}").Indent(); ctx.WriteLine(tagstr); ctx.WriteLine(WriteString(mapMsgType.Fields[0].type, "item.Key")); ctx.WriteLine(WriteString(mapMsgType.Fields[1].type, "item.Value")); ctx.Outdent().WriteLine("}"); ctx.Outdent().WriteLine("}"); } else { ctx.WriteLine($"if({obj.Name}.Count > 0 ){"{"}").Indent(); ctx.WriteLine($"for (int i = 0; i < {obj.Name}.Count; i++){"{"}").Indent(); ctx.WriteLine(tagstr); ctx.WriteLine(WriteString(obj.type, obj.Name + "[i]")); ctx.Outdent().WriteLine("}"); ctx.Outdent().WriteLine("}"); } } else { ctx.WriteLine(tagstr); ctx.WriteLine(WriteString(obj.type, obj.Name)); } }
protected override void WriteFile(GeneratorContext ctx, FileDescriptorProto obj) { var file = ctx.File; var ast = new ProtoFile { Filename = file.Name, PackageName = file.Package, CsNamespace = file.Options?.CsharpNamespace ?? file.Package, Messages = file .MessageTypes .ToArray() .Select(mt => new ProtoMessage { Name = mt.Name, Fields = mt.Fields.Select(f => new ProtoField() { TypeName = f.TypeName, Name = f.Name, Number = f.Number, IsRepeated = f.label == FieldDescriptorProto.Label.LabelRepeated, OneOfIndex = f.OneofIndex, Type = f.type, Object = ctx.TryFind <DescriptorProto>(f.TypeName), }).ToArray() }) .ToArray(), Services = file .Services .ToArray() .Select( s => new ProtoService { Name = s.Name, Methods = s.Methods.ToArray() .Select( (m, i) => new ProtoMethod { Index = i, Name = m.Name, InputNameRaw = RemovePackageName(m.InputType), OutputNameRaw = RemovePackageName(m.OutputType), InputObject = ctx.TryFind <DescriptorProto>(m.InputType), OutputObject = ctx.TryFind <DescriptorProto>(m.OutputType), } ) .ToArray() } ) .ToArray() }; Handlebars.RegisterHelper("StringEquality", (output, options, context, arguments) => { if (arguments.Length != 2) { throw new HandlebarsException("{{#StringEquality}} helper must have exactly two arguments"); } var left = arguments.At <string>(0); var right = arguments[1] as string; if (left == right) { options.Template(output, context); } else { options.Inverse(output, context); } }); var f = Handlebars.Compile(_template); var result = f(ast); ctx.WriteLine(result);
private string GetTypeName(GeneratorContext ctx, FieldDescriptorProto field, out string dataFormat, out bool isMap, bool nonNullable = false) { 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: return(GetTypeName(ctx, field, field.TypeName, ref dataFormat, ref isMap, nonNullable)); default: return(field.TypeName); } }
/// <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"); } bool isOptional = obj.label == FieldDescriptorProto.Label.LabelOptional; bool isRepeated = obj.label == FieldDescriptorProto.Label.LabelRepeated; 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) { 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; } } } } var typeName = GetTypeName(ctx, obj, out var dataFormat, out var isMap); 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) { var keyTypeName = GetTypeName(ctx, mapMsgType.Fields.Single(x => x.Number == 1), out var keyDataFormat, out var _); var valueTypeName = GetTypeName(ctx, mapMsgType.Fields.Single(x => x.Number == 2), out var valueDataFormat, out var _); 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> /// Write a field /// </summary> protected override void WriteField(GeneratorContext ctx, FieldDescriptorProto field, ref object state, OneOfStub[] oneOfs) { var name = ctx.NameNormalizer.GetName(field); var tw = ctx.Write($"<Global.ProtoBuf.ProtoMember({field.Number}"); if (name != field.Name) { tw.Write($@", Name := ""{field.Name}"""); } var options = field.Options?.GetOptions(); if (options?.AsReference == true) { tw.Write(", AsReference := True"); } if (options?.DynamicType == true) { tw.Write(", DynamicType := True"); } bool isOptional = field.label == FieldDescriptorProto.Label.LabelOptional; bool isRepeated = field.label == FieldDescriptorProto.Label.LabelRepeated; OneOfStub oneOf = field.ShouldSerializeOneofIndex() ? oneOfs?[field.OneofIndex] : null; if (oneOf != null && !ctx.OneOfEnums && oneOf.CountTotal == 1) { oneOf = null; // not really a one-of, then! } bool explicitValues = isOptional && oneOf == null && ctx.Syntax == FileDescriptorProto.SyntaxProto2 && field.type != FieldDescriptorProto.Type.TypeMessage && field.type != FieldDescriptorProto.Type.TypeGroup; bool suppressDefaultAttribute = !isOptional; var typeName = GetTypeName(ctx, field, out var dataFormat, out var isMap); string defaultValue = GetDefaultValue(ctx, field, typeName); if (!string.IsNullOrWhiteSpace(dataFormat)) { tw.Write($", DataFormat := Global.ProtoBuf.DataFormat.{dataFormat}"); } if (field.IsPacked(ctx.Syntax)) { tw.Write($", IsPacked := True"); } if (field.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, field.Options); if (isRepeated) { var mapMsgType = isMap ? ctx.TryFind <DescriptorProto>(field.TypeName) : null; if (mapMsgType != null) { var keyTypeName = GetTypeName(ctx, mapMsgType.Fields.Single(x => x.Number == 1), out var keyDataFormat, out var _); var valueTypeName = GetTypeName(ctx, mapMsgType.Fields.Single(x => x.Number == 2), out var valueDataFormat, out var _); 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 ? "> _" : ")> _"); if (ctx.Supports(VB14)) { ctx.WriteLine($"{GetAccess(GetAccess(field))} Readonly Property {Escape(name)} As New Global.System.Collections.Generic.Dictionary(Of {keyTypeName}, {valueTypeName})"); } else { var fieldName = FieldPrefix + name; ctx.WriteLine($"{GetAccess(GetAccess(field))} Readonly Property {Escape(name)} As Global.System.Collections.Generic.Dictionary(Of {keyTypeName}, {valueTypeName})").Indent() .WriteLine("Get").Indent() .WriteLine($"Return {fieldName}") .Outdent().WriteLine("End Get").Outdent().WriteLine("End Property").WriteLine() .WriteLine($"Private ReadOnly {fieldName} As New Global.System.Collections.Generic.Dictionary(Of {keyTypeName}, {valueTypeName})").WriteLine(); } } else if (UseArray(field)) { if (ctx.Supports(VB11)) { ctx.WriteLine($"{GetAccess(GetAccess(field))} Property {Escape(name)} As {typeName}()"); } else { var fieldName = FieldPrefix + name; ctx.WriteLine($"{GetAccess(GetAccess(field))} Property {Escape(name)} As {typeName}()") .Indent().WriteLine("Get").Indent().WriteLine($"Return {fieldName}").Outdent().WriteLine("End Get").Outdent() .Indent().WriteLine($"Set(ByVal value as {typeName}())").Indent().WriteLine($"{fieldName} = value").Outdent().WriteLine("End Set").Outdent() .WriteLine("End Property").WriteLine() .WriteLine($"Private {fieldName} As {typeName}()").WriteLine(); } } else { if (ctx.Supports(VB14)) { ctx.WriteLine($"{GetAccess(GetAccess(field))} Readonly Property {Escape(name)} As New Global.System.Collections.Generic.List(Of {typeName})"); } else { var fieldName = FieldPrefix + name; ctx.WriteLine($"{GetAccess(GetAccess(field))} Readonly Property {Escape(name)} As Global.System.Collections.Generic.List(Of {typeName})").Indent() .WriteLine("Get").Indent() .WriteLine($"Return {fieldName}") .Outdent().WriteLine("End Get").Outdent().WriteLine("End Property").WriteLine() .WriteLine($"Private ReadOnly {fieldName} As New Global.System.Collections.Generic.List(Of {typeName})").WriteLine(); } } } else if (oneOf != null) { var defValue = string.IsNullOrWhiteSpace(defaultValue) ? $"CType(Nothing, {typeName})" : defaultValue; var fieldName = GetOneOfFieldName(oneOf.OneOf); var storage = oneOf.GetStorage(field.type, field.TypeName); ctx.WriteLine($"{GetAccess(GetAccess(field))} Property {Escape(name)} As {typeName}").Indent().WriteLine("Get").Indent(); switch (field.type) { case FieldDescriptorProto.Type.TypeMessage: case FieldDescriptorProto.Type.TypeGroup: case FieldDescriptorProto.Type.TypeEnum: case FieldDescriptorProto.Type.TypeBytes: case FieldDescriptorProto.Type.TypeString: ctx.WriteLine($"Return If({fieldName}.Is({field.Number}), CType({fieldName}.{storage}, {typeName}), {defValue})"); break; default: ctx.WriteLine($"Return If({fieldName}.Is({field.Number}), {fieldName}.{storage}, {defValue})"); break; } ctx.Outdent().WriteLine("End Get"); var unionType = oneOf.GetUnionType(); ctx.WriteLine($"Set(ByVal value As {typeName})").Indent() .WriteLine($"{fieldName} = New Global.ProtoBuf.{unionType}({field.Number}, value)").Outdent().WriteLine("End Set"); ctx.Outdent().WriteLine("End Property").WriteLine(); ctx.WriteLine($"{GetAccess(GetAccess(field))} Function ShouldSerialize{name}() As Boolean").Indent() .WriteLine($"Return {fieldName}.Is({field.Number})").Outdent() .WriteLine("End Function").WriteLine() .WriteLine($"{GetAccess(GetAccess(field))} Sub Reset{name}()").Indent() .WriteLine($"Global.ProtoBuf.{unionType}.Reset({fieldName}, {field.Number})") .Outdent().WriteLine("End Sub"); if (oneOf.IsFirst()) { ctx.WriteLine().WriteLine($"Private {fieldName} As Global.ProtoBuf.{unionType}"); } } else if (explicitValues) { string fieldName = FieldPrefix + name, fieldType; bool isRef = false; switch (field.type) { case FieldDescriptorProto.Type.TypeString: case FieldDescriptorProto.Type.TypeBytes: fieldType = typeName; isRef = true; break; default: fieldType = typeName + "?"; break; } ctx.WriteLine($"{GetAccess(GetAccess(field))} Property {Escape(name)} As {typeName}").Indent() .WriteLine("Get").Indent(); if (!string.IsNullOrWhiteSpace(defaultValue)) { ctx.WriteLine($"Return If({fieldName}, {defaultValue})"); } else if (!isRef) { ctx.WriteLine($"Return {fieldName}.GetValueOrDefault()"); } else { ctx.WriteLine($"Return {fieldName}"); } ctx.Outdent().WriteLine("End Get").WriteLine($"Set(ByVal value As {typeName})").Indent() .WriteLine($"{fieldName} = value").Outdent().WriteLine("End Set"). Outdent().WriteLine("End Property"); ctx.WriteLine($"{GetAccess(GetAccess(field))} Function ShouldSerialize{name}() As Boolean").Indent() .WriteLine($"Return Not ({fieldName} Is Nothing)").Outdent() .WriteLine("End Function") .WriteLine($"{GetAccess(GetAccess(field))} Sub Reset{name}()").Indent() .WriteLine($"{fieldName} = Nothing").Outdent().WriteLine("End Sub"); ctx.WriteLine($"Private {fieldName} As {fieldType}"); } else { if (ctx.Supports(VB11)) { tw = ctx.Write($"{GetAccess(GetAccess(field))} Property {Escape(name)} As {typeName}"); if (!string.IsNullOrWhiteSpace(defaultValue)) { tw.Write($" = {defaultValue}"); } tw.WriteLine(); } else { var fieldName = FieldPrefix + name; tw = ctx.WriteLine($"{GetAccess(GetAccess(field))} Property {Escape(name)} As {typeName}") .Indent().WriteLine("Get").Indent().WriteLine($"Return {fieldName}").Outdent().WriteLine("End Get").Outdent() .Indent().WriteLine($"Set(ByVal value as {typeName})").Indent().WriteLine($"{fieldName} = value").Outdent().WriteLine("End Set").Outdent() .WriteLine("End Property").WriteLine() .Write($"Private {fieldName} As {typeName}"); if (!string.IsNullOrWhiteSpace(defaultValue)) { tw.Write($" = {defaultValue}"); } tw.WriteLine(); } } ctx.WriteLine(); }
/// <summary> /// Write an extension /// </summary> protected override void WriteExtension(GeneratorContext ctx, FieldDescriptorProto field) { var type = GetTypeName(ctx, field, out string dataFormat, out bool isMap, false); var nonNullableType = GetTypeName(ctx, field, out _, out _, true); 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); TextWriter tw; if (isMap) { ctx.WriteLine("#error map extensions not yet implemented; please file an issue"); } else { bool isRepeated = field.label == FieldDescriptorProto.Label.LabelRepeated; var getMethodName = isRepeated ? nameof(Extensible.GetValues) : nameof(Extensible.GetValue); if (isRepeated) { ctx.WriteLine($"{GetAccess(GetAccess(field))} static global::System.Collections.Generic.IEnumerable<{nonNullableType}> Get{name}({@this}{extendee} obj)"); } else { ctx.WriteLine($"{GetAccess(GetAccess(field))} static {type} Get{name}({@this}{extendee} obj)"); } if (ctx.Supports(CSharp6)) { tw = ctx.Indent().Write($"=> "); } else { ctx.WriteLine("{").Indent(); tw = ctx.Write("return "); } var defaultValue = isRepeated ? "null" : ctx.Supports(CSharp7_1) ? "default" : $"default({type})"; tw.Write($"obj == null ? {defaultValue} : global::ProtoBuf.Extensible.{getMethodName}<{(isRepeated ? nonNullableType : type)}>(obj, {field.Number}"); if (!string.IsNullOrEmpty(dataFormat)) { tw.Write($", global::ProtoBuf.DataFormat.{dataFormat}"); } tw.WriteLine(");"); if (ctx.Supports(CSharp6)) { ctx.Outdent().WriteLine(); } else { ctx.Outdent().WriteLine("}").WriteLine(); } var setAccessorName = isRepeated ? "Add" : "Set"; ctx.WriteLine($"{GetAccess(GetAccess(field))} static void {setAccessorName}{name}({@this}{extendee} obj, {nonNullableType} value)"); if (ctx.Supports(CSharp6)) { tw = ctx.Indent().Write($"=> "); } else { ctx.WriteLine("{").Indent(); tw = ctx.Write(""); } tw.Write($"global::ProtoBuf.Extensible.AppendValue<{nonNullableType}>(obj, {field.Number}"); if (!string.IsNullOrEmpty(dataFormat)) { tw.Write($", global::ProtoBuf.DataFormat.{dataFormat}"); } tw.WriteLine(", value);"); if (ctx.Supports(CSharp6)) { ctx.Outdent().WriteLine(); } else { ctx.Outdent().WriteLine("}").WriteLine(); } } }
private string GetTypeName(GeneratorContext ctx, FieldDescriptorProto field, out string dataFormat, out bool isMap, bool nonNullable = false) { 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(nonNullable ? "global::System.DateTime" : "global::System.DateTime?"); case WellKnownTypeDuration: dataFormat = "WellKnown"; return(nonNullable ? "global::System.TimeSpan" : "global::System.TimeSpan?"); case ".bcl.NetObjectProxy": return("object"); case ".bcl.DateTime": return(nonNullable ? "global::System.DateTime" : "global::System.DateTime?"); case ".bcl.TimeSpan": return(nonNullable ? "global::System.TimeSpan" : "global::System.TimeSpan?"); case ".bcl.Decimal": return(nonNullable ? "decimal" : "decimal?"); case ".bcl.Guid": return(nonNullable ? "global::System.Guid" : "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); } }
protected void ReaderString(GeneratorContext ctx, FieldDescriptorProto obj) { bool isRepeated = obj.label == FieldDescriptorProto.Label.LabelRepeated; var typeName = GetTypeName(ctx, obj, out var dataFormat, out var isMap); string tfirstvalue = obj.Name; if (isRepeated) { tfirstvalue = $"{typeName} tvalue"; ctx.WriteLine("{").Indent(); } ReadBaseDataStr(ctx, obj.type, tfirstvalue, typeName); if (isRepeated) { var mapMsgType = isMap ? ctx.TryFind <DescriptorProto>(obj.TypeName) : null; if (mapMsgType != null) { var keyTypeName = GetTypeName(ctx, mapMsgType.Fields.Single(x => x.Number == 1), out var keyDataFormat, out var _); var valueTypeName = GetTypeName(ctx, mapMsgType.Fields.Single(x => x.Number == 2), out var valueDataFormat, out var _); string tkey = "tkey"; if (FieldDescriptorProto.Type.TypeMessage == mapMsgType.Fields[0].type) { ReadCreatObjectStr(ctx, keyTypeName, tkey); } else { ReadBaseDataStr(ctx, mapMsgType.Fields[0].type, $"{keyTypeName} {tkey}", keyTypeName); } string tvalue = "tvalue"; if (FieldDescriptorProto.Type.TypeMessage == mapMsgType.Fields[1].type) { ReadCreatObjectStr(ctx, valueTypeName, tvalue); } else { ReadBaseDataStr(ctx, mapMsgType.Fields[1].type, $"{valueTypeName} {tvalue}", valueTypeName); } ctx.WriteLine($"{obj.Name}.Add({tkey}, {tvalue});"); } else { if (FieldDescriptorProto.Type.TypeMessage == obj.type) { ReadCreatObjectStr(ctx, typeName, "tobj"); ctx.WriteLine($"{obj.Name}.Add(tobj);"); } else { ctx.WriteLine($"{obj.Name}.Add(tvalue);"); } } ctx.Outdent().WriteLine("}"); } else { switch (obj.type) { case FieldDescriptorProto.Type.TypeMessage: ctx.WriteLine("{").Indent(); ctx.WriteLine($"byte[] tchildbuffer = input.ReadBytes().ToByteArray();"); ctx.WriteLine($"{tfirstvalue}.MergeFrom(tchildbuffer);"); ctx.Outdent().WriteLine("}"); break; } } }