github.com/cosmos/cosmos-proto@v1.0.0-beta.3/features/protoc/main.go (about)

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package protoc is used to generate protoc-gen-go files
     6  package protoc
     7  
     8  import (
     9  	"fmt"
    10  	"github.com/cosmos/cosmos-proto/features/protoc/genid"
    11  	"github.com/cosmos/cosmos-proto/generator"
    12  	"go/ast"
    13  	"go/parser"
    14  	"go/token"
    15  	"google.golang.org/protobuf/encoding/protowire"
    16  	"google.golang.org/protobuf/proto"
    17  	"math"
    18  	"strconv"
    19  	"strings"
    20  	"unicode"
    21  	"unicode/utf8"
    22  
    23  	pref "google.golang.org/protobuf/reflect/protoreflect"
    24  
    25  	"github.com/cosmos/cosmos-proto/features/protoc/version"
    26  	"google.golang.org/protobuf/compiler/protogen"
    27  	"google.golang.org/protobuf/reflect/protoreflect"
    28  	"google.golang.org/protobuf/runtime/protoimpl"
    29  
    30  	"google.golang.org/protobuf/types/descriptorpb"
    31  	"google.golang.org/protobuf/types/pluginpb"
    32  )
    33  
    34  // SupportedFeatures reports the set of supported protobuf language features.
    35  var SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL)
    36  
    37  // GenerateVersionMarkers specifies whether to generate version markers.
    38  var GenerateVersionMarkers = true
    39  
    40  // Standard library dependencies.
    41  const (
    42  	base64Package  = protogen.GoImportPath("encoding/base64")
    43  	mathPackage    = protogen.GoImportPath("math")
    44  	reflectPackage = protogen.GoImportPath("reflect")
    45  	sortPackage    = protogen.GoImportPath("sort")
    46  	stringsPackage = protogen.GoImportPath("strings")
    47  	syncPackage    = protogen.GoImportPath("sync")
    48  	timePackage    = protogen.GoImportPath("time")
    49  	utf8Package    = protogen.GoImportPath("unicode/utf8")
    50  )
    51  
    52  // Protobuf library dependencies.
    53  //
    54  // These are declared as an interface type so that they can be more easily
    55  // patched to support unique build environments that impose restrictions
    56  // on the dependencies of generated source code.
    57  var (
    58  	protoPackage         goImportPath = protogen.GoImportPath("google.golang.org/protobuf/proto")
    59  	protoimplPackage     goImportPath = protogen.GoImportPath("google.golang.org/protobuf/runtime/protoimpl")
    60  	protojsonPackage     goImportPath = protogen.GoImportPath("google.golang.org/protobuf/encoding/protojson")
    61  	protoreflectPackage  goImportPath = protogen.GoImportPath("google.golang.org/protobuf/reflect/protoreflect")
    62  	protoregistryPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/reflect/protoregistry")
    63  )
    64  
    65  // GenerateFile generates the contents of a .pb.go file.
    66  func GenerateFile(gen *protogen.Plugin, file *protogen.File, g *generator.GeneratedFile) *generator.GeneratedFile {
    67  	// filename := file.GeneratedFilenamePrefix + ".pb.go"
    68  	// g := gen.NewGeneratedFile(filename, file.GoImportPath)
    69  	f := newFileInfo(file)
    70  
    71  	genStandaloneComments(g, f, int32(genid.FileDescriptorProto_Syntax_field_number))
    72  	genGeneratedHeader(gen, g, f)
    73  	genStandaloneComments(g, f, int32(genid.FileDescriptorProto_Package_field_number))
    74  
    75  	// Emit a static check that enforces a minimum version of the proto package.
    76  	if GenerateVersionMarkers {
    77  		g.P("const (")
    78  		g.P("// Verify that this generated code is sufficiently up-to-date.")
    79  		g.P("_ = ", protoimplPackage.Ident("EnforceVersion"), "(", protoimpl.GenVersion, " - ", protoimplPackage.Ident("MinVersion"), ")")
    80  		g.P("// Verify that runtime/protoimpl is sufficiently up-to-date.")
    81  		g.P("_ = ", protoimplPackage.Ident("EnforceVersion"), "(", protoimplPackage.Ident("MaxVersion"), " - ", protoimpl.GenVersion, ")")
    82  		g.P(")")
    83  		g.P()
    84  	}
    85  
    86  	for i, imps := 0, f.Desc.Imports(); i < imps.Len(); i++ {
    87  		genImport(gen, g, f, imps.Get(i))
    88  	}
    89  	for _, enum := range f.allEnums {
    90  		genEnum(g, f, enum)
    91  	}
    92  	for _, message := range f.allMessages {
    93  		genMessage(g, f, message)
    94  	}
    95  	genExtensions(g, f)
    96  
    97  	genReflectFileDescriptor(gen, g, f)
    98  
    99  	return g
   100  }
   101  
   102  func fileVarName(f *protogen.File, suffix string) string {
   103  	prefix := f.GoDescriptorIdent.GoName
   104  	_, n := utf8.DecodeRuneInString(prefix)
   105  	prefix = strings.ToLower(prefix[:n]) + prefix[n:]
   106  	return prefix + "_" + suffix
   107  }
   108  
   109  func rawDescVarName(f *fileInfo) string {
   110  	return fileVarName(f.File, "rawDesc")
   111  }
   112  func goTypesVarName(f *fileInfo) string {
   113  	return fileVarName(f.File, "goTypes")
   114  }
   115  func depIdxsVarName(f *fileInfo) string {
   116  	return fileVarName(f.File, "depIdxs")
   117  }
   118  func enumTypesVarName(f *fileInfo) string {
   119  	return fileVarName(f.File, "enumTypes")
   120  }
   121  func messageTypesVarName(f *fileInfo) string {
   122  	return fileVarName(f.File, "msgTypes")
   123  }
   124  func extensionTypesVarName(f *fileInfo) string {
   125  	return fileVarName(f.File, "extTypes")
   126  }
   127  func initFuncName(f *protogen.File) string {
   128  	return fileVarName(f, "init")
   129  }
   130  
   131  func genFileDescriptor(gen *protogen.Plugin, g *generator.GeneratedFile, f *fileInfo) {
   132  	descProto := proto.Clone(f.Proto).(*descriptorpb.FileDescriptorProto)
   133  	descProto.SourceCodeInfo = nil // drop source code information
   134  
   135  	b, err := proto.MarshalOptions{AllowPartial: true, Deterministic: true}.Marshal(descProto)
   136  	if err != nil {
   137  		gen.Error(err)
   138  		return
   139  	}
   140  
   141  	g.P("var ", rawDescVarName(f), " = []byte{")
   142  	for len(b) > 0 {
   143  		n := 16
   144  		if n > len(b) {
   145  			n = len(b)
   146  		}
   147  
   148  		s := ""
   149  		for _, c := range b[:n] {
   150  			s += fmt.Sprintf("0x%02x,", c)
   151  		}
   152  		g.P(s)
   153  
   154  		b = b[n:]
   155  	}
   156  	g.P("}")
   157  	g.P()
   158  
   159  	if f.needRawDesc {
   160  		onceVar := rawDescVarName(f) + "Once"
   161  		dataVar := rawDescVarName(f) + "Data"
   162  		g.P("var (")
   163  		g.P(onceVar, " ", syncPackage.Ident("Once"))
   164  		g.P(dataVar, " = ", rawDescVarName(f))
   165  		g.P(")")
   166  		g.P()
   167  
   168  		g.P("func ", rawDescVarName(f), "GZIP() []byte {")
   169  		g.P(onceVar, ".Do(func() {")
   170  		g.P(dataVar, " = ", protoimplPackage.Ident("X"), ".CompressGZIP(", dataVar, ")")
   171  		g.P("})")
   172  		g.P("return ", dataVar)
   173  		g.P("}")
   174  		g.P()
   175  	}
   176  }
   177  
   178  func genReflectFileDescriptor(gen *protogen.Plugin, g *generator.GeneratedFile, f *fileInfo) {
   179  	g.P("var ", f.GoDescriptorIdent, " ", protoreflectPackage.Ident("FileDescriptor"))
   180  	g.P()
   181  
   182  	genFileDescriptor(gen, g, f)
   183  	if len(f.allEnums) > 0 {
   184  		g.P("var ", enumTypesVarName(f), " = make([]", protoimplPackage.Ident("EnumInfo"), ",", len(f.allEnums), ")")
   185  	}
   186  	if len(f.allMessages) > 0 {
   187  		g.P("var ", messageTypesVarName(f), " = make([]", protoimplPackage.Ident("MessageInfo"), ",", len(f.allMessages), ")")
   188  	}
   189  
   190  	// Generate a unique list of Go types for all declarations and dependencies,
   191  	// and the associated index into the type list for all dependencies.
   192  	var goTypes []string
   193  	var depIdxs []string
   194  	seen := map[protoreflect.FullName]int{}
   195  	genDep := func(name protoreflect.FullName, depSource string) {
   196  		if depSource != "" {
   197  			line := fmt.Sprintf("%d, // %d: %s -> %s", seen[name], len(depIdxs), depSource, name)
   198  			depIdxs = append(depIdxs, line)
   199  		}
   200  	}
   201  	genEnum := func(e *protogen.Enum, depSource string) {
   202  		if e != nil {
   203  			name := e.Desc.FullName()
   204  			if _, ok := seen[name]; !ok {
   205  				line := fmt.Sprintf("(%s)(0), // %d: %s", g.QualifiedGoIdent(e.GoIdent), len(goTypes), name)
   206  				goTypes = append(goTypes, line)
   207  				seen[name] = len(seen)
   208  			}
   209  			if depSource != "" {
   210  				genDep(name, depSource)
   211  			}
   212  		}
   213  	}
   214  	genMessage := func(m *protogen.Message, depSource string) {
   215  		if m != nil {
   216  			name := m.Desc.FullName()
   217  			if _, ok := seen[name]; !ok {
   218  				line := fmt.Sprintf("(*%s)(nil), // %d: %s", g.QualifiedGoIdent(m.GoIdent), len(goTypes), name)
   219  				if m.Desc.IsMapEntry() {
   220  					// Map entry messages have no associated Go type.
   221  					line = fmt.Sprintf("nil, // %d: %s", len(goTypes), name)
   222  				}
   223  				goTypes = append(goTypes, line)
   224  				seen[name] = len(seen)
   225  			}
   226  			if depSource != "" {
   227  				genDep(name, depSource)
   228  			}
   229  		}
   230  	}
   231  
   232  	// This ordering is significant.
   233  	// See filetype.TypeBuilder.DependencyIndexes.
   234  	type offsetEntry struct {
   235  		start int
   236  		name  string
   237  	}
   238  	var depOffsets []offsetEntry
   239  	for _, enum := range f.allEnums {
   240  		genEnum(enum.Enum, "")
   241  	}
   242  	for _, message := range f.allMessages {
   243  		genMessage(message.Message, "")
   244  	}
   245  	depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "field type_name"})
   246  	for _, message := range f.allMessages {
   247  		for _, field := range message.Fields {
   248  			if field.Desc.IsWeak() {
   249  				continue
   250  			}
   251  			source := string(field.Desc.FullName())
   252  			genEnum(field.Enum, source+":type_name")
   253  			genMessage(field.Message, source+":type_name")
   254  		}
   255  	}
   256  	depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "extension extendee"})
   257  	for _, extension := range f.allExtensions {
   258  		source := string(extension.Desc.FullName())
   259  		genMessage(extension.Extendee, source+":extendee")
   260  	}
   261  	depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "extension type_name"})
   262  	for _, extension := range f.allExtensions {
   263  		source := string(extension.Desc.FullName())
   264  		genEnum(extension.Enum, source+":type_name")
   265  		genMessage(extension.Message, source+":type_name")
   266  	}
   267  	depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "method input_type"})
   268  	for _, service := range f.Services {
   269  		for _, method := range service.Methods {
   270  			source := string(method.Desc.FullName())
   271  			genMessage(method.Input, source+":input_type")
   272  		}
   273  	}
   274  	depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "method output_type"})
   275  	for _, service := range f.Services {
   276  		for _, method := range service.Methods {
   277  			source := string(method.Desc.FullName())
   278  			genMessage(method.Output, source+":output_type")
   279  		}
   280  	}
   281  	depOffsets = append(depOffsets, offsetEntry{len(depIdxs), ""})
   282  	for i := len(depOffsets) - 2; i >= 0; i-- {
   283  		curr, next := depOffsets[i], depOffsets[i+1]
   284  		depIdxs = append(depIdxs, fmt.Sprintf("%d, // [%d:%d] is the sub-list for %s",
   285  			curr.start, curr.start, next.start, curr.name))
   286  	}
   287  	if len(depIdxs) > math.MaxInt32 {
   288  		panic("too many dependencies") // sanity check
   289  	}
   290  
   291  	g.P("var ", goTypesVarName(f), " = []interface{}{")
   292  	for _, s := range goTypes {
   293  		g.P(s)
   294  	}
   295  	g.P("}")
   296  
   297  	g.P("var ", depIdxsVarName(f), " = []int32{")
   298  	for _, s := range depIdxs {
   299  		g.P(s)
   300  	}
   301  	g.P("}")
   302  
   303  	g.P("func init() { ", initFuncName(f.File), "() }")
   304  
   305  	g.P("func ", initFuncName(f.File), "() {")
   306  	g.P("if ", f.GoDescriptorIdent, " != nil {")
   307  	g.P("return")
   308  	g.P("}")
   309  
   310  	// Ensure that initialization functions for different files in the same Go
   311  	// package run in the correct order: Call the init funcs for every .proto file
   312  	// imported by this one that is in the same Go package.
   313  	for i, imps := 0, f.Desc.Imports(); i < imps.Len(); i++ {
   314  		impFile := gen.FilesByPath[imps.Get(i).Path()]
   315  		if impFile.GoImportPath != f.GoImportPath {
   316  			continue
   317  		}
   318  		g.P(initFuncName(impFile), "()")
   319  	}
   320  
   321  	if len(f.allMessages) > 0 {
   322  		// Populate MessageInfo.Exporters.
   323  		g.P("if !", protoimplPackage.Ident("UnsafeEnabled"), " {")
   324  		for _, message := range f.allMessages {
   325  			if sf := f.allMessageFieldsByPtr[message]; len(sf.unexported) > 0 {
   326  				idx := f.allMessagesByPtr[message]
   327  				typesVar := messageTypesVarName(f)
   328  
   329  				g.P(typesVar, "[", idx, "].Exporter = func(v interface{}, i int) interface{} {")
   330  				g.P("switch v := v.(*", message.GoIdent, "); i {")
   331  				for i := 0; i < sf.count; i++ {
   332  					if name := sf.unexported[i]; name != "" {
   333  						g.P("case ", i, ": return &v.", name)
   334  					}
   335  				}
   336  				g.P("default: return nil")
   337  				g.P("}")
   338  				g.P("}")
   339  			}
   340  		}
   341  		g.P("}")
   342  
   343  		// Populate MessageInfo.OneofWrappers.
   344  		for _, message := range f.allMessages {
   345  			if len(message.Oneofs) > 0 {
   346  				idx := f.allMessagesByPtr[message]
   347  				typesVar := messageTypesVarName(f)
   348  
   349  				// Associate the wrapper types by directly passing them to the MessageInfo.
   350  				g.P(typesVar, "[", idx, "].OneofWrappers = []interface{} {")
   351  				for _, oneof := range message.Oneofs {
   352  					if !oneof.Desc.IsSynthetic() {
   353  						for _, field := range oneof.Fields {
   354  							g.P("(*", field.GoIdent, ")(nil),")
   355  						}
   356  					}
   357  				}
   358  				g.P("}")
   359  			}
   360  		}
   361  	}
   362  
   363  	g.P("type x struct{}")
   364  	g.P("out := ", protoimplPackage.Ident("TypeBuilder"), "{")
   365  	g.P("File: ", protoimplPackage.Ident("DescBuilder"), "{")
   366  	g.P("GoPackagePath: ", reflectPackage.Ident("TypeOf"), "(x{}).PkgPath(),")
   367  	g.P("RawDescriptor: ", rawDescVarName(f), ",")
   368  	g.P("NumEnums: ", len(f.allEnums), ",")
   369  	g.P("NumMessages: ", len(f.allMessages), ",")
   370  	g.P("NumExtensions: ", len(f.allExtensions), ",")
   371  	g.P("NumServices: ", len(f.Services), ",")
   372  	g.P("},")
   373  	g.P("GoTypes: ", goTypesVarName(f), ",")
   374  	g.P("DependencyIndexes: ", depIdxsVarName(f), ",")
   375  	if len(f.allEnums) > 0 {
   376  		g.P("EnumInfos: ", enumTypesVarName(f), ",")
   377  	}
   378  	if len(f.allMessages) > 0 {
   379  		g.P("MessageInfos: ", messageTypesVarName(f), ",")
   380  	}
   381  	if len(f.allExtensions) > 0 {
   382  		g.P("ExtensionInfos: ", extensionTypesVarName(f), ",")
   383  	}
   384  	g.P("}.Build()")
   385  	g.P(f.GoDescriptorIdent, " = out.File")
   386  
   387  	// Set inputs to nil to allow GC to reclaim resources.
   388  	g.P(rawDescVarName(f), " = nil")
   389  	g.P(goTypesVarName(f), " = nil")
   390  	g.P(depIdxsVarName(f), " = nil")
   391  	g.P("}")
   392  }
   393  
   394  // genStandaloneComments prints all leading comments for a FileDescriptorProto
   395  // location identified by the field number n.
   396  func genStandaloneComments(g *generator.GeneratedFile, f *fileInfo, n int32) {
   397  	loc := f.Desc.SourceLocations().ByPath(protoreflect.SourcePath{n})
   398  	for _, s := range loc.LeadingDetachedComments {
   399  		g.P(protogen.Comments(s))
   400  		g.P()
   401  	}
   402  	if s := loc.LeadingComments; s != "" {
   403  		g.P(protogen.Comments(s))
   404  		g.P()
   405  	}
   406  }
   407  
   408  func genGeneratedHeader(gen *protogen.Plugin, g *generator.GeneratedFile, f *fileInfo) {
   409  	g.P("// Code generated by protoc-gen-go. DO NOT EDIT.")
   410  
   411  	if GenerateVersionMarkers {
   412  		g.P("// versions:")
   413  		protocGenGoVersion := version.String()
   414  		protocVersion := "(unknown)"
   415  		if v := gen.Request.GetCompilerVersion(); v != nil {
   416  			protocVersion = fmt.Sprintf("v%v.%v.%v", v.GetMajor(), v.GetMinor(), v.GetPatch())
   417  			if s := v.GetSuffix(); s != "" {
   418  				protocVersion += "-" + s
   419  			}
   420  		}
   421  		g.P("// \tprotoc-gen-go ", protocGenGoVersion)
   422  		g.P("// \tprotoc        ", protocVersion)
   423  	}
   424  
   425  	if f.Proto.GetOptions().GetDeprecated() {
   426  		g.P("// ", f.Desc.Path(), " is a deprecated file.")
   427  	} else {
   428  		g.P("// source: ", f.Desc.Path())
   429  	}
   430  	g.P()
   431  }
   432  
   433  func genImport(gen *protogen.Plugin, g *generator.GeneratedFile, f *fileInfo, imp protoreflect.FileImport) {
   434  	impFile, ok := gen.FilesByPath[imp.Path()]
   435  	if !ok {
   436  		return
   437  	}
   438  	if impFile.GoImportPath == f.GoImportPath {
   439  		// Don't generate imports or aliases for types in the same Go package.
   440  		return
   441  	}
   442  	// Generate imports for all non-weak dependencies, even if they are not
   443  	// referenced, because other code and tools depend on having the
   444  	// full transitive closure of protocol buffer types in the binary.
   445  	if !imp.IsWeak {
   446  		g.Import(impFile.GoImportPath)
   447  	}
   448  	if !imp.IsPublic {
   449  		return
   450  	}
   451  
   452  	// Generate public imports by generating the imported file, parsing it,
   453  	// and extracting every symbol that should receive a forwarding declaration.
   454  	impGen := GenerateFile(gen, impFile, g)
   455  	impGen.Skip()
   456  	b, err := impGen.Content()
   457  	if err != nil {
   458  		gen.Error(err)
   459  		return
   460  	}
   461  	fset := token.NewFileSet()
   462  	astFile, err := parser.ParseFile(fset, "", b, parser.ParseComments)
   463  	if err != nil {
   464  		gen.Error(err)
   465  		return
   466  	}
   467  	genForward := func(tok token.Token, name string, expr ast.Expr) {
   468  		// Don't import unexported symbols.
   469  		r, _ := utf8.DecodeRuneInString(name)
   470  		if !unicode.IsUpper(r) {
   471  			return
   472  		}
   473  		// Don't import the FileDescriptor.
   474  		if name == impFile.GoDescriptorIdent.GoName {
   475  			return
   476  		}
   477  		// Don't import decls referencing a symbol defined in another package.
   478  		// i.e., don't import decls which are themselves public imports:
   479  		//
   480  		//	type T = somepackage.T
   481  		if _, ok := expr.(*ast.SelectorExpr); ok {
   482  			return
   483  		}
   484  		g.P(tok, " ", name, " = ", impFile.GoImportPath.Ident(name))
   485  	}
   486  	g.P("// Symbols defined in public import of ", imp.Path(), ".")
   487  	g.P()
   488  	for _, decl := range astFile.Decls {
   489  		switch decl := decl.(type) {
   490  		case *ast.GenDecl:
   491  			for _, spec := range decl.Specs {
   492  				switch spec := spec.(type) {
   493  				case *ast.TypeSpec:
   494  					genForward(decl.Tok, spec.Name.Name, spec.Type)
   495  				case *ast.ValueSpec:
   496  					for i, name := range spec.Names {
   497  						var expr ast.Expr
   498  						if i < len(spec.Values) {
   499  							expr = spec.Values[i]
   500  						}
   501  						genForward(decl.Tok, name.Name, expr)
   502  					}
   503  				case *ast.ImportSpec:
   504  				default:
   505  					panic(fmt.Sprintf("can't generate forward for spec type %T", spec))
   506  				}
   507  			}
   508  		}
   509  	}
   510  	g.P()
   511  }
   512  
   513  func genEnumReflectMethods(g *generator.GeneratedFile, f *fileInfo, e *enumInfo) {
   514  	idx := f.allEnumsByPtr[e]
   515  	typesVar := enumTypesVarName(f)
   516  
   517  	// Descriptor method.
   518  	g.P("func (", e.GoIdent, ") Descriptor() ", protoreflectPackage.Ident("EnumDescriptor"), " {")
   519  	g.P("return ", typesVar, "[", idx, "].Descriptor()")
   520  	g.P("}")
   521  	g.P()
   522  
   523  	// Type method.
   524  	g.P("func (", e.GoIdent, ") Type() ", protoreflectPackage.Ident("EnumType"), " {")
   525  	g.P("return &", typesVar, "[", idx, "]")
   526  	g.P("}")
   527  	g.P()
   528  
   529  	// Number method.
   530  	g.P("func (x ", e.GoIdent, ") Number() ", protoreflectPackage.Ident("EnumNumber"), " {")
   531  	g.P("return ", protoreflectPackage.Ident("EnumNumber"), "(x)")
   532  	g.P("}")
   533  	g.P()
   534  }
   535  
   536  func genEnum(g *generator.GeneratedFile, f *fileInfo, e *enumInfo) {
   537  	// Enum type declaration.
   538  	g.Annotate(e.GoIdent.GoName, e.Location)
   539  	leadingComments := appendDeprecationSuffix(e.Comments.Leading,
   540  		e.Desc.Options().(*descriptorpb.EnumOptions).GetDeprecated())
   541  	g.P(leadingComments,
   542  		"type ", e.GoIdent, " int32")
   543  
   544  	// Enum value constants.
   545  	g.P("const (")
   546  	for _, value := range e.Values {
   547  		g.Annotate(value.GoIdent.GoName, value.Location)
   548  		leadingComments := appendDeprecationSuffix(value.Comments.Leading,
   549  			value.Desc.Options().(*descriptorpb.EnumValueOptions).GetDeprecated())
   550  		g.P(leadingComments,
   551  			value.GoIdent, " ", e.GoIdent, " = ", value.Desc.Number(),
   552  			trailingComment(value.Comments.Trailing))
   553  	}
   554  	g.P(")")
   555  	g.P()
   556  
   557  	// Enum value maps.
   558  	g.P("// Enum value maps for ", e.GoIdent, ".")
   559  	g.P("var (")
   560  	g.P(e.GoIdent.GoName+"_name", " = map[int32]string{")
   561  	for _, value := range e.Values {
   562  		duplicate := ""
   563  		if value.Desc != e.Desc.Values().ByNumber(value.Desc.Number()) {
   564  			duplicate = "// Duplicate value: "
   565  		}
   566  		g.P(duplicate, value.Desc.Number(), ": ", strconv.Quote(string(value.Desc.Name())), ",")
   567  	}
   568  	g.P("}")
   569  	g.P(e.GoIdent.GoName+"_value", " = map[string]int32{")
   570  	for _, value := range e.Values {
   571  		g.P(strconv.Quote(string(value.Desc.Name())), ": ", value.Desc.Number(), ",")
   572  	}
   573  	g.P("}")
   574  	g.P(")")
   575  	g.P()
   576  
   577  	// Enum method.
   578  	//
   579  	// NOTE: A pointer value is needed to represent presence in proto2.
   580  	// Since a proto2 message can reference a proto3 enum, it is useful to
   581  	// always generate this method (even on proto3 enums) to support that case.
   582  	g.P("func (x ", e.GoIdent, ") Enum() *", e.GoIdent, " {")
   583  	g.P("p := new(", e.GoIdent, ")")
   584  	g.P("*p = x")
   585  	g.P("return p")
   586  	g.P("}")
   587  	g.P()
   588  
   589  	// String method.
   590  	g.P("func (x ", e.GoIdent, ") String() string {")
   591  	g.P("return ", protoimplPackage.Ident("X"), ".EnumStringOf(x.Descriptor(), ", protoreflectPackage.Ident("EnumNumber"), "(x))")
   592  	g.P("}")
   593  	g.P()
   594  
   595  	genEnumReflectMethods(g, f, e)
   596  
   597  	// UnmarshalJSON method.
   598  	if e.genJSONMethod && e.Desc.Syntax() == protoreflect.Proto2 {
   599  		g.P("// Deprecated: Do not use.")
   600  		g.P("func (x *", e.GoIdent, ") UnmarshalJSON(b []byte) error {")
   601  		g.P("num, err := ", protoimplPackage.Ident("X"), ".UnmarshalJSONEnum(x.Descriptor(), b)")
   602  		g.P("if err != nil {")
   603  		g.P("return err")
   604  		g.P("}")
   605  		g.P("*x = ", e.GoIdent, "(num)")
   606  		g.P("return nil")
   607  		g.P("}")
   608  		g.P()
   609  	}
   610  
   611  	// EnumDescriptor method.
   612  	if e.genRawDescMethod {
   613  		var indexes []string
   614  		for i := 1; i < len(e.Location.Path); i += 2 {
   615  			indexes = append(indexes, strconv.Itoa(int(e.Location.Path[i])))
   616  		}
   617  		g.P("// Deprecated: Use ", e.GoIdent, ".Descriptor instead.")
   618  		g.P("func (", e.GoIdent, ") EnumDescriptor() ([]byte, []int) {")
   619  		g.P("return ", rawDescVarName(f), "GZIP(), []int{", strings.Join(indexes, ","), "}")
   620  		g.P("}")
   621  		g.P()
   622  		f.needRawDesc = true
   623  	}
   624  }
   625  
   626  func genMessage(g *generator.GeneratedFile, f *fileInfo, m *messageInfo) {
   627  	if m.Desc.IsMapEntry() {
   628  		return
   629  	}
   630  
   631  	// Message type declaration.
   632  	g.Annotate(m.GoIdent.GoName, m.Location)
   633  	leadingComments := appendDeprecationSuffix(m.Comments.Leading,
   634  		m.Desc.Options().(*descriptorpb.MessageOptions).GetDeprecated())
   635  	g.P(leadingComments,
   636  		"type ", m.GoIdent, " struct {")
   637  	genMessageFields(g, f, m)
   638  	g.P("}")
   639  	g.P()
   640  
   641  	genMessageKnownFunctions(g, f, m)
   642  	genMessageDefaultDecls(g, f, m)
   643  	genMessageMethods(g, f, m)
   644  	genMessageOneofWrapperTypes(g, f, m)
   645  }
   646  
   647  func genMessageKnownFunctions(g *generator.GeneratedFile, f *fileInfo, m *messageInfo) {
   648  	switch m.Desc.FullName() {
   649  	case genid.Any_message_fullname:
   650  		g.P("// New marshals src into a new Any instance.")
   651  		g.P("func New(src ", protoPackage.Ident("Message"), ") (*Any, error) {")
   652  		g.P("	dst := new(Any)")
   653  		g.P("	if err := dst.MarshalFrom(src); err != nil {")
   654  		g.P("		return nil, err")
   655  		g.P("	}")
   656  		g.P("	return dst, nil")
   657  		g.P("}")
   658  		g.P()
   659  
   660  		g.P("// MarshalFrom marshals src into dst as the underlying message")
   661  		g.P("// using the provided marshal options.")
   662  		g.P("//")
   663  		g.P("// If no options are specified, call dst.MarshalFrom instead.")
   664  		g.P("func MarshalFrom(dst *Any, src ", protoPackage.Ident("Message"), ", opts ", protoPackage.Ident("MarshalOptions"), ") error {")
   665  		g.P("	const urlPrefix = \"type.googleapis.com/\"")
   666  		g.P("	if src == nil {")
   667  		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"invalid nil source message\")")
   668  		g.P("	}")
   669  		g.P("	b, err := opts.Marshal(src)")
   670  		g.P("	if err != nil {")
   671  		g.P("		return err")
   672  		g.P("	}")
   673  		g.P("	dst.TypeUrl = urlPrefix + string(src.ProtoReflect().Descriptor().FullName())")
   674  		g.P("	dst.Value = b")
   675  		g.P("	return nil")
   676  		g.P("}")
   677  		g.P()
   678  
   679  		g.P("// UnmarshalTo unmarshals the underlying message from src into dst")
   680  		g.P("// using the provided unmarshal options.")
   681  		g.P("// It reports an error if dst is not of the right message type.")
   682  		g.P("//")
   683  		g.P("// If no options are specified, call src.UnmarshalTo instead.")
   684  		g.P("func UnmarshalTo(src *Any, dst ", protoPackage.Ident("Message"), ", opts ", protoPackage.Ident("UnmarshalOptions"), ") error {")
   685  		g.P("	if src == nil {")
   686  		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"invalid nil source message\")")
   687  		g.P("	}")
   688  		g.P("	if !src.MessageIs(dst) {")
   689  		g.P("		got := dst.ProtoReflect().Descriptor().FullName()")
   690  		g.P("		want := src.MessageName()")
   691  		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"mismatched message type: got %q, want %q\", got, want)")
   692  		g.P("	}")
   693  		g.P("	return opts.Unmarshal(src.GetValue(), dst)")
   694  		g.P("}")
   695  		g.P()
   696  
   697  		g.P("// UnmarshalNew unmarshals the underlying message from src into dst,")
   698  		g.P("// which is newly created message using a type resolved from the type URL.")
   699  		g.P("// The message type is resolved according to opt.Resolver,")
   700  		g.P("// which should implement protoregistry.MessageTypeResolver.")
   701  		g.P("// It reports an error if the underlying message type could not be resolved.")
   702  		g.P("//")
   703  		g.P("// If no options are specified, call src.UnmarshalNew instead.")
   704  		g.P("func UnmarshalNew(src *Any, opts ", protoPackage.Ident("UnmarshalOptions"), ") (dst ", protoPackage.Ident("Message"), ", err error) {")
   705  		g.P("	if src.GetTypeUrl() == \"\" {")
   706  		g.P("		return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid empty type URL\")")
   707  		g.P("	}")
   708  		g.P("	if opts.Resolver == nil {")
   709  		g.P("		opts.Resolver = ", protoregistryPackage.Ident("GlobalTypes"))
   710  		g.P("	}")
   711  		g.P("	r, ok := opts.Resolver.(", protoregistryPackage.Ident("MessageTypeResolver"), ")")
   712  		g.P("	if !ok {")
   713  		g.P("		return nil, ", protoregistryPackage.Ident("NotFound"))
   714  		g.P("	}")
   715  		g.P("	mt, err := r.FindMessageByURL(src.GetTypeUrl())")
   716  		g.P("	if err != nil {")
   717  		g.P("		if err == ", protoregistryPackage.Ident("NotFound"), " {")
   718  		g.P("			return nil, err")
   719  		g.P("		}")
   720  		g.P("		return nil, ", protoimplPackage.Ident("X"), ".NewError(\"could not resolve %q: %v\", src.GetTypeUrl(), err)")
   721  		g.P("	}")
   722  		g.P("	dst = mt.New().Interface()")
   723  		g.P("	return dst, opts.Unmarshal(src.GetValue(), dst)")
   724  		g.P("}")
   725  		g.P()
   726  
   727  		g.P("// MessageIs reports whether the underlying message is of the same type as m.")
   728  		g.P("func (x *Any) MessageIs(m ", protoPackage.Ident("Message"), ") bool {")
   729  		g.P("	if m == nil {")
   730  		g.P("		return false")
   731  		g.P("	}")
   732  		g.P("	url := x.GetTypeUrl()")
   733  		g.P("	name := string(m.ProtoReflect().Descriptor().FullName())")
   734  		g.P("	if !", stringsPackage.Ident("HasSuffix"), "(url, name) {")
   735  		g.P("		return false")
   736  		g.P("	}")
   737  		g.P("	return len(url) == len(name) || url[len(url)-len(name)-1] == '/'")
   738  		g.P("}")
   739  		g.P()
   740  
   741  		g.P("// MessageName reports the full name of the underlying message,")
   742  		g.P("// returning an empty string if invalid.")
   743  		g.P("func (x *Any) MessageName() ", protoreflectPackage.Ident("FullName"), " {")
   744  		g.P("	url := x.GetTypeUrl()")
   745  		g.P("	name := ", protoreflectPackage.Ident("FullName"), "(url)")
   746  		g.P("	if i := ", stringsPackage.Ident("LastIndexByte"), "(url, '/'); i >= 0 {")
   747  		g.P("		name = name[i+len(\"/\"):]")
   748  		g.P("	}")
   749  		g.P("	if !name.IsValid() {")
   750  		g.P("		return \"\"")
   751  		g.P("	}")
   752  		g.P("	return name")
   753  		g.P("}")
   754  		g.P()
   755  
   756  		g.P("// MarshalFrom marshals m into x as the underlying message.")
   757  		g.P("func (x *Any) MarshalFrom(m ", protoPackage.Ident("Message"), ") error {")
   758  		g.P("	return MarshalFrom(x, m, ", protoPackage.Ident("MarshalOptions"), "{})")
   759  		g.P("}")
   760  		g.P()
   761  
   762  		g.P("// UnmarshalTo unmarshals the contents of the underlying message of x into m.")
   763  		g.P("// It resets m before performing the unmarshal operation.")
   764  		g.P("// It reports an error if m is not of the right message type.")
   765  		g.P("func (x *Any) UnmarshalTo(m ", protoPackage.Ident("Message"), ") error {")
   766  		g.P("	return UnmarshalTo(x, m, ", protoPackage.Ident("UnmarshalOptions"), "{})")
   767  		g.P("}")
   768  		g.P()
   769  
   770  		g.P("// UnmarshalNew unmarshals the contents of the underlying message of x into")
   771  		g.P("// a newly allocated message of the specified type.")
   772  		g.P("// It reports an error if the underlying message type could not be resolved.")
   773  		g.P("func (x *Any) UnmarshalNew() (", protoPackage.Ident("Message"), ", error) {")
   774  		g.P("	return UnmarshalNew(x, ", protoPackage.Ident("UnmarshalOptions"), "{})")
   775  		g.P("}")
   776  		g.P()
   777  
   778  	case genid.Timestamp_message_fullname:
   779  		g.P("// Now constructs a new Timestamp from the current time.")
   780  		g.P("func Now() *Timestamp {")
   781  		g.P("	return New(", timePackage.Ident("Now"), "())")
   782  		g.P("}")
   783  		g.P()
   784  
   785  		g.P("// New constructs a new Timestamp from the provided time.Time.")
   786  		g.P("func New(t ", timePackage.Ident("Time"), ") *Timestamp {")
   787  		g.P("	return &Timestamp{Seconds: int64(t.Unix()), Nanos: int32(t.Nanosecond())}")
   788  		g.P("}")
   789  		g.P()
   790  
   791  		g.P("// AsTime converts x to a time.Time.")
   792  		g.P("func (x *Timestamp) AsTime() ", timePackage.Ident("Time"), " {")
   793  		g.P("	return ", timePackage.Ident("Unix"), "(int64(x.GetSeconds()), int64(x.GetNanos())).UTC()")
   794  		g.P("}")
   795  		g.P()
   796  
   797  		g.P("// IsValid reports whether the timestamp is valid.")
   798  		g.P("// It is equivalent to CheckValid == nil.")
   799  		g.P("func (x *Timestamp) IsValid() bool {")
   800  		g.P("	return x.check() == 0")
   801  		g.P("}")
   802  		g.P()
   803  
   804  		g.P("// CheckValid returns an error if the timestamp is invalid.")
   805  		g.P("// In particular, it checks whether the value represents a date that is")
   806  		g.P("// in the range of 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.")
   807  		g.P("// An error is reported for a nil Timestamp.")
   808  		g.P("func (x *Timestamp) CheckValid() error {")
   809  		g.P("	switch x.check() {")
   810  		g.P("	case invalidNil:")
   811  		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"invalid nil Timestamp\")")
   812  		g.P("	case invalidUnderflow:")
   813  		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"timestamp (%v) before 0001-01-01\", x)")
   814  		g.P("	case invalidOverflow:")
   815  		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"timestamp (%v) after 9999-12-31\", x)")
   816  		g.P("	case invalidNanos:")
   817  		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"timestamp (%v) has out-of-range nanos\", x)")
   818  		g.P("	default:")
   819  		g.P("		return nil")
   820  		g.P("	}")
   821  		g.P("}")
   822  		g.P()
   823  
   824  		g.P("const (")
   825  		g.P("	_ = iota")
   826  		g.P("	invalidNil")
   827  		g.P("	invalidUnderflow")
   828  		g.P("	invalidOverflow")
   829  		g.P("	invalidNanos")
   830  		g.P(")")
   831  		g.P()
   832  
   833  		g.P("func (x *Timestamp) check() uint {")
   834  		g.P("	const minTimestamp = -62135596800  // Seconds between 1970-01-01T00:00:00Z and 0001-01-01T00:00:00Z, inclusive")
   835  		g.P("	const maxTimestamp = +253402300799 // Seconds between 1970-01-01T00:00:00Z and 9999-12-31T23:59:59Z, inclusive")
   836  		g.P("	secs := x.GetSeconds()")
   837  		g.P("	nanos := x.GetNanos()")
   838  		g.P("	switch {")
   839  		g.P("	case x == nil:")
   840  		g.P("		return invalidNil")
   841  		g.P("	case secs < minTimestamp:")
   842  		g.P("		return invalidUnderflow")
   843  		g.P("	case secs > maxTimestamp:")
   844  		g.P("		return invalidOverflow")
   845  		g.P("	case nanos < 0 || nanos >= 1e9:")
   846  		g.P("		return invalidNanos")
   847  		g.P("	default:")
   848  		g.P("		return 0")
   849  		g.P("	}")
   850  		g.P("}")
   851  		g.P()
   852  
   853  	case genid.Duration_message_fullname:
   854  		g.P("// New constructs a new Duration from the provided time.Duration.")
   855  		g.P("func New(d ", timePackage.Ident("Duration"), ") *Duration {")
   856  		g.P("	nanos := d.Nanoseconds()")
   857  		g.P("	secs := nanos / 1e9")
   858  		g.P("	nanos -= secs * 1e9")
   859  		g.P("	return &Duration{Seconds: int64(secs), Nanos: int32(nanos)}")
   860  		g.P("}")
   861  		g.P()
   862  
   863  		g.P("// AsDuration converts x to a time.Duration,")
   864  		g.P("// returning the closest duration value in the event of overflow.")
   865  		g.P("func (x *Duration) AsDuration() ", timePackage.Ident("Duration"), " {")
   866  		g.P("	secs := x.GetSeconds()")
   867  		g.P("	nanos := x.GetNanos()")
   868  		g.P("	d := ", timePackage.Ident("Duration"), "(secs) * ", timePackage.Ident("Second"))
   869  		g.P("	overflow := d/", timePackage.Ident("Second"), " != ", timePackage.Ident("Duration"), "(secs)")
   870  		g.P("	d += ", timePackage.Ident("Duration"), "(nanos) * ", timePackage.Ident("Nanosecond"))
   871  		g.P("	overflow = overflow || (secs < 0 && nanos < 0 && d > 0)")
   872  		g.P("	overflow = overflow || (secs > 0 && nanos > 0 && d < 0)")
   873  		g.P("	if overflow {")
   874  		g.P("		switch {")
   875  		g.P("		case secs < 0:")
   876  		g.P("			return ", timePackage.Ident("Duration"), "(", mathPackage.Ident("MinInt64"), ")")
   877  		g.P("		case secs > 0:")
   878  		g.P("			return ", timePackage.Ident("Duration"), "(", mathPackage.Ident("MaxInt64"), ")")
   879  		g.P("		}")
   880  		g.P("	}")
   881  		g.P("	return d")
   882  		g.P("}")
   883  		g.P()
   884  
   885  		g.P("// IsValid reports whether the duration is valid.")
   886  		g.P("// It is equivalent to CheckValid == nil.")
   887  		g.P("func (x *Duration) IsValid() bool {")
   888  		g.P("	return x.check() == 0")
   889  		g.P("}")
   890  		g.P()
   891  
   892  		g.P("// CheckValid returns an error if the duration is invalid.")
   893  		g.P("// In particular, it checks whether the value is within the range of")
   894  		g.P("// -10000 years to +10000 years inclusive.")
   895  		g.P("// An error is reported for a nil Duration.")
   896  		g.P("func (x *Duration) CheckValid() error {")
   897  		g.P("	switch x.check() {")
   898  		g.P("	case invalidNil:")
   899  		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"invalid nil Duration\")")
   900  		g.P("	case invalidUnderflow:")
   901  		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"duration (%v) exceeds -10000 years\", x)")
   902  		g.P("	case invalidOverflow:")
   903  		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"duration (%v) exceeds +10000 years\", x)")
   904  		g.P("	case invalidNanosRange:")
   905  		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"duration (%v) has out-of-range nanos\", x)")
   906  		g.P("	case invalidNanosSign:")
   907  		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"duration (%v) has seconds and nanos with different signs\", x)")
   908  		g.P("	default:")
   909  		g.P("		return nil")
   910  		g.P("	}")
   911  		g.P("}")
   912  		g.P()
   913  
   914  		g.P("const (")
   915  		g.P("	_ = iota")
   916  		g.P("	invalidNil")
   917  		g.P("	invalidUnderflow")
   918  		g.P("	invalidOverflow")
   919  		g.P("	invalidNanosRange")
   920  		g.P("	invalidNanosSign")
   921  		g.P(")")
   922  		g.P()
   923  
   924  		g.P("func (x *Duration) check() uint {")
   925  		g.P("	const absDuration = 315576000000 // 10000yr * 365.25day/yr * 24hr/day * 60min/hr * 60sec/min")
   926  		g.P("	secs := x.GetSeconds()")
   927  		g.P("	nanos := x.GetNanos()")
   928  		g.P("	switch {")
   929  		g.P("	case x == nil:")
   930  		g.P("		return invalidNil")
   931  		g.P("	case secs < -absDuration:")
   932  		g.P("		return invalidUnderflow")
   933  		g.P("	case secs > +absDuration:")
   934  		g.P("		return invalidOverflow")
   935  		g.P("	case nanos <= -1e9 || nanos >= +1e9:")
   936  		g.P("		return invalidNanosRange")
   937  		g.P("	case (secs > 0 && nanos < 0) || (secs < 0 && nanos > 0):")
   938  		g.P("		return invalidNanosSign")
   939  		g.P("	default:")
   940  		g.P("		return 0")
   941  		g.P("	}")
   942  		g.P("}")
   943  		g.P()
   944  
   945  	case genid.Struct_message_fullname:
   946  		g.P("// NewStruct constructs a Struct from a general-purpose Go map.")
   947  		g.P("// The map keys must be valid UTF-8.")
   948  		g.P("// The map values are converted using NewValue.")
   949  		g.P("func NewStruct(v map[string]interface{}) (*Struct, error) {")
   950  		g.P("	x := &Struct{Fields: make(map[string]*Value, len(v))}")
   951  		g.P("	for k, v := range v {")
   952  		g.P("		if !", utf8Package.Ident("ValidString"), "(k) {")
   953  		g.P("			return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid UTF-8 in string: %q\", k)")
   954  		g.P("		}")
   955  		g.P("		var err error")
   956  		g.P("		x.Fields[k], err = NewValue(v)")
   957  		g.P("		if err != nil {")
   958  		g.P("			return nil, err")
   959  		g.P("		}")
   960  		g.P("	}")
   961  		g.P("	return x, nil")
   962  		g.P("}")
   963  		g.P()
   964  
   965  		g.P("// AsMap converts x to a general-purpose Go map.")
   966  		g.P("// The map values are converted by calling Value.AsInterface.")
   967  		g.P("func (x *Struct) AsMap() map[string]interface{} {")
   968  		g.P("	vs := make(map[string]interface{})")
   969  		g.P("	for k, v := range x.GetFields() {")
   970  		g.P("		vs[k] = v.AsInterface()")
   971  		g.P("	}")
   972  		g.P("	return vs")
   973  		g.P("}")
   974  		g.P()
   975  
   976  		g.P("func (x *Struct) MarshalJSON() ([]byte, error) {")
   977  		g.P("	return ", protojsonPackage.Ident("Marshal"), "(x)")
   978  		g.P("}")
   979  		g.P()
   980  
   981  		g.P("func (x *Struct) UnmarshalJSON(b []byte) error {")
   982  		g.P("	return ", protojsonPackage.Ident("Unmarshal"), "(b, x)")
   983  		g.P("}")
   984  		g.P()
   985  
   986  	case genid.ListValue_message_fullname:
   987  		g.P("// NewList constructs a ListValue from a general-purpose Go slice.")
   988  		g.P("// The slice elements are converted using NewValue.")
   989  		g.P("func NewList(v []interface{}) (*ListValue, error) {")
   990  		g.P("	x := &ListValue{Values: make([]*Value, len(v))}")
   991  		g.P("	for i, v := range v {")
   992  		g.P("		var err error")
   993  		g.P("		x.Values[i], err = NewValue(v)")
   994  		g.P("		if err != nil {")
   995  		g.P("			return nil, err")
   996  		g.P("		}")
   997  		g.P("	}")
   998  		g.P("	return x, nil")
   999  		g.P("}")
  1000  		g.P()
  1001  
  1002  		g.P("// AsSlice converts x to a general-purpose Go slice.")
  1003  		g.P("// The slice elements are converted by calling Value.AsInterface.")
  1004  		g.P("func (x *ListValue) AsSlice() []interface{} {")
  1005  		g.P("	vs := make([]interface{}, len(x.GetValues()))")
  1006  		g.P("	for i, v := range x.GetValues() {")
  1007  		g.P("		vs[i] = v.AsInterface()")
  1008  		g.P("	}")
  1009  		g.P("	return vs")
  1010  		g.P("}")
  1011  		g.P()
  1012  
  1013  		g.P("func (x *ListValue) MarshalJSON() ([]byte, error) {")
  1014  		g.P("	return ", protojsonPackage.Ident("Marshal"), "(x)")
  1015  		g.P("}")
  1016  		g.P()
  1017  
  1018  		g.P("func (x *ListValue) UnmarshalJSON(b []byte) error {")
  1019  		g.P("	return ", protojsonPackage.Ident("Unmarshal"), "(b, x)")
  1020  		g.P("}")
  1021  		g.P()
  1022  
  1023  	case genid.Value_message_fullname:
  1024  		g.P("// NewValue constructs a Value from a general-purpose Go interface.")
  1025  		g.P("//")
  1026  		g.P("//	╔════════════════════════╤════════════════════════════════════════════╗")
  1027  		g.P("//	║ Go type                │ Conversion                                 ║")
  1028  		g.P("//	╠════════════════════════╪════════════════════════════════════════════╣")
  1029  		g.P("//	║ nil                    │ stored as NullValue                        ║")
  1030  		g.P("//	║ bool                   │ stored as BoolValue                        ║")
  1031  		g.P("//	║ int, int32, int64      │ stored as NumberValue                      ║")
  1032  		g.P("//	║ uint, uint32, uint64   │ stored as NumberValue                      ║")
  1033  		g.P("//	║ float32, float64       │ stored as NumberValue                      ║")
  1034  		g.P("//	║ string                 │ stored as StringValue; must be valid UTF-8 ║")
  1035  		g.P("//	║ []byte                 │ stored as StringValue; base64-encoded      ║")
  1036  		g.P("//	║ map[string]interface{} │ stored as StructValue                      ║")
  1037  		g.P("//	║ []interface{}          │ stored as ListValue                        ║")
  1038  		g.P("//	╚════════════════════════╧════════════════════════════════════════════╝")
  1039  		g.P("//")
  1040  		g.P("// When converting an int64 or uint64 to a NumberValue, numeric precision loss")
  1041  		g.P("// is possible since they are stored as a float64.")
  1042  		g.P("func NewValue(v interface{}) (*Value, error) {")
  1043  		g.P("	switch v := v.(type) {")
  1044  		g.P("	case nil:")
  1045  		g.P("		return NewNullValue(), nil")
  1046  		g.P("	case bool:")
  1047  		g.P("		return NewBoolValue(v), nil")
  1048  		g.P("	case int:")
  1049  		g.P("		return NewNumberValue(float64(v)), nil")
  1050  		g.P("	case int32:")
  1051  		g.P("		return NewNumberValue(float64(v)), nil")
  1052  		g.P("	case int64:")
  1053  		g.P("		return NewNumberValue(float64(v)), nil")
  1054  		g.P("	case uint:")
  1055  		g.P("		return NewNumberValue(float64(v)), nil")
  1056  		g.P("	case uint32:")
  1057  		g.P("		return NewNumberValue(float64(v)), nil")
  1058  		g.P("	case uint64:")
  1059  		g.P("		return NewNumberValue(float64(v)), nil")
  1060  		g.P("	case float32:")
  1061  		g.P("		return NewNumberValue(float64(v)), nil")
  1062  		g.P("	case float64:")
  1063  		g.P("		return NewNumberValue(float64(v)), nil")
  1064  		g.P("	case string:")
  1065  		g.P("		if !", utf8Package.Ident("ValidString"), "(v) {")
  1066  		g.P("			return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid UTF-8 in string: %q\", v)")
  1067  		g.P("		}")
  1068  		g.P("		return NewStringValue(v), nil")
  1069  		g.P("	case []byte:")
  1070  		g.P("		s := ", base64Package.Ident("StdEncoding"), ".EncodeToString(v)")
  1071  		g.P("		return NewStringValue(s), nil")
  1072  		g.P("	case map[string]interface{}:")
  1073  		g.P("		v2, err := NewStruct(v)")
  1074  		g.P("		if err != nil {")
  1075  		g.P("			return nil, err")
  1076  		g.P("		}")
  1077  		g.P("		return NewStructValue(v2), nil")
  1078  		g.P("	case []interface{}:")
  1079  		g.P("		v2, err := NewList(v)")
  1080  		g.P("		if err != nil {")
  1081  		g.P("			return nil, err")
  1082  		g.P("		}")
  1083  		g.P("		return NewListValue(v2), nil")
  1084  		g.P("	default:")
  1085  		g.P("		return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid type: %T\", v)")
  1086  		g.P("	}")
  1087  		g.P("}")
  1088  		g.P()
  1089  
  1090  		g.P("// NewNullValue constructs a new null Value.")
  1091  		g.P("func NewNullValue() *Value {")
  1092  		g.P("	return &Value{Kind: &Value_NullValue{NullValue: NullValue_NULL_VALUE}}")
  1093  		g.P("}")
  1094  		g.P()
  1095  
  1096  		g.P("// NewBoolValue constructs a new boolean Value.")
  1097  		g.P("func NewBoolValue(v bool) *Value {")
  1098  		g.P("	return &Value{Kind: &Value_BoolValue{BoolValue: v}}")
  1099  		g.P("}")
  1100  		g.P()
  1101  
  1102  		g.P("// NewNumberValue constructs a new number Value.")
  1103  		g.P("func NewNumberValue(v float64) *Value {")
  1104  		g.P("	return &Value{Kind: &Value_NumberValue{NumberValue: v}}")
  1105  		g.P("}")
  1106  		g.P()
  1107  
  1108  		g.P("// NewStringValue constructs a new string Value.")
  1109  		g.P("func NewStringValue(v string) *Value {")
  1110  		g.P("	return &Value{Kind: &Value_StringValue{StringValue: v}}")
  1111  		g.P("}")
  1112  		g.P()
  1113  
  1114  		g.P("// NewStructValue constructs a new struct Value.")
  1115  		g.P("func NewStructValue(v *Struct) *Value {")
  1116  		g.P("	return &Value{Kind: &Value_StructValue{StructValue: v}}")
  1117  		g.P("}")
  1118  		g.P()
  1119  
  1120  		g.P("// NewListValue constructs a new list Value.")
  1121  		g.P("func NewListValue(v *ListValue) *Value {")
  1122  		g.P("	return &Value{Kind: &Value_ListValue{ListValue: v}}")
  1123  		g.P("}")
  1124  		g.P()
  1125  
  1126  		g.P("// AsInterface converts x to a general-purpose Go interface.")
  1127  		g.P("//")
  1128  		g.P("// Calling Value.MarshalJSON and \"encoding/json\".Marshal on this output produce")
  1129  		g.P("// semantically equivalent JSON (assuming no errors occur).")
  1130  		g.P("//")
  1131  		g.P("// Floating-point values (i.e., \"NaN\", \"Infinity\", and \"-Infinity\") are")
  1132  		g.P("// converted as strings to remain compatible with MarshalJSON.")
  1133  		g.P("func (x *Value) AsInterface() interface{} {")
  1134  		g.P("	switch v := x.GetKind().(type) {")
  1135  		g.P("	case *Value_NumberValue:")
  1136  		g.P("		if v != nil {")
  1137  		g.P("			switch {")
  1138  		g.P("			case ", mathPackage.Ident("IsNaN"), "(v.NumberValue):")
  1139  		g.P("				return \"NaN\"")
  1140  		g.P("			case ", mathPackage.Ident("IsInf"), "(v.NumberValue, +1):")
  1141  		g.P("				return \"Infinity\"")
  1142  		g.P("			case ", mathPackage.Ident("IsInf"), "(v.NumberValue, -1):")
  1143  		g.P("				return \"-Infinity\"")
  1144  		g.P("			default:")
  1145  		g.P("				return v.NumberValue")
  1146  		g.P("			}")
  1147  		g.P("		}")
  1148  		g.P("	case *Value_StringValue:")
  1149  		g.P("		if v != nil {")
  1150  		g.P("			return v.StringValue")
  1151  		g.P("		}")
  1152  		g.P("	case *Value_BoolValue:")
  1153  		g.P("		if v != nil {")
  1154  		g.P("			return v.BoolValue")
  1155  		g.P("		}")
  1156  		g.P("	case *Value_StructValue:")
  1157  		g.P("		if v != nil {")
  1158  		g.P("			return v.StructValue.AsMap()")
  1159  		g.P("		}")
  1160  		g.P("	case *Value_ListValue:")
  1161  		g.P("		if v != nil {")
  1162  		g.P("			return v.ListValue.AsSlice()")
  1163  		g.P("		}")
  1164  		g.P("	}")
  1165  		g.P("	return nil")
  1166  		g.P("}")
  1167  		g.P()
  1168  
  1169  		g.P("func (x *Value) MarshalJSON() ([]byte, error) {")
  1170  		g.P("	return ", protojsonPackage.Ident("Marshal"), "(x)")
  1171  		g.P("}")
  1172  		g.P()
  1173  
  1174  		g.P("func (x *Value) UnmarshalJSON(b []byte) error {")
  1175  		g.P("	return ", protojsonPackage.Ident("Unmarshal"), "(b, x)")
  1176  		g.P("}")
  1177  		g.P()
  1178  
  1179  	case genid.FieldMask_message_fullname:
  1180  		g.P("// New constructs a field mask from a list of paths and verifies that")
  1181  		g.P("// each one is valid according to the specified message type.")
  1182  		g.P("func New(m ", protoPackage.Ident("Message"), ", paths ...string) (*FieldMask, error) {")
  1183  		g.P("	x := new(FieldMask)")
  1184  		g.P("	return x, x.Append(m, paths...)")
  1185  		g.P("}")
  1186  		g.P()
  1187  
  1188  		g.P("// Union returns the union of all the paths in the input field masks.")
  1189  		g.P("func Union(mx *FieldMask, my *FieldMask, ms ...*FieldMask) *FieldMask {")
  1190  		g.P("	var out []string")
  1191  		g.P("	out = append(out, mx.GetPaths()...)")
  1192  		g.P("	out = append(out, my.GetPaths()...)")
  1193  		g.P("	for _, m := range ms {")
  1194  		g.P("		out = append(out, m.GetPaths()...)")
  1195  		g.P("	}")
  1196  		g.P("	return &FieldMask{Paths: normalizePaths(out)}")
  1197  		g.P("}")
  1198  		g.P()
  1199  
  1200  		g.P("// Intersect returns the intersection of all the paths in the input field masks.")
  1201  		g.P("func Intersect(mx *FieldMask, my *FieldMask, ms ...*FieldMask) *FieldMask {")
  1202  		g.P("	var ss1, ss2 []string // reused buffers for performance")
  1203  		g.P("	intersect := func(out, in []string) []string {")
  1204  		g.P("		ss1 = normalizePaths(append(ss1[:0], in...))")
  1205  		g.P("		ss2 = normalizePaths(append(ss2[:0], out...))")
  1206  		g.P("		out = out[:0]")
  1207  		g.P("		for i1, i2 := 0, 0; i1 < len(ss1) && i2 < len(ss2); {")
  1208  		g.P("			switch s1, s2 := ss1[i1], ss2[i2]; {")
  1209  		g.P("			case hasPathPrefix(s1, s2):")
  1210  		g.P("				out = append(out, s1)")
  1211  		g.P("				i1++")
  1212  		g.P("			case hasPathPrefix(s2, s1):")
  1213  		g.P("				out = append(out, s2)")
  1214  		g.P("				i2++")
  1215  		g.P("			case lessPath(s1, s2):")
  1216  		g.P("				i1++")
  1217  		g.P("			case lessPath(s2, s1):")
  1218  		g.P("				i2++")
  1219  		g.P("			}")
  1220  		g.P("		}")
  1221  		g.P("		return out")
  1222  		g.P("	}")
  1223  		g.P()
  1224  		g.P("	out := Union(mx, my, ms...).GetPaths()")
  1225  		g.P("	out = intersect(out, mx.GetPaths())")
  1226  		g.P("	out = intersect(out, my.GetPaths())")
  1227  		g.P("	for _, m := range ms {")
  1228  		g.P("		out = intersect(out, m.GetPaths())")
  1229  		g.P("	}")
  1230  		g.P("	return &FieldMask{Paths: normalizePaths(out)}")
  1231  		g.P("}")
  1232  		g.P()
  1233  
  1234  		g.P("// IsValid reports whether all the paths are syntactically valid and")
  1235  		g.P("// refer to known fields in the specified message type.")
  1236  		g.P("// It reports false for a nil FieldMask.")
  1237  		g.P("func (x *FieldMask) IsValid(m ", protoPackage.Ident("Message"), ") bool {")
  1238  		g.P("	paths := x.GetPaths()")
  1239  		g.P("	return x != nil && numValidPaths(m, paths) == len(paths)")
  1240  		g.P("}")
  1241  		g.P()
  1242  
  1243  		g.P("// Append appends a list of paths to the mask and verifies that each one")
  1244  		g.P("// is valid according to the specified message type.")
  1245  		g.P("// An invalid path is not appended and breaks insertion of subsequent paths.")
  1246  		g.P("func (x *FieldMask) Append(m ", protoPackage.Ident("Message"), ", paths ...string) error {")
  1247  		g.P("	numValid := numValidPaths(m, paths)")
  1248  		g.P("	x.Paths = append(x.Paths, paths[:numValid]...)")
  1249  		g.P("	paths = paths[numValid:]")
  1250  		g.P("	if len(paths) > 0 {")
  1251  		g.P("		name := m.ProtoReflect().Descriptor().FullName()")
  1252  		g.P("		return ", protoimplPackage.Ident("X"), ".NewError(\"invalid path %q for message %q\", paths[0], name)")
  1253  		g.P("	}")
  1254  		g.P("	return nil")
  1255  		g.P("}")
  1256  		g.P()
  1257  
  1258  		g.P("func numValidPaths(m ", protoPackage.Ident("Message"), ", paths []string) int {")
  1259  		g.P("	md0 := m.ProtoReflect().Descriptor()")
  1260  		g.P("	for i, path := range paths {")
  1261  		g.P("		md := md0")
  1262  		g.P("		if !rangeFields(path, func(field string) bool {")
  1263  		g.P("			// Search the field within the message.")
  1264  		g.P("			if md == nil {")
  1265  		g.P("				return false // not within a message")
  1266  		g.P("			}")
  1267  		g.P("			fd := md.Fields().ByName(", protoreflectPackage.Ident("Name"), "(field))")
  1268  		g.P("			// The real field name of a group is the message name.")
  1269  		g.P("			if fd == nil {")
  1270  		g.P("				gd := md.Fields().ByName(", protoreflectPackage.Ident("Name"), "(", stringsPackage.Ident("ToLower"), "(field)))")
  1271  		g.P("				if gd != nil && gd.Kind() == ", protoreflectPackage.Ident("GroupKind"), " && string(gd.Message().Name()) == field {")
  1272  		g.P("					fd = gd")
  1273  		g.P("				}")
  1274  		g.P("			} else if fd.Kind() == ", protoreflectPackage.Ident("GroupKind"), " && string(fd.Message().Name()) != field {")
  1275  		g.P("				fd = nil")
  1276  		g.P("			}")
  1277  		g.P("			if fd == nil {")
  1278  		g.P("				return false // message has does not have this field")
  1279  		g.P("			}")
  1280  		g.P()
  1281  		g.P("			// Identify the next message to search within.")
  1282  		g.P("			md = fd.Message() // may be nil")
  1283  		g.P()
  1284  		g.P("			// Repeated fields are only allowed at the last postion.")
  1285  		g.P("			if fd.IsList() || fd.IsMap() {")
  1286  		g.P("				md = nil")
  1287  		g.P("			}")
  1288  		g.P()
  1289  		g.P("			return true")
  1290  		g.P("		}) {")
  1291  		g.P("			return i")
  1292  		g.P("		}")
  1293  		g.P("	}")
  1294  		g.P("	return len(paths)")
  1295  		g.P("}")
  1296  		g.P()
  1297  
  1298  		g.P("// Normalize converts the mask to its canonical form where all paths are sorted")
  1299  		g.P("// and redundant paths are removed.")
  1300  		g.P("func (x *FieldMask) Normalize() {")
  1301  		g.P("	x.Paths = normalizePaths(x.Paths)")
  1302  		g.P("}")
  1303  		g.P()
  1304  		g.P("func normalizePaths(paths []string) []string {")
  1305  		g.P("	", sortPackage.Ident("Slice"), "(paths, func(i, j int) bool {")
  1306  		g.P("		return lessPath(paths[i], paths[j])")
  1307  		g.P("	})")
  1308  		g.P()
  1309  		g.P("	// Elide any path that is a prefix match on the previous.")
  1310  		g.P("	out := paths[:0]")
  1311  		g.P("	for _, path := range paths {")
  1312  		g.P("		if len(out) > 0 && hasPathPrefix(path, out[len(out)-1]) {")
  1313  		g.P("			continue")
  1314  		g.P("		}")
  1315  		g.P("		out = append(out, path)")
  1316  		g.P("	}")
  1317  		g.P("	return out")
  1318  		g.P("}")
  1319  		g.P()
  1320  
  1321  		g.P("// hasPathPrefix is like strings.HasPrefix, but further checks for either")
  1322  		g.P("// an exact matche or that the prefix is delimited by a dot.")
  1323  		g.P("func hasPathPrefix(path, prefix string) bool {")
  1324  		g.P("	return ", stringsPackage.Ident("HasPrefix"), "(path, prefix) && (len(path) == len(prefix) || path[len(prefix)] == '.')")
  1325  		g.P("}")
  1326  		g.P()
  1327  
  1328  		g.P("// lessPath is a lexicographical comparison where dot is specially treated")
  1329  		g.P("// as the smallest symbol.")
  1330  		g.P("func lessPath(x, y string) bool {")
  1331  		g.P("	for i := 0; i < len(x) && i < len(y); i++ {")
  1332  		g.P("		if x[i] != y[i] {")
  1333  		g.P("			return (x[i] - '.') < (y[i] - '.')")
  1334  		g.P("		}")
  1335  		g.P("	}")
  1336  		g.P("	return len(x) < len(y)")
  1337  		g.P("}")
  1338  		g.P()
  1339  
  1340  		g.P("// rangeFields is like strings.Split(path, \".\"), but avoids allocations by")
  1341  		g.P("// iterating over each field in place and calling a iterator function.")
  1342  		g.P("func rangeFields(path string, f func(field string) bool) bool {")
  1343  		g.P("	for {")
  1344  		g.P("		var field string")
  1345  		g.P("		if i := ", stringsPackage.Ident("IndexByte"), "(path, '.'); i >= 0 {")
  1346  		g.P("			field, path = path[:i], path[i:]")
  1347  		g.P("		} else {")
  1348  		g.P("			field, path = path, \"\"")
  1349  		g.P("		}")
  1350  		g.P()
  1351  		g.P("		if !f(field) {")
  1352  		g.P("			return false")
  1353  		g.P("		}")
  1354  		g.P()
  1355  		g.P("		if len(path) == 0 {")
  1356  		g.P("			return true")
  1357  		g.P("		}")
  1358  		g.P("		path = ", stringsPackage.Ident("TrimPrefix"), "(path, \".\")")
  1359  		g.P("	}")
  1360  		g.P("}")
  1361  		g.P()
  1362  
  1363  	case genid.BoolValue_message_fullname,
  1364  		genid.Int32Value_message_fullname,
  1365  		genid.Int64Value_message_fullname,
  1366  		genid.UInt32Value_message_fullname,
  1367  		genid.UInt64Value_message_fullname,
  1368  		genid.FloatValue_message_fullname,
  1369  		genid.DoubleValue_message_fullname,
  1370  		genid.StringValue_message_fullname,
  1371  		genid.BytesValue_message_fullname:
  1372  		funcName := strings.TrimSuffix(m.GoIdent.GoName, "Value")
  1373  		typeName := strings.ToLower(funcName)
  1374  		switch typeName {
  1375  		case "float":
  1376  			typeName = "float32"
  1377  		case "double":
  1378  			typeName = "float64"
  1379  		case "bytes":
  1380  			typeName = "[]byte"
  1381  		}
  1382  
  1383  		g.P("// ", funcName, " stores v in a new ", m.GoIdent, " and returns a pointer to it.")
  1384  		g.P("func ", funcName, "(v ", typeName, ") *", m.GoIdent, " {")
  1385  		g.P("	return &", m.GoIdent, "{Value: v}")
  1386  		g.P("}")
  1387  		g.P()
  1388  	}
  1389  }
  1390  
  1391  func genMessageFields(g *generator.GeneratedFile, f *fileInfo, m *messageInfo) {
  1392  	sf := f.allMessageFieldsByPtr[m]
  1393  	genMessageInternalFields(g, f, m, sf)
  1394  	for _, field := range m.Fields {
  1395  		genMessageField(g, f, m, field, sf)
  1396  	}
  1397  }
  1398  
  1399  func genMessageInternalFields(g *generator.GeneratedFile, f *fileInfo, m *messageInfo, sf *structFields) {
  1400  	g.P(genid.State_goname, " ", protoimplPackage.Ident("MessageState"))
  1401  	sf.append(genid.State_goname)
  1402  	g.P(genid.SizeCache_goname, " ", protoimplPackage.Ident("SizeCache"))
  1403  	sf.append(genid.SizeCache_goname)
  1404  	if m.hasWeak {
  1405  		g.P(genid.WeakFields_goname, " ", protoimplPackage.Ident("WeakFields"))
  1406  		sf.append(genid.WeakFields_goname)
  1407  	}
  1408  	g.P(genid.UnknownFields_goname, " ", protoimplPackage.Ident("UnknownFields"))
  1409  	sf.append(genid.UnknownFields_goname)
  1410  	if m.Desc.ExtensionRanges().Len() > 0 {
  1411  		g.P(genid.ExtensionFields_goname, " ", protoimplPackage.Ident("ExtensionFields"))
  1412  		sf.append(genid.ExtensionFields_goname)
  1413  	}
  1414  	if sf.count > 0 {
  1415  		g.P()
  1416  	}
  1417  }
  1418  
  1419  func genMessageField(g *generator.GeneratedFile, f *fileInfo, m *messageInfo, field *protogen.Field, sf *structFields) {
  1420  	if oneof := field.Oneof; oneof != nil && !oneof.Desc.IsSynthetic() {
  1421  		// It would be a bit simpler to iterate over the oneofs below,
  1422  		// but generating the field here keeps the contents of the Go
  1423  		// struct in the same order as the contents of the source
  1424  		// .proto file.
  1425  		if oneof.Fields[0] != field {
  1426  			return // only generate for first appearance
  1427  		}
  1428  
  1429  		tags := structTags{
  1430  			{"protobuf_oneof", string(oneof.Desc.Name())},
  1431  		}
  1432  		if m.isTracked {
  1433  			tags = append(tags, gotrackTags...)
  1434  		}
  1435  
  1436  		g.Annotate(m.GoIdent.GoName+"."+oneof.GoName, oneof.Location)
  1437  		leadingComments := oneof.Comments.Leading
  1438  		if leadingComments != "" {
  1439  			leadingComments += "\n"
  1440  		}
  1441  		ss := []string{fmt.Sprintf(" Types that are assignable to %s:\n", oneof.GoName)}
  1442  		for _, field := range oneof.Fields {
  1443  			ss = append(ss, "\t*"+field.GoIdent.GoName+"\n")
  1444  		}
  1445  		leadingComments += protogen.Comments(strings.Join(ss, ""))
  1446  		g.P(leadingComments,
  1447  			oneof.GoName, " ", oneofInterfaceName(oneof), tags)
  1448  		sf.append(oneof.GoName)
  1449  		return
  1450  	}
  1451  	goType, pointer := fieldGoType(g, f, field)
  1452  	if pointer {
  1453  		goType = "*" + goType
  1454  	}
  1455  	tags := structTags{
  1456  		{"protobuf", fieldProtobufTagValue(field)},
  1457  		{"json", fieldJSONTagValue(field)},
  1458  	}
  1459  	if field.Desc.IsMap() {
  1460  		key := field.Message.Fields[0]
  1461  		val := field.Message.Fields[1]
  1462  		tags = append(tags, structTags{
  1463  			{"protobuf_key", fieldProtobufTagValue(key)},
  1464  			{"protobuf_val", fieldProtobufTagValue(val)},
  1465  		}...)
  1466  	}
  1467  	if m.isTracked {
  1468  		tags = append(tags, gotrackTags...)
  1469  	}
  1470  
  1471  	name := field.GoName
  1472  	if field.Desc.IsWeak() {
  1473  		name = genid.WeakFieldPrefix_goname + name
  1474  	}
  1475  	g.Annotate(m.GoIdent.GoName+"."+name, field.Location)
  1476  	leadingComments := appendDeprecationSuffix(field.Comments.Leading,
  1477  		field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
  1478  	g.P(leadingComments,
  1479  		name, " ", goType, tags,
  1480  		trailingComment(field.Comments.Trailing))
  1481  	sf.append(field.GoName)
  1482  }
  1483  
  1484  // genMessageDefaultDecls generates consts and vars holding the default
  1485  // values of fields.
  1486  func genMessageDefaultDecls(g *generator.GeneratedFile, f *fileInfo, m *messageInfo) {
  1487  	var consts, vars []string
  1488  	for _, field := range m.Fields {
  1489  		if !field.Desc.HasDefault() {
  1490  			continue
  1491  		}
  1492  		name := "Default_" + m.GoIdent.GoName + "_" + field.GoName
  1493  		goType, _ := fieldGoType(g, f, field)
  1494  		defVal := field.Desc.Default()
  1495  		switch field.Desc.Kind() {
  1496  		case protoreflect.StringKind:
  1497  			consts = append(consts, fmt.Sprintf("%s = %s(%q)", name, goType, defVal.String()))
  1498  		case protoreflect.BytesKind:
  1499  			vars = append(vars, fmt.Sprintf("%s = %s(%q)", name, goType, defVal.Bytes()))
  1500  		case protoreflect.EnumKind:
  1501  			idx := field.Desc.DefaultEnumValue().Index()
  1502  			val := field.Enum.Values[idx]
  1503  			if val.GoIdent.GoImportPath == f.GoImportPath {
  1504  				consts = append(consts, fmt.Sprintf("%s = %s", name, g.QualifiedGoIdent(val.GoIdent)))
  1505  			} else {
  1506  				// If the enum value is declared in a different Go package,
  1507  				// reference it by number since the name may not be correct.
  1508  				// See https://github.com/golang/protobuf/issues/513.
  1509  				consts = append(consts, fmt.Sprintf("%s = %s(%d) // %s",
  1510  					name, g.QualifiedGoIdent(field.Enum.GoIdent), val.Desc.Number(), g.QualifiedGoIdent(val.GoIdent)))
  1511  			}
  1512  		case protoreflect.FloatKind, protoreflect.DoubleKind:
  1513  			if f := defVal.Float(); math.IsNaN(f) || math.IsInf(f, 0) {
  1514  				var fn, arg string
  1515  				switch f := defVal.Float(); {
  1516  				case math.IsInf(f, -1):
  1517  					fn, arg = g.QualifiedGoIdent(mathPackage.Ident("Inf")), "-1"
  1518  				case math.IsInf(f, +1):
  1519  					fn, arg = g.QualifiedGoIdent(mathPackage.Ident("Inf")), "+1"
  1520  				case math.IsNaN(f):
  1521  					fn, arg = g.QualifiedGoIdent(mathPackage.Ident("NaN")), ""
  1522  				}
  1523  				vars = append(vars, fmt.Sprintf("%s = %s(%s(%s))", name, goType, fn, arg))
  1524  			} else {
  1525  				consts = append(consts, fmt.Sprintf("%s = %s(%v)", name, goType, f))
  1526  			}
  1527  		default:
  1528  			consts = append(consts, fmt.Sprintf("%s = %s(%v)", name, goType, defVal.Interface()))
  1529  		}
  1530  	}
  1531  	if len(consts) > 0 {
  1532  		g.P("// Default values for ", m.GoIdent, " fields.")
  1533  		g.P("const (")
  1534  		for _, s := range consts {
  1535  			g.P(s)
  1536  		}
  1537  		g.P(")")
  1538  	}
  1539  	if len(vars) > 0 {
  1540  		g.P("// Default values for ", m.GoIdent, " fields.")
  1541  		g.P("var (")
  1542  		for _, s := range vars {
  1543  			g.P(s)
  1544  		}
  1545  		g.P(")")
  1546  	}
  1547  	g.P()
  1548  }
  1549  
  1550  func genMessageMethods(g *generator.GeneratedFile, f *fileInfo, m *messageInfo) {
  1551  	genMessageBaseMethods(g, f, m)
  1552  	genMessageGetterMethods(g, f, m)
  1553  	genMessageSetterMethods(g, f, m)
  1554  }
  1555  
  1556  func genMessageBaseMethods(g *generator.GeneratedFile, f *fileInfo, m *messageInfo) {
  1557  	// Reset method.
  1558  	g.P("func (x *", m.GoIdent, ") Reset() {")
  1559  	g.P("*x = ", m.GoIdent, "{}")
  1560  	g.P("if ", protoimplPackage.Ident("UnsafeEnabled"), " {")
  1561  	g.P("mi := &", messageTypesVarName(f), "[", f.allMessagesByPtr[m], "]")
  1562  	g.P("ms := ", protoimplPackage.Ident("X"), ".MessageStateOf(", protoimplPackage.Ident("Pointer"), "(x))")
  1563  	g.P("ms.StoreMessageInfo(mi)")
  1564  	g.P("}")
  1565  	g.P("}")
  1566  	g.P()
  1567  
  1568  	// String method.
  1569  	g.P("func (x *", m.GoIdent, ") String() string {")
  1570  	g.P("return ", protoimplPackage.Ident("X"), ".MessageStringOf(x)")
  1571  	g.P("}")
  1572  	g.P()
  1573  
  1574  	// ProtoMessage method.
  1575  	g.P("func (*", m.GoIdent, ") ProtoMessage() {}")
  1576  	g.P()
  1577  
  1578  	// ProtoReflect method.
  1579  	genMessageReflectMethods(g, f, m)
  1580  
  1581  	// Descriptor method.
  1582  	if m.genRawDescMethod {
  1583  		var indexes []string
  1584  		for i := 1; i < len(m.Location.Path); i += 2 {
  1585  			indexes = append(indexes, strconv.Itoa(int(m.Location.Path[i])))
  1586  		}
  1587  		g.P("// Deprecated: Use ", m.GoIdent, ".ProtoReflect.Descriptor instead.")
  1588  		g.P("func (*", m.GoIdent, ") Descriptor() ([]byte, []int) {")
  1589  		g.P("return ", rawDescVarName(f), "GZIP(), []int{", strings.Join(indexes, ","), "}")
  1590  		g.P("}")
  1591  		g.P()
  1592  		f.needRawDesc = true
  1593  	}
  1594  }
  1595  
  1596  func genMessageGetterMethods(g *generator.GeneratedFile, f *fileInfo, m *messageInfo) {
  1597  	for _, field := range m.Fields {
  1598  		genNoInterfacePragma(g, m.isTracked)
  1599  
  1600  		// Getter for parent oneof.
  1601  		if oneof := field.Oneof; oneof != nil && oneof.Fields[0] == field && !oneof.Desc.IsSynthetic() {
  1602  			g.Annotate(m.GoIdent.GoName+".Get"+oneof.GoName, oneof.Location)
  1603  			g.P("func (x *", m.GoIdent.GoName, ") Get", oneof.GoName, "() ", oneofInterfaceName(oneof), " {")
  1604  			g.P("if x != nil {")
  1605  			g.P("return x.", oneof.GoName)
  1606  			g.P("}")
  1607  			g.P("return nil")
  1608  			g.P("}")
  1609  			g.P()
  1610  		}
  1611  
  1612  		// Getter for message field.
  1613  		goType, pointer := fieldGoType(g, f, field)
  1614  		defaultValue := fieldDefaultValue(g, f, m, field)
  1615  		g.Annotate(m.GoIdent.GoName+".Get"+field.GoName, field.Location)
  1616  		leadingComments := appendDeprecationSuffix("",
  1617  			field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
  1618  		switch {
  1619  		case field.Desc.IsWeak():
  1620  			g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", protoPackage.Ident("Message"), "{")
  1621  			g.P("var w ", protoimplPackage.Ident("WeakFields"))
  1622  			g.P("if x != nil {")
  1623  			g.P("w = x.", genid.WeakFields_goname)
  1624  			if m.isTracked {
  1625  				g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName)
  1626  			}
  1627  			g.P("}")
  1628  			g.P("return ", protoimplPackage.Ident("X"), ".GetWeak(w, ", field.Desc.Number(), ", ", strconv.Quote(string(field.Message.Desc.FullName())), ")")
  1629  			g.P("}")
  1630  		case field.Oneof != nil && !field.Oneof.Desc.IsSynthetic():
  1631  			g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", goType, " {")
  1632  			g.P("if x, ok := x.Get", field.Oneof.GoName, "().(*", field.GoIdent, "); ok {")
  1633  			g.P("return x.", field.GoName)
  1634  			g.P("}")
  1635  			g.P("return ", defaultValue)
  1636  			g.P("}")
  1637  		default:
  1638  			g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", goType, " {")
  1639  			if !field.Desc.HasPresence() || defaultValue == "nil" {
  1640  				g.P("if x != nil {")
  1641  			} else {
  1642  				g.P("if x != nil && x.", field.GoName, " != nil {")
  1643  			}
  1644  			star := ""
  1645  			if pointer {
  1646  				star = "*"
  1647  			}
  1648  			g.P("return ", star, " x.", field.GoName)
  1649  			g.P("}")
  1650  			g.P("return ", defaultValue)
  1651  			g.P("}")
  1652  		}
  1653  		g.P()
  1654  	}
  1655  }
  1656  
  1657  func genMessageSetterMethods(g *generator.GeneratedFile, f *fileInfo, m *messageInfo) {
  1658  	for _, field := range m.Fields {
  1659  		if !field.Desc.IsWeak() {
  1660  			continue
  1661  		}
  1662  
  1663  		genNoInterfacePragma(g, m.isTracked)
  1664  
  1665  		g.Annotate(m.GoIdent.GoName+".Set"+field.GoName, field.Location)
  1666  		leadingComments := appendDeprecationSuffix("",
  1667  			field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
  1668  		g.P(leadingComments, "func (x *", m.GoIdent, ") Set", field.GoName, "(v ", protoPackage.Ident("Message"), ") {")
  1669  		g.P("var w *", protoimplPackage.Ident("WeakFields"))
  1670  		g.P("if x != nil {")
  1671  		g.P("w = &x.", genid.WeakFields_goname)
  1672  		if m.isTracked {
  1673  			g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName)
  1674  		}
  1675  		g.P("}")
  1676  		g.P(protoimplPackage.Ident("X"), ".SetWeak(w, ", field.Desc.Number(), ", ", strconv.Quote(string(field.Message.Desc.FullName())), ", v)")
  1677  		g.P("}")
  1678  		g.P()
  1679  	}
  1680  }
  1681  
  1682  // fieldGoType returns the Go type used for a field.
  1683  //
  1684  // If it returns pointer=true, the struct field is a pointer to the type.
  1685  func fieldGoType(g *generator.GeneratedFile, f *fileInfo, field *protogen.Field) (goType string, pointer bool) {
  1686  	if field.Desc.IsWeak() {
  1687  		return "struct{}", false
  1688  	}
  1689  
  1690  	pointer = field.Desc.HasPresence()
  1691  	switch field.Desc.Kind() {
  1692  	case protoreflect.BoolKind:
  1693  		goType = "bool"
  1694  	case protoreflect.EnumKind:
  1695  		goType = g.QualifiedGoIdent(field.Enum.GoIdent)
  1696  	case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
  1697  		goType = "int32"
  1698  	case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
  1699  		goType = "uint32"
  1700  	case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
  1701  		goType = "int64"
  1702  	case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
  1703  		goType = "uint64"
  1704  	case protoreflect.FloatKind:
  1705  		goType = "float32"
  1706  	case protoreflect.DoubleKind:
  1707  		goType = "float64"
  1708  	case protoreflect.StringKind:
  1709  		goType = "string"
  1710  	case protoreflect.BytesKind:
  1711  		goType = "[]byte"
  1712  		pointer = false // rely on nullability of slices for presence
  1713  	case protoreflect.MessageKind, protoreflect.GroupKind:
  1714  		goType = "*" + g.QualifiedGoIdent(field.Message.GoIdent)
  1715  		pointer = false // pointer captured as part of the type
  1716  	}
  1717  	switch {
  1718  	case field.Desc.IsList():
  1719  		return "[]" + goType, false
  1720  	case field.Desc.IsMap():
  1721  		keyType, _ := fieldGoType(g, f, field.Message.Fields[0])
  1722  		valType, _ := fieldGoType(g, f, field.Message.Fields[1])
  1723  		return fmt.Sprintf("map[%v]%v", keyType, valType), false
  1724  	}
  1725  	return goType, pointer
  1726  }
  1727  
  1728  func fieldProtobufTagValue(field *protogen.Field) string {
  1729  	var enumName string
  1730  	if field.Desc.Kind() == protoreflect.EnumKind {
  1731  		enumName = protoimpl.X.LegacyEnumName(field.Enum.Desc)
  1732  	}
  1733  	return TagMarshal(field.Desc, enumName)
  1734  }
  1735  
  1736  func fieldDefaultValue(g *generator.GeneratedFile, f *fileInfo, m *messageInfo, field *protogen.Field) string {
  1737  	if field.Desc.IsList() {
  1738  		return "nil"
  1739  	}
  1740  	if field.Desc.HasDefault() {
  1741  		defVarName := "Default_" + m.GoIdent.GoName + "_" + field.GoName
  1742  		if field.Desc.Kind() == protoreflect.BytesKind {
  1743  			return "append([]byte(nil), " + defVarName + "...)"
  1744  		}
  1745  		return defVarName
  1746  	}
  1747  	switch field.Desc.Kind() {
  1748  	case protoreflect.BoolKind:
  1749  		return "false"
  1750  	case protoreflect.StringKind:
  1751  		return `""`
  1752  	case protoreflect.MessageKind, protoreflect.GroupKind, protoreflect.BytesKind:
  1753  		return "nil"
  1754  	case protoreflect.EnumKind:
  1755  		val := field.Enum.Values[0]
  1756  		if val.GoIdent.GoImportPath == f.GoImportPath {
  1757  			return g.QualifiedGoIdent(val.GoIdent)
  1758  		} else {
  1759  			// If the enum value is declared in a different Go package,
  1760  			// reference it by number since the name may not be correct.
  1761  			// See https://github.com/golang/protobuf/issues/513.
  1762  			return g.QualifiedGoIdent(field.Enum.GoIdent) + "(" + strconv.FormatInt(int64(val.Desc.Number()), 10) + ")"
  1763  		}
  1764  	default:
  1765  		return "0"
  1766  	}
  1767  }
  1768  
  1769  func fieldJSONTagValue(field *protogen.Field) string {
  1770  	return string(field.Desc.Name()) + ",omitempty"
  1771  }
  1772  
  1773  func genExtensions(g *generator.GeneratedFile, f *fileInfo) {
  1774  	if len(f.allExtensions) == 0 {
  1775  		return
  1776  	}
  1777  
  1778  	g.P("var ", extensionTypesVarName(f), " = []", protoimplPackage.Ident("ExtensionInfo"), "{")
  1779  	for _, x := range f.allExtensions {
  1780  		g.P("{")
  1781  		g.P("ExtendedType: (*", x.Extendee.GoIdent, ")(nil),")
  1782  		goType, pointer := fieldGoType(g, f, x.Extension)
  1783  		if pointer {
  1784  			goType = "*" + goType
  1785  		}
  1786  		g.P("ExtensionType: (", goType, ")(nil),")
  1787  		g.P("Field: ", x.Desc.Number(), ",")
  1788  		g.P("Name: ", strconv.Quote(string(x.Desc.FullName())), ",")
  1789  		g.P("Tag: ", strconv.Quote(fieldProtobufTagValue(x.Extension)), ",")
  1790  		g.P("Filename: ", strconv.Quote(f.Desc.Path()), ",")
  1791  		g.P("},")
  1792  	}
  1793  	g.P("}")
  1794  	g.P()
  1795  
  1796  	// Group extensions by the target message.
  1797  	var orderedTargets []protogen.GoIdent
  1798  	allExtensionsByTarget := make(map[protogen.GoIdent][]*extensionInfo)
  1799  	allExtensionsByPtr := make(map[*extensionInfo]int)
  1800  	for i, x := range f.allExtensions {
  1801  		target := x.Extendee.GoIdent
  1802  		if len(allExtensionsByTarget[target]) == 0 {
  1803  			orderedTargets = append(orderedTargets, target)
  1804  		}
  1805  		allExtensionsByTarget[target] = append(allExtensionsByTarget[target], x)
  1806  		allExtensionsByPtr[x] = i
  1807  	}
  1808  	for _, target := range orderedTargets {
  1809  		g.P("// Extension fields to ", target, ".")
  1810  		g.P("var (")
  1811  		for _, x := range allExtensionsByTarget[target] {
  1812  			xd := x.Desc
  1813  			typeName := xd.Kind().String()
  1814  			switch xd.Kind() {
  1815  			case protoreflect.EnumKind:
  1816  				typeName = string(xd.Enum().FullName())
  1817  			case protoreflect.MessageKind, protoreflect.GroupKind:
  1818  				typeName = string(xd.Message().FullName())
  1819  			}
  1820  			fieldName := string(xd.Name())
  1821  
  1822  			leadingComments := x.Comments.Leading
  1823  			if leadingComments != "" {
  1824  				leadingComments += "\n"
  1825  			}
  1826  			leadingComments += protogen.Comments(fmt.Sprintf(" %v %v %v = %v;\n",
  1827  				xd.Cardinality(), typeName, fieldName, xd.Number()))
  1828  			leadingComments = appendDeprecationSuffix(leadingComments,
  1829  				x.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
  1830  			g.P(leadingComments,
  1831  				"E_", x.GoIdent, " = &", extensionTypesVarName(f), "[", allExtensionsByPtr[x], "]",
  1832  				trailingComment(x.Comments.Trailing))
  1833  		}
  1834  		g.P(")")
  1835  		g.P()
  1836  	}
  1837  }
  1838  
  1839  // genMessageOneofWrapperTypes generates the oneof wrapper types and
  1840  // associates the types with the parent message type.
  1841  func genMessageOneofWrapperTypes(g *generator.GeneratedFile, f *fileInfo, m *messageInfo) {
  1842  	for _, oneof := range m.Oneofs {
  1843  		if oneof.Desc.IsSynthetic() {
  1844  			continue
  1845  		}
  1846  		ifName := oneofInterfaceName(oneof)
  1847  		g.P("type ", ifName, " interface {")
  1848  		g.P(ifName, "()")
  1849  		g.P("}")
  1850  		g.P()
  1851  		for _, field := range oneof.Fields {
  1852  			g.Annotate(field.GoIdent.GoName, field.Location)
  1853  			g.Annotate(field.GoIdent.GoName+"."+field.GoName, field.Location)
  1854  			g.P("type ", field.GoIdent, " struct {")
  1855  			goType, _ := fieldGoType(g, f, field)
  1856  			tags := structTags{
  1857  				{"protobuf", fieldProtobufTagValue(field)},
  1858  			}
  1859  			if m.isTracked {
  1860  				tags = append(tags, gotrackTags...)
  1861  			}
  1862  			leadingComments := appendDeprecationSuffix(field.Comments.Leading,
  1863  				field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
  1864  			g.P(leadingComments,
  1865  				field.GoName, " ", goType, tags,
  1866  				trailingComment(field.Comments.Trailing))
  1867  			g.P("}")
  1868  			g.P()
  1869  		}
  1870  		for _, field := range oneof.Fields {
  1871  			g.P("func (*", field.GoIdent, ") ", ifName, "() {}")
  1872  			g.P()
  1873  		}
  1874  	}
  1875  }
  1876  
  1877  // oneofInterfaceName returns the name of the interface type implemented by
  1878  // the oneof field value types.
  1879  func oneofInterfaceName(oneof *protogen.Oneof) string {
  1880  	return "is" + oneof.GoIdent.GoName
  1881  }
  1882  
  1883  // genNoInterfacePragma generates a standalone "nointerface" pragma to
  1884  // decorate methods with field-tracking support.
  1885  func genNoInterfacePragma(g *generator.GeneratedFile, tracked bool) {
  1886  	if tracked {
  1887  		g.P("//go:nointerface")
  1888  		g.P()
  1889  	}
  1890  }
  1891  
  1892  var gotrackTags = structTags{{"go", "track"}}
  1893  
  1894  // structTags is a data structure for build idiomatic Go struct tags.
  1895  // Each [2]string is a key-value pair, where value is the unescaped string.
  1896  //
  1897  // Example: structTags{{"key", "value"}}.String() -> `key:"value"`
  1898  type structTags [][2]string
  1899  
  1900  func (tags structTags) String() string {
  1901  	if len(tags) == 0 {
  1902  		return ""
  1903  	}
  1904  	var ss []string
  1905  	for _, tag := range tags {
  1906  		// NOTE: When quoting the value, we need to make sure the backtick
  1907  		// character does not appear. Convert all cases to the escaped hex form.
  1908  		key := tag[0]
  1909  		val := strings.Replace(strconv.Quote(tag[1]), "`", `\x60`, -1)
  1910  		ss = append(ss, fmt.Sprintf("%s:%s", key, val))
  1911  	}
  1912  	return "`" + strings.Join(ss, " ") + "`"
  1913  }
  1914  
  1915  // appendDeprecationSuffix optionally appends a deprecation notice as a suffix.
  1916  func appendDeprecationSuffix(prefix protogen.Comments, deprecated bool) protogen.Comments {
  1917  	if !deprecated {
  1918  		return prefix
  1919  	}
  1920  	if prefix != "" {
  1921  		prefix += "\n"
  1922  	}
  1923  	return prefix + " Deprecated: Do not use.\n"
  1924  }
  1925  
  1926  // trailingComment is like protogen.Comments, but lacks a trailing newline.
  1927  type trailingComment protogen.Comments
  1928  
  1929  func (c trailingComment) String() string {
  1930  	s := strings.TrimSuffix(protogen.Comments(c).String(), "\n")
  1931  	if strings.Contains(s, "\n") {
  1932  		// We don't support multi-lined trailing comments as it is unclear
  1933  		// how to best render them in the generated code.
  1934  		return ""
  1935  	}
  1936  	return s
  1937  }
  1938  
  1939  // TagMarshal encodes the protoreflect.FieldDescriptor as a tag.
  1940  //
  1941  // The enumName must be provided if the kind is an enum.
  1942  // Historically, the formulation of the enum "name" was the proto package
  1943  // dot-concatenated with the generated Go identifier for the enum type.
  1944  // Depending on the context on how Marshal is called, there are different ways
  1945  // through which that information is determined. As such it is the caller's
  1946  // responsibility to provide a function to obtain that information.
  1947  func TagMarshal(fd pref.FieldDescriptor, enumName string) string {
  1948  	var tag []string
  1949  	switch fd.Kind() {
  1950  	case pref.BoolKind, pref.EnumKind, pref.Int32Kind, pref.Uint32Kind, pref.Int64Kind, pref.Uint64Kind:
  1951  		tag = append(tag, "varint")
  1952  	case pref.Sint32Kind:
  1953  		tag = append(tag, "zigzag32")
  1954  	case pref.Sint64Kind:
  1955  		tag = append(tag, "zigzag64")
  1956  	case pref.Sfixed32Kind, pref.Fixed32Kind, pref.FloatKind:
  1957  		tag = append(tag, "fixed32")
  1958  	case pref.Sfixed64Kind, pref.Fixed64Kind, pref.DoubleKind:
  1959  		tag = append(tag, "fixed64")
  1960  	case pref.StringKind, pref.BytesKind, pref.MessageKind:
  1961  		tag = append(tag, "bytes")
  1962  	case pref.GroupKind:
  1963  		tag = append(tag, "group")
  1964  	}
  1965  	tag = append(tag, strconv.Itoa(int(fd.Number())))
  1966  	switch fd.Cardinality() {
  1967  	case pref.Optional:
  1968  		tag = append(tag, "opt")
  1969  	case pref.Required:
  1970  		tag = append(tag, "req")
  1971  	case pref.Repeated:
  1972  		tag = append(tag, "rep")
  1973  	}
  1974  	if fd.IsPacked() {
  1975  		tag = append(tag, "packed")
  1976  	}
  1977  	name := string(fd.Name())
  1978  	if fd.Kind() == pref.GroupKind {
  1979  		// The name of the FieldDescriptor for a group field is
  1980  		// lowercased. To find the original capitalization, we
  1981  		// look in the field's MessageType.
  1982  		name = string(fd.Message().Name())
  1983  	}
  1984  	tag = append(tag, "name="+name)
  1985  	if jsonName := fd.JSONName(); jsonName != "" && jsonName != name && !fd.IsExtension() {
  1986  		// NOTE: The jsonName != name condition is suspect, but it preserve
  1987  		// the exact same semantics from the previous generator.
  1988  		tag = append(tag, "json="+jsonName)
  1989  	}
  1990  	if fd.IsWeak() {
  1991  		tag = append(tag, "weak="+string(fd.Message().FullName()))
  1992  	}
  1993  	// The previous implementation does not tag extension fields as proto3,
  1994  	// even when the field is defined in a proto3 file. Match that behavior
  1995  	// for consistency.
  1996  	if fd.Syntax() == pref.Proto3 && !fd.IsExtension() {
  1997  		tag = append(tag, "proto3")
  1998  	}
  1999  	if fd.Kind() == pref.EnumKind && enumName != "" {
  2000  		tag = append(tag, "enum="+enumName)
  2001  	}
  2002  	if fd.ContainingOneof() != nil {
  2003  		tag = append(tag, "oneof")
  2004  	}
  2005  	// This must appear last in the tag, since commas in strings aren't escaped.
  2006  	if fd.HasDefault() {
  2007  		def, _ := DefValMarshal(fd.Default(), fd.DefaultEnumValue(), fd.Kind(), 2) // 2 = defval.GoTag
  2008  		tag = append(tag, "def="+def)
  2009  	}
  2010  	return strings.Join(tag, ",")
  2011  }
  2012  
  2013  func genMessageReflectMethods(g *generator.GeneratedFile, f *fileInfo, m *messageInfo) {
  2014  	// This is being handled by the fast reflection feature.
  2015  
  2016  	//idx := f.allMessagesByPtr[m]
  2017  	//typesVar := messageTypesVarName(f)
  2018  
  2019  	// ProtoReflect method.
  2020  	//g.P("func (x *", m.GoIdent, ") ProtoReflect() ", protoreflectPackage.Ident("Message"), " {")
  2021  	//g.P("mi := &", typesVar, "[", idx, "]")
  2022  	//g.P("if ", protoimplPackage.Ident("UnsafeEnabled"), " && x != nil {")
  2023  	//g.P("ms := ", protoimplPackage.Ident("X"), ".MessageStateOf(", protoimplPackage.Ident("Pointer"), "(x))")
  2024  	//g.P("if ms.LoadMessageInfo() == nil {")
  2025  	//g.P("ms.StoreMessageInfo(mi)")
  2026  	//g.P("}")
  2027  	//g.P("return ms")
  2028  	//g.P("}")
  2029  	//g.P("return mi.MessageOf(x)")
  2030  	//g.P("}")
  2031  	//g.P()
  2032  }
  2033  
  2034  // DefValMarshal serializes v as the default string according to the given kind k.
  2035  // When specifying the Descriptor format for an enum kind, the associated
  2036  // enum value descriptor must be provided.
  2037  func DefValMarshal(v pref.Value, ev pref.EnumValueDescriptor, k pref.Kind, f Format) (string, error) {
  2038  	switch k {
  2039  	case pref.BoolKind:
  2040  		if f == GoTag {
  2041  			if v.Bool() {
  2042  				return "1", nil
  2043  			} else {
  2044  				return "0", nil
  2045  			}
  2046  		} else {
  2047  			if v.Bool() {
  2048  				return "true", nil
  2049  			} else {
  2050  				return "false", nil
  2051  			}
  2052  		}
  2053  	case pref.EnumKind:
  2054  		if f == GoTag {
  2055  			return strconv.FormatInt(int64(v.Enum()), 10), nil
  2056  		} else {
  2057  			return string(ev.Name()), nil
  2058  		}
  2059  	case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind, pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind:
  2060  		return strconv.FormatInt(v.Int(), 10), nil
  2061  	case pref.Uint32Kind, pref.Fixed32Kind, pref.Uint64Kind, pref.Fixed64Kind:
  2062  		return strconv.FormatUint(v.Uint(), 10), nil
  2063  	case pref.FloatKind, pref.DoubleKind:
  2064  		f := v.Float()
  2065  		switch {
  2066  		case math.IsInf(f, -1):
  2067  			return "-inf", nil
  2068  		case math.IsInf(f, +1):
  2069  			return "inf", nil
  2070  		case math.IsNaN(f):
  2071  			return "nan", nil
  2072  		default:
  2073  			if k == pref.FloatKind {
  2074  				return strconv.FormatFloat(f, 'g', -1, 32), nil
  2075  			} else {
  2076  				return strconv.FormatFloat(f, 'g', -1, 64), nil
  2077  			}
  2078  		}
  2079  	case pref.StringKind:
  2080  		// String values are serialized as is without any escaping.
  2081  		return v.String(), nil
  2082  	case pref.BytesKind:
  2083  		if s, ok := marshalBytes(v.Bytes()); ok {
  2084  			return s, nil
  2085  		}
  2086  	}
  2087  	return "", fmt.Errorf("could not format value for %v: %v", k, v)
  2088  }
  2089  
  2090  type Format int
  2091  
  2092  const (
  2093  	_ Format = iota
  2094  
  2095  	// Descriptor uses the serialization format that protoc uses with the
  2096  	// google.protobuf.FieldDescriptorProto.default_value field.
  2097  	Descriptor
  2098  
  2099  	// GoTag uses the historical serialization format in Go struct field tags.
  2100  	GoTag
  2101  )
  2102  
  2103  // marshalBytes serializes bytes by using C escaping.
  2104  // To match the exact output of protoc, this is identical to the
  2105  // CEscape function in strutil.cc of the protoc source code.
  2106  func marshalBytes(b []byte) (string, bool) {
  2107  	var s []byte
  2108  	for _, c := range b {
  2109  		switch c {
  2110  		case '\n':
  2111  			s = append(s, `\n`...)
  2112  		case '\r':
  2113  			s = append(s, `\r`...)
  2114  		case '\t':
  2115  			s = append(s, `\t`...)
  2116  		case '"':
  2117  			s = append(s, `\"`...)
  2118  		case '\'':
  2119  			s = append(s, `\'`...)
  2120  		case '\\':
  2121  			s = append(s, `\\`...)
  2122  		default:
  2123  			if printableASCII := c >= 0x20 && c <= 0x7e; printableASCII {
  2124  				s = append(s, c)
  2125  			} else {
  2126  				s = append(s, fmt.Sprintf(`\%03o`, c)...)
  2127  			}
  2128  		}
  2129  	}
  2130  	return string(s), true
  2131  }
  2132  
  2133  type goImportPath interface {
  2134  	String() string
  2135  	Ident(string) protogen.GoIdent
  2136  }
  2137  
  2138  type enumInfo struct {
  2139  	*protogen.Enum
  2140  
  2141  	genJSONMethod    bool
  2142  	genRawDescMethod bool
  2143  }
  2144  
  2145  func newEnumInfo(f *fileInfo, enum *protogen.Enum) *enumInfo {
  2146  	e := &enumInfo{Enum: enum}
  2147  	e.genJSONMethod = true
  2148  	e.genRawDescMethod = true
  2149  	return e
  2150  }
  2151  
  2152  type messageInfo struct {
  2153  	*protogen.Message
  2154  
  2155  	genRawDescMethod  bool
  2156  	genExtRangeMethod bool
  2157  
  2158  	isTracked bool
  2159  	hasWeak   bool
  2160  }
  2161  
  2162  // isTrackedMessage reports whether field tracking is enabled on the message.
  2163  func isTrackedMessage(m *messageInfo) (tracked bool) {
  2164  	const trackFieldUse_fieldNumber = 37383685
  2165  
  2166  	// Decode the option from unknown fields to avoid a dependency on the
  2167  	// annotation proto from protoc-gen-go.
  2168  	b := m.Desc.Options().(*descriptorpb.MessageOptions).ProtoReflect().GetUnknown()
  2169  	for len(b) > 0 {
  2170  		num, typ, n := protowire.ConsumeTag(b)
  2171  		b = b[n:]
  2172  		if num == trackFieldUse_fieldNumber && typ == protowire.VarintType {
  2173  			v, _ := protowire.ConsumeVarint(b)
  2174  			tracked = protowire.DecodeBool(v)
  2175  		}
  2176  		m := protowire.ConsumeFieldValue(num, typ, b)
  2177  		b = b[m:]
  2178  	}
  2179  	return tracked
  2180  }
  2181  
  2182  func newMessageInfo(f *fileInfo, message *protogen.Message) *messageInfo {
  2183  	m := &messageInfo{Message: message}
  2184  	m.genRawDescMethod = true
  2185  	m.genExtRangeMethod = true
  2186  	m.isTracked = isTrackedMessage(m)
  2187  	for _, field := range m.Fields {
  2188  		m.hasWeak = m.hasWeak || field.Desc.IsWeak()
  2189  	}
  2190  	return m
  2191  }
  2192  
  2193  type extensionInfo struct {
  2194  	*protogen.Extension
  2195  }
  2196  
  2197  func newExtensionInfo(f *fileInfo, extension *protogen.Extension) *extensionInfo {
  2198  	x := &extensionInfo{Extension: extension}
  2199  	return x
  2200  }
  2201  
  2202  type structFields struct {
  2203  	count      int
  2204  	unexported map[int]string
  2205  }
  2206  
  2207  func (sf *structFields) append(name string) {
  2208  	if r, _ := utf8.DecodeRuneInString(name); !unicode.IsUpper(r) {
  2209  		if sf.unexported == nil {
  2210  			sf.unexported = make(map[int]string)
  2211  		}
  2212  		sf.unexported[sf.count] = name
  2213  	}
  2214  	sf.count++
  2215  }
  2216  
  2217  type fileInfo struct {
  2218  	*protogen.File
  2219  
  2220  	allEnums      []*enumInfo
  2221  	allMessages   []*messageInfo
  2222  	allExtensions []*extensionInfo
  2223  
  2224  	allEnumsByPtr         map[*enumInfo]int    // value is index into allEnums
  2225  	allMessagesByPtr      map[*messageInfo]int // value is index into allMessages
  2226  	allMessageFieldsByPtr map[*messageInfo]*structFields
  2227  
  2228  	// needRawDesc specifies whether the generator should emit logic to provide
  2229  	// the legacy raw descriptor in GZIP'd form.
  2230  	// This is updated by enum and message generation logic as necessary,
  2231  	// and checked at the end of file generation.
  2232  	needRawDesc bool
  2233  }
  2234  
  2235  func newFileInfo(file *protogen.File) *fileInfo {
  2236  	f := &fileInfo{File: file}
  2237  
  2238  	// Collect all enums, messages, and extensions in "flattened ordering".
  2239  	// See filetype.TypeBuilder.
  2240  	var walkMessages func([]*protogen.Message, func(*protogen.Message))
  2241  	walkMessages = func(messages []*protogen.Message, f func(*protogen.Message)) {
  2242  		for _, m := range messages {
  2243  			f(m)
  2244  			walkMessages(m.Messages, f)
  2245  		}
  2246  	}
  2247  	initEnumInfos := func(enums []*protogen.Enum) {
  2248  		for _, enum := range enums {
  2249  			f.allEnums = append(f.allEnums, newEnumInfo(f, enum))
  2250  		}
  2251  	}
  2252  	initMessageInfos := func(messages []*protogen.Message) {
  2253  		for _, message := range messages {
  2254  			f.allMessages = append(f.allMessages, newMessageInfo(f, message))
  2255  		}
  2256  	}
  2257  	initExtensionInfos := func(extensions []*protogen.Extension) {
  2258  		for _, extension := range extensions {
  2259  			f.allExtensions = append(f.allExtensions, newExtensionInfo(f, extension))
  2260  		}
  2261  	}
  2262  	initEnumInfos(f.Enums)
  2263  	initMessageInfos(f.Messages)
  2264  	initExtensionInfos(f.Extensions)
  2265  	walkMessages(f.Messages, func(m *protogen.Message) {
  2266  		initEnumInfos(m.Enums)
  2267  		initMessageInfos(m.Messages)
  2268  		initExtensionInfos(m.Extensions)
  2269  	})
  2270  
  2271  	// Derive a reverse mapping of enum and message pointers to their index
  2272  	// in allEnums and allMessages.
  2273  	if len(f.allEnums) > 0 {
  2274  		f.allEnumsByPtr = make(map[*enumInfo]int)
  2275  		for i, e := range f.allEnums {
  2276  			f.allEnumsByPtr[e] = i
  2277  		}
  2278  	}
  2279  	if len(f.allMessages) > 0 {
  2280  		f.allMessagesByPtr = make(map[*messageInfo]int)
  2281  		f.allMessageFieldsByPtr = make(map[*messageInfo]*structFields)
  2282  		for i, m := range f.allMessages {
  2283  			f.allMessagesByPtr[m] = i
  2284  			f.allMessageFieldsByPtr[m] = new(structFields)
  2285  		}
  2286  	}
  2287  
  2288  	return f
  2289  }