1// Protocol Buffers for Go with Gadgets
2//
3// Copyright (c) 2013, The GoGo Authors. All rights reserved.
4// http://github.com/gogo/protobuf
5//
6// Go support for Protocol Buffers - Google's data interchange format
7//
8// Copyright 2010 The Go Authors.  All rights reserved.
9// https://github.com/golang/protobuf
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions are
13// met:
14//
15//     * Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17//     * Redistributions in binary form must reproduce the above
18// copyright notice, this list of conditions and the following disclaimer
19// in the documentation and/or other materials provided with the
20// distribution.
21//     * Neither the name of Google Inc. nor the names of its
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
37/*
38	The code generator for the plugin for the Google protocol buffer compiler.
39	It generates Go code from the protocol buffer description files read by the
40	main routine.
41*/
42package generator
43
44import (
45	"bufio"
46	"bytes"
47	"compress/gzip"
48	"crypto/sha256"
49	"encoding/hex"
50	"fmt"
51	"go/build"
52	"go/parser"
53	"go/printer"
54	"go/token"
55	"log"
56	"os"
57	"path"
58	"sort"
59	"strconv"
60	"strings"
61	"unicode"
62	"unicode/utf8"
63
64	"github.com/gogo/protobuf/gogoproto"
65	"github.com/gogo/protobuf/proto"
66	descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
67	"github.com/gogo/protobuf/protoc-gen-gogo/generator/internal/remap"
68	plugin "github.com/gogo/protobuf/protoc-gen-gogo/plugin"
69)
70
71// generatedCodeVersion indicates a version of the generated code.
72// It is incremented whenever an incompatibility between the generated code and
73// proto package is introduced; the generated code references
74// a constant, proto.ProtoPackageIsVersionN (where N is generatedCodeVersion).
75const generatedCodeVersion = 2
76
77// A Plugin provides functionality to add to the output during Go code generation,
78// such as to produce RPC stubs.
79type Plugin interface {
80	// Name identifies the plugin.
81	Name() string
82	// Init is called once after data structures are built but before
83	// code generation begins.
84	Init(g *Generator)
85	// Generate produces the code generated by the plugin for this file,
86	// except for the imports, by calling the generator's methods P, In, and Out.
87	Generate(file *FileDescriptor)
88	// GenerateImports produces the import declarations for this file.
89	// It is called after Generate.
90	GenerateImports(file *FileDescriptor)
91}
92
93type pluginSlice []Plugin
94
95func (ps pluginSlice) Len() int {
96	return len(ps)
97}
98
99func (ps pluginSlice) Less(i, j int) bool {
100	return ps[i].Name() < ps[j].Name()
101}
102
103func (ps pluginSlice) Swap(i, j int) {
104	ps[i], ps[j] = ps[j], ps[i]
105}
106
107var plugins pluginSlice
108
109// RegisterPlugin installs a (second-order) plugin to be run when the Go output is generated.
110// It is typically called during initialization.
111func RegisterPlugin(p Plugin) {
112	plugins = append(plugins, p)
113}
114
115// A GoImportPath is the import path of a Go package. e.g., "google.golang.org/genproto/protobuf".
116type GoImportPath string
117
118func (p GoImportPath) String() string { return strconv.Quote(string(p)) }
119
120// A GoPackageName is the name of a Go package. e.g., "protobuf".
121type GoPackageName string
122
123// Each type we import as a protocol buffer (other than FileDescriptorProto) needs
124// a pointer to the FileDescriptorProto that represents it.  These types achieve that
125// wrapping by placing each Proto inside a struct with the pointer to its File. The
126// structs have the same names as their contents, with "Proto" removed.
127// FileDescriptor is used to store the things that it points to.
128
129// The file and package name method are common to messages and enums.
130type common struct {
131	file *FileDescriptor // File this object comes from.
132}
133
134// GoImportPath is the import path of the Go package containing the type.
135func (c *common) GoImportPath() GoImportPath {
136	return c.file.importPath
137}
138
139func (c *common) File() *FileDescriptor { return c.file }
140
141func fileIsProto3(file *descriptor.FileDescriptorProto) bool {
142	return file.GetSyntax() == "proto3"
143}
144
145func (c *common) proto3() bool { return fileIsProto3(c.file.FileDescriptorProto) }
146
147// Descriptor represents a protocol buffer message.
148type Descriptor struct {
149	common
150	*descriptor.DescriptorProto
151	parent   *Descriptor            // The containing message, if any.
152	nested   []*Descriptor          // Inner messages, if any.
153	enums    []*EnumDescriptor      // Inner enums, if any.
154	ext      []*ExtensionDescriptor // Extensions, if any.
155	typename []string               // Cached typename vector.
156	index    int                    // The index into the container, whether the file or another message.
157	path     string                 // The SourceCodeInfo path as comma-separated integers.
158	group    bool
159}
160
161// TypeName returns the elements of the dotted type name.
162// The package name is not part of this name.
163func (d *Descriptor) TypeName() []string {
164	if d.typename != nil {
165		return d.typename
166	}
167	n := 0
168	for parent := d; parent != nil; parent = parent.parent {
169		n++
170	}
171	s := make([]string, n)
172	for parent := d; parent != nil; parent = parent.parent {
173		n--
174		s[n] = parent.GetName()
175	}
176	d.typename = s
177	return s
178}
179
180func (d *Descriptor) allowOneof() bool {
181	return true
182}
183
184// EnumDescriptor describes an enum. If it's at top level, its parent will be nil.
185// Otherwise it will be the descriptor of the message in which it is defined.
186type EnumDescriptor struct {
187	common
188	*descriptor.EnumDescriptorProto
189	parent   *Descriptor // The containing message, if any.
190	typename []string    // Cached typename vector.
191	index    int         // The index into the container, whether the file or a message.
192	path     string      // The SourceCodeInfo path as comma-separated integers.
193}
194
195// TypeName returns the elements of the dotted type name.
196// The package name is not part of this name.
197func (e *EnumDescriptor) TypeName() (s []string) {
198	if e.typename != nil {
199		return e.typename
200	}
201	name := e.GetName()
202	if e.parent == nil {
203		s = make([]string, 1)
204	} else {
205		pname := e.parent.TypeName()
206		s = make([]string, len(pname)+1)
207		copy(s, pname)
208	}
209	s[len(s)-1] = name
210	e.typename = s
211	return s
212}
213
214// alias provides the TypeName corrected for the application of any naming
215// extensions on the enum type. It should be used for generating references to
216// the Go types and for calculating prefixes.
217func (e *EnumDescriptor) alias() (s []string) {
218	s = e.TypeName()
219	if gogoproto.IsEnumCustomName(e.EnumDescriptorProto) {
220		s[len(s)-1] = gogoproto.GetEnumCustomName(e.EnumDescriptorProto)
221	}
222
223	return
224}
225
226// Everything but the last element of the full type name, CamelCased.
227// The values of type Foo.Bar are call Foo_value1... not Foo_Bar_value1... .
228func (e *EnumDescriptor) prefix() string {
229	typeName := e.alias()
230	if e.parent == nil {
231		// If the enum is not part of a message, the prefix is just the type name.
232		return CamelCase(typeName[len(typeName)-1]) + "_"
233	}
234	return CamelCaseSlice(typeName[0:len(typeName)-1]) + "_"
235}
236
237// The integer value of the named constant in this enumerated type.
238func (e *EnumDescriptor) integerValueAsString(name string) string {
239	for _, c := range e.Value {
240		if c.GetName() == name {
241			return fmt.Sprint(c.GetNumber())
242		}
243	}
244	log.Fatal("cannot find value for enum constant")
245	return ""
246}
247
248// ExtensionDescriptor describes an extension. If it's at top level, its parent will be nil.
249// Otherwise it will be the descriptor of the message in which it is defined.
250type ExtensionDescriptor struct {
251	common
252	*descriptor.FieldDescriptorProto
253	parent *Descriptor // The containing message, if any.
254}
255
256// TypeName returns the elements of the dotted type name.
257// The package name is not part of this name.
258func (e *ExtensionDescriptor) TypeName() (s []string) {
259	name := e.GetName()
260	if e.parent == nil {
261		// top-level extension
262		s = make([]string, 1)
263	} else {
264		pname := e.parent.TypeName()
265		s = make([]string, len(pname)+1)
266		copy(s, pname)
267	}
268	s[len(s)-1] = name
269	return s
270}
271
272// DescName returns the variable name used for the generated descriptor.
273func (e *ExtensionDescriptor) DescName() string {
274	// The full type name.
275	typeName := e.TypeName()
276	// Each scope of the extension is individually CamelCased, and all are joined with "_" with an "E_" prefix.
277	for i, s := range typeName {
278		typeName[i] = CamelCase(s)
279	}
280	return "E_" + strings.Join(typeName, "_")
281}
282
283// ImportedDescriptor describes a type that has been publicly imported from another file.
284type ImportedDescriptor struct {
285	common
286	o Object
287}
288
289func (id *ImportedDescriptor) TypeName() []string { return id.o.TypeName() }
290
291// FileDescriptor describes an protocol buffer descriptor file (.proto).
292// It includes slices of all the messages and enums defined within it.
293// Those slices are constructed by WrapTypes.
294type FileDescriptor struct {
295	*descriptor.FileDescriptorProto
296	desc []*Descriptor          // All the messages defined in this file.
297	enum []*EnumDescriptor      // All the enums defined in this file.
298	ext  []*ExtensionDescriptor // All the top-level extensions defined in this file.
299	imp  []*ImportedDescriptor  // All types defined in files publicly imported by this file.
300
301	// Comments, stored as a map of path (comma-separated integers) to the comment.
302	comments map[string]*descriptor.SourceCodeInfo_Location
303
304	// The full list of symbols that are exported,
305	// as a map from the exported object to its symbols.
306	// This is used for supporting public imports.
307	exported map[Object][]symbol
308
309	fingerprint string        // Fingerprint of this file's contents.
310	importPath  GoImportPath  // Import path of this file's package.
311	packageName GoPackageName // Name of this file's Go package.
312
313	proto3 bool // whether to generate proto3 code for this file
314}
315
316// VarName is the variable name we'll use in the generated code to refer
317// to the compressed bytes of this descriptor. It is not exported, so
318// it is only valid inside the generated package.
319func (d *FileDescriptor) VarName() string {
320	name := strings.Map(badToUnderscore, baseName(d.GetName()))
321	return fmt.Sprintf("fileDescriptor_%s_%s", name, d.fingerprint)
322}
323
324// goPackageOption interprets the file's go_package option.
325// If there is no go_package, it returns ("", "", false).
326// If there's a simple name, it returns ("", pkg, true).
327// If the option implies an import path, it returns (impPath, pkg, true).
328func (d *FileDescriptor) goPackageOption() (impPath GoImportPath, pkg GoPackageName, ok bool) {
329	opt := d.GetOptions().GetGoPackage()
330	if opt == "" {
331		return "", "", false
332	}
333	// A semicolon-delimited suffix delimits the import path and package name.
334	sc := strings.Index(opt, ";")
335	if sc >= 0 {
336		return GoImportPath(opt[:sc]), cleanPackageName(opt[sc+1:]), true
337	}
338	// The presence of a slash implies there's an import path.
339	slash := strings.LastIndex(opt, "/")
340	if slash >= 0 {
341		return GoImportPath(opt), cleanPackageName(opt[slash+1:]), true
342	}
343	return "", cleanPackageName(opt), true
344}
345
346// goFileName returns the output name for the generated Go file.
347func (d *FileDescriptor) goFileName(pathType pathType) string {
348	name := *d.Name
349	if ext := path.Ext(name); ext == ".proto" || ext == ".protodevel" {
350		name = name[:len(name)-len(ext)]
351	}
352	name += ".pb.go"
353
354	if pathType == pathTypeSourceRelative {
355		return name
356	}
357
358	// Does the file have a "go_package" option?
359	// If it does, it may override the filename.
360	if impPath, _, ok := d.goPackageOption(); ok && impPath != "" {
361		// Replace the existing dirname with the declared import path.
362		_, name = path.Split(name)
363		name = path.Join(string(impPath), name)
364		return name
365	}
366
367	return name
368}
369
370func (d *FileDescriptor) addExport(obj Object, sym symbol) {
371	d.exported[obj] = append(d.exported[obj], sym)
372}
373
374// symbol is an interface representing an exported Go symbol.
375type symbol interface {
376	// GenerateAlias should generate an appropriate alias
377	// for the symbol from the named package.
378	GenerateAlias(g *Generator, pkg GoPackageName)
379}
380
381type messageSymbol struct {
382	sym                         string
383	hasExtensions, isMessageSet bool
384	oneofTypes                  []string
385}
386
387type getterSymbol struct {
388	name     string
389	typ      string
390	typeName string // canonical name in proto world; empty for proto.Message and similar
391	genType  bool   // whether typ contains a generated type (message/group/enum)
392}
393
394func (ms *messageSymbol) GenerateAlias(g *Generator, pkg GoPackageName) {
395	g.P("type ", ms.sym, " = ", pkg, ".", ms.sym)
396	for _, name := range ms.oneofTypes {
397		g.P("type ", name, " = ", pkg, ".", name)
398	}
399}
400
401type enumSymbol struct {
402	name   string
403	proto3 bool // Whether this came from a proto3 file.
404}
405
406func (es enumSymbol) GenerateAlias(g *Generator, pkg GoPackageName) {
407	s := es.name
408	g.P("type ", s, " = ", pkg, ".", s)
409	g.P("var ", s, "_name = ", pkg, ".", s, "_name")
410	g.P("var ", s, "_value = ", pkg, ".", s, "_value")
411}
412
413type constOrVarSymbol struct {
414	sym  string
415	typ  string // either "const" or "var"
416	cast string // if non-empty, a type cast is required (used for enums)
417}
418
419func (cs constOrVarSymbol) GenerateAlias(g *Generator, pkg GoPackageName) {
420	v := string(pkg) + "." + cs.sym
421	if cs.cast != "" {
422		v = cs.cast + "(" + v + ")"
423	}
424	g.P(cs.typ, " ", cs.sym, " = ", v)
425}
426
427// Object is an interface abstracting the abilities shared by enums, messages, extensions and imported objects.
428type Object interface {
429	GoImportPath() GoImportPath
430	TypeName() []string
431	File() *FileDescriptor
432}
433
434// Generator is the type whose methods generate the output, stored in the associated response structure.
435type Generator struct {
436	*bytes.Buffer
437
438	Request  *plugin.CodeGeneratorRequest  // The input.
439	Response *plugin.CodeGeneratorResponse // The output.
440
441	Param             map[string]string // Command-line parameters.
442	PackageImportPath string            // Go import path of the package we're generating code for
443	ImportPrefix      string            // String to prefix to imported package file names.
444	ImportMap         map[string]string // Mapping from .proto file name to import path
445
446	Pkg map[string]string // The names under which we import support packages
447
448	outputImportPath GoImportPath                   // Package we're generating code for.
449	allFiles         []*FileDescriptor              // All files in the tree
450	allFilesByName   map[string]*FileDescriptor     // All files by filename.
451	genFiles         []*FileDescriptor              // Those files we will generate output for.
452	file             *FileDescriptor                // The file we are compiling now.
453	packageNames     map[GoImportPath]GoPackageName // Imported package names in the current file.
454	usedPackages     map[GoImportPath]bool          // Packages used in current file.
455	usedPackageNames map[GoPackageName]bool         // Package names used in the current file.
456	typeNameToObject map[string]Object              // Key is a fully-qualified name in input syntax.
457	init             []string                       // Lines to emit in the init function.
458	indent           string
459	pathType         pathType // How to generate output filenames.
460	writeOutput      bool
461	annotateCode     bool                                       // whether to store annotations
462	annotations      []*descriptor.GeneratedCodeInfo_Annotation // annotations to store
463
464	customImports  []string
465	writtenImports map[string]bool // For de-duplicating written imports
466}
467
468type pathType int
469
470const (
471	pathTypeImport pathType = iota
472	pathTypeSourceRelative
473)
474
475// New creates a new generator and allocates the request and response protobufs.
476func New() *Generator {
477	g := new(Generator)
478	g.Buffer = new(bytes.Buffer)
479	g.Request = new(plugin.CodeGeneratorRequest)
480	g.Response = new(plugin.CodeGeneratorResponse)
481	g.writtenImports = make(map[string]bool)
482	return g
483}
484
485// Error reports a problem, including an error, and exits the program.
486func (g *Generator) Error(err error, msgs ...string) {
487	s := strings.Join(msgs, " ") + ":" + err.Error()
488	log.Print("protoc-gen-gogo: error:", s)
489	os.Exit(1)
490}
491
492// Fail reports a problem and exits the program.
493func (g *Generator) Fail(msgs ...string) {
494	s := strings.Join(msgs, " ")
495	log.Print("protoc-gen-gogo: error:", s)
496	os.Exit(1)
497}
498
499// CommandLineParameters breaks the comma-separated list of key=value pairs
500// in the parameter (a member of the request protobuf) into a key/value map.
501// It then sets file name mappings defined by those entries.
502func (g *Generator) CommandLineParameters(parameter string) {
503	g.Param = make(map[string]string)
504	for _, p := range strings.Split(parameter, ",") {
505		if i := strings.Index(p, "="); i < 0 {
506			g.Param[p] = ""
507		} else {
508			g.Param[p[0:i]] = p[i+1:]
509		}
510	}
511
512	g.ImportMap = make(map[string]string)
513	pluginList := "none" // Default list of plugin names to enable (empty means all).
514	for k, v := range g.Param {
515		switch k {
516		case "import_prefix":
517			g.ImportPrefix = v
518		case "import_path":
519			g.PackageImportPath = v
520		case "paths":
521			switch v {
522			case "import":
523				g.pathType = pathTypeImport
524			case "source_relative":
525				g.pathType = pathTypeSourceRelative
526			default:
527				g.Fail(fmt.Sprintf(`Unknown path type %q: want "import" or "source_relative".`, v))
528			}
529		case "plugins":
530			pluginList = v
531		case "annotate_code":
532			if v == "true" {
533				g.annotateCode = true
534			}
535		default:
536			if len(k) > 0 && k[0] == 'M' {
537				g.ImportMap[k[1:]] = v
538			}
539		}
540	}
541	if pluginList == "" {
542		return
543	}
544	if pluginList == "none" {
545		pluginList = ""
546	}
547	gogoPluginNames := []string{"unmarshal", "unsafeunmarshaler", "union", "stringer", "size", "protosizer", "populate", "marshalto", "unsafemarshaler", "gostring", "face", "equal", "enumstringer", "embedcheck", "description", "defaultcheck", "oneofcheck", "compare"}
548	pluginList = strings.Join(append(gogoPluginNames, pluginList), "+")
549	if pluginList != "" {
550		// Amend the set of plugins.
551		enabled := make(map[string]bool)
552		for _, name := range strings.Split(pluginList, "+") {
553			enabled[name] = true
554		}
555		var nplugins pluginSlice
556		for _, p := range plugins {
557			if enabled[p.Name()] {
558				nplugins = append(nplugins, p)
559			}
560		}
561		sort.Sort(nplugins)
562		plugins = nplugins
563	}
564}
565
566// DefaultPackageName returns the package name printed for the object.
567// If its file is in a different package, it returns the package name we're using for this file, plus ".".
568// Otherwise it returns the empty string.
569func (g *Generator) DefaultPackageName(obj Object) string {
570	importPath := obj.GoImportPath()
571	if importPath == g.outputImportPath {
572		return ""
573	}
574	return string(g.GoPackageName(importPath)) + "."
575}
576
577// GoPackageName returns the name used for a package.
578func (g *Generator) GoPackageName(importPath GoImportPath) GoPackageName {
579	if name, ok := g.packageNames[importPath]; ok {
580		return name
581	}
582	name := cleanPackageName(baseName(string(importPath)))
583	for i, orig := 1, name; g.usedPackageNames[name]; i++ {
584		name = orig + GoPackageName(strconv.Itoa(i))
585	}
586	if g.packageNames == nil {
587		g.packageNames = make(map[GoImportPath]GoPackageName)
588	}
589	g.packageNames[importPath] = name
590	if g.usedPackageNames == nil {
591		g.usedPackageNames = make(map[GoPackageName]bool)
592	}
593	g.usedPackageNames[name] = true
594	return name
595}
596
597var globalPackageNames = map[GoPackageName]bool{
598	"fmt":   true,
599	"math":  true,
600	"proto": true,
601}
602
603// Create and remember a guaranteed unique package name. Pkg is the candidate name.
604// The FileDescriptor parameter is unused.
605func RegisterUniquePackageName(pkg string, f *FileDescriptor) string {
606	name := cleanPackageName(pkg)
607	for i, orig := 1, name; globalPackageNames[name]; i++ {
608		name = orig + GoPackageName(strconv.Itoa(i))
609	}
610	globalPackageNames[name] = true
611	return string(name)
612}
613
614var isGoKeyword = map[string]bool{
615	"break":       true,
616	"case":        true,
617	"chan":        true,
618	"const":       true,
619	"continue":    true,
620	"default":     true,
621	"else":        true,
622	"defer":       true,
623	"fallthrough": true,
624	"for":         true,
625	"func":        true,
626	"go":          true,
627	"goto":        true,
628	"if":          true,
629	"import":      true,
630	"interface":   true,
631	"map":         true,
632	"package":     true,
633	"range":       true,
634	"return":      true,
635	"select":      true,
636	"struct":      true,
637	"switch":      true,
638	"type":        true,
639	"var":         true,
640}
641
642func cleanPackageName(name string) GoPackageName {
643	name = strings.Map(badToUnderscore, name)
644	// Identifier must not be keyword: insert _.
645	if isGoKeyword[name] {
646		name = "_" + name
647	}
648	// Identifier must not begin with digit: insert _.
649	if r, _ := utf8.DecodeRuneInString(name); unicode.IsDigit(r) {
650		name = "_" + name
651	}
652	return GoPackageName(name)
653}
654
655// defaultGoPackage returns the package name to use,
656// derived from the import path of the package we're building code for.
657func (g *Generator) defaultGoPackage() GoPackageName {
658	p := g.PackageImportPath
659	if i := strings.LastIndex(p, "/"); i >= 0 {
660		p = p[i+1:]
661	}
662	return cleanPackageName(p)
663}
664
665// SetPackageNames sets the package name for this run.
666// The package name must agree across all files being generated.
667// It also defines unique package names for all imported files.
668func (g *Generator) SetPackageNames() {
669	g.outputImportPath = g.genFiles[0].importPath
670
671	defaultPackageNames := make(map[GoImportPath]GoPackageName)
672	for _, f := range g.genFiles {
673		if _, p, ok := f.goPackageOption(); ok {
674			defaultPackageNames[f.importPath] = p
675		}
676	}
677	for _, f := range g.genFiles {
678		if _, p, ok := f.goPackageOption(); ok {
679			// Source file: option go_package = "quux/bar";
680			f.packageName = p
681		} else if p, ok := defaultPackageNames[f.importPath]; ok {
682			// A go_package option in another file in the same package.
683			//
684			// This is a poor choice in general, since every source file should
685			// contain a go_package option. Supported mainly for historical
686			// compatibility.
687			f.packageName = p
688		} else if p := g.defaultGoPackage(); p != "" {
689			// Command-line: import_path=quux/bar.
690			//
691			// The import_path flag sets a package name for files which don't
692			// contain a go_package option.
693			f.packageName = p
694		} else if p := f.GetPackage(); p != "" {
695			// Source file: package quux.bar;
696			f.packageName = cleanPackageName(p)
697		} else {
698			// Source filename.
699			f.packageName = cleanPackageName(baseName(f.GetName()))
700		}
701	}
702
703	// Check that all files have a consistent package name and import path.
704	for _, f := range g.genFiles[1:] {
705		if a, b := g.genFiles[0].importPath, f.importPath; a != b {
706			g.Fail(fmt.Sprintf("inconsistent package import paths: %v, %v", a, b))
707		}
708		if a, b := g.genFiles[0].packageName, f.packageName; a != b {
709			g.Fail(fmt.Sprintf("inconsistent package names: %v, %v", a, b))
710		}
711	}
712
713	// Names of support packages. These never vary (if there are conflicts,
714	// we rename the conflicting package), so this could be removed someday.
715	g.Pkg = map[string]string{
716		"fmt":          "fmt",
717		"math":         "math",
718		"proto":        "proto",
719		"golang_proto": "golang_proto",
720	}
721}
722
723// WrapTypes walks the incoming data, wrapping DescriptorProtos, EnumDescriptorProtos
724// and FileDescriptorProtos into file-referenced objects within the Generator.
725// It also creates the list of files to generate and so should be called before GenerateAllFiles.
726func (g *Generator) WrapTypes() {
727	g.allFiles = make([]*FileDescriptor, 0, len(g.Request.ProtoFile))
728	g.allFilesByName = make(map[string]*FileDescriptor, len(g.allFiles))
729	genFileNames := make(map[string]bool)
730	for _, n := range g.Request.FileToGenerate {
731		genFileNames[n] = true
732	}
733	for _, f := range g.Request.ProtoFile {
734		fd := &FileDescriptor{
735			FileDescriptorProto: f,
736			exported:            make(map[Object][]symbol),
737			proto3:              fileIsProto3(f),
738		}
739		// The import path may be set in a number of ways.
740		if substitution, ok := g.ImportMap[f.GetName()]; ok {
741			// Command-line: M=foo.proto=quux/bar.
742			//
743			// Explicit mapping of source file to import path.
744			fd.importPath = GoImportPath(substitution)
745		} else if genFileNames[f.GetName()] && g.PackageImportPath != "" {
746			// Command-line: import_path=quux/bar.
747			//
748			// The import_path flag sets the import path for every file that
749			// we generate code for.
750			fd.importPath = GoImportPath(g.PackageImportPath)
751		} else if p, _, _ := fd.goPackageOption(); p != "" {
752			// Source file: option go_package = "quux/bar";
753			//
754			// The go_package option sets the import path. Most users should use this.
755			fd.importPath = p
756		} else {
757			// Source filename.
758			//
759			// Last resort when nothing else is available.
760			fd.importPath = GoImportPath(path.Dir(f.GetName()))
761		}
762		// We must wrap the descriptors before we wrap the enums
763		fd.desc = wrapDescriptors(fd)
764		g.buildNestedDescriptors(fd.desc)
765		fd.enum = wrapEnumDescriptors(fd, fd.desc)
766		g.buildNestedEnums(fd.desc, fd.enum)
767		fd.ext = wrapExtensions(fd)
768		extractComments(fd)
769		g.allFiles = append(g.allFiles, fd)
770		g.allFilesByName[f.GetName()] = fd
771	}
772	for _, fd := range g.allFiles {
773		fd.imp = wrapImported(fd, g)
774	}
775
776	g.genFiles = make([]*FileDescriptor, 0, len(g.Request.FileToGenerate))
777	for _, fileName := range g.Request.FileToGenerate {
778		fd := g.allFilesByName[fileName]
779		if fd == nil {
780			g.Fail("could not find file named", fileName)
781		}
782		fingerprint, err := fingerprintProto(fd.FileDescriptorProto)
783		if err != nil {
784			g.Error(err)
785		}
786		fd.fingerprint = fingerprint
787		g.genFiles = append(g.genFiles, fd)
788	}
789}
790
791// fingerprintProto returns a fingerprint for a message.
792// The fingerprint is intended to prevent conflicts between generated fileds,
793// not to provide cryptographic security.
794func fingerprintProto(m proto.Message) (string, error) {
795	b, err := proto.Marshal(m)
796	if err != nil {
797		return "", err
798	}
799	h := sha256.Sum256(b)
800	return hex.EncodeToString(h[:8]), nil
801}
802
803// Scan the descriptors in this file.  For each one, build the slice of nested descriptors
804func (g *Generator) buildNestedDescriptors(descs []*Descriptor) {
805	for _, desc := range descs {
806		if len(desc.NestedType) != 0 {
807			for _, nest := range descs {
808				if nest.parent == desc {
809					desc.nested = append(desc.nested, nest)
810				}
811			}
812			if len(desc.nested) != len(desc.NestedType) {
813				g.Fail("internal error: nesting failure for", desc.GetName())
814			}
815		}
816	}
817}
818
819func (g *Generator) buildNestedEnums(descs []*Descriptor, enums []*EnumDescriptor) {
820	for _, desc := range descs {
821		if len(desc.EnumType) != 0 {
822			for _, enum := range enums {
823				if enum.parent == desc {
824					desc.enums = append(desc.enums, enum)
825				}
826			}
827			if len(desc.enums) != len(desc.EnumType) {
828				g.Fail("internal error: enum nesting failure for", desc.GetName())
829			}
830		}
831	}
832}
833
834// Construct the Descriptor
835func newDescriptor(desc *descriptor.DescriptorProto, parent *Descriptor, file *FileDescriptor, index int) *Descriptor {
836	d := &Descriptor{
837		common:          common{file},
838		DescriptorProto: desc,
839		parent:          parent,
840		index:           index,
841	}
842	if parent == nil {
843		d.path = fmt.Sprintf("%d,%d", messagePath, index)
844	} else {
845		d.path = fmt.Sprintf("%s,%d,%d", parent.path, messageMessagePath, index)
846	}
847
848	// The only way to distinguish a group from a message is whether
849	// the containing message has a TYPE_GROUP field that matches.
850	if parent != nil {
851		parts := d.TypeName()
852		if file.Package != nil {
853			parts = append([]string{*file.Package}, parts...)
854		}
855		exp := "." + strings.Join(parts, ".")
856		for _, field := range parent.Field {
857			if field.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP && field.GetTypeName() == exp {
858				d.group = true
859				break
860			}
861		}
862	}
863
864	for _, field := range desc.Extension {
865		d.ext = append(d.ext, &ExtensionDescriptor{common{file}, field, d})
866	}
867
868	return d
869}
870
871// Return a slice of all the Descriptors defined within this file
872func wrapDescriptors(file *FileDescriptor) []*Descriptor {
873	sl := make([]*Descriptor, 0, len(file.MessageType)+10)
874	for i, desc := range file.MessageType {
875		sl = wrapThisDescriptor(sl, desc, nil, file, i)
876	}
877	return sl
878}
879
880// Wrap this Descriptor, recursively
881func wrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *FileDescriptor, index int) []*Descriptor {
882	sl = append(sl, newDescriptor(desc, parent, file, index))
883	me := sl[len(sl)-1]
884	for i, nested := range desc.NestedType {
885		sl = wrapThisDescriptor(sl, nested, me, file, i)
886	}
887	return sl
888}
889
890// Construct the EnumDescriptor
891func newEnumDescriptor(desc *descriptor.EnumDescriptorProto, parent *Descriptor, file *FileDescriptor, index int) *EnumDescriptor {
892	ed := &EnumDescriptor{
893		common:              common{file},
894		EnumDescriptorProto: desc,
895		parent:              parent,
896		index:               index,
897	}
898	if parent == nil {
899		ed.path = fmt.Sprintf("%d,%d", enumPath, index)
900	} else {
901		ed.path = fmt.Sprintf("%s,%d,%d", parent.path, messageEnumPath, index)
902	}
903	return ed
904}
905
906// Return a slice of all the EnumDescriptors defined within this file
907func wrapEnumDescriptors(file *FileDescriptor, descs []*Descriptor) []*EnumDescriptor {
908	sl := make([]*EnumDescriptor, 0, len(file.EnumType)+10)
909	// Top-level enums.
910	for i, enum := range file.EnumType {
911		sl = append(sl, newEnumDescriptor(enum, nil, file, i))
912	}
913	// Enums within messages. Enums within embedded messages appear in the outer-most message.
914	for _, nested := range descs {
915		for i, enum := range nested.EnumType {
916			sl = append(sl, newEnumDescriptor(enum, nested, file, i))
917		}
918	}
919	return sl
920}
921
922// Return a slice of all the top-level ExtensionDescriptors defined within this file.
923func wrapExtensions(file *FileDescriptor) []*ExtensionDescriptor {
924	var sl []*ExtensionDescriptor
925	for _, field := range file.Extension {
926		sl = append(sl, &ExtensionDescriptor{common{file}, field, nil})
927	}
928	return sl
929}
930
931// Return a slice of all the types that are publicly imported into this file.
932func wrapImported(file *FileDescriptor, g *Generator) (sl []*ImportedDescriptor) {
933	for _, index := range file.PublicDependency {
934		df := g.fileByName(file.Dependency[index])
935		for _, d := range df.desc {
936			if d.GetOptions().GetMapEntry() {
937				continue
938			}
939			sl = append(sl, &ImportedDescriptor{common{file}, d})
940		}
941		for _, e := range df.enum {
942			sl = append(sl, &ImportedDescriptor{common{file}, e})
943		}
944		for _, ext := range df.ext {
945			sl = append(sl, &ImportedDescriptor{common{file}, ext})
946		}
947	}
948	return
949}
950
951func extractComments(file *FileDescriptor) {
952	file.comments = make(map[string]*descriptor.SourceCodeInfo_Location)
953	for _, loc := range file.GetSourceCodeInfo().GetLocation() {
954		if loc.LeadingComments == nil {
955			continue
956		}
957		var p []string
958		for _, n := range loc.Path {
959			p = append(p, strconv.Itoa(int(n)))
960		}
961		file.comments[strings.Join(p, ",")] = loc
962	}
963}
964
965// BuildTypeNameMap builds the map from fully qualified type names to objects.
966// The key names for the map come from the input data, which puts a period at the beginning.
967// It should be called after SetPackageNames and before GenerateAllFiles.
968func (g *Generator) BuildTypeNameMap() {
969	g.typeNameToObject = make(map[string]Object)
970	for _, f := range g.allFiles {
971		// The names in this loop are defined by the proto world, not us, so the
972		// package name may be empty.  If so, the dotted package name of X will
973		// be ".X"; otherwise it will be ".pkg.X".
974		dottedPkg := "." + f.GetPackage()
975		if dottedPkg != "." {
976			dottedPkg += "."
977		}
978		for _, enum := range f.enum {
979			name := dottedPkg + dottedSlice(enum.TypeName())
980			g.typeNameToObject[name] = enum
981		}
982		for _, desc := range f.desc {
983			name := dottedPkg + dottedSlice(desc.TypeName())
984			g.typeNameToObject[name] = desc
985		}
986	}
987}
988
989// ObjectNamed, given a fully-qualified input type name as it appears in the input data,
990// returns the descriptor for the message or enum with that name.
991func (g *Generator) ObjectNamed(typeName string) Object {
992	o, ok := g.typeNameToObject[typeName]
993	if !ok {
994		g.Fail("can't find object with type", typeName)
995	}
996
997	// If the file of this object isn't a direct dependency of the current file,
998	// or in the current file, then this object has been publicly imported into
999	// a dependency of the current file.
1000	// We should return the ImportedDescriptor object for it instead.
1001	direct := *o.File().Name == *g.file.Name
1002	if !direct {
1003		for _, dep := range g.file.Dependency {
1004			if *g.fileByName(dep).Name == *o.File().Name {
1005				direct = true
1006				break
1007			}
1008		}
1009	}
1010	if !direct {
1011		found := false
1012	Loop:
1013		for _, dep := range g.file.Dependency {
1014			df := g.fileByName(*g.fileByName(dep).Name)
1015			for _, td := range df.imp {
1016				if td.o == o {
1017					// Found it!
1018					o = td
1019					found = true
1020					break Loop
1021				}
1022			}
1023		}
1024		if !found {
1025			log.Printf("protoc-gen-gogo: WARNING: failed finding publicly imported dependency for %v, used in %v", typeName, *g.file.Name)
1026		}
1027	}
1028
1029	return o
1030}
1031
1032// AnnotatedAtoms is a list of atoms (as consumed by P) that records the file name and proto AST path from which they originated.
1033type AnnotatedAtoms struct {
1034	source string
1035	path   string
1036	atoms  []interface{}
1037}
1038
1039// Annotate records the file name and proto AST path of a list of atoms
1040// so that a later call to P can emit a link from each atom to its origin.
1041func Annotate(file *FileDescriptor, path string, atoms ...interface{}) *AnnotatedAtoms {
1042	return &AnnotatedAtoms{source: *file.Name, path: path, atoms: atoms}
1043}
1044
1045// printAtom prints the (atomic, non-annotation) argument to the generated output.
1046func (g *Generator) printAtom(v interface{}) {
1047	switch v := v.(type) {
1048	case string:
1049		g.WriteString(v)
1050	case *string:
1051		g.WriteString(*v)
1052	case bool:
1053		fmt.Fprint(g, v)
1054	case *bool:
1055		fmt.Fprint(g, *v)
1056	case int:
1057		fmt.Fprint(g, v)
1058	case *int32:
1059		fmt.Fprint(g, *v)
1060	case *int64:
1061		fmt.Fprint(g, *v)
1062	case float64:
1063		fmt.Fprint(g, v)
1064	case *float64:
1065		fmt.Fprint(g, *v)
1066	case GoPackageName:
1067		g.WriteString(string(v))
1068	case GoImportPath:
1069		g.WriteString(strconv.Quote(string(v)))
1070	default:
1071		g.Fail(fmt.Sprintf("unknown type in printer: %T", v))
1072	}
1073}
1074
1075// P prints the arguments to the generated output.  It handles strings and int32s, plus
1076// handling indirections because they may be *string, etc.  Any inputs of type AnnotatedAtoms may emit
1077// annotations in a .meta file in addition to outputting the atoms themselves (if g.annotateCode
1078// is true).
1079func (g *Generator) P(str ...interface{}) {
1080	if !g.writeOutput {
1081		return
1082	}
1083	g.WriteString(g.indent)
1084	for _, v := range str {
1085		switch v := v.(type) {
1086		case *AnnotatedAtoms:
1087			begin := int32(g.Len())
1088			for _, v := range v.atoms {
1089				g.printAtom(v)
1090			}
1091			if g.annotateCode {
1092				end := int32(g.Len())
1093				var path []int32
1094				for _, token := range strings.Split(v.path, ",") {
1095					val, err := strconv.ParseInt(token, 10, 32)
1096					if err != nil {
1097						g.Fail("could not parse proto AST path: ", err.Error())
1098					}
1099					path = append(path, int32(val))
1100				}
1101				g.annotations = append(g.annotations, &descriptor.GeneratedCodeInfo_Annotation{
1102					Path:       path,
1103					SourceFile: &v.source,
1104					Begin:      &begin,
1105					End:        &end,
1106				})
1107			}
1108		default:
1109			g.printAtom(v)
1110		}
1111	}
1112	g.WriteByte('\n')
1113}
1114
1115// addInitf stores the given statement to be printed inside the file's init function.
1116// The statement is given as a format specifier and arguments.
1117func (g *Generator) addInitf(stmt string, a ...interface{}) {
1118	g.init = append(g.init, fmt.Sprintf(stmt, a...))
1119}
1120
1121func (g *Generator) PrintImport(alias GoPackageName, pkg GoImportPath) {
1122	statement := "import " + string(alias) + " " + strconv.Quote(string(pkg))
1123	if g.writtenImports[statement] {
1124		return
1125	}
1126	g.P(statement)
1127	g.writtenImports[statement] = true
1128}
1129
1130// In Indents the output one tab stop.
1131func (g *Generator) In() { g.indent += "\t" }
1132
1133// Out unindents the output one tab stop.
1134func (g *Generator) Out() {
1135	if len(g.indent) > 0 {
1136		g.indent = g.indent[1:]
1137	}
1138}
1139
1140// GenerateAllFiles generates the output for all the files we're outputting.
1141func (g *Generator) GenerateAllFiles() {
1142	// Initialize the plugins
1143	for _, p := range plugins {
1144		p.Init(g)
1145	}
1146	// Generate the output. The generator runs for every file, even the files
1147	// that we don't generate output for, so that we can collate the full list
1148	// of exported symbols to support public imports.
1149	genFileMap := make(map[*FileDescriptor]bool, len(g.genFiles))
1150	for _, file := range g.genFiles {
1151		genFileMap[file] = true
1152	}
1153	for _, file := range g.allFiles {
1154		g.Reset()
1155		g.annotations = nil
1156		g.writeOutput = genFileMap[file]
1157		g.generate(file)
1158		if !g.writeOutput {
1159			continue
1160		}
1161		fname := file.goFileName(g.pathType)
1162		g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{
1163			Name:    proto.String(fname),
1164			Content: proto.String(g.String()),
1165		})
1166		if g.annotateCode {
1167			// Store the generated code annotations in text, as the protoc plugin protocol requires that
1168			// strings contain valid UTF-8.
1169			g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{
1170				Name:    proto.String(file.goFileName(g.pathType) + ".meta"),
1171				Content: proto.String(proto.CompactTextString(&descriptor.GeneratedCodeInfo{Annotation: g.annotations})),
1172			})
1173		}
1174	}
1175}
1176
1177// Run all the plugins associated with the file.
1178func (g *Generator) runPlugins(file *FileDescriptor) {
1179	for _, p := range plugins {
1180		p.Generate(file)
1181	}
1182}
1183
1184// Fill the response protocol buffer with the generated output for all the files we're
1185// supposed to generate.
1186func (g *Generator) generate(file *FileDescriptor) {
1187	g.customImports = make([]string, 0)
1188	g.file = file
1189	g.usedPackages = make(map[GoImportPath]bool)
1190	g.packageNames = make(map[GoImportPath]GoPackageName)
1191	g.usedPackageNames = make(map[GoPackageName]bool)
1192	for name := range globalPackageNames {
1193		g.usedPackageNames[name] = true
1194	}
1195
1196	g.P("// This is a compile-time assertion to ensure that this generated file")
1197	g.P("// is compatible with the proto package it is being compiled against.")
1198	g.P("// A compilation error at this line likely means your copy of the")
1199	g.P("// proto package needs to be updated.")
1200	if gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
1201		g.P("const _ = ", g.Pkg["proto"], ".GoGoProtoPackageIsVersion", generatedCodeVersion, " // please upgrade the proto package")
1202	} else {
1203		g.P("const _ = ", g.Pkg["proto"], ".ProtoPackageIsVersion", generatedCodeVersion, " // please upgrade the proto package")
1204	}
1205	g.P()
1206	// Reset on each file
1207	g.writtenImports = make(map[string]bool)
1208	for _, td := range g.file.imp {
1209		g.generateImported(td)
1210	}
1211	for _, enum := range g.file.enum {
1212		g.generateEnum(enum)
1213	}
1214	for _, desc := range g.file.desc {
1215		// Don't generate virtual messages for maps.
1216		if desc.GetOptions().GetMapEntry() {
1217			continue
1218		}
1219		g.generateMessage(desc)
1220	}
1221	for _, ext := range g.file.ext {
1222		g.generateExtension(ext)
1223	}
1224	g.generateInitFunction()
1225
1226	// Run the plugins before the imports so we know which imports are necessary.
1227	g.runPlugins(file)
1228
1229	g.generateFileDescriptor(file)
1230
1231	// Generate header and imports last, though they appear first in the output.
1232	rem := g.Buffer
1233	remAnno := g.annotations
1234	g.Buffer = new(bytes.Buffer)
1235	g.annotations = nil
1236	g.generateHeader()
1237	g.generateImports()
1238	if !g.writeOutput {
1239		return
1240	}
1241	// Adjust the offsets for annotations displaced by the header and imports.
1242	for _, anno := range remAnno {
1243		*anno.Begin += int32(g.Len())
1244		*anno.End += int32(g.Len())
1245		g.annotations = append(g.annotations, anno)
1246	}
1247	g.Write(rem.Bytes())
1248
1249	// Reformat generated code and patch annotation locations.
1250	fset := token.NewFileSet()
1251	original := g.Bytes()
1252	if g.annotateCode {
1253		// make a copy independent of g; we'll need it after Reset.
1254		original = append([]byte(nil), original...)
1255	}
1256	ast, err := parser.ParseFile(fset, "", original, parser.ParseComments)
1257	if err != nil {
1258		// Print out the bad code with line numbers.
1259		// This should never happen in practice, but it can while changing generated code,
1260		// so consider this a debugging aid.
1261		var src bytes.Buffer
1262		s := bufio.NewScanner(bytes.NewReader(original))
1263		for line := 1; s.Scan(); line++ {
1264			fmt.Fprintf(&src, "%5d\t%s\n", line, s.Bytes())
1265		}
1266		if serr := s.Err(); serr != nil {
1267			g.Fail("bad Go source code was generated:", err.Error(), "\n"+string(original))
1268		} else {
1269			g.Fail("bad Go source code was generated:", err.Error(), "\n"+src.String())
1270		}
1271	}
1272	g.Reset()
1273	err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(g, fset, ast)
1274	if err != nil {
1275		g.Fail("generated Go source code could not be reformatted:", err.Error())
1276	}
1277	if g.annotateCode {
1278		m, err := remap.Compute(original, g.Bytes())
1279		if err != nil {
1280			g.Fail("formatted generated Go source code could not be mapped back to the original code:", err.Error())
1281		}
1282		for _, anno := range g.annotations {
1283			new, ok := m.Find(int(*anno.Begin), int(*anno.End))
1284			if !ok {
1285				g.Fail("span in formatted generated Go source code could not be mapped back to the original code")
1286			}
1287			*anno.Begin = int32(new.Pos)
1288			*anno.End = int32(new.End)
1289		}
1290	}
1291}
1292
1293// Generate the header, including package definition
1294func (g *Generator) generateHeader() {
1295	g.P("// Code generated by protoc-gen-gogo. DO NOT EDIT.")
1296	if g.file.GetOptions().GetDeprecated() {
1297		g.P("// ", *g.file.Name, " is a deprecated file.")
1298	} else {
1299		g.P("// source: ", *g.file.Name)
1300	}
1301	g.P()
1302
1303	importPath, _, _ := g.file.goPackageOption()
1304	if importPath == "" {
1305		g.P("package ", g.file.packageName)
1306	} else {
1307		g.P("package ", g.file.packageName, " // import ", GoImportPath(g.ImportPrefix)+importPath)
1308	}
1309	g.P()
1310
1311	if loc, ok := g.file.comments[strconv.Itoa(packagePath)]; ok {
1312		g.P("/*")
1313		// not using g.PrintComments because this is a /* */ comment block.
1314		text := strings.TrimSuffix(loc.GetLeadingComments(), "\n")
1315		for _, line := range strings.Split(text, "\n") {
1316			line = strings.TrimPrefix(line, " ")
1317			// ensure we don't escape from the block comment
1318			line = strings.Replace(line, "*/", "* /", -1)
1319			g.P(line)
1320		}
1321		g.P("*/")
1322		g.P()
1323	}
1324}
1325
1326// deprecationComment is the standard comment added to deprecated
1327// messages, fields, enums, and enum values.
1328var deprecationComment = "// Deprecated: Do not use."
1329
1330// PrintComments prints any comments from the source .proto file.
1331// The path is a comma-separated list of integers.
1332// It returns an indication of whether any comments were printed.
1333// See descriptor.proto for its format.
1334func (g *Generator) PrintComments(path string) bool {
1335	if !g.writeOutput {
1336		return false
1337	}
1338	if loc, ok := g.file.comments[path]; ok {
1339		text := strings.TrimSuffix(loc.GetLeadingComments(), "\n")
1340		for _, line := range strings.Split(text, "\n") {
1341			g.P("// ", strings.TrimPrefix(line, " "))
1342		}
1343		return true
1344	}
1345	return false
1346}
1347
1348// Comments returns any comments from the source .proto file and empty string if comments not found.
1349// The path is a comma-separated list of intergers.
1350// See descriptor.proto for its format.
1351func (g *Generator) Comments(path string) string {
1352	loc, ok := g.file.comments[path]
1353	if !ok {
1354		return ""
1355	}
1356	text := strings.TrimSuffix(loc.GetLeadingComments(), "\n")
1357	return text
1358}
1359
1360func (g *Generator) fileByName(filename string) *FileDescriptor {
1361	return g.allFilesByName[filename]
1362}
1363
1364// weak returns whether the ith import of the current file is a weak import.
1365func (g *Generator) weak(i int32) bool {
1366	for _, j := range g.file.WeakDependency {
1367		if j == i {
1368			return true
1369		}
1370	}
1371	return false
1372}
1373
1374// Generate the imports
1375func (g *Generator) generateImports() {
1376	// We almost always need a proto import.  Rather than computing when we
1377	// do, which is tricky when there's a plugin, just import it and
1378	// reference it later. The same argument applies to the fmt and math packages.
1379	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) {
1380		g.PrintImport(GoPackageName(g.Pkg["proto"]), GoImportPath(g.ImportPrefix)+GoImportPath("github.com/gogo/protobuf/proto"))
1381		if gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
1382			g.PrintImport(GoPackageName(g.Pkg["golang_proto"]), GoImportPath(g.ImportPrefix)+GoImportPath("github.com/golang/protobuf/proto"))
1383		}
1384	} else {
1385		g.PrintImport(GoPackageName(g.Pkg["proto"]), GoImportPath(g.ImportPrefix)+GoImportPath("github.com/golang/protobuf/proto"))
1386	}
1387	g.PrintImport(GoPackageName(g.Pkg["fmt"]), "fmt")
1388	g.PrintImport(GoPackageName(g.Pkg["math"]), "math")
1389
1390	var (
1391		imports       = make(map[GoImportPath]bool)
1392		strongImports = make(map[GoImportPath]bool)
1393		importPaths   []string
1394	)
1395	for i, s := range g.file.Dependency {
1396		fd := g.fileByName(s)
1397		importPath := fd.importPath
1398		// Do not import our own package.
1399		if importPath == g.file.importPath {
1400			continue
1401		}
1402		if !imports[importPath] {
1403			importPaths = append(importPaths, string(importPath))
1404		}
1405		imports[importPath] = true
1406		if !g.weak(int32(i)) {
1407			strongImports[importPath] = true
1408		}
1409	}
1410	sort.Strings(importPaths)
1411	for i := range importPaths {
1412		importPath := GoImportPath(importPaths[i])
1413		packageName := g.GoPackageName(importPath)
1414		fullPath := GoImportPath(g.ImportPrefix) + importPath
1415		// Skip weak imports.
1416		if !strongImports[importPath] {
1417			g.P("// skipping weak import ", packageName, " ", fullPath)
1418			continue
1419		}
1420		// We need to import all the dependencies, even if we don't reference them,
1421		// because other code and tools depend on having the full transitive closure
1422		// of protocol buffer types in the binary.
1423		if _, ok := g.usedPackages[importPath]; ok {
1424			g.PrintImport(packageName, fullPath)
1425		} else {
1426			g.P("import _ ", fullPath)
1427		}
1428	}
1429	g.P()
1430	for _, s := range g.customImports {
1431		s1 := strings.Map(badToUnderscore, s)
1432		g.PrintImport(GoPackageName(s1), GoImportPath(s))
1433	}
1434	g.P()
1435	// TODO: may need to worry about uniqueness across plugins
1436	for _, p := range plugins {
1437		p.GenerateImports(g.file)
1438		g.P()
1439	}
1440	g.P("// Reference imports to suppress errors if they are not otherwise used.")
1441	g.P("var _ = ", g.Pkg["proto"], ".Marshal")
1442	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
1443		g.P("var _ = ", g.Pkg["golang_proto"], ".Marshal")
1444	}
1445	g.P("var _ = ", g.Pkg["fmt"], ".Errorf")
1446	g.P("var _ = ", g.Pkg["math"], ".Inf")
1447	for _, cimport := range g.customImports {
1448		if cimport == "time" {
1449			g.P("var _ = time.Kitchen")
1450			break
1451		}
1452	}
1453	g.P()
1454}
1455
1456func (g *Generator) generateImported(id *ImportedDescriptor) {
1457	tn := id.TypeName()
1458	sn := tn[len(tn)-1]
1459	df := id.o.File()
1460	filename := *df.Name
1461	if df.importPath == g.file.importPath {
1462		// Don't generate type aliases for files in the same Go package as this one.
1463		g.P("// Ignoring public import of ", sn, " from ", filename)
1464		g.P()
1465		return
1466	}
1467	if !supportTypeAliases {
1468		g.Fail(fmt.Sprintf("%s: public imports require at least go1.9", filename))
1469	}
1470	g.P("// ", sn, " from public import ", filename)
1471	g.usedPackages[df.importPath] = true
1472
1473	for _, sym := range df.exported[id.o] {
1474		sym.GenerateAlias(g, g.GoPackageName(df.importPath))
1475	}
1476
1477	g.P()
1478}
1479
1480// Generate the enum definitions for this EnumDescriptor.
1481func (g *Generator) generateEnum(enum *EnumDescriptor) {
1482	// The full type name
1483	typeName := enum.alias()
1484	// The full type name, CamelCased.
1485	ccTypeName := CamelCaseSlice(typeName)
1486	ccPrefix := enum.prefix()
1487
1488	deprecatedEnum := ""
1489	if enum.GetOptions().GetDeprecated() {
1490		deprecatedEnum = deprecationComment
1491	}
1492
1493	g.PrintComments(enum.path)
1494	if !gogoproto.EnabledGoEnumPrefix(enum.file.FileDescriptorProto, enum.EnumDescriptorProto) {
1495		ccPrefix = ""
1496	}
1497
1498	if gogoproto.HasEnumDecl(enum.file.FileDescriptorProto, enum.EnumDescriptorProto) {
1499		g.P("type ", Annotate(enum.file, enum.path, ccTypeName), " int32", deprecatedEnum)
1500		g.file.addExport(enum, enumSymbol{ccTypeName, enum.proto3()})
1501		g.P("const (")
1502		g.In()
1503		for i, e := range enum.Value {
1504			etorPath := fmt.Sprintf("%s,%d,%d", enum.path, enumValuePath, i)
1505			g.PrintComments(etorPath)
1506
1507			deprecatedValue := ""
1508			if e.GetOptions().GetDeprecated() {
1509				deprecatedValue = deprecationComment
1510			}
1511			name := *e.Name
1512			if gogoproto.IsEnumValueCustomName(e) {
1513				name = gogoproto.GetEnumValueCustomName(e)
1514			}
1515			name = ccPrefix + name
1516
1517			g.P(Annotate(enum.file, etorPath, name), " ", ccTypeName, " = ", e.Number, " ", deprecatedValue)
1518			g.file.addExport(enum, constOrVarSymbol{name, "const", ccTypeName})
1519		}
1520		g.Out()
1521		g.P(")")
1522	}
1523
1524	g.P("var ", ccTypeName, "_name = map[int32]string{")
1525	g.In()
1526	generated := make(map[int32]bool) // avoid duplicate values
1527	for _, e := range enum.Value {
1528		duplicate := ""
1529		if _, present := generated[*e.Number]; present {
1530			duplicate = "// Duplicate value: "
1531		}
1532		g.P(duplicate, e.Number, ": ", strconv.Quote(*e.Name), ",")
1533		generated[*e.Number] = true
1534	}
1535	g.Out()
1536	g.P("}")
1537	g.P("var ", ccTypeName, "_value = map[string]int32{")
1538	g.In()
1539	for _, e := range enum.Value {
1540		g.P(strconv.Quote(*e.Name), ": ", e.Number, ",")
1541	}
1542	g.Out()
1543	g.P("}")
1544
1545	if !enum.proto3() {
1546		g.P("func (x ", ccTypeName, ") Enum() *", ccTypeName, " {")
1547		g.In()
1548		g.P("p := new(", ccTypeName, ")")
1549		g.P("*p = x")
1550		g.P("return p")
1551		g.Out()
1552		g.P("}")
1553	}
1554
1555	if gogoproto.IsGoEnumStringer(g.file.FileDescriptorProto, enum.EnumDescriptorProto) {
1556		g.P("func (x ", ccTypeName, ") String() string {")
1557		g.In()
1558		g.P("return ", g.Pkg["proto"], ".EnumName(", ccTypeName, "_name, int32(x))")
1559		g.Out()
1560		g.P("}")
1561	}
1562
1563	if !enum.proto3() && !gogoproto.IsGoEnumStringer(g.file.FileDescriptorProto, enum.EnumDescriptorProto) {
1564		g.P("func (x ", ccTypeName, ") MarshalJSON() ([]byte, error) {")
1565		g.In()
1566		g.P("return ", g.Pkg["proto"], ".MarshalJSONEnum(", ccTypeName, "_name, int32(x))")
1567		g.Out()
1568		g.P("}")
1569	}
1570	if !enum.proto3() {
1571		g.P("func (x *", ccTypeName, ") UnmarshalJSON(data []byte) error {")
1572		g.In()
1573		g.P("value, err := ", g.Pkg["proto"], ".UnmarshalJSONEnum(", ccTypeName, `_value, data, "`, ccTypeName, `")`)
1574		g.P("if err != nil {")
1575		g.In()
1576		g.P("return err")
1577		g.Out()
1578		g.P("}")
1579		g.P("*x = ", ccTypeName, "(value)")
1580		g.P("return nil")
1581		g.Out()
1582		g.P("}")
1583	}
1584
1585	var indexes []string
1586	for m := enum.parent; m != nil; m = m.parent {
1587		// XXX: skip groups?
1588		indexes = append([]string{strconv.Itoa(m.index)}, indexes...)
1589	}
1590	indexes = append(indexes, strconv.Itoa(enum.index))
1591	g.P("func (", ccTypeName, ") EnumDescriptor() ([]byte, []int) {")
1592	g.In()
1593	g.P("return ", g.file.VarName(), ", []int{", strings.Join(indexes, ", "), "}")
1594	g.Out()
1595	g.P("}")
1596	if enum.file.GetPackage() == "google.protobuf" && enum.GetName() == "NullValue" {
1597		g.P("func (", ccTypeName, `) XXX_WellKnownType() string { return "`, enum.GetName(), `" }`)
1598	}
1599
1600	g.P()
1601}
1602
1603// The tag is a string like "varint,2,opt,name=fieldname,def=7" that
1604// identifies details of the field for the protocol buffer marshaling and unmarshaling
1605// code.  The fields are:
1606//	wire encoding
1607//	protocol tag number
1608//	opt,req,rep for optional, required, or repeated
1609//	packed whether the encoding is "packed" (optional; repeated primitives only)
1610//	name= the original declared name
1611//	enum= the name of the enum type if it is an enum-typed field.
1612//	proto3 if this field is in a proto3 message
1613//	def= string representation of the default value, if any.
1614// The default value must be in a representation that can be used at run-time
1615// to generate the default value. Thus bools become 0 and 1, for instance.
1616func (g *Generator) goTag(message *Descriptor, field *descriptor.FieldDescriptorProto, wiretype string) string {
1617	optrepreq := ""
1618	switch {
1619	case isOptional(field):
1620		optrepreq = "opt"
1621	case isRequired(field):
1622		optrepreq = "req"
1623	case isRepeated(field):
1624		optrepreq = "rep"
1625	}
1626	var defaultValue string
1627	if dv := field.DefaultValue; dv != nil { // set means an explicit default
1628		defaultValue = *dv
1629		// Some types need tweaking.
1630		switch *field.Type {
1631		case descriptor.FieldDescriptorProto_TYPE_BOOL:
1632			if defaultValue == "true" {
1633				defaultValue = "1"
1634			} else {
1635				defaultValue = "0"
1636			}
1637		case descriptor.FieldDescriptorProto_TYPE_STRING,
1638			descriptor.FieldDescriptorProto_TYPE_BYTES:
1639			// Nothing to do. Quoting is done for the whole tag.
1640		case descriptor.FieldDescriptorProto_TYPE_ENUM:
1641			// For enums we need to provide the integer constant.
1642			obj := g.ObjectNamed(field.GetTypeName())
1643			if id, ok := obj.(*ImportedDescriptor); ok {
1644				// It is an enum that was publicly imported.
1645				// We need the underlying type.
1646				obj = id.o
1647			}
1648			enum, ok := obj.(*EnumDescriptor)
1649			if !ok {
1650				log.Printf("obj is a %T", obj)
1651				if id, ok := obj.(*ImportedDescriptor); ok {
1652					log.Printf("id.o is a %T", id.o)
1653				}
1654				g.Fail("unknown enum type", CamelCaseSlice(obj.TypeName()))
1655			}
1656			defaultValue = enum.integerValueAsString(defaultValue)
1657		}
1658		defaultValue = ",def=" + defaultValue
1659	}
1660	enum := ""
1661	if *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM {
1662		// We avoid using obj.goPackageNamehe
1663		// original (proto-world) package name.
1664		obj := g.ObjectNamed(field.GetTypeName())
1665		if id, ok := obj.(*ImportedDescriptor); ok {
1666			obj = id.o
1667		}
1668		enum = ",enum="
1669		if pkg := obj.File().GetPackage(); pkg != "" {
1670			enum += pkg + "."
1671		}
1672		enum += CamelCaseSlice(obj.TypeName())
1673	}
1674	packed := ""
1675	if (field.Options != nil && field.Options.GetPacked()) ||
1676		// Per https://developers.google.com/protocol-buffers/docs/proto3#simple:
1677		// "In proto3, repeated fields of scalar numeric types use packed encoding by default."
1678		(message.proto3() && (field.Options == nil || field.Options.Packed == nil) &&
1679			isRepeated(field) && IsScalar(field)) {
1680		packed = ",packed"
1681	}
1682	fieldName := field.GetName()
1683	name := fieldName
1684	if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP {
1685		// We must use the type name for groups instead of
1686		// the field name to preserve capitalization.
1687		// type_name in FieldDescriptorProto is fully-qualified,
1688		// but we only want the local part.
1689		name = *field.TypeName
1690		if i := strings.LastIndex(name, "."); i >= 0 {
1691			name = name[i+1:]
1692		}
1693	}
1694	if json := field.GetJsonName(); json != "" && json != name {
1695		// TODO: escaping might be needed, in which case
1696		// perhaps this should be in its own "json" tag.
1697		name += ",json=" + json
1698	}
1699	name = ",name=" + name
1700
1701	embed := ""
1702	if gogoproto.IsEmbed(field) {
1703		embed = ",embedded=" + fieldName
1704	}
1705
1706	ctype := ""
1707	if gogoproto.IsCustomType(field) {
1708		ctype = ",customtype=" + gogoproto.GetCustomType(field)
1709	}
1710
1711	casttype := ""
1712	if gogoproto.IsCastType(field) {
1713		casttype = ",casttype=" + gogoproto.GetCastType(field)
1714	}
1715
1716	castkey := ""
1717	if gogoproto.IsCastKey(field) {
1718		castkey = ",castkey=" + gogoproto.GetCastKey(field)
1719	}
1720
1721	castvalue := ""
1722	if gogoproto.IsCastValue(field) {
1723		castvalue = ",castvalue=" + gogoproto.GetCastValue(field)
1724		// record the original message type for jsonpb reconstruction
1725		desc := g.ObjectNamed(field.GetTypeName())
1726		if d, ok := desc.(*Descriptor); ok && d.GetOptions().GetMapEntry() {
1727			valueField := d.Field[1]
1728			if valueField.IsMessage() {
1729				castvalue += ",castvaluetype=" + strings.TrimPrefix(valueField.GetTypeName(), ".")
1730			}
1731		}
1732	}
1733
1734	if message.proto3() {
1735		// We only need the extra tag for []byte fields;
1736		// no need to add noise for the others.
1737		if *field.Type != descriptor.FieldDescriptorProto_TYPE_MESSAGE &&
1738			*field.Type != descriptor.FieldDescriptorProto_TYPE_GROUP &&
1739			!field.IsRepeated() {
1740			name += ",proto3"
1741		}
1742	}
1743	oneof := ""
1744	if field.OneofIndex != nil {
1745		oneof = ",oneof"
1746	}
1747	stdtime := ""
1748	if gogoproto.IsStdTime(field) {
1749		stdtime = ",stdtime"
1750	}
1751	stdduration := ""
1752	if gogoproto.IsStdDuration(field) {
1753		stdduration = ",stdduration"
1754	}
1755	return strconv.Quote(fmt.Sprintf("%s,%d,%s%s%s%s%s%s%s%s%s%s%s%s%s",
1756		wiretype,
1757		field.GetNumber(),
1758		optrepreq,
1759		packed,
1760		name,
1761		enum,
1762		oneof,
1763		defaultValue,
1764		embed,
1765		ctype,
1766		casttype,
1767		castkey,
1768		castvalue,
1769		stdtime,
1770		stdduration))
1771}
1772
1773func needsStar(field *descriptor.FieldDescriptorProto, proto3 bool, allowOneOf bool) bool {
1774	if isRepeated(field) &&
1775		(*field.Type != descriptor.FieldDescriptorProto_TYPE_MESSAGE || gogoproto.IsCustomType(field)) &&
1776		(*field.Type != descriptor.FieldDescriptorProto_TYPE_GROUP) {
1777		return false
1778	}
1779	if *field.Type == descriptor.FieldDescriptorProto_TYPE_BYTES && !gogoproto.IsCustomType(field) {
1780		return false
1781	}
1782	if !gogoproto.IsNullable(field) {
1783		return false
1784	}
1785	if field.OneofIndex != nil && allowOneOf &&
1786		(*field.Type != descriptor.FieldDescriptorProto_TYPE_MESSAGE) &&
1787		(*field.Type != descriptor.FieldDescriptorProto_TYPE_GROUP) {
1788		return false
1789	}
1790	if proto3 &&
1791		(*field.Type != descriptor.FieldDescriptorProto_TYPE_MESSAGE) &&
1792		(*field.Type != descriptor.FieldDescriptorProto_TYPE_GROUP) &&
1793		!gogoproto.IsCustomType(field) {
1794		return false
1795	}
1796	return true
1797}
1798
1799// TypeName is the printed name appropriate for an item. If the object is in the current file,
1800// TypeName drops the package name and underscores the rest.
1801// Otherwise the object is from another package; and the result is the underscored
1802// package name followed by the item name.
1803// The result always has an initial capital.
1804func (g *Generator) TypeName(obj Object) string {
1805	return g.DefaultPackageName(obj) + CamelCaseSlice(obj.TypeName())
1806}
1807
1808// GoType returns a string representing the type name, and the wire type
1809func (g *Generator) GoType(message *Descriptor, field *descriptor.FieldDescriptorProto) (typ string, wire string) {
1810	// TODO: Options.
1811	switch *field.Type {
1812	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
1813		typ, wire = "float64", "fixed64"
1814	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
1815		typ, wire = "float32", "fixed32"
1816	case descriptor.FieldDescriptorProto_TYPE_INT64:
1817		typ, wire = "int64", "varint"
1818	case descriptor.FieldDescriptorProto_TYPE_UINT64:
1819		typ, wire = "uint64", "varint"
1820	case descriptor.FieldDescriptorProto_TYPE_INT32:
1821		typ, wire = "int32", "varint"
1822	case descriptor.FieldDescriptorProto_TYPE_UINT32:
1823		typ, wire = "uint32", "varint"
1824	case descriptor.FieldDescriptorProto_TYPE_FIXED64:
1825		typ, wire = "uint64", "fixed64"
1826	case descriptor.FieldDescriptorProto_TYPE_FIXED32:
1827		typ, wire = "uint32", "fixed32"
1828	case descriptor.FieldDescriptorProto_TYPE_BOOL:
1829		typ, wire = "bool", "varint"
1830	case descriptor.FieldDescriptorProto_TYPE_STRING:
1831		typ, wire = "string", "bytes"
1832	case descriptor.FieldDescriptorProto_TYPE_GROUP:
1833		desc := g.ObjectNamed(field.GetTypeName())
1834		typ, wire = g.TypeName(desc), "group"
1835	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
1836		desc := g.ObjectNamed(field.GetTypeName())
1837		typ, wire = g.TypeName(desc), "bytes"
1838	case descriptor.FieldDescriptorProto_TYPE_BYTES:
1839		typ, wire = "[]byte", "bytes"
1840	case descriptor.FieldDescriptorProto_TYPE_ENUM:
1841		desc := g.ObjectNamed(field.GetTypeName())
1842		typ, wire = g.TypeName(desc), "varint"
1843	case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
1844		typ, wire = "int32", "fixed32"
1845	case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
1846		typ, wire = "int64", "fixed64"
1847	case descriptor.FieldDescriptorProto_TYPE_SINT32:
1848		typ, wire = "int32", "zigzag32"
1849	case descriptor.FieldDescriptorProto_TYPE_SINT64:
1850		typ, wire = "int64", "zigzag64"
1851	default:
1852		g.Fail("unknown type for", field.GetName())
1853	}
1854	switch {
1855	case gogoproto.IsCustomType(field) && gogoproto.IsCastType(field):
1856		g.Fail(field.GetName() + " cannot be custom type and cast type")
1857	case gogoproto.IsCustomType(field):
1858		var packageName string
1859		var err error
1860		packageName, typ, err = getCustomType(field)
1861		if err != nil {
1862			g.Fail(err.Error())
1863		}
1864		if len(packageName) > 0 {
1865			g.customImports = append(g.customImports, packageName)
1866		}
1867	case gogoproto.IsCastType(field):
1868		var packageName string
1869		var err error
1870		packageName, typ, err = getCastType(field)
1871		if err != nil {
1872			g.Fail(err.Error())
1873		}
1874		if len(packageName) > 0 {
1875			g.customImports = append(g.customImports, packageName)
1876		}
1877	case gogoproto.IsStdTime(field):
1878		g.customImports = append(g.customImports, "time")
1879		typ = "time.Time"
1880	case gogoproto.IsStdDuration(field):
1881		g.customImports = append(g.customImports, "time")
1882		typ = "time.Duration"
1883	}
1884	if needsStar(field, g.file.proto3 && field.Extendee == nil, message != nil && message.allowOneof()) {
1885		typ = "*" + typ
1886	}
1887	if isRepeated(field) {
1888		typ = "[]" + typ
1889	}
1890	return
1891}
1892
1893// GoMapDescriptor is a full description of the map output struct.
1894type GoMapDescriptor struct {
1895	GoType string
1896
1897	KeyField      *descriptor.FieldDescriptorProto
1898	KeyAliasField *descriptor.FieldDescriptorProto
1899	KeyTag        string
1900
1901	ValueField      *descriptor.FieldDescriptorProto
1902	ValueAliasField *descriptor.FieldDescriptorProto
1903	ValueTag        string
1904}
1905
1906func (g *Generator) GoMapType(d *Descriptor, field *descriptor.FieldDescriptorProto) *GoMapDescriptor {
1907	if d == nil {
1908		byName := g.ObjectNamed(field.GetTypeName())
1909		desc, ok := byName.(*Descriptor)
1910		if byName == nil || !ok || !desc.GetOptions().GetMapEntry() {
1911			g.Fail(fmt.Sprintf("field %s is not a map", field.GetTypeName()))
1912			return nil
1913		}
1914		d = desc
1915	}
1916
1917	m := &GoMapDescriptor{
1918		KeyField:   d.Field[0],
1919		ValueField: d.Field[1],
1920	}
1921
1922	// Figure out the Go types and tags for the key and value types.
1923	m.KeyAliasField, m.ValueAliasField = g.GetMapKeyField(field, m.KeyField), g.GetMapValueField(field, m.ValueField)
1924	keyType, keyWire := g.GoType(d, m.KeyAliasField)
1925	valType, valWire := g.GoType(d, m.ValueAliasField)
1926
1927	m.KeyTag, m.ValueTag = g.goTag(d, m.KeyField, keyWire), g.goTag(d, m.ValueField, valWire)
1928
1929	if gogoproto.IsCastType(field) {
1930		var packageName string
1931		var err error
1932		packageName, typ, err := getCastType(field)
1933		if err != nil {
1934			g.Fail(err.Error())
1935		}
1936		if len(packageName) > 0 {
1937			g.customImports = append(g.customImports, packageName)
1938		}
1939		m.GoType = typ
1940		return m
1941	}
1942
1943	// We don't use stars, except for message-typed values.
1944	// Message and enum types are the only two possibly foreign types used in maps,
1945	// so record their use. They are not permitted as map keys.
1946	keyType = strings.TrimPrefix(keyType, "*")
1947	switch *m.ValueAliasField.Type {
1948	case descriptor.FieldDescriptorProto_TYPE_ENUM:
1949		valType = strings.TrimPrefix(valType, "*")
1950		g.RecordTypeUse(m.ValueAliasField.GetTypeName())
1951	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
1952		if !gogoproto.IsNullable(m.ValueAliasField) {
1953			valType = strings.TrimPrefix(valType, "*")
1954		}
1955		if !gogoproto.IsStdTime(field) && !gogoproto.IsStdDuration(field) && !gogoproto.IsCustomType(field) && !gogoproto.IsCastType(field) {
1956			g.RecordTypeUse(m.ValueAliasField.GetTypeName())
1957		}
1958	default:
1959		if gogoproto.IsCustomType(m.ValueAliasField) {
1960			if !gogoproto.IsNullable(m.ValueAliasField) {
1961				valType = strings.TrimPrefix(valType, "*")
1962			}
1963			g.RecordTypeUse(m.ValueAliasField.GetTypeName())
1964		} else {
1965			valType = strings.TrimPrefix(valType, "*")
1966		}
1967	}
1968
1969	m.GoType = fmt.Sprintf("map[%s]%s", keyType, valType)
1970	return m
1971}
1972
1973func (g *Generator) RecordTypeUse(t string) {
1974	if _, ok := g.typeNameToObject[t]; ok {
1975		// Call ObjectNamed to get the true object to record the use.
1976		obj := g.ObjectNamed(t)
1977		g.usedPackages[obj.GoImportPath()] = true
1978	}
1979}
1980
1981// Method names that may be generated.  Fields with these names get an
1982// underscore appended. Any change to this set is a potential incompatible
1983// API change because it changes generated field names.
1984var methodNames = [...]string{
1985	"Reset",
1986	"String",
1987	"ProtoMessage",
1988	"Marshal",
1989	"Unmarshal",
1990	"ExtensionRangeArray",
1991	"ExtensionMap",
1992	"Descriptor",
1993	"MarshalTo",
1994	"Equal",
1995	"VerboseEqual",
1996	"GoString",
1997	"ProtoSize",
1998}
1999
2000// Names of messages in the `google.protobuf` package for which
2001// we will generate XXX_WellKnownType methods.
2002var wellKnownTypes = map[string]bool{
2003	"Any":       true,
2004	"Duration":  true,
2005	"Empty":     true,
2006	"Struct":    true,
2007	"Timestamp": true,
2008
2009	"Value":       true,
2010	"ListValue":   true,
2011	"DoubleValue": true,
2012	"FloatValue":  true,
2013	"Int64Value":  true,
2014	"UInt64Value": true,
2015	"Int32Value":  true,
2016	"UInt32Value": true,
2017	"BoolValue":   true,
2018	"StringValue": true,
2019	"BytesValue":  true,
2020}
2021
2022// Generate the type and default constant definitions for this Descriptor.
2023func (g *Generator) generateMessage(message *Descriptor) {
2024	// The full type name
2025	typeName := message.TypeName()
2026	// The full type name, CamelCased.
2027	ccTypeName := CamelCaseSlice(typeName)
2028
2029	usedNames := make(map[string]bool)
2030	for _, n := range methodNames {
2031		usedNames[n] = true
2032	}
2033	if !gogoproto.IsProtoSizer(message.file.FileDescriptorProto, message.DescriptorProto) {
2034		usedNames["Size"] = true
2035	}
2036	fieldNames := make(map[*descriptor.FieldDescriptorProto]string)
2037	fieldGetterNames := make(map[*descriptor.FieldDescriptorProto]string)
2038	fieldTypes := make(map[*descriptor.FieldDescriptorProto]string)
2039	mapFieldTypes := make(map[*descriptor.FieldDescriptorProto]string)
2040
2041	oneofFieldName := make(map[int32]string)                           // indexed by oneof_index field of FieldDescriptorProto
2042	oneofDisc := make(map[int32]string)                                // name of discriminator method
2043	oneofTypeName := make(map[*descriptor.FieldDescriptorProto]string) // without star
2044	oneofInsertPoints := make(map[int32]int)                           // oneof_index => offset of g.Buffer
2045
2046	// allocNames finds a conflict-free variation of the given strings,
2047	// consistently mutating their suffixes.
2048	// It returns the same number of strings.
2049	allocNames := func(ns ...string) []string {
2050	Loop:
2051		for {
2052			for _, n := range ns {
2053				if usedNames[n] {
2054					for i := range ns {
2055						ns[i] += "_"
2056					}
2057					continue Loop
2058				}
2059			}
2060			for _, n := range ns {
2061				usedNames[n] = true
2062			}
2063			return ns
2064		}
2065	}
2066
2067	for _, field := range message.Field {
2068		// Allocate the getter and the field at the same time so name
2069		// collisions create field/method consistent names.
2070		// TODO: This allocation occurs based on the order of the fields
2071		// in the proto file, meaning that a change in the field
2072		// ordering can change generated Method/Field names.
2073		base := CamelCase(*field.Name)
2074		if gogoproto.IsCustomName(field) {
2075			base = gogoproto.GetCustomName(field)
2076		}
2077		ns := allocNames(base, "Get"+base)
2078		fieldName, fieldGetterName := ns[0], ns[1]
2079		fieldNames[field] = fieldName
2080		fieldGetterNames[field] = fieldGetterName
2081	}
2082
2083	if gogoproto.HasTypeDecl(message.file.FileDescriptorProto, message.DescriptorProto) {
2084		comments := g.PrintComments(message.path)
2085
2086		// Guarantee deprecation comments appear after user-provided comments.
2087		if message.GetOptions().GetDeprecated() {
2088			if comments {
2089				// Convention: Separate deprecation comments from original
2090				// comments with an empty line.
2091				g.P("//")
2092			}
2093			g.P(deprecationComment)
2094		}
2095		g.P("type ", Annotate(message.file, message.path, ccTypeName), " struct {")
2096		g.In()
2097
2098		for i, field := range message.Field {
2099			fieldName := fieldNames[field]
2100			typename, wiretype := g.GoType(message, field)
2101			jsonName := *field.Name
2102			jsonTag := jsonName + ",omitempty"
2103			repeatedNativeType := (!field.IsMessage() && !gogoproto.IsCustomType(field) && field.IsRepeated())
2104			if !gogoproto.IsNullable(field) && !repeatedNativeType {
2105				jsonTag = jsonName
2106			}
2107			gogoJsonTag := gogoproto.GetJsonTag(field)
2108			if gogoJsonTag != nil {
2109				jsonTag = *gogoJsonTag
2110			}
2111			gogoMoreTags := gogoproto.GetMoreTags(field)
2112			moreTags := ""
2113			if gogoMoreTags != nil {
2114				moreTags = " " + *gogoMoreTags
2115			}
2116			tag := fmt.Sprintf("protobuf:%s json:%q%s", g.goTag(message, field, wiretype), jsonTag, moreTags)
2117			if *field.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE && gogoproto.IsEmbed(field) {
2118				fieldName = ""
2119			}
2120
2121			oneof := field.OneofIndex != nil && message.allowOneof()
2122			if oneof && oneofFieldName[*field.OneofIndex] == "" {
2123				odp := message.OneofDecl[int(*field.OneofIndex)]
2124				fname := allocNames(CamelCase(odp.GetName()))[0]
2125
2126				// This is the first field of a oneof we haven't seen before.
2127				// Generate the union field.
2128				oneofFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageOneofPath, *field.OneofIndex)
2129				com := g.PrintComments(oneofFullPath)
2130				if com {
2131					g.P("//")
2132				}
2133				g.P("// Types that are valid to be assigned to ", fname, ":")
2134				// Generate the rest of this comment later,
2135				// when we've computed any disambiguation.
2136				oneofInsertPoints[*field.OneofIndex] = g.Buffer.Len()
2137
2138				dname := "is" + ccTypeName + "_" + fname
2139				oneofFieldName[*field.OneofIndex] = fname
2140				oneofDisc[*field.OneofIndex] = dname
2141				otag := `protobuf_oneof:"` + odp.GetName() + `"`
2142				g.P(Annotate(message.file, oneofFullPath, fname), " ", dname, " `", otag, "`")
2143			}
2144
2145			if *field.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE {
2146				desc := g.ObjectNamed(field.GetTypeName())
2147				if d, ok := desc.(*Descriptor); ok && d.GetOptions().GetMapEntry() {
2148					m := g.GoMapType(d, field)
2149					typename = m.GoType
2150					mapFieldTypes[field] = typename // record for the getter generation
2151
2152					tag += fmt.Sprintf(" protobuf_key:%s protobuf_val:%s", m.KeyTag, m.ValueTag)
2153				}
2154			}
2155
2156			fieldTypes[field] = typename
2157
2158			if oneof {
2159				tname := ccTypeName + "_" + fieldName
2160				// It is possible for this to collide with a message or enum
2161				// nested in this message. Check for collisions.
2162				for {
2163					ok := true
2164					for _, desc := range message.nested {
2165						if CamelCaseSlice(desc.TypeName()) == tname {
2166							ok = false
2167							break
2168						}
2169					}
2170					for _, enum := range message.enums {
2171						if CamelCaseSlice(enum.TypeName()) == tname {
2172							ok = false
2173							break
2174						}
2175					}
2176					if !ok {
2177						tname += "_"
2178						continue
2179					}
2180					break
2181				}
2182
2183				oneofTypeName[field] = tname
2184				continue
2185			}
2186
2187			fieldDeprecated := ""
2188			if field.GetOptions().GetDeprecated() {
2189				fieldDeprecated = deprecationComment
2190			}
2191
2192			fieldFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i)
2193			g.PrintComments(fieldFullPath)
2194			g.P(Annotate(message.file, fieldFullPath, fieldName), "\t", typename, "\t`", tag, "`", fieldDeprecated)
2195			if !gogoproto.IsStdTime(field) && !gogoproto.IsStdDuration(field) && !gogoproto.IsCustomType(field) && !gogoproto.IsCastType(field) {
2196				g.RecordTypeUse(field.GetTypeName())
2197			}
2198		}
2199		g.P("XXX_NoUnkeyedLiteral\tstruct{} `json:\"-\"`") // prevent unkeyed struct literals
2200		if len(message.ExtensionRange) > 0 {
2201			if gogoproto.HasExtensionsMap(g.file.FileDescriptorProto, message.DescriptorProto) {
2202				messageset := ""
2203				if opts := message.Options; opts != nil && opts.GetMessageSetWireFormat() {
2204					messageset = "protobuf_messageset:\"1\" "
2205				}
2206				g.P(g.Pkg["proto"], ".XXX_InternalExtensions `", messageset, "json:\"-\"`")
2207			} else {
2208				g.P("XXX_extensions\t\t[]byte `protobuf:\"bytes,0,opt\" json:\"-\"`")
2209			}
2210		}
2211		if gogoproto.HasUnrecognized(g.file.FileDescriptorProto, message.DescriptorProto) {
2212			g.P("XXX_unrecognized\t[]byte `json:\"-\"`")
2213		}
2214		g.P("XXX_sizecache\tint32 `json:\"-\"`")
2215		g.Out()
2216		g.P("}")
2217	} else {
2218		// Even if the type does not need to be generated, we need to iterate
2219		// over all its fields to be able to mark as used any imported types
2220		// used by those fields.
2221		for _, field := range message.Field {
2222			if !gogoproto.IsStdTime(field) && !gogoproto.IsStdDuration(field) && !gogoproto.IsCustomType(field) && !gogoproto.IsCastType(field) {
2223				g.RecordTypeUse(field.GetTypeName())
2224			}
2225		}
2226	}
2227
2228	// Update g.Buffer to list valid oneof types.
2229	// We do this down here, after we've disambiguated the oneof type names.
2230	// We go in reverse order of insertion point to avoid invalidating offsets.
2231	for oi := int32(len(message.OneofDecl)); oi >= 0; oi-- {
2232		ip := oneofInsertPoints[oi]
2233		all := g.Buffer.Bytes()
2234		rem := all[ip:]
2235		g.Buffer = bytes.NewBuffer(all[:ip:ip]) // set cap so we don't scribble on rem
2236		oldLen := g.Buffer.Len()
2237		for _, field := range message.Field {
2238			if field.OneofIndex == nil || *field.OneofIndex != oi {
2239				continue
2240			}
2241			g.P("//\t*", oneofTypeName[field])
2242		}
2243		// If we've inserted text, we also need to fix up affected annotations (as
2244		// they contain offsets that may need to be changed).
2245		offset := int32(g.Buffer.Len() - oldLen)
2246		ip32 := int32(ip)
2247		for _, anno := range g.annotations {
2248			if *anno.Begin >= ip32 {
2249				*anno.Begin += offset
2250			}
2251			if *anno.End >= ip32 {
2252				*anno.End += offset
2253			}
2254		}
2255		g.Buffer.Write(rem)
2256	}
2257
2258	// Reset, String and ProtoMessage methods.
2259	g.P("func (m *", ccTypeName, ") Reset() { *m = ", ccTypeName, "{} }")
2260	if gogoproto.EnabledGoStringer(g.file.FileDescriptorProto, message.DescriptorProto) {
2261		g.P("func (m *", ccTypeName, ") String() string { return ", g.Pkg["proto"], ".CompactTextString(m) }")
2262	}
2263	g.P("func (*", ccTypeName, ") ProtoMessage() {}")
2264	var indexes []string
2265	for m := message; m != nil; m = m.parent {
2266		indexes = append([]string{strconv.Itoa(m.index)}, indexes...)
2267	}
2268	g.P("func (*", ccTypeName, ") Descriptor() ([]byte, []int) {")
2269	g.In()
2270	g.P("return ", g.file.VarName(), ", []int{", strings.Join(indexes, ", "), "}")
2271	g.Out()
2272	g.P("}")
2273	// TODO: Revisit the decision to use a XXX_WellKnownType method
2274	// if we change proto.MessageName to work with multiple equivalents.
2275	if message.file.GetPackage() == "google.protobuf" && wellKnownTypes[message.GetName()] {
2276		g.P("func (*", ccTypeName, `) XXX_WellKnownType() string { return "`, message.GetName(), `" }`)
2277	}
2278	// Extension support methods
2279	var hasExtensions, isMessageSet bool
2280	if len(message.ExtensionRange) > 0 {
2281		hasExtensions = true
2282		// message_set_wire_format only makes sense when extensions are defined.
2283		if opts := message.Options; opts != nil && opts.GetMessageSetWireFormat() {
2284			isMessageSet = true
2285			g.P()
2286			g.P("func (m *", ccTypeName, ") MarshalJSON() ([]byte, error) {")
2287			g.In()
2288			g.P("return ", g.Pkg["proto"], ".MarshalMessageSetJSON(&m.XXX_InternalExtensions)")
2289			g.Out()
2290			g.P("}")
2291			g.P("func (m *", ccTypeName, ") UnmarshalJSON(buf []byte) error {")
2292			g.In()
2293			g.P("return ", g.Pkg["proto"], ".UnmarshalMessageSetJSON(buf, &m.XXX_InternalExtensions)")
2294			g.Out()
2295			g.P("}")
2296		}
2297
2298		g.P()
2299		g.P("var extRange_", ccTypeName, " = []", g.Pkg["proto"], ".ExtensionRange{")
2300		g.In()
2301		for _, r := range message.ExtensionRange {
2302			end := fmt.Sprint(*r.End - 1) // make range inclusive on both ends
2303			g.P("{Start: ", r.Start, ", End: ", end, "},")
2304		}
2305		g.Out()
2306		g.P("}")
2307		g.P("func (*", ccTypeName, ") ExtensionRangeArray() []", g.Pkg["proto"], ".ExtensionRange {")
2308		g.In()
2309		g.P("return extRange_", ccTypeName)
2310		g.Out()
2311		g.P("}")
2312		if !gogoproto.HasExtensionsMap(g.file.FileDescriptorProto, message.DescriptorProto) {
2313			g.P("func (m *", ccTypeName, ") GetExtensions() *[]byte {")
2314			g.In()
2315			g.P("if m.XXX_extensions == nil {")
2316			g.In()
2317			g.P("m.XXX_extensions = make([]byte, 0)")
2318			g.Out()
2319			g.P("}")
2320			g.P("return &m.XXX_extensions")
2321			g.Out()
2322			g.P("}")
2323		}
2324	}
2325
2326	// TODO: It does not scale to keep adding another method for every
2327	// operation on protos that we want to switch over to using the
2328	// table-driven approach. Instead, we should only add a single method
2329	// that allows getting access to the *InternalMessageInfo struct and then
2330	// calling Unmarshal, Marshal, Merge, Size, and Discard directly on that.
2331
2332	// Wrapper for table-driven marshaling and unmarshaling.
2333	g.P("func (m *", ccTypeName, ") XXX_Unmarshal(b []byte) error {")
2334	g.In()
2335	if gogoproto.IsUnmarshaler(g.file.FileDescriptorProto, message.DescriptorProto) {
2336		g.P("return m.Unmarshal(b)")
2337	} else {
2338		g.P("return xxx_messageInfo_", ccTypeName, ".Unmarshal(m, b)")
2339	}
2340	g.Out()
2341	g.P("}")
2342
2343	g.P("func (m *", ccTypeName, ") XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {")
2344	g.In()
2345	if gogoproto.IsMarshaler(g.file.FileDescriptorProto, message.DescriptorProto) ||
2346		gogoproto.IsUnsafeMarshaler(g.file.FileDescriptorProto, message.DescriptorProto) {
2347		if gogoproto.IsStableMarshaler(g.file.FileDescriptorProto, message.DescriptorProto) {
2348			g.P("b = b[:cap(b)]")
2349			g.P("n, err := m.MarshalTo(b)")
2350			g.P("if err != nil {")
2351			g.In()
2352			g.P("return nil, err")
2353			g.Out()
2354			g.P("}")
2355			g.P("return b[:n], nil")
2356		} else {
2357			g.P("if deterministic {")
2358			g.In()
2359			g.P("return xxx_messageInfo_", ccTypeName, ".Marshal(b, m, deterministic)")
2360			g.P("} else {")
2361			g.In()
2362			g.P("b = b[:cap(b)]")
2363			g.P("n, err := m.MarshalTo(b)")
2364			g.P("if err != nil {")
2365			g.In()
2366			g.P("return nil, err")
2367			g.Out()
2368			g.P("}")
2369			g.Out()
2370			g.P("return b[:n], nil")
2371			g.Out()
2372			g.P("}")
2373		}
2374	} else {
2375		g.P("return xxx_messageInfo_", ccTypeName, ".Marshal(b, m, deterministic)")
2376	}
2377	g.Out()
2378	g.P("}")
2379
2380	g.P("func (dst *", ccTypeName, ") XXX_Merge(src ", g.Pkg["proto"], ".Message) {")
2381	g.In()
2382	g.P("xxx_messageInfo_", ccTypeName, ".Merge(dst, src)")
2383	g.Out()
2384	g.P("}")
2385
2386	g.P("func (m *", ccTypeName, ") XXX_Size() int {") // avoid name clash with "Size" field in some message
2387	g.In()
2388	if (gogoproto.IsMarshaler(g.file.FileDescriptorProto, message.DescriptorProto) ||
2389		gogoproto.IsUnsafeMarshaler(g.file.FileDescriptorProto, message.DescriptorProto)) &&
2390		gogoproto.IsSizer(g.file.FileDescriptorProto, message.DescriptorProto) {
2391		g.P("return m.Size()")
2392	} else if (gogoproto.IsMarshaler(g.file.FileDescriptorProto, message.DescriptorProto) ||
2393		gogoproto.IsUnsafeMarshaler(g.file.FileDescriptorProto, message.DescriptorProto)) &&
2394		gogoproto.IsProtoSizer(g.file.FileDescriptorProto, message.DescriptorProto) {
2395		g.P("return m.ProtoSize()")
2396	} else {
2397		g.P("return xxx_messageInfo_", ccTypeName, ".Size(m)")
2398	}
2399	g.Out()
2400	g.P("}")
2401
2402	g.P("func (m *", ccTypeName, ") XXX_DiscardUnknown() {")
2403	g.In()
2404	g.P("xxx_messageInfo_", ccTypeName, ".DiscardUnknown(m)")
2405	g.Out()
2406	g.P("}")
2407
2408	g.P("var xxx_messageInfo_", ccTypeName, " ", g.Pkg["proto"], ".InternalMessageInfo")
2409
2410	// Default constants
2411	defNames := make(map[*descriptor.FieldDescriptorProto]string)
2412	for _, field := range message.Field {
2413		def := field.GetDefaultValue()
2414		if def == "" {
2415			continue
2416		}
2417		if !gogoproto.IsNullable(field) {
2418			g.Fail("illegal default value: ", field.GetName(), " in ", message.GetName(), " is not nullable and is thus not allowed to have a default value")
2419		}
2420		fieldname := "Default_" + ccTypeName + "_" + CamelCase(*field.Name)
2421		defNames[field] = fieldname
2422		typename, _ := g.GoType(message, field)
2423		if typename[0] == '*' {
2424			typename = typename[1:]
2425		}
2426		kind := "const "
2427		switch {
2428		case typename == "bool":
2429		case typename == "string":
2430			def = strconv.Quote(def)
2431		case typename == "[]byte":
2432			def = "[]byte(" + strconv.Quote(unescape(def)) + ")"
2433			kind = "var "
2434		case def == "inf", def == "-inf", def == "nan":
2435			// These names are known to, and defined by, the protocol language.
2436			switch def {
2437			case "inf":
2438				def = "math.Inf(1)"
2439			case "-inf":
2440				def = "math.Inf(-1)"
2441			case "nan":
2442				def = "math.NaN()"
2443			}
2444			if *field.Type == descriptor.FieldDescriptorProto_TYPE_FLOAT {
2445				def = "float32(" + def + ")"
2446			}
2447			kind = "var "
2448		case *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM:
2449			// Must be an enum.  Need to construct the prefixed name.
2450			obj := g.ObjectNamed(field.GetTypeName())
2451			var enum *EnumDescriptor
2452			if id, ok := obj.(*ImportedDescriptor); ok {
2453				// The enum type has been publicly imported.
2454				enum, _ = id.o.(*EnumDescriptor)
2455			} else {
2456				enum, _ = obj.(*EnumDescriptor)
2457			}
2458			if enum == nil {
2459				log.Printf("don't know how to generate constant for %s", fieldname)
2460				continue
2461			}
2462
2463			// hunt down the actual enum corresponding to the default
2464			var enumValue *descriptor.EnumValueDescriptorProto
2465			for _, ev := range enum.Value {
2466				if def == ev.GetName() {
2467					enumValue = ev
2468				}
2469			}
2470
2471			if enumValue != nil {
2472				if gogoproto.IsEnumValueCustomName(enumValue) {
2473					def = gogoproto.GetEnumValueCustomName(enumValue)
2474				}
2475			} else {
2476				g.Fail(fmt.Sprintf("could not resolve default enum value for %v.%v",
2477					g.DefaultPackageName(obj), def))
2478
2479			}
2480
2481			if gogoproto.EnabledGoEnumPrefix(enum.file.FileDescriptorProto, enum.EnumDescriptorProto) {
2482				def = g.DefaultPackageName(obj) + enum.prefix() + def
2483			} else {
2484				def = g.DefaultPackageName(obj) + def
2485			}
2486		}
2487		g.P(kind, fieldname, " ", typename, " = ", def)
2488		g.file.addExport(message, constOrVarSymbol{fieldname, kind, ""})
2489	}
2490	g.P()
2491
2492	// Oneof per-field types, discriminants and getters.
2493	// Generate unexported named types for the discriminant interfaces.
2494	// We shouldn't have to do this, but there was (~19 Aug 2015) a compiler/linker bug
2495	// that was triggered by using anonymous interfaces here.
2496	// TODO: Revisit this and consider reverting back to anonymous interfaces.
2497	for oi := range message.OneofDecl {
2498		dname := oneofDisc[int32(oi)]
2499		g.P("type ", dname, " interface {")
2500		g.In()
2501		g.P(dname, "()")
2502		if gogoproto.HasEqual(g.file.FileDescriptorProto, message.DescriptorProto) {
2503			g.P(`Equal(interface{}) bool`)
2504		}
2505		if gogoproto.HasVerboseEqual(g.file.FileDescriptorProto, message.DescriptorProto) {
2506			g.P(`VerboseEqual(interface{}) error`)
2507		}
2508		if gogoproto.IsMarshaler(g.file.FileDescriptorProto, message.DescriptorProto) ||
2509			gogoproto.IsUnsafeMarshaler(g.file.FileDescriptorProto, message.DescriptorProto) ||
2510			gogoproto.IsStableMarshaler(g.file.FileDescriptorProto, message.DescriptorProto) {
2511			g.P(`MarshalTo([]byte) (int, error)`)
2512		}
2513		if gogoproto.IsSizer(g.file.FileDescriptorProto, message.DescriptorProto) {
2514			g.P(`Size() int`)
2515		}
2516		if gogoproto.IsProtoSizer(g.file.FileDescriptorProto, message.DescriptorProto) {
2517			g.P(`ProtoSize() int`)
2518		}
2519		g.Out()
2520		g.P("}")
2521	}
2522	g.P()
2523	var oneofTypes []string
2524	for i, field := range message.Field {
2525		if field.OneofIndex == nil {
2526			continue
2527		}
2528		_, wiretype := g.GoType(message, field)
2529		tag := "protobuf:" + g.goTag(message, field, wiretype)
2530		fieldFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i)
2531		g.P("type ", Annotate(message.file, fieldFullPath, oneofTypeName[field]), " struct{ ", Annotate(message.file, fieldFullPath, fieldNames[field]), " ", fieldTypes[field], " `", tag, "` }")
2532		if !gogoproto.IsStdTime(field) && !gogoproto.IsStdDuration(field) && !gogoproto.IsCustomType(field) && !gogoproto.IsCastType(field) {
2533			g.RecordTypeUse(field.GetTypeName())
2534		}
2535		oneofTypes = append(oneofTypes, oneofTypeName[field])
2536	}
2537	g.P()
2538	for _, field := range message.Field {
2539		if field.OneofIndex == nil {
2540			continue
2541		}
2542		g.P("func (*", oneofTypeName[field], ") ", oneofDisc[*field.OneofIndex], "() {}")
2543	}
2544	g.P()
2545	for oi := range message.OneofDecl {
2546		fname := oneofFieldName[int32(oi)]
2547		g.P("func (m *", ccTypeName, ") Get", fname, "() ", oneofDisc[int32(oi)], " {")
2548		g.P("if m != nil { return m.", fname, " }")
2549		g.P("return nil")
2550		g.P("}")
2551	}
2552	g.P()
2553
2554	// Field getters
2555	for i, field := range message.Field {
2556		oneof := field.OneofIndex != nil && message.allowOneof()
2557		if !oneof && !gogoproto.HasGoGetters(g.file.FileDescriptorProto, message.DescriptorProto) {
2558			continue
2559		}
2560		if gogoproto.IsEmbed(field) || gogoproto.IsCustomType(field) {
2561			continue
2562		}
2563		fname := fieldNames[field]
2564		typename, _ := g.GoType(message, field)
2565		if t, ok := mapFieldTypes[field]; ok {
2566			typename = t
2567		}
2568		mname := fieldGetterNames[field]
2569		star := ""
2570		if (*field.Type != descriptor.FieldDescriptorProto_TYPE_MESSAGE) &&
2571			(*field.Type != descriptor.FieldDescriptorProto_TYPE_GROUP) &&
2572			needsStar(field, g.file.proto3, message != nil && message.allowOneof()) && typename[0] == '*' {
2573			typename = typename[1:]
2574			star = "*"
2575		}
2576		fieldFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i)
2577
2578		if field.GetOptions().GetDeprecated() {
2579			g.P(deprecationComment)
2580		}
2581
2582		g.P("func (m *", ccTypeName, ") ", Annotate(message.file, fieldFullPath, mname), "() "+typename+" {")
2583		g.In()
2584		def, hasDef := defNames[field]
2585		typeDefaultIsNil := false // whether this field type's default value is a literal nil unless specified
2586		switch *field.Type {
2587		case descriptor.FieldDescriptorProto_TYPE_BYTES:
2588			typeDefaultIsNil = !hasDef
2589		case descriptor.FieldDescriptorProto_TYPE_GROUP, descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2590			typeDefaultIsNil = gogoproto.IsNullable(field)
2591		}
2592		if isRepeated(field) {
2593			typeDefaultIsNil = true
2594		}
2595		if typeDefaultIsNil && !oneof {
2596			// A bytes field with no explicit default needs less generated code,
2597			// as does a message or group field, or a repeated field.
2598			g.P("if m != nil {")
2599			g.In()
2600			g.P("return m." + fname)
2601			g.Out()
2602			g.P("}")
2603			g.P("return nil")
2604			g.Out()
2605			g.P("}")
2606			g.P()
2607			continue
2608		}
2609		if !gogoproto.IsNullable(field) {
2610			g.P("if m != nil {")
2611			g.In()
2612			g.P("return m." + fname)
2613			g.Out()
2614			g.P("}")
2615		} else if !oneof {
2616			if message.proto3() {
2617				g.P("if m != nil {")
2618			} else {
2619				g.P("if m != nil && m." + fname + " != nil {")
2620			}
2621			g.In()
2622			g.P("return " + star + "m." + fname)
2623			g.Out()
2624			g.P("}")
2625		} else {
2626			uname := oneofFieldName[*field.OneofIndex]
2627			tname := oneofTypeName[field]
2628			g.P("if x, ok := m.Get", uname, "().(*", tname, "); ok {")
2629			g.P("return x.", fname)
2630			g.P("}")
2631		}
2632		if hasDef {
2633			if *field.Type != descriptor.FieldDescriptorProto_TYPE_BYTES {
2634				g.P("return " + def)
2635			} else {
2636				// The default is a []byte var.
2637				// Make a copy when returning it to be safe.
2638				g.P("return append([]byte(nil), ", def, "...)")
2639			}
2640		} else {
2641			switch *field.Type {
2642			case descriptor.FieldDescriptorProto_TYPE_GROUP,
2643				descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2644				if field.OneofIndex != nil {
2645					g.P(`return nil`)
2646				} else {
2647					goTyp, _ := g.GoType(message, field)
2648					goTypName := GoTypeToName(goTyp)
2649					if !gogoproto.IsNullable(field) && gogoproto.IsStdDuration(field) {
2650						g.P("return 0")
2651					} else {
2652						g.P("return ", goTypName, "{}")
2653					}
2654				}
2655			case descriptor.FieldDescriptorProto_TYPE_BOOL:
2656				g.P("return false")
2657			case descriptor.FieldDescriptorProto_TYPE_STRING:
2658				g.P(`return ""`)
2659			case descriptor.FieldDescriptorProto_TYPE_BYTES:
2660				// This is only possible for oneof fields.
2661				g.P("return nil")
2662			case descriptor.FieldDescriptorProto_TYPE_ENUM:
2663				// The default default for an enum is the first value in the enum,
2664				// not zero.
2665				obj := g.ObjectNamed(field.GetTypeName())
2666				var enum *EnumDescriptor
2667				if id, ok := obj.(*ImportedDescriptor); ok {
2668					// The enum type has been publicly imported.
2669					enum, _ = id.o.(*EnumDescriptor)
2670				} else {
2671					enum, _ = obj.(*EnumDescriptor)
2672				}
2673				if enum == nil {
2674					log.Printf("don't know how to generate getter for %s", field.GetName())
2675					continue
2676				}
2677				if len(enum.Value) == 0 {
2678					g.P("return 0 // empty enum")
2679				} else {
2680					first := enum.Value[0].GetName()
2681					if gogoproto.IsEnumValueCustomName(enum.Value[0]) {
2682						first = gogoproto.GetEnumValueCustomName(enum.Value[0])
2683					}
2684
2685					if gogoproto.EnabledGoEnumPrefix(enum.file.FileDescriptorProto, enum.EnumDescriptorProto) {
2686						g.P("return ", g.DefaultPackageName(obj)+enum.prefix()+first)
2687					} else {
2688						g.P("return ", g.DefaultPackageName(obj)+first)
2689					}
2690				}
2691			default:
2692				g.P("return 0")
2693			}
2694		}
2695		g.Out()
2696		g.P("}")
2697		g.P()
2698	}
2699
2700	if !message.group {
2701		ms := &messageSymbol{
2702			sym:           ccTypeName,
2703			hasExtensions: hasExtensions,
2704			isMessageSet:  isMessageSet,
2705			oneofTypes:    oneofTypes,
2706		}
2707		g.file.addExport(message, ms)
2708	}
2709
2710	// Oneof functions
2711	if len(message.OneofDecl) > 0 && message.allowOneof() {
2712		fieldWire := make(map[*descriptor.FieldDescriptorProto]string)
2713
2714		// method
2715		enc := "_" + ccTypeName + "_OneofMarshaler"
2716		dec := "_" + ccTypeName + "_OneofUnmarshaler"
2717		size := "_" + ccTypeName + "_OneofSizer"
2718		encSig := "(msg " + g.Pkg["proto"] + ".Message, b *" + g.Pkg["proto"] + ".Buffer) error"
2719		decSig := "(msg " + g.Pkg["proto"] + ".Message, tag, wire int, b *" + g.Pkg["proto"] + ".Buffer) (bool, error)"
2720		sizeSig := "(msg " + g.Pkg["proto"] + ".Message) (n int)"
2721
2722		g.P("// XXX_OneofFuncs is for the internal use of the proto package.")
2723		g.P("func (*", ccTypeName, ") XXX_OneofFuncs() (func", encSig, ", func", decSig, ", func", sizeSig, ", []interface{}) {")
2724		g.P("return ", enc, ", ", dec, ", ", size, ", []interface{}{")
2725		for _, field := range message.Field {
2726			if field.OneofIndex == nil {
2727				continue
2728			}
2729			g.P("(*", oneofTypeName[field], ")(nil),")
2730		}
2731		g.P("}")
2732		g.P("}")
2733		g.P()
2734
2735		// marshaler
2736		g.P("func ", enc, encSig, " {")
2737		g.P("m := msg.(*", ccTypeName, ")")
2738		for oi, odp := range message.OneofDecl {
2739			g.P("// ", odp.GetName())
2740			fname := oneofFieldName[int32(oi)]
2741			g.P("switch x := m.", fname, ".(type) {")
2742			for _, field := range message.Field {
2743				if field.OneofIndex == nil || int(*field.OneofIndex) != oi {
2744					continue
2745				}
2746				g.P("case *", oneofTypeName[field], ":")
2747				var wire, pre, post string
2748				val := "x." + fieldNames[field] // overridden for TYPE_BOOL
2749				canFail := false                // only TYPE_MESSAGE and TYPE_GROUP can fail
2750				switch *field.Type {
2751				case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
2752					wire = "WireFixed64"
2753					pre = "b.EncodeFixed64(" + g.Pkg["math"] + ".Float64bits("
2754					post = "))"
2755				case descriptor.FieldDescriptorProto_TYPE_FLOAT:
2756					wire = "WireFixed32"
2757					pre = "b.EncodeFixed32(uint64(" + g.Pkg["math"] + ".Float32bits("
2758					post = ")))"
2759				case descriptor.FieldDescriptorProto_TYPE_INT64,
2760					descriptor.FieldDescriptorProto_TYPE_UINT64:
2761					wire = "WireVarint"
2762					pre, post = "b.EncodeVarint(uint64(", "))"
2763				case descriptor.FieldDescriptorProto_TYPE_INT32,
2764					descriptor.FieldDescriptorProto_TYPE_UINT32,
2765					descriptor.FieldDescriptorProto_TYPE_ENUM:
2766					wire = "WireVarint"
2767					pre, post = "b.EncodeVarint(uint64(", "))"
2768				case descriptor.FieldDescriptorProto_TYPE_FIXED64,
2769					descriptor.FieldDescriptorProto_TYPE_SFIXED64:
2770					wire = "WireFixed64"
2771					pre, post = "b.EncodeFixed64(uint64(", "))"
2772				case descriptor.FieldDescriptorProto_TYPE_FIXED32,
2773					descriptor.FieldDescriptorProto_TYPE_SFIXED32:
2774					wire = "WireFixed32"
2775					pre, post = "b.EncodeFixed32(uint64(", "))"
2776				case descriptor.FieldDescriptorProto_TYPE_BOOL:
2777					// bool needs special handling.
2778					g.P("t := uint64(0)")
2779					g.P("if ", val, " { t = 1 }")
2780					val = "t"
2781					wire = "WireVarint"
2782					pre, post = "b.EncodeVarint(", ")"
2783				case descriptor.FieldDescriptorProto_TYPE_STRING:
2784					wire = "WireBytes"
2785					pre, post = "b.EncodeStringBytes(", ")"
2786				case descriptor.FieldDescriptorProto_TYPE_GROUP:
2787					wire = "WireStartGroup"
2788					pre, post = "b.Marshal(", ")"
2789					canFail = true
2790				case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2791					wire = "WireBytes"
2792					pre, post = "b.EncodeMessage(", ")"
2793					canFail = true
2794				case descriptor.FieldDescriptorProto_TYPE_BYTES:
2795					wire = "WireBytes"
2796					pre, post = "b.EncodeRawBytes(", ")"
2797				case descriptor.FieldDescriptorProto_TYPE_SINT32:
2798					wire = "WireVarint"
2799					pre, post = "b.EncodeZigzag32(uint64(", "))"
2800				case descriptor.FieldDescriptorProto_TYPE_SINT64:
2801					wire = "WireVarint"
2802					pre, post = "b.EncodeZigzag64(uint64(", "))"
2803				default:
2804					g.Fail("unhandled oneof field type ", field.Type.String())
2805				}
2806				fieldWire[field] = wire
2807				g.P("_ = b.EncodeVarint(", field.Number, "<<3|", g.Pkg["proto"], ".", wire, ")")
2808				if *field.Type == descriptor.FieldDescriptorProto_TYPE_BYTES && gogoproto.IsCustomType(field) {
2809					g.P(`dAtA, err := `, val, `.Marshal()`)
2810					g.P(`if err != nil {`)
2811					g.In()
2812					g.P(`return err`)
2813					g.Out()
2814					g.P(`}`)
2815					val = "dAtA"
2816				} else if gogoproto.IsStdTime(field) {
2817					pkg := g.useTypes()
2818					if gogoproto.IsNullable(field) {
2819						g.P(`dAtA, err := `, pkg, `.StdTimeMarshal(*`, val, `)`)
2820					} else {
2821						g.P(`dAtA, err := `, pkg, `.StdTimeMarshal(`, val, `)`)
2822					}
2823					g.P(`if err != nil {`)
2824					g.In()
2825					g.P(`return err`)
2826					g.Out()
2827					g.P(`}`)
2828					val = "dAtA"
2829					pre, post = "b.EncodeRawBytes(", ")"
2830				} else if gogoproto.IsStdDuration(field) {
2831					pkg := g.useTypes()
2832					if gogoproto.IsNullable(field) {
2833						g.P(`dAtA, err := `, pkg, `.StdDurationMarshal(*`, val, `)`)
2834					} else {
2835						g.P(`dAtA, err := `, pkg, `.StdDurationMarshal(`, val, `)`)
2836					}
2837					g.P(`if err != nil {`)
2838					g.In()
2839					g.P(`return err`)
2840					g.Out()
2841					g.P(`}`)
2842					val = "dAtA"
2843					pre, post = "b.EncodeRawBytes(", ")"
2844				}
2845				if !canFail {
2846					g.P("_ = ", pre, val, post)
2847				} else {
2848					g.P("if err := ", pre, val, post, "; err != nil {")
2849					g.In()
2850					g.P("return err")
2851					g.Out()
2852					g.P("}")
2853				}
2854				if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP {
2855					g.P("_ = b.EncodeVarint(", field.Number, "<<3|", g.Pkg["proto"], ".WireEndGroup)")
2856				}
2857			}
2858			g.P("case nil:")
2859			g.P("default: return ", g.Pkg["fmt"], `.Errorf("`, ccTypeName, ".", fname, ` has unexpected type %T", x)`)
2860			g.P("}")
2861		}
2862		g.P("return nil")
2863		g.P("}")
2864		g.P()
2865
2866		// unmarshaler
2867		g.P("func ", dec, decSig, " {")
2868		g.P("m := msg.(*", ccTypeName, ")")
2869		g.P("switch tag {")
2870		for _, field := range message.Field {
2871			if field.OneofIndex == nil {
2872				continue
2873			}
2874			odp := message.OneofDecl[int(*field.OneofIndex)]
2875			g.P("case ", field.Number, ": // ", odp.GetName(), ".", *field.Name)
2876			g.P("if wire != ", g.Pkg["proto"], ".", fieldWire[field], " {")
2877			g.P("return true, ", g.Pkg["proto"], ".ErrInternalBadWireType")
2878			g.P("}")
2879			lhs := "x, err" // overridden for TYPE_MESSAGE and TYPE_GROUP
2880			var dec, cast, cast2 string
2881			switch *field.Type {
2882			case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
2883				dec, cast = "b.DecodeFixed64()", g.Pkg["math"]+".Float64frombits"
2884			case descriptor.FieldDescriptorProto_TYPE_FLOAT:
2885				dec, cast, cast2 = "b.DecodeFixed32()", "uint32", g.Pkg["math"]+".Float32frombits"
2886			case descriptor.FieldDescriptorProto_TYPE_INT64:
2887				dec, cast = "b.DecodeVarint()", "int64"
2888			case descriptor.FieldDescriptorProto_TYPE_UINT64:
2889				dec = "b.DecodeVarint()"
2890			case descriptor.FieldDescriptorProto_TYPE_INT32:
2891				dec, cast = "b.DecodeVarint()", "int32"
2892			case descriptor.FieldDescriptorProto_TYPE_FIXED64:
2893				dec = "b.DecodeFixed64()"
2894			case descriptor.FieldDescriptorProto_TYPE_FIXED32:
2895				dec, cast = "b.DecodeFixed32()", "uint32"
2896			case descriptor.FieldDescriptorProto_TYPE_BOOL:
2897				dec = "b.DecodeVarint()"
2898				// handled specially below
2899			case descriptor.FieldDescriptorProto_TYPE_STRING:
2900				dec = "b.DecodeStringBytes()"
2901			case descriptor.FieldDescriptorProto_TYPE_GROUP:
2902				g.P("msg := new(", fieldTypes[field][1:], ")") // drop star
2903				lhs = "err"
2904				dec = "b.DecodeGroup(msg)"
2905				// handled specially below
2906			case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2907				if gogoproto.IsStdTime(field) || gogoproto.IsStdDuration(field) {
2908					dec = "b.DecodeRawBytes(true)"
2909				} else {
2910					g.P("msg := new(", fieldTypes[field][1:], ")") // drop star
2911					lhs = "err"
2912					dec = "b.DecodeMessage(msg)"
2913				}
2914				// handled specially below
2915			case descriptor.FieldDescriptorProto_TYPE_BYTES:
2916				dec = "b.DecodeRawBytes(true)"
2917			case descriptor.FieldDescriptorProto_TYPE_UINT32:
2918				dec, cast = "b.DecodeVarint()", "uint32"
2919			case descriptor.FieldDescriptorProto_TYPE_ENUM:
2920				dec, cast = "b.DecodeVarint()", fieldTypes[field]
2921			case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
2922				dec, cast = "b.DecodeFixed32()", "int32"
2923			case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
2924				dec, cast = "b.DecodeFixed64()", "int64"
2925			case descriptor.FieldDescriptorProto_TYPE_SINT32:
2926				dec, cast = "b.DecodeZigzag32()", "int32"
2927			case descriptor.FieldDescriptorProto_TYPE_SINT64:
2928				dec, cast = "b.DecodeZigzag64()", "int64"
2929			default:
2930				g.Fail("unhandled oneof field type ", field.Type.String())
2931			}
2932			g.P(lhs, " := ", dec)
2933			val := "x"
2934			if *field.Type == descriptor.FieldDescriptorProto_TYPE_BYTES && gogoproto.IsCustomType(field) {
2935				g.P(`if err != nil {`)
2936				g.In()
2937				g.P(`return true, err`)
2938				g.Out()
2939				g.P(`}`)
2940				_, ctyp, err := GetCustomType(field)
2941				if err != nil {
2942					panic(err)
2943				}
2944				g.P(`var cc `, ctyp)
2945				g.P(`c := &cc`)
2946				g.P(`err = c.Unmarshal(`, val, `)`)
2947				val = "*c"
2948			} else if gogoproto.IsStdTime(field) {
2949				pkg := g.useTypes()
2950				g.P(`if err != nil {`)
2951				g.In()
2952				g.P(`return true, err`)
2953				g.Out()
2954				g.P(`}`)
2955				g.P(`c := new(time.Time)`)
2956				g.P(`if err2 := `, pkg, `.StdTimeUnmarshal(c, `, val, `); err2 != nil {`)
2957				g.In()
2958				g.P(`return true, err`)
2959				g.Out()
2960				g.P(`}`)
2961				val = "c"
2962			} else if gogoproto.IsStdDuration(field) {
2963				pkg := g.useTypes()
2964				g.P(`if err != nil {`)
2965				g.In()
2966				g.P(`return true, err`)
2967				g.Out()
2968				g.P(`}`)
2969				g.P(`c := new(time.Duration)`)
2970				g.P(`if err2 := `, pkg, `.StdDurationUnmarshal(c, `, val, `); err2 != nil {`)
2971				g.In()
2972				g.P(`return true, err`)
2973				g.Out()
2974				g.P(`}`)
2975				val = "c"
2976			}
2977			if cast != "" {
2978				val = cast + "(" + val + ")"
2979			}
2980			if cast2 != "" {
2981				val = cast2 + "(" + val + ")"
2982			}
2983			switch *field.Type {
2984			case descriptor.FieldDescriptorProto_TYPE_BOOL:
2985				val += " != 0"
2986			case descriptor.FieldDescriptorProto_TYPE_GROUP,
2987				descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2988				if !gogoproto.IsStdTime(field) && !gogoproto.IsStdDuration(field) {
2989					val = "msg"
2990				}
2991			}
2992			if gogoproto.IsCastType(field) {
2993				_, typ, err := getCastType(field)
2994				if err != nil {
2995					g.Fail(err.Error())
2996				}
2997				val = typ + "(" + val + ")"
2998			}
2999			g.P("m.", oneofFieldName[*field.OneofIndex], " = &", oneofTypeName[field], "{", val, "}")
3000			g.P("return true, err")
3001		}
3002		g.P("default: return false, nil")
3003		g.P("}")
3004		g.P("}")
3005		g.P()
3006
3007		// sizer
3008		g.P("func ", size, sizeSig, " {")
3009		g.P("m := msg.(*", ccTypeName, ")")
3010		for oi, odp := range message.OneofDecl {
3011			g.P("// ", odp.GetName())
3012			fname := oneofFieldName[int32(oi)]
3013			g.P("switch x := m.", fname, ".(type) {")
3014			for _, field := range message.Field {
3015				if field.OneofIndex == nil || int(*field.OneofIndex) != oi {
3016					continue
3017				}
3018				g.P("case *", oneofTypeName[field], ":")
3019				val := "x." + fieldNames[field]
3020				var varint, fixed string
3021				switch *field.Type {
3022				case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
3023					fixed = "8"
3024				case descriptor.FieldDescriptorProto_TYPE_FLOAT:
3025					fixed = "4"
3026				case descriptor.FieldDescriptorProto_TYPE_INT64,
3027					descriptor.FieldDescriptorProto_TYPE_UINT64,
3028					descriptor.FieldDescriptorProto_TYPE_INT32,
3029					descriptor.FieldDescriptorProto_TYPE_UINT32,
3030					descriptor.FieldDescriptorProto_TYPE_ENUM:
3031					varint = val
3032				case descriptor.FieldDescriptorProto_TYPE_FIXED64,
3033					descriptor.FieldDescriptorProto_TYPE_SFIXED64:
3034					fixed = "8"
3035				case descriptor.FieldDescriptorProto_TYPE_FIXED32,
3036					descriptor.FieldDescriptorProto_TYPE_SFIXED32:
3037					fixed = "4"
3038				case descriptor.FieldDescriptorProto_TYPE_BOOL:
3039					fixed = "1"
3040				case descriptor.FieldDescriptorProto_TYPE_STRING:
3041					fixed = "len(" + val + ")"
3042					varint = fixed
3043				case descriptor.FieldDescriptorProto_TYPE_GROUP:
3044					fixed = g.Pkg["proto"] + ".Size(" + val + ")"
3045				case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
3046					if gogoproto.IsStdTime(field) {
3047						if gogoproto.IsNullable(field) {
3048							val = "*" + val
3049						}
3050						pkg := g.useTypes()
3051						g.P("s := ", pkg, ".SizeOfStdTime(", val, ")")
3052					} else if gogoproto.IsStdDuration(field) {
3053						if gogoproto.IsNullable(field) {
3054							val = "*" + val
3055						}
3056						pkg := g.useTypes()
3057						g.P("s := ", pkg, ".SizeOfStdDuration(", val, ")")
3058					} else {
3059						g.P("s := ", g.Pkg["proto"], ".Size(", val, ")")
3060					}
3061					fixed = "s"
3062					varint = fixed
3063				case descriptor.FieldDescriptorProto_TYPE_BYTES:
3064					if gogoproto.IsCustomType(field) {
3065						fixed = val + ".Size()"
3066					} else {
3067						fixed = "len(" + val + ")"
3068					}
3069					varint = fixed
3070				case descriptor.FieldDescriptorProto_TYPE_SINT32:
3071					varint = "(uint32(" + val + ") << 1) ^ uint32((int32(" + val + ") >> 31))"
3072				case descriptor.FieldDescriptorProto_TYPE_SINT64:
3073					varint = "uint64(" + val + " << 1) ^ uint64((int64(" + val + ") >> 63))"
3074				default:
3075					g.Fail("unhandled oneof field type ", field.Type.String())
3076				}
3077				// Tag and wire varint is known statically,
3078				// so don't generate code for that part of the size computation.
3079				tagAndWireSize := proto.SizeVarint(uint64(*field.Number << 3)) // wire doesn't affect varint size
3080				g.P("n += ", tagAndWireSize, " // tag and wire")
3081				if varint != "" {
3082					g.P("n += ", g.Pkg["proto"], ".SizeVarint(uint64(", varint, "))")
3083				}
3084				if fixed != "" {
3085					g.P("n += ", fixed)
3086				}
3087				if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP {
3088					g.P("n += ", tagAndWireSize, " // tag and wire")
3089				}
3090			}
3091			g.P("case nil:")
3092			g.P("default:")
3093			g.P("panic(", g.Pkg["fmt"], ".Sprintf(\"proto: unexpected type %T in oneof\", x))")
3094			g.P("}")
3095		}
3096		g.P("return n")
3097		g.P("}")
3098		g.P()
3099	}
3100
3101	for _, ext := range message.ext {
3102		g.generateExtension(ext)
3103	}
3104
3105	fullName := strings.Join(message.TypeName(), ".")
3106	if g.file.Package != nil {
3107		fullName = *g.file.Package + "." + fullName
3108	}
3109
3110	g.addInitf("%s.RegisterType((*%s)(nil), %q)", g.Pkg["proto"], ccTypeName, fullName)
3111	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
3112		g.addInitf("%s.RegisterType((*%s)(nil), %q)", g.Pkg["golang_proto"], ccTypeName, fullName)
3113	}
3114	if gogoproto.HasMessageName(g.file.FileDescriptorProto, message.DescriptorProto) {
3115		g.P("func (*", ccTypeName, ") XXX_MessageName() string {")
3116		g.In()
3117		g.P("return ", strconv.Quote(fullName))
3118		g.Out()
3119		g.P("}")
3120	}
3121	// Register types for native map types.
3122	for _, k := range mapFieldKeys(mapFieldTypes) {
3123		fullName := strings.TrimPrefix(*k.TypeName, ".")
3124		g.addInitf("%s.RegisterMapType((%s)(nil), %q)", g.Pkg["proto"], mapFieldTypes[k], fullName)
3125		if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
3126			g.addInitf("%s.RegisterMapType((%s)(nil), %q)", g.Pkg["golang_proto"], mapFieldTypes[k], fullName)
3127		}
3128	}
3129}
3130
3131type byTypeName []*descriptor.FieldDescriptorProto
3132
3133func (a byTypeName) Len() int           { return len(a) }
3134func (a byTypeName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
3135func (a byTypeName) Less(i, j int) bool { return *a[i].TypeName < *a[j].TypeName }
3136
3137// mapFieldKeys returns the keys of m in a consistent order.
3138func mapFieldKeys(m map[*descriptor.FieldDescriptorProto]string) []*descriptor.FieldDescriptorProto {
3139	keys := make([]*descriptor.FieldDescriptorProto, 0, len(m))
3140	for k := range m {
3141		keys = append(keys, k)
3142	}
3143	sort.Sort(byTypeName(keys))
3144	return keys
3145}
3146
3147var escapeChars = [256]byte{
3148	'a': '\a', 'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t', 'v': '\v', '\\': '\\', '"': '"', '\'': '\'', '?': '?',
3149}
3150
3151// unescape reverses the "C" escaping that protoc does for default values of bytes fields.
3152// It is best effort in that it effectively ignores malformed input. Seemingly invalid escape
3153// sequences are conveyed, unmodified, into the decoded result.
3154func unescape(s string) string {
3155	// NB: Sadly, we can't use strconv.Unquote because protoc will escape both
3156	// single and double quotes, but strconv.Unquote only allows one or the
3157	// other (based on actual surrounding quotes of its input argument).
3158
3159	var out []byte
3160	for len(s) > 0 {
3161		// regular character, or too short to be valid escape
3162		if s[0] != '\\' || len(s) < 2 {
3163			out = append(out, s[0])
3164			s = s[1:]
3165		} else if c := escapeChars[s[1]]; c != 0 {
3166			// escape sequence
3167			out = append(out, c)
3168			s = s[2:]
3169		} else if s[1] == 'x' || s[1] == 'X' {
3170			// hex escape, e.g. "\x80
3171			if len(s) < 4 {
3172				// too short to be valid
3173				out = append(out, s[:2]...)
3174				s = s[2:]
3175				continue
3176			}
3177			v, err := strconv.ParseUint(s[2:4], 16, 8)
3178			if err != nil {
3179				out = append(out, s[:4]...)
3180			} else {
3181				out = append(out, byte(v))
3182			}
3183			s = s[4:]
3184		} else if '0' <= s[1] && s[1] <= '7' {
3185			// octal escape, can vary from 1 to 3 octal digits; e.g., "\0" "\40" or "\164"
3186			// so consume up to 2 more bytes or up to end-of-string
3187			n := len(s[1:]) - len(strings.TrimLeft(s[1:], "01234567"))
3188			if n > 3 {
3189				n = 3
3190			}
3191			v, err := strconv.ParseUint(s[1:1+n], 8, 8)
3192			if err != nil {
3193				out = append(out, s[:1+n]...)
3194			} else {
3195				out = append(out, byte(v))
3196			}
3197			s = s[1+n:]
3198		} else {
3199			// bad escape, just propagate the slash as-is
3200			out = append(out, s[0])
3201			s = s[1:]
3202		}
3203	}
3204
3205	return string(out)
3206}
3207
3208func (g *Generator) generateExtension(ext *ExtensionDescriptor) {
3209	ccTypeName := ext.DescName()
3210
3211	extObj := g.ObjectNamed(*ext.Extendee)
3212	var extDesc *Descriptor
3213	if id, ok := extObj.(*ImportedDescriptor); ok {
3214		// This is extending a publicly imported message.
3215		// We need the underlying type for goTag.
3216		extDesc = id.o.(*Descriptor)
3217	} else {
3218		extDesc = extObj.(*Descriptor)
3219	}
3220	extendedType := "*" + g.TypeName(extObj) // always use the original
3221	field := ext.FieldDescriptorProto
3222	fieldType, wireType := g.GoType(ext.parent, field)
3223	tag := g.goTag(extDesc, field, wireType)
3224	g.RecordTypeUse(*ext.Extendee)
3225	if n := ext.FieldDescriptorProto.TypeName; n != nil {
3226		// foreign extension type
3227		g.RecordTypeUse(*n)
3228	}
3229
3230	typeName := ext.TypeName()
3231
3232	// Special case for proto2 message sets: If this extension is extending
3233	// proto2.bridge.MessageSet, and its final name component is "message_set_extension",
3234	// then drop that last component.
3235	//
3236	// TODO: This should be implemented in the text formatter rather than the generator.
3237	// In addition, the situation for when to apply this special case is implemented
3238	// differently in other languages:
3239	// https://github.com/google/protobuf/blob/aff10976/src/google/protobuf/text_format.cc#L1560
3240	mset := false
3241	if extDesc.GetOptions().GetMessageSetWireFormat() && typeName[len(typeName)-1] == "message_set_extension" {
3242		typeName = typeName[:len(typeName)-1]
3243		mset = true
3244	}
3245
3246	// For text formatting, the package must be exactly what the .proto file declares,
3247	// ignoring overrides such as the go_package option, and with no dot/underscore mapping.
3248	extName := strings.Join(typeName, ".")
3249	if g.file.Package != nil {
3250		extName = *g.file.Package + "." + extName
3251	}
3252
3253	g.P("var ", ccTypeName, " = &", g.Pkg["proto"], ".ExtensionDesc{")
3254	g.In()
3255	g.P("ExtendedType: (", extendedType, ")(nil),")
3256	g.P("ExtensionType: (", fieldType, ")(nil),")
3257	g.P("Field: ", field.Number, ",")
3258	g.P(`Name: "`, extName, `",`)
3259	g.P("Tag: ", tag, ",")
3260	g.P(`Filename: "`, g.file.GetName(), `",`)
3261
3262	g.Out()
3263	g.P("}")
3264	g.P()
3265
3266	if mset {
3267		// Generate a bit more code to register with message_set.go.
3268		g.addInitf("%s.RegisterMessageSetType((%s)(nil), %d, %q)", g.Pkg["proto"], fieldType, *field.Number, extName)
3269		if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
3270			g.addInitf("%s.RegisterMessageSetType((%s)(nil), %d, %q)", g.Pkg["golang_proto"], fieldType, *field.Number, extName)
3271		}
3272	}
3273
3274	g.file.addExport(ext, constOrVarSymbol{ccTypeName, "var", ""})
3275}
3276
3277func (g *Generator) generateInitFunction() {
3278	for _, enum := range g.file.enum {
3279		g.generateEnumRegistration(enum)
3280	}
3281	for _, d := range g.file.desc {
3282		for _, ext := range d.ext {
3283			g.generateExtensionRegistration(ext)
3284		}
3285	}
3286	for _, ext := range g.file.ext {
3287		g.generateExtensionRegistration(ext)
3288	}
3289	if len(g.init) == 0 {
3290		return
3291	}
3292	g.P("func init() {")
3293	g.In()
3294	for _, l := range g.init {
3295		g.P(l)
3296	}
3297	g.Out()
3298	g.P("}")
3299	g.init = nil
3300}
3301
3302func (g *Generator) generateFileDescriptor(file *FileDescriptor) {
3303	// Make a copy and trim source_code_info data.
3304	// TODO: Trim this more when we know exactly what we need.
3305	pb := proto.Clone(file.FileDescriptorProto).(*descriptor.FileDescriptorProto)
3306	pb.SourceCodeInfo = nil
3307
3308	b, err := proto.Marshal(pb)
3309	if err != nil {
3310		g.Fail(err.Error())
3311	}
3312
3313	var buf bytes.Buffer
3314	w, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression)
3315	w.Write(b)
3316	w.Close()
3317	b = buf.Bytes()
3318
3319	v := file.VarName()
3320	g.P()
3321	g.P("func init() { ", g.Pkg["proto"], ".RegisterFile(", strconv.Quote(*file.Name), ", ", v, ") }")
3322	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
3323		g.P("func init() { ", g.Pkg["golang_proto"], ".RegisterFile(", strconv.Quote(*file.Name), ", ", v, ") }")
3324	}
3325	g.P("var ", v, " = []byte{")
3326	g.In()
3327	g.P("// ", len(b), " bytes of a gzipped FileDescriptorProto")
3328	for len(b) > 0 {
3329		n := 16
3330		if n > len(b) {
3331			n = len(b)
3332		}
3333
3334		s := ""
3335		for _, c := range b[:n] {
3336			s += fmt.Sprintf("0x%02x,", c)
3337		}
3338		g.P(s)
3339
3340		b = b[n:]
3341	}
3342	g.Out()
3343	g.P("}")
3344}
3345
3346func (g *Generator) generateEnumRegistration(enum *EnumDescriptor) {
3347	// // We always print the full (proto-world) package name here.
3348	pkg := enum.File().GetPackage()
3349	if pkg != "" {
3350		pkg += "."
3351	}
3352	// The full type name
3353	typeName := enum.TypeName()
3354	// The full type name, CamelCased.
3355	ccTypeName := CamelCaseSlice(typeName)
3356	g.addInitf("%s.RegisterEnum(%q, %[3]s_name, %[3]s_value)", g.Pkg["proto"], pkg+ccTypeName, ccTypeName)
3357	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
3358		g.addInitf("%s.RegisterEnum(%q, %[3]s_name, %[3]s_value)", g.Pkg["golang_proto"], pkg+ccTypeName, ccTypeName)
3359	}
3360}
3361
3362func (g *Generator) generateExtensionRegistration(ext *ExtensionDescriptor) {
3363	g.addInitf("%s.RegisterExtension(%s)", g.Pkg["proto"], ext.DescName())
3364	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
3365		g.addInitf("%s.RegisterExtension(%s)", g.Pkg["golang_proto"], ext.DescName())
3366	}
3367}
3368
3369// And now lots of helper functions.
3370
3371// Is c an ASCII lower-case letter?
3372func isASCIILower(c byte) bool {
3373	return 'a' <= c && c <= 'z'
3374}
3375
3376// Is c an ASCII digit?
3377func isASCIIDigit(c byte) bool {
3378	return '0' <= c && c <= '9'
3379}
3380
3381// CamelCase returns the CamelCased name.
3382// If there is an interior underscore followed by a lower case letter,
3383// drop the underscore and convert the letter to upper case.
3384// There is a remote possibility of this rewrite causing a name collision,
3385// but it's so remote we're prepared to pretend it's nonexistent - since the
3386// C++ generator lowercases names, it's extremely unlikely to have two fields
3387// with different capitalizations.
3388// In short, _my_field_name_2 becomes XMyFieldName_2.
3389func CamelCase(s string) string {
3390	if s == "" {
3391		return ""
3392	}
3393	t := make([]byte, 0, 32)
3394	i := 0
3395	if s[0] == '_' {
3396		// Need a capital letter; drop the '_'.
3397		t = append(t, 'X')
3398		i++
3399	}
3400	// Invariant: if the next letter is lower case, it must be converted
3401	// to upper case.
3402	// That is, we process a word at a time, where words are marked by _ or
3403	// upper case letter. Digits are treated as words.
3404	for ; i < len(s); i++ {
3405		c := s[i]
3406		if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) {
3407			continue // Skip the underscore in s.
3408		}
3409		if isASCIIDigit(c) {
3410			t = append(t, c)
3411			continue
3412		}
3413		// Assume we have a letter now - if not, it's a bogus identifier.
3414		// The next word is a sequence of characters that must start upper case.
3415		if isASCIILower(c) {
3416			c ^= ' ' // Make it a capital letter.
3417		}
3418		t = append(t, c) // Guaranteed not lower case.
3419		// Accept lower case sequence that follows.
3420		for i+1 < len(s) && isASCIILower(s[i+1]) {
3421			i++
3422			t = append(t, s[i])
3423		}
3424	}
3425	return string(t)
3426}
3427
3428// CamelCaseSlice is like CamelCase, but the argument is a slice of strings to
3429// be joined with "_".
3430func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) }
3431
3432// dottedSlice turns a sliced name into a dotted name.
3433func dottedSlice(elem []string) string { return strings.Join(elem, ".") }
3434
3435// Is this field optional?
3436func isOptional(field *descriptor.FieldDescriptorProto) bool {
3437	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_OPTIONAL
3438}
3439
3440// Is this field required?
3441func isRequired(field *descriptor.FieldDescriptorProto) bool {
3442	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REQUIRED
3443}
3444
3445// Is this field repeated?
3446func isRepeated(field *descriptor.FieldDescriptorProto) bool {
3447	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED
3448}
3449
3450// Is this field a scalar numeric type?
3451func IsScalar(field *descriptor.FieldDescriptorProto) bool {
3452	if field.Type == nil {
3453		return false
3454	}
3455	switch *field.Type {
3456	case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
3457		descriptor.FieldDescriptorProto_TYPE_FLOAT,
3458		descriptor.FieldDescriptorProto_TYPE_INT64,
3459		descriptor.FieldDescriptorProto_TYPE_UINT64,
3460		descriptor.FieldDescriptorProto_TYPE_INT32,
3461		descriptor.FieldDescriptorProto_TYPE_FIXED64,
3462		descriptor.FieldDescriptorProto_TYPE_FIXED32,
3463		descriptor.FieldDescriptorProto_TYPE_BOOL,
3464		descriptor.FieldDescriptorProto_TYPE_UINT32,
3465		descriptor.FieldDescriptorProto_TYPE_ENUM,
3466		descriptor.FieldDescriptorProto_TYPE_SFIXED32,
3467		descriptor.FieldDescriptorProto_TYPE_SFIXED64,
3468		descriptor.FieldDescriptorProto_TYPE_SINT32,
3469		descriptor.FieldDescriptorProto_TYPE_SINT64:
3470		return true
3471	default:
3472		return false
3473	}
3474}
3475
3476// badToUnderscore is the mapping function used to generate Go names from package names,
3477// which can be dotted in the input .proto file.  It replaces non-identifier characters such as
3478// dot or dash with underscore.
3479func badToUnderscore(r rune) rune {
3480	if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' {
3481		return r
3482	}
3483	return '_'
3484}
3485
3486// baseName returns the last path element of the name, with the last dotted suffix removed.
3487func baseName(name string) string {
3488	// First, find the last element
3489	if i := strings.LastIndex(name, "/"); i >= 0 {
3490		name = name[i+1:]
3491	}
3492	// Now drop the suffix
3493	if i := strings.LastIndex(name, "."); i >= 0 {
3494		name = name[0:i]
3495	}
3496	return name
3497}
3498
3499// The SourceCodeInfo message describes the location of elements of a parsed
3500// .proto file by way of a "path", which is a sequence of integers that
3501// describe the route from a FileDescriptorProto to the relevant submessage.
3502// The path alternates between a field number of a repeated field, and an index
3503// into that repeated field. The constants below define the field numbers that
3504// are used.
3505//
3506// See descriptor.proto for more information about this.
3507const (
3508	// tag numbers in FileDescriptorProto
3509	packagePath = 2 // package
3510	messagePath = 4 // message_type
3511	enumPath    = 5 // enum_type
3512	// tag numbers in DescriptorProto
3513	messageFieldPath   = 2 // field
3514	messageMessagePath = 3 // nested_type
3515	messageEnumPath    = 4 // enum_type
3516	messageOneofPath   = 8 // oneof_decl
3517	// tag numbers in EnumDescriptorProto
3518	enumValuePath = 2 // value
3519)
3520
3521var supportTypeAliases bool
3522
3523func init() {
3524	for _, tag := range build.Default.ReleaseTags {
3525		if tag == "go1.9" {
3526			supportTypeAliases = true
3527			return
3528		}
3529	}
3530}
3531