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 c, ok := g.makeComments(path); ok {
1339		g.P(c)
1340		return true
1341	}
1342	return false
1343}
1344
1345// makeComments generates the comment string for the field, no "\n" at the end
1346func (g *Generator) makeComments(path string) (string, bool) {
1347	loc, ok := g.file.comments[path]
1348	if !ok {
1349		return "", false
1350	}
1351	w := new(bytes.Buffer)
1352	nl := ""
1353	for _, line := range strings.Split(strings.TrimSuffix(loc.GetLeadingComments(), "\n"), "\n") {
1354		fmt.Fprintf(w, "%s// %s", nl, strings.TrimPrefix(line, " "))
1355		nl = "\n"
1356	}
1357	return w.String(), true
1358}
1359
1360// Comments returns any comments from the source .proto file and empty string if comments not found.
1361// The path is a comma-separated list of intergers.
1362// See descriptor.proto for its format.
1363func (g *Generator) Comments(path string) string {
1364	loc, ok := g.file.comments[path]
1365	if !ok {
1366		return ""
1367	}
1368	text := strings.TrimSuffix(loc.GetLeadingComments(), "\n")
1369	return text
1370}
1371
1372func (g *Generator) fileByName(filename string) *FileDescriptor {
1373	return g.allFilesByName[filename]
1374}
1375
1376// weak returns whether the ith import of the current file is a weak import.
1377func (g *Generator) weak(i int32) bool {
1378	for _, j := range g.file.WeakDependency {
1379		if j == i {
1380			return true
1381		}
1382	}
1383	return false
1384}
1385
1386// Generate the imports
1387func (g *Generator) generateImports() {
1388	// We almost always need a proto import.  Rather than computing when we
1389	// do, which is tricky when there's a plugin, just import it and
1390	// reference it later. The same argument applies to the fmt and math packages.
1391	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) {
1392		g.PrintImport(GoPackageName(g.Pkg["proto"]), GoImportPath(g.ImportPrefix)+GoImportPath("github.com/gogo/protobuf/proto"))
1393		if gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
1394			g.PrintImport(GoPackageName(g.Pkg["golang_proto"]), GoImportPath(g.ImportPrefix)+GoImportPath("github.com/golang/protobuf/proto"))
1395		}
1396	} else {
1397		g.PrintImport(GoPackageName(g.Pkg["proto"]), GoImportPath(g.ImportPrefix)+GoImportPath("github.com/golang/protobuf/proto"))
1398	}
1399	g.PrintImport(GoPackageName(g.Pkg["fmt"]), "fmt")
1400	g.PrintImport(GoPackageName(g.Pkg["math"]), "math")
1401
1402	var (
1403		imports       = make(map[GoImportPath]bool)
1404		strongImports = make(map[GoImportPath]bool)
1405		importPaths   []string
1406	)
1407	for i, s := range g.file.Dependency {
1408		fd := g.fileByName(s)
1409		importPath := fd.importPath
1410		// Do not import our own package.
1411		if importPath == g.file.importPath {
1412			continue
1413		}
1414		if !imports[importPath] {
1415			importPaths = append(importPaths, string(importPath))
1416		}
1417		imports[importPath] = true
1418		if !g.weak(int32(i)) {
1419			strongImports[importPath] = true
1420		}
1421	}
1422	sort.Strings(importPaths)
1423	for i := range importPaths {
1424		importPath := GoImportPath(importPaths[i])
1425		packageName := g.GoPackageName(importPath)
1426		fullPath := GoImportPath(g.ImportPrefix) + importPath
1427		// Skip weak imports.
1428		if !strongImports[importPath] {
1429			g.P("// skipping weak import ", packageName, " ", fullPath)
1430			continue
1431		}
1432		// We need to import all the dependencies, even if we don't reference them,
1433		// because other code and tools depend on having the full transitive closure
1434		// of protocol buffer types in the binary.
1435		if _, ok := g.usedPackages[importPath]; ok {
1436			g.PrintImport(packageName, fullPath)
1437		} else {
1438			g.P("import _ ", fullPath)
1439		}
1440	}
1441	g.P()
1442	for _, s := range g.customImports {
1443		s1 := strings.Map(badToUnderscore, s)
1444		g.PrintImport(GoPackageName(s1), GoImportPath(s))
1445	}
1446	g.P()
1447	// TODO: may need to worry about uniqueness across plugins
1448	for _, p := range plugins {
1449		p.GenerateImports(g.file)
1450		g.P()
1451	}
1452	g.P("// Reference imports to suppress errors if they are not otherwise used.")
1453	g.P("var _ = ", g.Pkg["proto"], ".Marshal")
1454	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
1455		g.P("var _ = ", g.Pkg["golang_proto"], ".Marshal")
1456	}
1457	g.P("var _ = ", g.Pkg["fmt"], ".Errorf")
1458	g.P("var _ = ", g.Pkg["math"], ".Inf")
1459	for _, cimport := range g.customImports {
1460		if cimport == "time" {
1461			g.P("var _ = time.Kitchen")
1462			break
1463		}
1464	}
1465	g.P()
1466}
1467
1468func (g *Generator) generateImported(id *ImportedDescriptor) {
1469	tn := id.TypeName()
1470	sn := tn[len(tn)-1]
1471	df := id.o.File()
1472	filename := *df.Name
1473	if df.importPath == g.file.importPath {
1474		// Don't generate type aliases for files in the same Go package as this one.
1475		g.P("// Ignoring public import of ", sn, " from ", filename)
1476		g.P()
1477		return
1478	}
1479	if !supportTypeAliases {
1480		g.Fail(fmt.Sprintf("%s: public imports require at least go1.9", filename))
1481	}
1482	g.P("// ", sn, " from public import ", filename)
1483	g.usedPackages[df.importPath] = true
1484
1485	for _, sym := range df.exported[id.o] {
1486		sym.GenerateAlias(g, g.GoPackageName(df.importPath))
1487	}
1488
1489	g.P()
1490}
1491
1492// Generate the enum definitions for this EnumDescriptor.
1493func (g *Generator) generateEnum(enum *EnumDescriptor) {
1494	// The full type name
1495	typeName := enum.alias()
1496	// The full type name, CamelCased.
1497	ccTypeName := CamelCaseSlice(typeName)
1498	ccPrefix := enum.prefix()
1499
1500	deprecatedEnum := ""
1501	if enum.GetOptions().GetDeprecated() {
1502		deprecatedEnum = deprecationComment
1503	}
1504
1505	g.PrintComments(enum.path)
1506	if !gogoproto.EnabledGoEnumPrefix(enum.file.FileDescriptorProto, enum.EnumDescriptorProto) {
1507		ccPrefix = ""
1508	}
1509
1510	if gogoproto.HasEnumDecl(enum.file.FileDescriptorProto, enum.EnumDescriptorProto) {
1511		g.P("type ", Annotate(enum.file, enum.path, ccTypeName), " int32", deprecatedEnum)
1512		g.file.addExport(enum, enumSymbol{ccTypeName, enum.proto3()})
1513		g.P("const (")
1514		g.In()
1515		for i, e := range enum.Value {
1516			etorPath := fmt.Sprintf("%s,%d,%d", enum.path, enumValuePath, i)
1517			g.PrintComments(etorPath)
1518
1519			deprecatedValue := ""
1520			if e.GetOptions().GetDeprecated() {
1521				deprecatedValue = deprecationComment
1522			}
1523			name := *e.Name
1524			if gogoproto.IsEnumValueCustomName(e) {
1525				name = gogoproto.GetEnumValueCustomName(e)
1526			}
1527			name = ccPrefix + name
1528
1529			g.P(Annotate(enum.file, etorPath, name), " ", ccTypeName, " = ", e.Number, " ", deprecatedValue)
1530			g.file.addExport(enum, constOrVarSymbol{name, "const", ccTypeName})
1531		}
1532		g.Out()
1533		g.P(")")
1534	}
1535
1536	g.P("var ", ccTypeName, "_name = map[int32]string{")
1537	g.In()
1538	generated := make(map[int32]bool) // avoid duplicate values
1539	for _, e := range enum.Value {
1540		duplicate := ""
1541		if _, present := generated[*e.Number]; present {
1542			duplicate = "// Duplicate value: "
1543		}
1544		g.P(duplicate, e.Number, ": ", strconv.Quote(*e.Name), ",")
1545		generated[*e.Number] = true
1546	}
1547	g.Out()
1548	g.P("}")
1549	g.P("var ", ccTypeName, "_value = map[string]int32{")
1550	g.In()
1551	for _, e := range enum.Value {
1552		g.P(strconv.Quote(*e.Name), ": ", e.Number, ",")
1553	}
1554	g.Out()
1555	g.P("}")
1556
1557	if !enum.proto3() {
1558		g.P("func (x ", ccTypeName, ") Enum() *", ccTypeName, " {")
1559		g.In()
1560		g.P("p := new(", ccTypeName, ")")
1561		g.P("*p = x")
1562		g.P("return p")
1563		g.Out()
1564		g.P("}")
1565	}
1566
1567	if gogoproto.IsGoEnumStringer(g.file.FileDescriptorProto, enum.EnumDescriptorProto) {
1568		g.P("func (x ", ccTypeName, ") String() string {")
1569		g.In()
1570		g.P("return ", g.Pkg["proto"], ".EnumName(", ccTypeName, "_name, int32(x))")
1571		g.Out()
1572		g.P("}")
1573	}
1574
1575	if !enum.proto3() && !gogoproto.IsGoEnumStringer(g.file.FileDescriptorProto, enum.EnumDescriptorProto) {
1576		g.P("func (x ", ccTypeName, ") MarshalJSON() ([]byte, error) {")
1577		g.In()
1578		g.P("return ", g.Pkg["proto"], ".MarshalJSONEnum(", ccTypeName, "_name, int32(x))")
1579		g.Out()
1580		g.P("}")
1581	}
1582	if !enum.proto3() {
1583		g.P("func (x *", ccTypeName, ") UnmarshalJSON(data []byte) error {")
1584		g.In()
1585		g.P("value, err := ", g.Pkg["proto"], ".UnmarshalJSONEnum(", ccTypeName, `_value, data, "`, ccTypeName, `")`)
1586		g.P("if err != nil {")
1587		g.In()
1588		g.P("return err")
1589		g.Out()
1590		g.P("}")
1591		g.P("*x = ", ccTypeName, "(value)")
1592		g.P("return nil")
1593		g.Out()
1594		g.P("}")
1595	}
1596
1597	var indexes []string
1598	for m := enum.parent; m != nil; m = m.parent {
1599		// XXX: skip groups?
1600		indexes = append([]string{strconv.Itoa(m.index)}, indexes...)
1601	}
1602	indexes = append(indexes, strconv.Itoa(enum.index))
1603	g.P("func (", ccTypeName, ") EnumDescriptor() ([]byte, []int) {")
1604	g.In()
1605	g.P("return ", g.file.VarName(), ", []int{", strings.Join(indexes, ", "), "}")
1606	g.Out()
1607	g.P("}")
1608	if enum.file.GetPackage() == "google.protobuf" && enum.GetName() == "NullValue" {
1609		g.P("func (", ccTypeName, `) XXX_WellKnownType() string { return "`, enum.GetName(), `" }`)
1610	}
1611
1612	g.P()
1613}
1614
1615// The tag is a string like "varint,2,opt,name=fieldname,def=7" that
1616// identifies details of the field for the protocol buffer marshaling and unmarshaling
1617// code.  The fields are:
1618//	wire encoding
1619//	protocol tag number
1620//	opt,req,rep for optional, required, or repeated
1621//	packed whether the encoding is "packed" (optional; repeated primitives only)
1622//	name= the original declared name
1623//	enum= the name of the enum type if it is an enum-typed field.
1624//	proto3 if this field is in a proto3 message
1625//	def= string representation of the default value, if any.
1626// The default value must be in a representation that can be used at run-time
1627// to generate the default value. Thus bools become 0 and 1, for instance.
1628func (g *Generator) goTag(message *Descriptor, field *descriptor.FieldDescriptorProto, wiretype string) string {
1629	optrepreq := ""
1630	switch {
1631	case isOptional(field):
1632		optrepreq = "opt"
1633	case isRequired(field):
1634		optrepreq = "req"
1635	case isRepeated(field):
1636		optrepreq = "rep"
1637	}
1638	var defaultValue string
1639	if dv := field.DefaultValue; dv != nil { // set means an explicit default
1640		defaultValue = *dv
1641		// Some types need tweaking.
1642		switch *field.Type {
1643		case descriptor.FieldDescriptorProto_TYPE_BOOL:
1644			if defaultValue == "true" {
1645				defaultValue = "1"
1646			} else {
1647				defaultValue = "0"
1648			}
1649		case descriptor.FieldDescriptorProto_TYPE_STRING,
1650			descriptor.FieldDescriptorProto_TYPE_BYTES:
1651			// Nothing to do. Quoting is done for the whole tag.
1652		case descriptor.FieldDescriptorProto_TYPE_ENUM:
1653			// For enums we need to provide the integer constant.
1654			obj := g.ObjectNamed(field.GetTypeName())
1655			if id, ok := obj.(*ImportedDescriptor); ok {
1656				// It is an enum that was publicly imported.
1657				// We need the underlying type.
1658				obj = id.o
1659			}
1660			enum, ok := obj.(*EnumDescriptor)
1661			if !ok {
1662				log.Printf("obj is a %T", obj)
1663				if id, ok := obj.(*ImportedDescriptor); ok {
1664					log.Printf("id.o is a %T", id.o)
1665				}
1666				g.Fail("unknown enum type", CamelCaseSlice(obj.TypeName()))
1667			}
1668			defaultValue = enum.integerValueAsString(defaultValue)
1669		}
1670		defaultValue = ",def=" + defaultValue
1671	}
1672	enum := ""
1673	if *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM {
1674		// We avoid using obj.goPackageNamehe
1675		// original (proto-world) package name.
1676		obj := g.ObjectNamed(field.GetTypeName())
1677		if id, ok := obj.(*ImportedDescriptor); ok {
1678			obj = id.o
1679		}
1680		enum = ",enum="
1681		if pkg := obj.File().GetPackage(); pkg != "" {
1682			enum += pkg + "."
1683		}
1684		enum += CamelCaseSlice(obj.TypeName())
1685	}
1686	packed := ""
1687	if (field.Options != nil && field.Options.GetPacked()) ||
1688		// Per https://developers.google.com/protocol-buffers/docs/proto3#simple:
1689		// "In proto3, repeated fields of scalar numeric types use packed encoding by default."
1690		(message.proto3() && (field.Options == nil || field.Options.Packed == nil) &&
1691			isRepeated(field) && IsScalar(field)) {
1692		packed = ",packed"
1693	}
1694	fieldName := field.GetName()
1695	name := fieldName
1696	if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP {
1697		// We must use the type name for groups instead of
1698		// the field name to preserve capitalization.
1699		// type_name in FieldDescriptorProto is fully-qualified,
1700		// but we only want the local part.
1701		name = *field.TypeName
1702		if i := strings.LastIndex(name, "."); i >= 0 {
1703			name = name[i+1:]
1704		}
1705	}
1706	if json := field.GetJsonName(); json != "" && json != name {
1707		// TODO: escaping might be needed, in which case
1708		// perhaps this should be in its own "json" tag.
1709		name += ",json=" + json
1710	}
1711	name = ",name=" + name
1712
1713	embed := ""
1714	if gogoproto.IsEmbed(field) {
1715		embed = ",embedded=" + fieldName
1716	}
1717
1718	ctype := ""
1719	if gogoproto.IsCustomType(field) {
1720		ctype = ",customtype=" + gogoproto.GetCustomType(field)
1721	}
1722
1723	casttype := ""
1724	if gogoproto.IsCastType(field) {
1725		casttype = ",casttype=" + gogoproto.GetCastType(field)
1726	}
1727
1728	castkey := ""
1729	if gogoproto.IsCastKey(field) {
1730		castkey = ",castkey=" + gogoproto.GetCastKey(field)
1731	}
1732
1733	castvalue := ""
1734	if gogoproto.IsCastValue(field) {
1735		castvalue = ",castvalue=" + gogoproto.GetCastValue(field)
1736		// record the original message type for jsonpb reconstruction
1737		desc := g.ObjectNamed(field.GetTypeName())
1738		if d, ok := desc.(*Descriptor); ok && d.GetOptions().GetMapEntry() {
1739			valueField := d.Field[1]
1740			if valueField.IsMessage() {
1741				castvalue += ",castvaluetype=" + strings.TrimPrefix(valueField.GetTypeName(), ".")
1742			}
1743		}
1744	}
1745
1746	if message.proto3() {
1747		name += ",proto3"
1748	}
1749	oneof := ""
1750	if field.OneofIndex != nil {
1751		oneof = ",oneof"
1752	}
1753	stdtime := ""
1754	if gogoproto.IsStdTime(field) {
1755		stdtime = ",stdtime"
1756	}
1757	stdduration := ""
1758	if gogoproto.IsStdDuration(field) {
1759		stdduration = ",stdduration"
1760	}
1761	wktptr := ""
1762	if gogoproto.IsWktPtr(field) {
1763		wktptr = ",wktptr"
1764	}
1765	return strconv.Quote(fmt.Sprintf("%s,%d,%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
1766		wiretype,
1767		field.GetNumber(),
1768		optrepreq,
1769		packed,
1770		name,
1771		enum,
1772		oneof,
1773		defaultValue,
1774		embed,
1775		ctype,
1776		casttype,
1777		castkey,
1778		castvalue,
1779		stdtime,
1780		stdduration,
1781		wktptr))
1782}
1783
1784func needsStar(field *descriptor.FieldDescriptorProto, proto3 bool, allowOneOf bool) bool {
1785	if isRepeated(field) &&
1786		(*field.Type != descriptor.FieldDescriptorProto_TYPE_MESSAGE || gogoproto.IsCustomType(field)) &&
1787		(*field.Type != descriptor.FieldDescriptorProto_TYPE_GROUP) {
1788		return false
1789	}
1790	if *field.Type == descriptor.FieldDescriptorProto_TYPE_BYTES && !gogoproto.IsCustomType(field) {
1791		return false
1792	}
1793	if !gogoproto.IsNullable(field) {
1794		return false
1795	}
1796	if field.OneofIndex != nil && allowOneOf &&
1797		(*field.Type != descriptor.FieldDescriptorProto_TYPE_MESSAGE) &&
1798		(*field.Type != descriptor.FieldDescriptorProto_TYPE_GROUP) {
1799		return false
1800	}
1801	if proto3 &&
1802		(*field.Type != descriptor.FieldDescriptorProto_TYPE_MESSAGE) &&
1803		(*field.Type != descriptor.FieldDescriptorProto_TYPE_GROUP) &&
1804		!gogoproto.IsCustomType(field) {
1805		return false
1806	}
1807	return true
1808}
1809
1810// TypeName is the printed name appropriate for an item. If the object is in the current file,
1811// TypeName drops the package name and underscores the rest.
1812// Otherwise the object is from another package; and the result is the underscored
1813// package name followed by the item name.
1814// The result always has an initial capital.
1815func (g *Generator) TypeName(obj Object) string {
1816	return g.DefaultPackageName(obj) + CamelCaseSlice(obj.TypeName())
1817}
1818
1819// GoType returns a string representing the type name, and the wire type
1820func (g *Generator) GoType(message *Descriptor, field *descriptor.FieldDescriptorProto) (typ string, wire string) {
1821	// TODO: Options.
1822	switch *field.Type {
1823	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
1824		typ, wire = "float64", "fixed64"
1825	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
1826		typ, wire = "float32", "fixed32"
1827	case descriptor.FieldDescriptorProto_TYPE_INT64:
1828		typ, wire = "int64", "varint"
1829	case descriptor.FieldDescriptorProto_TYPE_UINT64:
1830		typ, wire = "uint64", "varint"
1831	case descriptor.FieldDescriptorProto_TYPE_INT32:
1832		typ, wire = "int32", "varint"
1833	case descriptor.FieldDescriptorProto_TYPE_UINT32:
1834		typ, wire = "uint32", "varint"
1835	case descriptor.FieldDescriptorProto_TYPE_FIXED64:
1836		typ, wire = "uint64", "fixed64"
1837	case descriptor.FieldDescriptorProto_TYPE_FIXED32:
1838		typ, wire = "uint32", "fixed32"
1839	case descriptor.FieldDescriptorProto_TYPE_BOOL:
1840		typ, wire = "bool", "varint"
1841	case descriptor.FieldDescriptorProto_TYPE_STRING:
1842		typ, wire = "string", "bytes"
1843	case descriptor.FieldDescriptorProto_TYPE_GROUP:
1844		desc := g.ObjectNamed(field.GetTypeName())
1845		typ, wire = g.TypeName(desc), "group"
1846	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
1847		desc := g.ObjectNamed(field.GetTypeName())
1848		typ, wire = g.TypeName(desc), "bytes"
1849	case descriptor.FieldDescriptorProto_TYPE_BYTES:
1850		typ, wire = "[]byte", "bytes"
1851	case descriptor.FieldDescriptorProto_TYPE_ENUM:
1852		desc := g.ObjectNamed(field.GetTypeName())
1853		typ, wire = g.TypeName(desc), "varint"
1854	case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
1855		typ, wire = "int32", "fixed32"
1856	case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
1857		typ, wire = "int64", "fixed64"
1858	case descriptor.FieldDescriptorProto_TYPE_SINT32:
1859		typ, wire = "int32", "zigzag32"
1860	case descriptor.FieldDescriptorProto_TYPE_SINT64:
1861		typ, wire = "int64", "zigzag64"
1862	default:
1863		g.Fail("unknown type for", field.GetName())
1864	}
1865	switch {
1866	case gogoproto.IsCustomType(field) && gogoproto.IsCastType(field):
1867		g.Fail(field.GetName() + " cannot be custom type and cast type")
1868	case gogoproto.IsCustomType(field):
1869		var packageName string
1870		var err error
1871		packageName, typ, err = getCustomType(field)
1872		if err != nil {
1873			g.Fail(err.Error())
1874		}
1875		if len(packageName) > 0 {
1876			g.customImports = append(g.customImports, packageName)
1877		}
1878	case gogoproto.IsCastType(field):
1879		var packageName string
1880		var err error
1881		packageName, typ, err = getCastType(field)
1882		if err != nil {
1883			g.Fail(err.Error())
1884		}
1885		if len(packageName) > 0 {
1886			g.customImports = append(g.customImports, packageName)
1887		}
1888	case gogoproto.IsStdTime(field):
1889		g.customImports = append(g.customImports, "time")
1890		typ = "time.Time"
1891	case gogoproto.IsStdDuration(field):
1892		g.customImports = append(g.customImports, "time")
1893		typ = "time.Duration"
1894	case gogoproto.IsStdDouble(field):
1895		typ = "float64"
1896	case gogoproto.IsStdFloat(field):
1897		typ = "float32"
1898	case gogoproto.IsStdInt64(field):
1899		typ = "int64"
1900	case gogoproto.IsStdUInt64(field):
1901		typ = "uint64"
1902	case gogoproto.IsStdInt32(field):
1903		typ = "int32"
1904	case gogoproto.IsStdUInt32(field):
1905		typ = "uint32"
1906	case gogoproto.IsStdBool(field):
1907		typ = "bool"
1908	case gogoproto.IsStdString(field):
1909		typ = "string"
1910	case gogoproto.IsStdBytes(field):
1911		typ = "[]byte"
1912	}
1913	if needsStar(field, g.file.proto3 && field.Extendee == nil, message != nil && message.allowOneof()) {
1914		typ = "*" + typ
1915	}
1916	if isRepeated(field) {
1917		typ = "[]" + typ
1918	}
1919	return
1920}
1921
1922// GoMapDescriptor is a full description of the map output struct.
1923type GoMapDescriptor struct {
1924	GoType string
1925
1926	KeyField      *descriptor.FieldDescriptorProto
1927	KeyAliasField *descriptor.FieldDescriptorProto
1928	KeyTag        string
1929
1930	ValueField      *descriptor.FieldDescriptorProto
1931	ValueAliasField *descriptor.FieldDescriptorProto
1932	ValueTag        string
1933}
1934
1935func (g *Generator) GoMapType(d *Descriptor, field *descriptor.FieldDescriptorProto) *GoMapDescriptor {
1936	if d == nil {
1937		byName := g.ObjectNamed(field.GetTypeName())
1938		desc, ok := byName.(*Descriptor)
1939		if byName == nil || !ok || !desc.GetOptions().GetMapEntry() {
1940			g.Fail(fmt.Sprintf("field %s is not a map", field.GetTypeName()))
1941			return nil
1942		}
1943		d = desc
1944	}
1945
1946	m := &GoMapDescriptor{
1947		KeyField:   d.Field[0],
1948		ValueField: d.Field[1],
1949	}
1950
1951	// Figure out the Go types and tags for the key and value types.
1952	m.KeyAliasField, m.ValueAliasField = g.GetMapKeyField(field, m.KeyField), g.GetMapValueField(field, m.ValueField)
1953	keyType, keyWire := g.GoType(d, m.KeyAliasField)
1954	valType, valWire := g.GoType(d, m.ValueAliasField)
1955
1956	m.KeyTag, m.ValueTag = g.goTag(d, m.KeyField, keyWire), g.goTag(d, m.ValueField, valWire)
1957
1958	if gogoproto.IsCastType(field) {
1959		var packageName string
1960		var err error
1961		packageName, typ, err := getCastType(field)
1962		if err != nil {
1963			g.Fail(err.Error())
1964		}
1965		if len(packageName) > 0 {
1966			g.customImports = append(g.customImports, packageName)
1967		}
1968		m.GoType = typ
1969		return m
1970	}
1971
1972	// We don't use stars, except for message-typed values.
1973	// Message and enum types are the only two possibly foreign types used in maps,
1974	// so record their use. They are not permitted as map keys.
1975	keyType = strings.TrimPrefix(keyType, "*")
1976	switch *m.ValueAliasField.Type {
1977	case descriptor.FieldDescriptorProto_TYPE_ENUM:
1978		valType = strings.TrimPrefix(valType, "*")
1979		g.RecordTypeUse(m.ValueAliasField.GetTypeName())
1980	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
1981		if !gogoproto.IsNullable(m.ValueAliasField) {
1982			valType = strings.TrimPrefix(valType, "*")
1983		}
1984		if !gogoproto.IsStdType(m.ValueAliasField) && !gogoproto.IsCustomType(field) && !gogoproto.IsCastType(field) {
1985			g.RecordTypeUse(m.ValueAliasField.GetTypeName())
1986		}
1987	default:
1988		if gogoproto.IsCustomType(m.ValueAliasField) {
1989			if !gogoproto.IsNullable(m.ValueAliasField) {
1990				valType = strings.TrimPrefix(valType, "*")
1991			}
1992			if !gogoproto.IsStdType(field) {
1993				g.RecordTypeUse(m.ValueAliasField.GetTypeName())
1994			}
1995		} else {
1996			valType = strings.TrimPrefix(valType, "*")
1997		}
1998	}
1999
2000	m.GoType = fmt.Sprintf("map[%s]%s", keyType, valType)
2001	return m
2002}
2003
2004func (g *Generator) RecordTypeUse(t string) {
2005	if _, ok := g.typeNameToObject[t]; ok {
2006		// Call ObjectNamed to get the true object to record the use.
2007		obj := g.ObjectNamed(t)
2008		g.usedPackages[obj.GoImportPath()] = true
2009	}
2010}
2011
2012// Method names that may be generated.  Fields with these names get an
2013// underscore appended. Any change to this set is a potential incompatible
2014// API change because it changes generated field names.
2015var methodNames = [...]string{
2016	"Reset",
2017	"String",
2018	"ProtoMessage",
2019	"Marshal",
2020	"Unmarshal",
2021	"ExtensionRangeArray",
2022	"ExtensionMap",
2023	"Descriptor",
2024	"MarshalTo",
2025	"Equal",
2026	"VerboseEqual",
2027	"GoString",
2028	"ProtoSize",
2029}
2030
2031// Names of messages in the `google.protobuf` package for which
2032// we will generate XXX_WellKnownType methods.
2033var wellKnownTypes = map[string]bool{
2034	"Any":       true,
2035	"Duration":  true,
2036	"Empty":     true,
2037	"Struct":    true,
2038	"Timestamp": true,
2039
2040	"Value":       true,
2041	"ListValue":   true,
2042	"DoubleValue": true,
2043	"FloatValue":  true,
2044	"Int64Value":  true,
2045	"UInt64Value": true,
2046	"Int32Value":  true,
2047	"UInt32Value": true,
2048	"BoolValue":   true,
2049	"StringValue": true,
2050	"BytesValue":  true,
2051}
2052
2053// getterDefault finds the default value for the field to return from a getter,
2054// regardless of if it's a built in default or explicit from the source. Returns e.g. "nil", `""`, "Default_MessageType_FieldName"
2055func (g *Generator) getterDefault(field *descriptor.FieldDescriptorProto, goMessageType, goTypeName string) string {
2056	if isRepeated(field) {
2057		return "nil"
2058	}
2059	if def := field.GetDefaultValue(); def != "" {
2060		defaultConstant := g.defaultConstantName(goMessageType, field.GetName())
2061		if *field.Type != descriptor.FieldDescriptorProto_TYPE_BYTES {
2062			return defaultConstant
2063		}
2064		return "append([]byte(nil), " + defaultConstant + "...)"
2065	}
2066	switch *field.Type {
2067	case descriptor.FieldDescriptorProto_TYPE_GROUP,
2068		descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2069		if field.OneofIndex != nil {
2070			return "nil"
2071		} else {
2072			if !gogoproto.IsNullable(field) && (gogoproto.IsStdDuration(field) ||
2073				gogoproto.IsStdDouble(field) || gogoproto.IsStdFloat(field) ||
2074				gogoproto.IsStdInt64(field) || gogoproto.IsStdUInt64(field) ||
2075				gogoproto.IsStdInt32(field) || gogoproto.IsStdUInt32(field)) {
2076				return "0"
2077			} else if !gogoproto.IsNullable(field) && gogoproto.IsStdBool(field) {
2078				return "false"
2079			} else if !gogoproto.IsNullable(field) && gogoproto.IsStdString(field) {
2080				return "\"\""
2081			} else if !gogoproto.IsNullable(field) && gogoproto.IsStdBytes(field) {
2082				return "[]byte{}"
2083			} else {
2084				return goTypeName + "{}"
2085			}
2086		}
2087	case descriptor.FieldDescriptorProto_TYPE_BOOL:
2088		return "false"
2089	case descriptor.FieldDescriptorProto_TYPE_STRING:
2090		return "\"\""
2091	case descriptor.FieldDescriptorProto_TYPE_BYTES:
2092		// This is only possible for oneof fields.
2093		return "nil"
2094	case descriptor.FieldDescriptorProto_TYPE_ENUM:
2095		// The default default for an enum is the first value in the enum,
2096		// not zero.
2097		obj := g.ObjectNamed(field.GetTypeName())
2098		var enum *EnumDescriptor
2099		if id, ok := obj.(*ImportedDescriptor); ok {
2100			// The enum type has been publicly imported.
2101			enum, _ = id.o.(*EnumDescriptor)
2102		} else {
2103			enum, _ = obj.(*EnumDescriptor)
2104		}
2105		if enum == nil {
2106			log.Printf("don't know how to generate getter for %s", field.GetName())
2107			return "nil"
2108		}
2109		if len(enum.Value) == 0 {
2110			return "0 // empty enum"
2111		} else {
2112			first := enum.Value[0].GetName()
2113			if gogoproto.IsEnumValueCustomName(enum.Value[0]) {
2114				first = gogoproto.GetEnumValueCustomName(enum.Value[0])
2115			}
2116			if gogoproto.EnabledGoEnumPrefix(enum.file.FileDescriptorProto, enum.EnumDescriptorProto) {
2117				return g.DefaultPackageName(obj) + enum.prefix() + first
2118			} else {
2119				return g.DefaultPackageName(obj) + first
2120			}
2121		}
2122	default:
2123		return "0"
2124	}
2125}
2126
2127// defaultConstantName builds the name of the default constant from the message
2128// type name and the untouched field name, e.g. "Default_MessageType_FieldName"
2129func (g *Generator) defaultConstantName(goMessageType, protoFieldName string) string {
2130	return "Default_" + goMessageType + "_" + CamelCase(protoFieldName)
2131}
2132
2133// The different types of fields in a message and how to actually print them
2134// Most of the logic for generateMessage is in the methods of these types.
2135//
2136// Note that the content of the field is irrelevant, a simpleField can contain
2137// anything from a scalar to a group (which is just a message).
2138//
2139// Extension fields (and message sets) are however handled separately.
2140//
2141// simpleField - a field that is neiter weak nor oneof, possibly repeated
2142// oneofField - field containing list of subfields:
2143// - oneofSubField - a field within the oneof
2144
2145// msgCtx contais the context for the generator functions.
2146type msgCtx struct {
2147	goName  string      // Go struct name of the message, e.g. MessageName
2148	message *Descriptor // The descriptor for the message
2149}
2150
2151// fieldCommon contains data common to all types of fields.
2152type fieldCommon struct {
2153	goName     string                           // Go name of field, e.g. "FieldName" or "Descriptor_"
2154	protoName  string                           // Name of field in proto language, e.g. "field_name" or "descriptor"
2155	getterName string                           // Name of the getter, e.g. "GetFieldName" or "GetDescriptor_"
2156	goType     string                           // The Go type as a string, e.g. "*int32" or "*OtherMessage"
2157	tags       string                           // The tag string/annotation for the type, e.g. `protobuf:"varint,8,opt,name=region_id,json=regionId"`
2158	fullPath   string                           // The full path of the field as used by Annotate etc, e.g. "4,0,2,0"
2159	protoField *descriptor.FieldDescriptorProto // gogo. Passing in the fieldDescriptor in for gogo options. TODO rethink this, we might need a better way of getting options.
2160}
2161
2162// getProtoName gets the proto name of a field, e.g. "field_name" or "descriptor".
2163func (f *fieldCommon) getProtoName() string {
2164	return f.protoName
2165}
2166
2167// getGoType returns the go type of the field  as a string, e.g. "*int32".
2168func (f *fieldCommon) getGoType() string {
2169	return f.goType
2170}
2171
2172// simpleField is not weak, not a oneof, not an extension. Can be required, optional or repeated.
2173type simpleField struct {
2174	fieldCommon
2175	protoTypeName string                               // Proto type name, empty if primitive, e.g. ".google.protobuf.Duration"
2176	protoType     descriptor.FieldDescriptorProto_Type // Actual type enum value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64
2177	deprecated    string                               // Deprecation comment, if any, e.g. "// Deprecated: Do not use."
2178	getterDef     string                               // Default for getters, e.g. "nil", `""` or "Default_MessageType_FieldName"
2179	protoDef      string                               // Default value as defined in the proto file, e.g "yoshi" or "5"
2180	comment       string                               // The full comment for the field, e.g. "// Useful information"
2181}
2182
2183// decl prints the declaration of the field in the struct (if any).
2184func (f *simpleField) decl(g *Generator, mc *msgCtx) {
2185	g.P(f.comment, Annotate(mc.message.file, f.fullPath, f.goName), "\t", f.goType, "\t`", f.tags, "`", f.deprecated)
2186}
2187
2188// getter prints the getter for the field.
2189func (f *simpleField) getter(g *Generator, mc *msgCtx) {
2190	oneof := false
2191	if !oneof && !gogoproto.HasGoGetters(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
2192		return
2193	}
2194	if gogoproto.IsEmbed(f.protoField) || gogoproto.IsCustomType(f.protoField) {
2195		return
2196	}
2197	if f.deprecated != "" {
2198		g.P(f.deprecated)
2199	}
2200	g.generateGet(mc, f.protoField, f.protoType, false, f.goName, f.goType, "", "", f.fullPath, f.getterName, f.getterDef)
2201}
2202
2203// setter prints the setter method of the field.
2204func (f *simpleField) setter(g *Generator, mc *msgCtx) {
2205	// No setter for regular fields yet
2206}
2207
2208// getProtoDef returns the default value explicitly stated in the proto file, e.g "yoshi" or "5".
2209func (f *simpleField) getProtoDef() string {
2210	return f.protoDef
2211}
2212
2213// getProtoTypeName returns the protobuf type name for the field as returned by field.GetTypeName(), e.g. ".google.protobuf.Duration".
2214func (f *simpleField) getProtoTypeName() string {
2215	return f.protoTypeName
2216}
2217
2218// getProtoType returns the *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64.
2219func (f *simpleField) getProtoType() descriptor.FieldDescriptorProto_Type {
2220	return f.protoType
2221}
2222
2223func (f *simpleField) getProto() *descriptor.FieldDescriptorProto {
2224	return f.protoField
2225}
2226
2227// oneofSubFields are kept slize held by each oneofField. They do not appear in the top level slize of fields for the message.
2228type oneofSubField struct {
2229	fieldCommon
2230	protoTypeName string                               // Proto type name, empty if primitive, e.g. ".google.protobuf.Duration"
2231	protoType     descriptor.FieldDescriptorProto_Type // Actual type enum value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64
2232	oneofTypeName string                               // Type name of the enclosing struct, e.g. "MessageName_FieldName"
2233	fieldNumber   int                                  // Actual field number, as defined in proto, e.g. 12
2234	getterDef     string                               // Default for getters, e.g. "nil", `""` or "Default_MessageType_FieldName"
2235	protoDef      string                               // Default value as defined in the proto file, e.g "yoshi" or "5"
2236	wireType      string                               // gogo. We can set this on creation, instead of using a function
2237}
2238
2239// wireTypeName returns a textual wire type, needed for oneof sub fields in generated code.
2240func (f *oneofSubField) wireTypeName() string {
2241	return f.wireType
2242}
2243
2244// typedNil prints a nil casted to the pointer to this field.
2245// - for XXX_OneofFuncs
2246func (f *oneofSubField) typedNil(g *Generator) {
2247	g.P("(*", f.oneofTypeName, ")(nil),")
2248}
2249
2250// marshalCase prints the case matching this oneof subfield in the marshalling code.
2251func (f *oneofSubField) marshalCase(g *Generator, mc *msgCtx) {
2252	// if field.OneofIndex == nil || int(*field.OneofIndex) != oi {
2253	// continue
2254	// }
2255	g.P("case *", f.oneofTypeName, ":")
2256	var pre, post string
2257	val := "x." + f.goName // overridden for TYPE_BOOL
2258	canFail := false       // only TYPE_MESSAGE and TYPE_GROUP can fail
2259	switch f.protoType {
2260	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
2261		pre = "b.EncodeFixed64(" + g.Pkg["math"] + ".Float64bits("
2262		post = "))"
2263	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
2264		pre = "b.EncodeFixed32(uint64(" + g.Pkg["math"] + ".Float32bits("
2265		post = ")))"
2266	case descriptor.FieldDescriptorProto_TYPE_INT64,
2267		descriptor.FieldDescriptorProto_TYPE_UINT64:
2268		pre, post = "b.EncodeVarint(uint64(", "))"
2269	case descriptor.FieldDescriptorProto_TYPE_INT32,
2270		descriptor.FieldDescriptorProto_TYPE_UINT32,
2271		descriptor.FieldDescriptorProto_TYPE_ENUM:
2272		pre, post = "b.EncodeVarint(uint64(", "))"
2273	case descriptor.FieldDescriptorProto_TYPE_FIXED64,
2274		descriptor.FieldDescriptorProto_TYPE_SFIXED64:
2275		pre, post = "b.EncodeFixed64(uint64(", "))"
2276	case descriptor.FieldDescriptorProto_TYPE_FIXED32,
2277		descriptor.FieldDescriptorProto_TYPE_SFIXED32:
2278		pre, post = "b.EncodeFixed32(uint64(", "))"
2279	case descriptor.FieldDescriptorProto_TYPE_BOOL:
2280		// bool needs special handling.
2281		g.P("t := uint64(0)")
2282		g.P("if ", val, " { t = 1 }")
2283		val = "t"
2284		pre, post = "b.EncodeVarint(", ")"
2285	case descriptor.FieldDescriptorProto_TYPE_STRING:
2286		pre, post = "b.EncodeStringBytes(", ")"
2287	case descriptor.FieldDescriptorProto_TYPE_GROUP:
2288		pre, post = "b.Marshal(", ")"
2289		canFail = true
2290	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2291		pre, post = "b.EncodeMessage(", ")"
2292		canFail = true
2293	case descriptor.FieldDescriptorProto_TYPE_BYTES:
2294		pre, post = "b.EncodeRawBytes(", ")"
2295	case descriptor.FieldDescriptorProto_TYPE_SINT32:
2296		pre, post = "b.EncodeZigzag32(uint64(", "))"
2297	case descriptor.FieldDescriptorProto_TYPE_SINT64:
2298		pre, post = "b.EncodeZigzag64(uint64(", "))"
2299	default:
2300		g.Fail("unhandled oneof field type ", f.protoType.String())
2301	}
2302	g.P("_ = b.EncodeVarint(", f.fieldNumber, "<<3|", g.Pkg["proto"], ".", f.wireTypeName(), ")")
2303	if f.protoType == descriptor.FieldDescriptorProto_TYPE_BYTES && gogoproto.IsCustomType(f.protoField) {
2304		g.P(`dAtA, err := `, val, `.Marshal()`)
2305		g.P(`if err != nil {`)
2306		g.In()
2307		g.P(`return err`)
2308		g.Out()
2309		g.P(`}`)
2310		val = "dAtA"
2311	} else if gogoproto.IsStdType(f.protoField) {
2312		pkg := g.useTypes()
2313		ptr := ""
2314		fnname := ""
2315		if gogoproto.IsNullable(f.protoField) {
2316			ptr = "*"
2317		}
2318		if gogoproto.IsStdTime(f.protoField) {
2319			fnname = "Time"
2320		} else if gogoproto.IsStdDuration(f.protoField) {
2321			fnname = "Duration"
2322		} else if gogoproto.IsStdDouble(f.protoField) {
2323			fnname = "Double"
2324		} else if gogoproto.IsStdFloat(f.protoField) {
2325			fnname = "Float"
2326		} else if gogoproto.IsStdInt64(f.protoField) {
2327			fnname = "Int64"
2328		} else if gogoproto.IsStdUInt64(f.protoField) {
2329			fnname = "UInt64"
2330		} else if gogoproto.IsStdInt32(f.protoField) {
2331			fnname = "Int32"
2332		} else if gogoproto.IsStdUInt32(f.protoField) {
2333			fnname = "UInt32"
2334		} else if gogoproto.IsStdBool(f.protoField) {
2335			fnname = "Bool"
2336		} else if gogoproto.IsStdString(f.protoField) {
2337			fnname = "String"
2338		} else if gogoproto.IsStdBytes(f.protoField) {
2339			fnname = "Bytes"
2340		} else {
2341			panic("internal error")
2342		}
2343		g.P(`dAtA, err := `, pkg, `.Std`, fnname, `Marshal(`, ptr, val, `)`)
2344		g.P(`if err != nil {`)
2345		g.In()
2346		g.P(`return err`)
2347		g.Out()
2348		g.P(`}`)
2349		val = "dAtA"
2350		pre, post = "b.EncodeRawBytes(", ")"
2351	}
2352	if !canFail {
2353		g.P("_ = ", pre, val, post)
2354	} else {
2355		g.P("if err := ", pre, val, post, "; err != nil {")
2356		g.In()
2357		g.P("return err")
2358		g.Out()
2359		g.P("}")
2360	}
2361	if f.protoType == descriptor.FieldDescriptorProto_TYPE_GROUP {
2362		g.P("_ = b.EncodeVarint(", f.fieldNumber, "<<3|", g.Pkg["proto"], ".WireEndGroup)")
2363	}
2364}
2365
2366// unmarshalCase prints the case matching this oneof subfield in the unmarshalling code.
2367func (f *oneofSubField) unmarshalCase(g *Generator, origOneofName string, oneofName string, mc *msgCtx) {
2368	// if field.OneofIndex == nil {
2369	// continue
2370	// }
2371	g.P("case ", f.fieldNumber, ": // ", origOneofName, ".", f.getProtoName())
2372	g.P("if wire != ", g.Pkg["proto"], ".", f.wireTypeName(), " {")
2373	g.P("return true, ", g.Pkg["proto"], ".ErrInternalBadWireType")
2374	g.P("}")
2375	lhs := "x, err" // overridden for TYPE_MESSAGE and TYPE_GROUP
2376	var dec, cast, cast2 string
2377	switch f.protoType {
2378	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
2379		dec, cast = "b.DecodeFixed64()", g.Pkg["math"]+".Float64frombits"
2380	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
2381		dec, cast, cast2 = "b.DecodeFixed32()", "uint32", g.Pkg["math"]+".Float32frombits"
2382	case descriptor.FieldDescriptorProto_TYPE_INT64:
2383		dec, cast = "b.DecodeVarint()", "int64"
2384	case descriptor.FieldDescriptorProto_TYPE_UINT64:
2385		dec = "b.DecodeVarint()"
2386	case descriptor.FieldDescriptorProto_TYPE_INT32:
2387		dec, cast = "b.DecodeVarint()", "int32"
2388	case descriptor.FieldDescriptorProto_TYPE_FIXED64:
2389		dec = "b.DecodeFixed64()"
2390	case descriptor.FieldDescriptorProto_TYPE_FIXED32:
2391		dec, cast = "b.DecodeFixed32()", "uint32"
2392	case descriptor.FieldDescriptorProto_TYPE_BOOL:
2393		dec = "b.DecodeVarint()"
2394		// handled specially below
2395	case descriptor.FieldDescriptorProto_TYPE_STRING:
2396		dec = "b.DecodeStringBytes()"
2397	case descriptor.FieldDescriptorProto_TYPE_GROUP:
2398		g.P("msg := new(", f.goType[1:], ")") // drop star
2399		lhs = "err"
2400		dec = "b.DecodeGroup(msg)"
2401		// handled specially below
2402	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2403		if gogoproto.IsStdType(f.protoField) {
2404			dec = "b.DecodeRawBytes(true)"
2405		} else {
2406			g.P("msg := new(", f.goType[1:], ")") // drop star
2407			lhs = "err"
2408			dec = "b.DecodeMessage(msg)"
2409		}
2410		// handled specially below
2411	case descriptor.FieldDescriptorProto_TYPE_BYTES:
2412		dec = "b.DecodeRawBytes(true)"
2413	case descriptor.FieldDescriptorProto_TYPE_UINT32:
2414		dec, cast = "b.DecodeVarint()", "uint32"
2415	case descriptor.FieldDescriptorProto_TYPE_ENUM:
2416		dec, cast = "b.DecodeVarint()", f.goType
2417	case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
2418		dec, cast = "b.DecodeFixed32()", "int32"
2419	case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
2420		dec, cast = "b.DecodeFixed64()", "int64"
2421	case descriptor.FieldDescriptorProto_TYPE_SINT32:
2422		dec, cast = "b.DecodeZigzag32()", "int32"
2423	case descriptor.FieldDescriptorProto_TYPE_SINT64:
2424		dec, cast = "b.DecodeZigzag64()", "int64"
2425	default:
2426		g.Fail("unhandled oneof field type ", f.protoType.String())
2427	}
2428	g.P(lhs, " := ", dec)
2429	val := "x"
2430	if f.protoType == descriptor.FieldDescriptorProto_TYPE_BYTES && gogoproto.IsCustomType(f.protoField) {
2431		g.P(`if err != nil {`)
2432		g.In()
2433		g.P(`return true, err`)
2434		g.Out()
2435		g.P(`}`)
2436		_, ctyp, err := GetCustomType(f.protoField)
2437		if err != nil {
2438			panic(err)
2439		}
2440		g.P(`var cc `, ctyp)
2441		g.P(`c := &cc`)
2442		g.P(`err = c.Unmarshal(`, val, `)`)
2443		val = "*c"
2444	} else if gogoproto.IsStdType(f.protoField) {
2445		var stdtype string
2446		var fnname string
2447		if gogoproto.IsStdTime(f.protoField) {
2448			stdtype = "time.Time"
2449			fnname = "Time"
2450		} else if gogoproto.IsStdDuration(f.protoField) {
2451			stdtype = "time.Duration"
2452			fnname = "Duration"
2453		} else if gogoproto.IsStdDouble(f.protoField) {
2454			stdtype = "float64"
2455			fnname = "Double"
2456		} else if gogoproto.IsStdFloat(f.protoField) {
2457			stdtype = "float32"
2458			fnname = "Float"
2459		} else if gogoproto.IsStdInt64(f.protoField) {
2460			stdtype = "int64"
2461			fnname = "Int64"
2462		} else if gogoproto.IsStdUInt64(f.protoField) {
2463			stdtype = "uint64"
2464			fnname = "UInt64"
2465		} else if gogoproto.IsStdInt32(f.protoField) {
2466			stdtype = "int32"
2467			fnname = "Int32"
2468		} else if gogoproto.IsStdUInt32(f.protoField) {
2469			stdtype = "uint32"
2470			fnname = "UInt32"
2471		} else if gogoproto.IsStdBool(f.protoField) {
2472			stdtype = "bool"
2473			fnname = "Bool"
2474		} else if gogoproto.IsStdString(f.protoField) {
2475			stdtype = "string"
2476			fnname = "String"
2477		} else if gogoproto.IsStdBytes(f.protoField) {
2478			stdtype = "[]byte"
2479			fnname = "Bytes"
2480		} else {
2481			panic("internal error")
2482		}
2483
2484		pkg := g.useTypes()
2485		g.P(`if err != nil {`)
2486		g.In()
2487		g.P(`return true, err`)
2488		g.Out()
2489		g.P(`}`)
2490		g.P(`c := new(`, stdtype, `)`)
2491		g.P(`if err2 := `, pkg, `.Std`, fnname, `Unmarshal(c, `, val, `); err2 != nil {`)
2492		g.In()
2493		g.P(`return true, err`)
2494		g.Out()
2495		g.P(`}`)
2496		val = "c"
2497	}
2498	if cast != "" {
2499		val = cast + "(" + val + ")"
2500	}
2501	if cast2 != "" {
2502		val = cast2 + "(" + val + ")"
2503	}
2504	switch f.protoType {
2505	case descriptor.FieldDescriptorProto_TYPE_BOOL:
2506		val += " != 0"
2507	case descriptor.FieldDescriptorProto_TYPE_GROUP,
2508		descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2509		if !gogoproto.IsStdType(f.protoField) {
2510			val = "msg"
2511		}
2512	}
2513	if gogoproto.IsCastType(f.protoField) {
2514		_, typ, err := getCastType(f.protoField)
2515		if err != nil {
2516			g.Fail(err.Error())
2517		}
2518		val = typ + "(" + val + ")"
2519	}
2520	g.P("m.", oneofName, " = &", f.oneofTypeName, "{", val, "}")
2521	g.P("return true, err")
2522}
2523
2524// sizerCase prints the case matching this oneof subfield in the sizer code.
2525func (f *oneofSubField) sizerCase(g *Generator) {
2526	// if field.OneofIndex == nil || int(*field.OneofIndex) != oi {
2527	// 	continue
2528	// }
2529	g.P("case *", f.oneofTypeName, ":")
2530	val := "x." + f.goName
2531	var varint, fixed string
2532	switch f.protoType {
2533	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
2534		fixed = "8"
2535	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
2536		fixed = "4"
2537	case descriptor.FieldDescriptorProto_TYPE_INT64,
2538		descriptor.FieldDescriptorProto_TYPE_UINT64,
2539		descriptor.FieldDescriptorProto_TYPE_INT32,
2540		descriptor.FieldDescriptorProto_TYPE_UINT32,
2541		descriptor.FieldDescriptorProto_TYPE_ENUM:
2542		varint = val
2543	case descriptor.FieldDescriptorProto_TYPE_FIXED64,
2544		descriptor.FieldDescriptorProto_TYPE_SFIXED64:
2545		fixed = "8"
2546	case descriptor.FieldDescriptorProto_TYPE_FIXED32,
2547		descriptor.FieldDescriptorProto_TYPE_SFIXED32:
2548		fixed = "4"
2549	case descriptor.FieldDescriptorProto_TYPE_BOOL:
2550		fixed = "1"
2551	case descriptor.FieldDescriptorProto_TYPE_STRING:
2552		fixed = "len(" + val + ")"
2553		varint = fixed
2554	case descriptor.FieldDescriptorProto_TYPE_GROUP:
2555		fixed = g.Pkg["proto"] + ".Size(" + val + ")"
2556	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2557		if gogoproto.IsStdType(f.protoField) {
2558			pkg := g.useTypes()
2559			if gogoproto.IsNullable(f.protoField) {
2560				val = "*" + val
2561			}
2562			if gogoproto.IsStdTime(f.protoField) {
2563				g.P("s := ", pkg, ".SizeOfStdTime(", val, ")")
2564			} else if gogoproto.IsStdDuration(f.protoField) {
2565				g.P("s := ", pkg, ".SizeOfStdDuration(", val, ")")
2566			} else if gogoproto.IsStdDouble(f.protoField) {
2567				g.P("s := ", pkg, ".SizeOfStdDouble(", val, ")")
2568			} else if gogoproto.IsStdFloat(f.protoField) {
2569				g.P("s := ", pkg, ".SizeOfStdFloat(", val, ")")
2570			} else if gogoproto.IsStdInt64(f.protoField) {
2571				g.P("s := ", pkg, ".SizeOfStdInt64(", val, ")")
2572			} else if gogoproto.IsStdUInt64(f.protoField) {
2573				g.P("s := ", pkg, ".SizeOfStdUInt64(", val, ")")
2574			} else if gogoproto.IsStdInt32(f.protoField) {
2575				g.P("s := ", pkg, ".SizeOfStdInt32(", val, ")")
2576			} else if gogoproto.IsStdUInt32(f.protoField) {
2577				g.P("s := ", pkg, ".SizeOfStdUInt32(", val, ")")
2578			} else if gogoproto.IsStdBool(f.protoField) {
2579				g.P("s := ", pkg, ".SizeOfStdBool(", val, ")")
2580			} else if gogoproto.IsStdString(f.protoField) {
2581				g.P("s := ", pkg, ".SizeOfStdString(", val, ")")
2582			} else if gogoproto.IsStdBytes(f.protoField) {
2583				g.P("s := ", pkg, ".SizeOfStdBytes(", val, ")")
2584			} else {
2585				panic("internal error")
2586			}
2587		} else {
2588			g.P("s := ", g.Pkg["proto"], ".Size(", val, ")")
2589		}
2590		fixed = "s"
2591		varint = fixed
2592	case descriptor.FieldDescriptorProto_TYPE_BYTES:
2593		if gogoproto.IsCustomType(f.protoField) {
2594			fixed = val + ".Size()"
2595		} else {
2596			fixed = "len(" + val + ")"
2597		}
2598		varint = fixed
2599	case descriptor.FieldDescriptorProto_TYPE_SINT32:
2600		varint = "(uint32(" + val + ") << 1) ^ uint32((int32(" + val + ") >> 31))"
2601	case descriptor.FieldDescriptorProto_TYPE_SINT64:
2602		varint = "uint64(" + val + " << 1) ^ uint64((int64(" + val + ") >> 63))"
2603	default:
2604		g.Fail("unhandled oneof field type ", f.protoType.String())
2605	}
2606	// Tag and wire varint is known statically,
2607	// so don't generate code for that part of the size computation.
2608	tagAndWireSize := proto.SizeVarint(uint64(f.fieldNumber << 3)) // wire doesn't affect varint size
2609	g.P("n += ", tagAndWireSize, " // tag and wire")
2610	if varint != "" {
2611		g.P("n += ", g.Pkg["proto"], ".SizeVarint(uint64(", varint, "))")
2612	}
2613	if fixed != "" {
2614		g.P("n += ", fixed)
2615	}
2616	if f.protoType == descriptor.FieldDescriptorProto_TYPE_GROUP {
2617		g.P("n += ", tagAndWireSize, " // tag and wire")
2618	}
2619}
2620
2621// getProtoDef returns the default value explicitly stated in the proto file, e.g "yoshi" or "5".
2622func (f *oneofSubField) getProtoDef() string {
2623	return f.protoDef
2624}
2625
2626// getProtoTypeName returns the protobuf type name for the field as returned by field.GetTypeName(), e.g. ".google.protobuf.Duration".
2627func (f *oneofSubField) getProtoTypeName() string {
2628	return f.protoTypeName
2629}
2630
2631// getProtoType returns the *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64.
2632func (f *oneofSubField) getProtoType() descriptor.FieldDescriptorProto_Type {
2633	return f.protoType
2634}
2635
2636func (f *oneofSubField) getProto() *descriptor.FieldDescriptorProto {
2637	return f.protoField
2638}
2639
2640// oneofField represents the oneof on top level.
2641// The alternative fields within the oneof are represented by oneofSubField.
2642type oneofField struct {
2643	fieldCommon
2644	subFields []*oneofSubField // All the possible oneof fields
2645	comment   string           // The full comment for the field, e.g. "// Types that are valid to be assigned to MyOneof:\n\\"
2646}
2647
2648// decl prints the declaration of the field in the struct (if any).
2649func (f *oneofField) decl(g *Generator, mc *msgCtx) {
2650	comment := f.comment
2651	for _, sf := range f.subFields {
2652		comment += "//\t*" + sf.oneofTypeName + "\n"
2653	}
2654	g.P(comment, Annotate(mc.message.file, f.fullPath, f.goName), " ", f.goType, " `", f.tags, "`")
2655}
2656
2657// getter for a oneof field will print additional discriminators and interfaces for the oneof,
2658// also it prints all the getters for the sub fields.
2659func (f *oneofField) getter(g *Generator, mc *msgCtx) {
2660	oneof := true
2661	if !oneof && !gogoproto.HasGoGetters(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
2662		return
2663	}
2664
2665	for _, of := range f.subFields {
2666		if gogoproto.IsEmbed(of.protoField) || gogoproto.IsCustomType(of.protoField) {
2667			continue
2668		}
2669		g.generateGet(mc, of.protoField, of.protoType, true, of.goName, of.goType, f.goName, of.oneofTypeName, of.fullPath, of.getterName, of.getterDef)
2670	}
2671}
2672
2673// setter prints the setter method of the field.
2674func (f *oneofField) setter(g *Generator, mc *msgCtx) {
2675	// No setters for oneof yet
2676}
2677
2678// topLevelField interface implemented by all types of fields on the top level (not oneofSubField).
2679type topLevelField interface {
2680	decl(g *Generator, mc *msgCtx)   // print declaration within the struct
2681	getter(g *Generator, mc *msgCtx) // print getter
2682	setter(g *Generator, mc *msgCtx) // print setter if applicable
2683}
2684
2685// defField interface implemented by all types of fields that can have defaults (not oneofField, but instead oneofSubField).
2686type defField interface {
2687	getProtoDef() string                                // default value explicitly stated in the proto file, e.g "yoshi" or "5"
2688	getProtoName() string                               // proto name of a field, e.g. "field_name" or "descriptor"
2689	getGoType() string                                  // go type of the field  as a string, e.g. "*int32"
2690	getProtoTypeName() string                           // protobuf type name for the field, e.g. ".google.protobuf.Duration"
2691	getProtoType() descriptor.FieldDescriptorProto_Type // *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64
2692	getProto() *descriptor.FieldDescriptorProto
2693}
2694
2695// generateDefaultConstants adds constants for default values if needed, which is only if the default value is.
2696// explicit in the proto.
2697func (g *Generator) generateDefaultConstants(mc *msgCtx, topLevelFields []topLevelField) {
2698	// Collect fields that can have defaults
2699	dFields := []defField{}
2700	for _, pf := range topLevelFields {
2701		if f, ok := pf.(*oneofField); ok {
2702			for _, osf := range f.subFields {
2703				dFields = append(dFields, osf)
2704			}
2705			continue
2706		}
2707		dFields = append(dFields, pf.(defField))
2708	}
2709	for _, df := range dFields {
2710		def := df.getProtoDef()
2711		if def == "" {
2712			continue
2713		}
2714		if !gogoproto.IsNullable(df.getProto()) {
2715			g.Fail("illegal default value: ", df.getProtoName(), " in ", mc.message.GetName(), " is not nullable and is thus not allowed to have a default value")
2716		}
2717		fieldname := g.defaultConstantName(mc.goName, df.getProtoName())
2718		typename := df.getGoType()
2719		if typename[0] == '*' {
2720			typename = typename[1:]
2721		}
2722		kind := "const "
2723		switch {
2724		case typename == "bool":
2725		case typename == "string":
2726			def = strconv.Quote(def)
2727		case typename == "[]byte":
2728			def = "[]byte(" + strconv.Quote(unescape(def)) + ")"
2729			kind = "var "
2730		case def == "inf", def == "-inf", def == "nan":
2731			// These names are known to, and defined by, the protocol language.
2732			switch def {
2733			case "inf":
2734				def = "math.Inf(1)"
2735			case "-inf":
2736				def = "math.Inf(-1)"
2737			case "nan":
2738				def = "math.NaN()"
2739			}
2740			if df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_FLOAT {
2741				def = "float32(" + def + ")"
2742			}
2743			kind = "var "
2744		case df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_ENUM:
2745			// Must be an enum.  Need to construct the prefixed name.
2746			obj := g.ObjectNamed(df.getProtoTypeName())
2747			var enum *EnumDescriptor
2748			if id, ok := obj.(*ImportedDescriptor); ok {
2749				// The enum type has been publicly imported.
2750				enum, _ = id.o.(*EnumDescriptor)
2751			} else {
2752				enum, _ = obj.(*EnumDescriptor)
2753			}
2754			if enum == nil {
2755				log.Printf("don't know how to generate constant for %s", fieldname)
2756				continue
2757			}
2758
2759			// hunt down the actual enum corresponding to the default
2760			var enumValue *descriptor.EnumValueDescriptorProto
2761			for _, ev := range enum.Value {
2762				if def == ev.GetName() {
2763					enumValue = ev
2764				}
2765			}
2766
2767			if enumValue != nil {
2768				if gogoproto.IsEnumValueCustomName(enumValue) {
2769					def = gogoproto.GetEnumValueCustomName(enumValue)
2770				}
2771			} else {
2772				g.Fail(fmt.Sprintf("could not resolve default enum value for %v.%v", g.DefaultPackageName(obj), def))
2773			}
2774
2775			if gogoproto.EnabledGoEnumPrefix(enum.file.FileDescriptorProto, enum.EnumDescriptorProto) {
2776				def = g.DefaultPackageName(obj) + enum.prefix() + def
2777			} else {
2778				def = g.DefaultPackageName(obj) + def
2779			}
2780		}
2781		g.P(kind, fieldname, " ", typename, " = ", def)
2782		g.file.addExport(mc.message, constOrVarSymbol{fieldname, kind, ""})
2783	}
2784	g.P()
2785}
2786
2787// generateGet generates the getter for both the simpleField and oneofSubField.
2788// We did not want to duplicate the code since it is quite intricate so we came
2789// up with this ugly method. At least the logic is in one place. This can be reworked.
2790func (g *Generator) generateGet(mc *msgCtx, protoField *descriptor.FieldDescriptorProto, protoType descriptor.FieldDescriptorProto_Type,
2791	oneof bool, fname, tname, uname, oneoftname, fullpath, gname, def string) {
2792	star := ""
2793	if (protoType != descriptor.FieldDescriptorProto_TYPE_MESSAGE) &&
2794		(protoType != descriptor.FieldDescriptorProto_TYPE_GROUP) &&
2795		needsStar(protoField, g.file.proto3, mc.message != nil && mc.message.allowOneof()) && tname[0] == '*' {
2796		tname = tname[1:]
2797		star = "*"
2798	}
2799	typeDefaultIsNil := false // whether this field type's default value is a literal nil unless specified
2800	switch protoType {
2801	case descriptor.FieldDescriptorProto_TYPE_BYTES:
2802		typeDefaultIsNil = def == "nil"
2803	case descriptor.FieldDescriptorProto_TYPE_GROUP, descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2804		typeDefaultIsNil = gogoproto.IsNullable(protoField)
2805	}
2806	if isRepeated(protoField) {
2807		typeDefaultIsNil = true
2808	}
2809	g.P("func (m *", mc.goName, ") ", Annotate(mc.message.file, fullpath, gname), "() "+tname+" {")
2810	if !oneof && typeDefaultIsNil {
2811		// A bytes field with no explicit default needs less generated code,
2812		// as does a message or group field, or a repeated field.
2813		g.P("if m != nil {")
2814		g.In()
2815		g.P("return m." + fname)
2816		g.Out()
2817		g.P("}")
2818		g.P("return nil")
2819		g.Out()
2820		g.P("}")
2821		g.P()
2822		return
2823	}
2824	if !gogoproto.IsNullable(protoField) {
2825		g.P("if m != nil {")
2826		g.In()
2827		g.P("return m." + fname)
2828		g.Out()
2829		g.P("}")
2830	} else if !oneof {
2831		if mc.message.proto3() {
2832			g.P("if m != nil {")
2833		} else {
2834			g.P("if m != nil && m." + fname + " != nil {")
2835		}
2836		g.In()
2837		g.P("return " + star + "m." + fname)
2838		g.Out()
2839		g.P("}")
2840	} else {
2841		uname := uname
2842		tname := oneoftname
2843		g.P("if x, ok := m.Get", uname, "().(*", tname, "); ok {")
2844		g.P("return x.", fname)
2845		g.P("}")
2846	}
2847	g.P("return ", def)
2848	g.Out()
2849	g.P("}")
2850	g.P()
2851}
2852
2853// generateInternalStructFields just adds the XXX_<something> fields to the message struct.
2854func (g *Generator) generateInternalStructFields(mc *msgCtx, topLevelFields []topLevelField) {
2855	if gogoproto.HasUnkeyed(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
2856		g.P("XXX_NoUnkeyedLiteral\tstruct{} `json:\"-\"`") // prevent unkeyed struct literals
2857	}
2858	if len(mc.message.ExtensionRange) > 0 {
2859		if gogoproto.HasExtensionsMap(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
2860			messageset := ""
2861			if opts := mc.message.Options; opts != nil && opts.GetMessageSetWireFormat() {
2862				messageset = "protobuf_messageset:\"1\" "
2863			}
2864			g.P(g.Pkg["proto"], ".XXX_InternalExtensions `", messageset, "json:\"-\"`")
2865		} else {
2866			g.P("XXX_extensions\t\t[]byte `protobuf:\"bytes,0,opt\" json:\"-\"`")
2867		}
2868	}
2869	if gogoproto.HasUnrecognized(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
2870		g.P("XXX_unrecognized\t[]byte `json:\"-\"`")
2871	}
2872	if gogoproto.HasSizecache(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
2873		g.P("XXX_sizecache\tint32 `json:\"-\"`")
2874	}
2875}
2876
2877// generateOneofFuncs adds all the utility functions for oneof, including marshalling, unmarshalling and sizer.
2878func (g *Generator) generateOneofFuncs(mc *msgCtx, topLevelFields []topLevelField) {
2879	ofields := []*oneofField{}
2880	for _, f := range topLevelFields {
2881		if o, ok := f.(*oneofField); ok {
2882			ofields = append(ofields, o)
2883		}
2884	}
2885	if len(ofields) == 0 {
2886		return
2887	}
2888	enc := "_" + mc.goName + "_OneofMarshaler"
2889	dec := "_" + mc.goName + "_OneofUnmarshaler"
2890	size := "_" + mc.goName + "_OneofSizer"
2891	encSig := "(msg " + g.Pkg["proto"] + ".Message, b *" + g.Pkg["proto"] + ".Buffer) error"
2892	decSig := "(msg " + g.Pkg["proto"] + ".Message, tag, wire int, b *" + g.Pkg["proto"] + ".Buffer) (bool, error)"
2893	sizeSig := "(msg " + g.Pkg["proto"] + ".Message) (n int)"
2894
2895	// OneofFuncs
2896	g.P("// XXX_OneofFuncs is for the internal use of the proto package.")
2897	g.P("func (*", mc.goName, ") XXX_OneofFuncs() (func", encSig, ", func", decSig, ", func", sizeSig, ", []interface{}) {")
2898	g.P("return ", enc, ", ", dec, ", ", size, ", []interface{}{")
2899	for _, of := range ofields {
2900		for _, sf := range of.subFields {
2901			sf.typedNil(g)
2902		}
2903	}
2904	g.P("}")
2905	g.P("}")
2906	g.P()
2907
2908	// marshaler
2909	g.P("func ", enc, encSig, " {")
2910	g.P("m := msg.(*", mc.goName, ")")
2911	for _, of := range ofields {
2912		g.P("// ", of.getProtoName())
2913		g.P("switch x := m.", of.goName, ".(type) {")
2914		for _, sf := range of.subFields {
2915			sf.marshalCase(g, mc)
2916		}
2917		g.P("case nil:")
2918		g.P("default: return ", g.Pkg["fmt"], `.Errorf("`, mc.goName, ".", of.goName, ` has unexpected type %T", x)`)
2919		g.P("}")
2920	}
2921	g.P("return nil")
2922	g.P("}")
2923	g.P()
2924
2925	// unmarshaler
2926	g.P("func ", dec, decSig, " {")
2927	g.P("m := msg.(*", mc.goName, ")")
2928	g.P("switch tag {")
2929	for _, of := range ofields {
2930		for _, sf := range of.subFields {
2931			sf.unmarshalCase(g, of.getProtoName(), of.goName, mc)
2932		}
2933	}
2934	g.P("default: return false, nil")
2935	g.P("}")
2936	g.P("}")
2937	g.P()
2938
2939	// sizer
2940	g.P("func ", size, sizeSig, " {")
2941	g.P("m := msg.(*", mc.goName, ")")
2942	for _, of := range ofields {
2943		g.P("// ", of.getProtoName())
2944		g.P("switch x := m.", of.goName, ".(type) {")
2945		for _, sf := range of.subFields {
2946			// also fills in field.wire
2947			sf.sizerCase(g)
2948		}
2949		g.P("case nil:")
2950		g.P("default:")
2951		g.P("panic(", g.Pkg["fmt"], ".Sprintf(\"proto: unexpected type %T in oneof\", x))")
2952		g.P("}")
2953	}
2954	g.P("return n")
2955	g.P("}")
2956	g.P()
2957}
2958
2959func (g *Generator) generateOneofDecls(mc *msgCtx, topLevelFields []topLevelField) {
2960	ofields := []*oneofField{}
2961	for _, f := range topLevelFields {
2962		if o, ok := f.(*oneofField); ok {
2963			ofields = append(ofields, o)
2964		}
2965	}
2966	if len(ofields) == 0 {
2967		return
2968	}
2969	// Oneof per-field types, discriminants and getters.
2970	// Generate unexported named types for the discriminant interfaces.
2971	// We shouldn't have to do this, but there was (~19 Aug 2015) a compiler/linker bug
2972	// that was triggered by using anonymous interfaces here.
2973	// TODO: Revisit this and consider reverting back to anonymous interfaces.
2974	// for oi := range message.OneofDecl {
2975	for _, of := range ofields {
2976		dname := of.goType
2977		g.P("type ", dname, " interface {")
2978		g.In()
2979		g.P(dname, "()")
2980		if gogoproto.HasEqual(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
2981			g.P(`Equal(interface{}) bool`)
2982		}
2983		if gogoproto.HasVerboseEqual(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
2984			g.P(`VerboseEqual(interface{}) error`)
2985		}
2986		if gogoproto.IsMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) ||
2987			gogoproto.IsUnsafeMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) ||
2988			gogoproto.IsStableMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
2989			g.P(`MarshalTo([]byte) (int, error)`)
2990		}
2991		if gogoproto.IsSizer(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
2992			g.P(`Size() int`)
2993		}
2994		if gogoproto.IsProtoSizer(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
2995			g.P(`ProtoSize() int`)
2996		}
2997		g.Out()
2998		g.P("}")
2999	}
3000	g.P()
3001	for _, of := range ofields {
3002		for i, sf := range of.subFields {
3003			_, wiretype := g.GoType(mc.message, sf.protoField)
3004			tag := "protobuf:" + g.goTag(mc.message, sf.protoField, wiretype)
3005			fieldFullPath := fmt.Sprintf("%s,%d,%d", mc.message.path, messageFieldPath, i)
3006			g.P("type ", Annotate(mc.message.file, fieldFullPath, sf.oneofTypeName), " struct{ ", Annotate(mc.message.file, fieldFullPath, sf.goName), " ", sf.goType, " `", tag, "` }")
3007			if !gogoproto.IsStdType(sf.protoField) && !gogoproto.IsCustomType(sf.protoField) && !gogoproto.IsCastType(sf.protoField) {
3008				g.RecordTypeUse(sf.protoField.GetTypeName())
3009			}
3010		}
3011	}
3012	g.P()
3013	for _, of := range ofields {
3014		for _, sf := range of.subFields {
3015			g.P("func (*", sf.oneofTypeName, ") ", of.goType, "() {}")
3016		}
3017	}
3018	g.P()
3019	for _, of := range ofields {
3020		fname := of.goName
3021		g.P("func (m *", mc.goName, ") Get", fname, "() ", of.goType, " {")
3022		g.P("if m != nil { return m.", fname, " }")
3023		g.P("return nil")
3024		g.P("}")
3025	}
3026	g.P()
3027}
3028
3029// generateMessageStruct adds the actual struct with it's members (but not methods) to the output.
3030func (g *Generator) generateMessageStruct(mc *msgCtx, topLevelFields []topLevelField) {
3031	comments := g.PrintComments(mc.message.path)
3032
3033	// Guarantee deprecation comments appear after user-provided comments.
3034	if mc.message.GetOptions().GetDeprecated() {
3035		if comments {
3036			// Convention: Separate deprecation comments from original
3037			// comments with an empty line.
3038			g.P("//")
3039		}
3040		g.P(deprecationComment)
3041	}
3042	g.P("type ", Annotate(mc.message.file, mc.message.path, mc.goName), " struct {")
3043	for _, pf := range topLevelFields {
3044		pf.decl(g, mc)
3045	}
3046	g.generateInternalStructFields(mc, topLevelFields)
3047	g.P("}")
3048}
3049
3050// generateGetters adds getters for all fields, including oneofs and weak fields when applicable.
3051func (g *Generator) generateGetters(mc *msgCtx, topLevelFields []topLevelField) {
3052	for _, pf := range topLevelFields {
3053		pf.getter(g, mc)
3054
3055	}
3056}
3057
3058// generateSetters add setters for all fields, including oneofs and weak fields when applicable.
3059func (g *Generator) generateSetters(mc *msgCtx, topLevelFields []topLevelField) {
3060	for _, pf := range topLevelFields {
3061		pf.setter(g, mc)
3062	}
3063}
3064
3065// generateCommonMethods adds methods to the message that are not on a per field basis.
3066func (g *Generator) generateCommonMethods(mc *msgCtx) {
3067	// Reset, String and ProtoMessage methods.
3068	g.P("func (m *", mc.goName, ") Reset() { *m = ", mc.goName, "{} }")
3069	if gogoproto.EnabledGoStringer(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
3070		g.P("func (m *", mc.goName, ") String() string { return ", g.Pkg["proto"], ".CompactTextString(m) }")
3071	}
3072	g.P("func (*", mc.goName, ") ProtoMessage() {}")
3073	var indexes []string
3074	for m := mc.message; m != nil; m = m.parent {
3075		indexes = append([]string{strconv.Itoa(m.index)}, indexes...)
3076	}
3077	g.P("func (*", mc.goName, ") Descriptor() ([]byte, []int) {")
3078	g.P("return ", g.file.VarName(), ", []int{", strings.Join(indexes, ", "), "}")
3079	g.P("}")
3080	// TODO: Revisit the decision to use a XXX_WellKnownType method
3081	// if we change proto.MessageName to work with multiple equivalents.
3082	if mc.message.file.GetPackage() == "google.protobuf" && wellKnownTypes[mc.message.GetName()] {
3083		g.P("func (*", mc.goName, `) XXX_WellKnownType() string { return "`, mc.message.GetName(), `" }`)
3084	}
3085
3086	// Extension support methods
3087	if len(mc.message.ExtensionRange) > 0 {
3088		// message_set_wire_format only makes sense when extensions are defined.
3089		if opts := mc.message.Options; opts != nil && opts.GetMessageSetWireFormat() {
3090			// isMessageSet = true
3091			g.P()
3092			g.P("func (m *", mc.goName, ") MarshalJSON() ([]byte, error) {")
3093			g.In()
3094			g.P("return ", g.Pkg["proto"], ".MarshalMessageSetJSON(&m.XXX_InternalExtensions)")
3095			g.Out()
3096			g.P("}")
3097			g.P("func (m *", mc.goName, ") UnmarshalJSON(buf []byte) error {")
3098			g.In()
3099			g.P("return ", g.Pkg["proto"], ".UnmarshalMessageSetJSON(buf, &m.XXX_InternalExtensions)")
3100			g.Out()
3101			g.P("}")
3102		}
3103
3104		g.P()
3105		g.P("var extRange_", mc.goName, " = []", g.Pkg["proto"], ".ExtensionRange{")
3106		g.In()
3107		for _, r := range mc.message.ExtensionRange {
3108			end := fmt.Sprint(*r.End - 1) // make range inclusive on both ends
3109			g.P("{Start: ", r.Start, ", End: ", end, "},")
3110		}
3111		g.Out()
3112		g.P("}")
3113		g.P("func (*", mc.goName, ") ExtensionRangeArray() []", g.Pkg["proto"], ".ExtensionRange {")
3114		g.In()
3115		g.P("return extRange_", mc.goName)
3116		g.Out()
3117		g.P("}")
3118		if !gogoproto.HasExtensionsMap(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
3119			g.P("func (m *", mc.goName, ") GetExtensions() *[]byte {")
3120			g.In()
3121			g.P("if m.XXX_extensions == nil {")
3122			g.In()
3123			g.P("m.XXX_extensions = make([]byte, 0)")
3124			g.Out()
3125			g.P("}")
3126			g.P("return &m.XXX_extensions")
3127			g.Out()
3128			g.P("}")
3129		}
3130	}
3131
3132	// TODO: It does not scale to keep adding another method for every
3133	// operation on protos that we want to switch over to using the
3134	// table-driven approach. Instead, we should only add a single method
3135	// that allows getting access to the *InternalMessageInfo struct and then
3136	// calling Unmarshal, Marshal, Merge, Size, and Discard directly on that.
3137
3138	// Wrapper for table-driven marshaling and unmarshaling.
3139	g.P("func (m *", mc.goName, ") XXX_Unmarshal(b []byte) error {")
3140	g.In()
3141	if gogoproto.IsUnmarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
3142		g.P("return m.Unmarshal(b)")
3143	} else {
3144		g.P("return xxx_messageInfo_", mc.goName, ".Unmarshal(m, b)")
3145	}
3146	g.Out()
3147	g.P("}")
3148
3149	g.P("func (m *", mc.goName, ") XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {")
3150	g.In()
3151	if gogoproto.IsMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) ||
3152		gogoproto.IsUnsafeMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
3153		if gogoproto.IsStableMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
3154			g.P("b = b[:cap(b)]")
3155			g.P("n, err := m.MarshalTo(b)")
3156			g.P("if err != nil {")
3157			g.In()
3158			g.P("return nil, err")
3159			g.Out()
3160			g.P("}")
3161			g.P("return b[:n], nil")
3162		} else {
3163			g.P("if deterministic {")
3164			g.In()
3165			g.P("return xxx_messageInfo_", mc.goName, ".Marshal(b, m, deterministic)")
3166			g.P("} else {")
3167			g.In()
3168			g.P("b = b[:cap(b)]")
3169			g.P("n, err := m.MarshalTo(b)")
3170			g.P("if err != nil {")
3171			g.In()
3172			g.P("return nil, err")
3173			g.Out()
3174			g.P("}")
3175			g.Out()
3176			g.P("return b[:n], nil")
3177			g.Out()
3178			g.P("}")
3179		}
3180	} else {
3181		g.P("return xxx_messageInfo_", mc.goName, ".Marshal(b, m, deterministic)")
3182	}
3183	g.Out()
3184	g.P("}")
3185
3186	g.P("func (dst *", mc.goName, ") XXX_Merge(src ", g.Pkg["proto"], ".Message) {")
3187	g.In()
3188	g.P("xxx_messageInfo_", mc.goName, ".Merge(dst, src)")
3189	g.Out()
3190	g.P("}")
3191
3192	g.P("func (m *", mc.goName, ") XXX_Size() int {") // avoid name clash with "Size" field in some message
3193	g.In()
3194	if (gogoproto.IsMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) ||
3195		gogoproto.IsUnsafeMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto)) &&
3196		gogoproto.IsSizer(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
3197		g.P("return m.Size()")
3198	} else if (gogoproto.IsMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto) ||
3199		gogoproto.IsUnsafeMarshaler(g.file.FileDescriptorProto, mc.message.DescriptorProto)) &&
3200		gogoproto.IsProtoSizer(g.file.FileDescriptorProto, mc.message.DescriptorProto) {
3201		g.P("return m.ProtoSize()")
3202	} else {
3203		g.P("return xxx_messageInfo_", mc.goName, ".Size(m)")
3204	}
3205	g.Out()
3206	g.P("}")
3207
3208	g.P("func (m *", mc.goName, ") XXX_DiscardUnknown() {")
3209	g.In()
3210	g.P("xxx_messageInfo_", mc.goName, ".DiscardUnknown(m)")
3211	g.Out()
3212	g.P("}")
3213
3214	g.P("var xxx_messageInfo_", mc.goName, " ", g.Pkg["proto"], ".InternalMessageInfo")
3215}
3216
3217// Generate the type and default constant definitions for this Descriptor.
3218func (g *Generator) generateMessage(message *Descriptor) {
3219	topLevelFields := []topLevelField{}
3220	oFields := make(map[int32]*oneofField)
3221	// The full type name
3222	typeName := message.TypeName()
3223	// The full type name, CamelCased.
3224	goTypeName := CamelCaseSlice(typeName)
3225
3226	usedNames := make(map[string]bool)
3227	for _, n := range methodNames {
3228		usedNames[n] = true
3229	}
3230	if !gogoproto.IsProtoSizer(message.file.FileDescriptorProto, message.DescriptorProto) {
3231		usedNames["Size"] = true
3232	}
3233
3234	// allocNames finds a conflict-free variation of the given strings,
3235	// consistently mutating their suffixes.
3236	// It returns the same number of strings.
3237	allocNames := func(ns ...string) []string {
3238	Loop:
3239		for {
3240			for _, n := range ns {
3241				if usedNames[n] {
3242					for i := range ns {
3243						ns[i] += "_"
3244					}
3245					continue Loop
3246				}
3247			}
3248			for _, n := range ns {
3249				usedNames[n] = true
3250			}
3251			return ns
3252		}
3253	}
3254
3255	mapFieldTypes := make(map[*descriptor.FieldDescriptorProto]string) // keep track of the map fields to be added later
3256
3257	for i, field := range message.Field {
3258		// Allocate the getter and the field at the same time so name
3259		// collisions create field/method consistent names.
3260		// TODO: This allocation occurs based on the order of the fields
3261		// in the proto file, meaning that a change in the field
3262		// ordering can change generated Method/Field names.
3263		base := CamelCase(*field.Name)
3264		if gogoproto.IsCustomName(field) {
3265			base = gogoproto.GetCustomName(field)
3266		}
3267		ns := allocNames(base, "Get"+base)
3268		fieldName, fieldGetterName := ns[0], ns[1]
3269
3270		typename, wiretype := g.GoType(message, field)
3271		jsonName := *field.Name
3272		jsonTag := jsonName + ",omitempty"
3273		repeatedNativeType := (!field.IsMessage() && !gogoproto.IsCustomType(field) && field.IsRepeated())
3274		if !gogoproto.IsNullable(field) && !repeatedNativeType {
3275			jsonTag = jsonName
3276		}
3277		gogoJsonTag := gogoproto.GetJsonTag(field)
3278		if gogoJsonTag != nil {
3279			jsonTag = *gogoJsonTag
3280		}
3281		gogoMoreTags := gogoproto.GetMoreTags(field)
3282		moreTags := ""
3283		if gogoMoreTags != nil {
3284			moreTags = " " + *gogoMoreTags
3285		}
3286		tag := fmt.Sprintf("protobuf:%s json:%q%s", g.goTag(message, field, wiretype), jsonTag, moreTags)
3287		if *field.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE && gogoproto.IsEmbed(field) {
3288			fieldName = ""
3289		}
3290
3291		oneof := field.OneofIndex != nil && message.allowOneof()
3292		if oneof && oFields[*field.OneofIndex] == nil {
3293			odp := message.OneofDecl[int(*field.OneofIndex)]
3294			base := CamelCase(odp.GetName())
3295			names := allocNames(base, "Get"+base)
3296			fname, gname := names[0], names[1]
3297
3298			// This is the first field of a oneof we haven't seen before.
3299			// Generate the union field.
3300			oneofFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageOneofPath, *field.OneofIndex)
3301			c, ok := g.makeComments(oneofFullPath)
3302			if ok {
3303				c += "\n//\n"
3304			}
3305			c += "// Types that are valid to be assigned to " + fname + ":\n"
3306			// Generate the rest of this comment later,
3307			// when we've computed any disambiguation.
3308
3309			dname := "is" + goTypeName + "_" + fname
3310			tag := `protobuf_oneof:"` + odp.GetName() + `"`
3311			of := oneofField{
3312				fieldCommon: fieldCommon{
3313					goName:     fname,
3314					getterName: gname,
3315					goType:     dname,
3316					tags:       tag,
3317					protoName:  odp.GetName(),
3318					fullPath:   oneofFullPath,
3319					protoField: field,
3320				},
3321				comment: c,
3322			}
3323			topLevelFields = append(topLevelFields, &of)
3324			oFields[*field.OneofIndex] = &of
3325		}
3326
3327		if *field.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE {
3328			desc := g.ObjectNamed(field.GetTypeName())
3329			if d, ok := desc.(*Descriptor); ok && d.GetOptions().GetMapEntry() {
3330				m := g.GoMapType(d, field)
3331				typename = m.GoType
3332				mapFieldTypes[field] = typename // record for the getter generation
3333
3334				tag += fmt.Sprintf(" protobuf_key:%s protobuf_val:%s", m.KeyTag, m.ValueTag)
3335			}
3336		}
3337		goTyp, _ := g.GoType(message, field)
3338		dvalue := g.getterDefault(field, goTypeName, GoTypeToName(goTyp))
3339		if oneof {
3340			tname := goTypeName + "_" + fieldName
3341			// It is possible for this to collide with a message or enum
3342			// nested in this message. Check for collisions.
3343			for {
3344				ok := true
3345				for _, desc := range message.nested {
3346					if CamelCaseSlice(desc.TypeName()) == tname {
3347						ok = false
3348						break
3349					}
3350				}
3351				for _, enum := range message.enums {
3352					if CamelCaseSlice(enum.TypeName()) == tname {
3353						ok = false
3354						break
3355					}
3356				}
3357				if !ok {
3358					tname += "_"
3359					continue
3360				}
3361				break
3362			}
3363
3364			oneofField := oFields[*field.OneofIndex]
3365			tag = "protobuf:" + g.goTag(message, field, wiretype)
3366			sf := oneofSubField{
3367				fieldCommon: fieldCommon{
3368					goName:     fieldName,
3369					getterName: fieldGetterName,
3370					goType:     typename,
3371					tags:       tag,
3372					protoName:  field.GetName(),
3373					fullPath:   fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i),
3374					protoField: field,
3375				},
3376				protoTypeName: field.GetTypeName(),
3377				fieldNumber:   int(*field.Number),
3378				protoType:     *field.Type,
3379				getterDef:     dvalue,
3380				protoDef:      field.GetDefaultValue(),
3381				oneofTypeName: tname,
3382				wireType:      wireTypeName(field),
3383			}
3384
3385			oneofField.subFields = append(oneofField.subFields, &sf)
3386			if !gogoproto.IsStdType(field) && !gogoproto.IsCustomType(field) && !gogoproto.IsCastType(field) {
3387				g.RecordTypeUse(field.GetTypeName())
3388			}
3389			continue
3390		}
3391
3392		fieldDeprecated := ""
3393		if field.GetOptions().GetDeprecated() {
3394			fieldDeprecated = deprecationComment
3395		}
3396
3397		fieldFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i)
3398		c, ok := g.makeComments(fieldFullPath)
3399		if ok {
3400			c += "\n"
3401		}
3402		rf := simpleField{
3403			fieldCommon: fieldCommon{
3404				goName:     fieldName,
3405				getterName: fieldGetterName,
3406				goType:     typename,
3407				tags:       tag,
3408				protoName:  field.GetName(),
3409				fullPath:   fieldFullPath,
3410				protoField: field,
3411			},
3412			protoTypeName: field.GetTypeName(),
3413			protoType:     *field.Type,
3414			deprecated:    fieldDeprecated,
3415			getterDef:     dvalue,
3416			protoDef:      field.GetDefaultValue(),
3417			comment:       c,
3418		}
3419		var pf topLevelField = &rf
3420
3421		topLevelFields = append(topLevelFields, pf)
3422
3423		if gogoproto.HasTypeDecl(message.file.FileDescriptorProto, message.DescriptorProto) {
3424			if !gogoproto.IsStdType(field) && !gogoproto.IsCustomType(field) && !gogoproto.IsCastType(field) {
3425				g.RecordTypeUse(field.GetTypeName())
3426			}
3427		} else {
3428			// Even if the type does not need to be generated, we need to iterate
3429			// over all its fields to be able to mark as used any imported types
3430			// used by those fields.
3431			for _, mfield := range message.Field {
3432				if !gogoproto.IsStdType(mfield) && !gogoproto.IsCustomType(mfield) && !gogoproto.IsCastType(mfield) {
3433					g.RecordTypeUse(mfield.GetTypeName())
3434				}
3435			}
3436		}
3437	}
3438
3439	mc := &msgCtx{
3440		goName:  goTypeName,
3441		message: message,
3442	}
3443
3444	if gogoproto.HasTypeDecl(message.file.FileDescriptorProto, message.DescriptorProto) {
3445		g.generateMessageStruct(mc, topLevelFields)
3446		g.P()
3447	}
3448	g.generateCommonMethods(mc)
3449	g.P()
3450	g.generateDefaultConstants(mc, topLevelFields)
3451	g.P()
3452	g.generateOneofDecls(mc, topLevelFields)
3453	g.P()
3454	g.generateGetters(mc, topLevelFields)
3455	g.P()
3456	g.generateSetters(mc, topLevelFields)
3457	g.P()
3458	g.generateOneofFuncs(mc, topLevelFields)
3459	g.P()
3460
3461	if !message.group {
3462		var oneofTypes []string
3463		for _, f := range topLevelFields {
3464			if of, ok := f.(*oneofField); ok {
3465				for _, osf := range of.subFields {
3466					oneofTypes = append(oneofTypes, osf.oneofTypeName)
3467				}
3468			}
3469		}
3470
3471		opts := message.Options
3472		ms := &messageSymbol{
3473			sym:           goTypeName,
3474			hasExtensions: len(message.ExtensionRange) > 0,
3475			isMessageSet:  opts != nil && opts.GetMessageSetWireFormat(),
3476			oneofTypes:    oneofTypes,
3477		}
3478		g.file.addExport(message, ms)
3479	}
3480
3481	for _, ext := range message.ext {
3482		g.generateExtension(ext)
3483	}
3484
3485	fullName := strings.Join(message.TypeName(), ".")
3486	if g.file.Package != nil {
3487		fullName = *g.file.Package + "." + fullName
3488	}
3489
3490	g.addInitf("%s.RegisterType((*%s)(nil), %q)", g.Pkg["proto"], goTypeName, fullName)
3491	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
3492		g.addInitf("%s.RegisterType((*%s)(nil), %q)", g.Pkg["golang_proto"], goTypeName, fullName)
3493	}
3494	if gogoproto.HasMessageName(g.file.FileDescriptorProto, message.DescriptorProto) {
3495		g.P("func (*", goTypeName, ") XXX_MessageName() string {")
3496		g.In()
3497		g.P("return ", strconv.Quote(fullName))
3498		g.Out()
3499		g.P("}")
3500	}
3501	// Register types for native map types.
3502	for _, k := range mapFieldKeys(mapFieldTypes) {
3503		fullName := strings.TrimPrefix(*k.TypeName, ".")
3504		g.addInitf("%s.RegisterMapType((%s)(nil), %q)", g.Pkg["proto"], mapFieldTypes[k], fullName)
3505		if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
3506			g.addInitf("%s.RegisterMapType((%s)(nil), %q)", g.Pkg["golang_proto"], mapFieldTypes[k], fullName)
3507		}
3508	}
3509}
3510
3511type byTypeName []*descriptor.FieldDescriptorProto
3512
3513func (a byTypeName) Len() int           { return len(a) }
3514func (a byTypeName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
3515func (a byTypeName) Less(i, j int) bool { return *a[i].TypeName < *a[j].TypeName }
3516
3517// mapFieldKeys returns the keys of m in a consistent order.
3518func mapFieldKeys(m map[*descriptor.FieldDescriptorProto]string) []*descriptor.FieldDescriptorProto {
3519	keys := make([]*descriptor.FieldDescriptorProto, 0, len(m))
3520	for k := range m {
3521		keys = append(keys, k)
3522	}
3523	sort.Sort(byTypeName(keys))
3524	return keys
3525}
3526
3527var escapeChars = [256]byte{
3528	'a': '\a', 'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t', 'v': '\v', '\\': '\\', '"': '"', '\'': '\'', '?': '?',
3529}
3530
3531// unescape reverses the "C" escaping that protoc does for default values of bytes fields.
3532// It is best effort in that it effectively ignores malformed input. Seemingly invalid escape
3533// sequences are conveyed, unmodified, into the decoded result.
3534func unescape(s string) string {
3535	// NB: Sadly, we can't use strconv.Unquote because protoc will escape both
3536	// single and double quotes, but strconv.Unquote only allows one or the
3537	// other (based on actual surrounding quotes of its input argument).
3538
3539	var out []byte
3540	for len(s) > 0 {
3541		// regular character, or too short to be valid escape
3542		if s[0] != '\\' || len(s) < 2 {
3543			out = append(out, s[0])
3544			s = s[1:]
3545		} else if c := escapeChars[s[1]]; c != 0 {
3546			// escape sequence
3547			out = append(out, c)
3548			s = s[2:]
3549		} else if s[1] == 'x' || s[1] == 'X' {
3550			// hex escape, e.g. "\x80
3551			if len(s) < 4 {
3552				// too short to be valid
3553				out = append(out, s[:2]...)
3554				s = s[2:]
3555				continue
3556			}
3557			v, err := strconv.ParseUint(s[2:4], 16, 8)
3558			if err != nil {
3559				out = append(out, s[:4]...)
3560			} else {
3561				out = append(out, byte(v))
3562			}
3563			s = s[4:]
3564		} else if '0' <= s[1] && s[1] <= '7' {
3565			// octal escape, can vary from 1 to 3 octal digits; e.g., "\0" "\40" or "\164"
3566			// so consume up to 2 more bytes or up to end-of-string
3567			n := len(s[1:]) - len(strings.TrimLeft(s[1:], "01234567"))
3568			if n > 3 {
3569				n = 3
3570			}
3571			v, err := strconv.ParseUint(s[1:1+n], 8, 8)
3572			if err != nil {
3573				out = append(out, s[:1+n]...)
3574			} else {
3575				out = append(out, byte(v))
3576			}
3577			s = s[1+n:]
3578		} else {
3579			// bad escape, just propagate the slash as-is
3580			out = append(out, s[0])
3581			s = s[1:]
3582		}
3583	}
3584
3585	return string(out)
3586}
3587
3588func (g *Generator) generateExtension(ext *ExtensionDescriptor) {
3589	ccTypeName := ext.DescName()
3590
3591	extObj := g.ObjectNamed(*ext.Extendee)
3592	var extDesc *Descriptor
3593	if id, ok := extObj.(*ImportedDescriptor); ok {
3594		// This is extending a publicly imported message.
3595		// We need the underlying type for goTag.
3596		extDesc = id.o.(*Descriptor)
3597	} else {
3598		extDesc = extObj.(*Descriptor)
3599	}
3600	extendedType := "*" + g.TypeName(extObj) // always use the original
3601	field := ext.FieldDescriptorProto
3602	fieldType, wireType := g.GoType(ext.parent, field)
3603	tag := g.goTag(extDesc, field, wireType)
3604	g.RecordTypeUse(*ext.Extendee)
3605	if n := ext.FieldDescriptorProto.TypeName; n != nil {
3606		// foreign extension type
3607		g.RecordTypeUse(*n)
3608	}
3609
3610	typeName := ext.TypeName()
3611
3612	// Special case for proto2 message sets: If this extension is extending
3613	// proto2.bridge.MessageSet, and its final name component is "message_set_extension",
3614	// then drop that last component.
3615	//
3616	// TODO: This should be implemented in the text formatter rather than the generator.
3617	// In addition, the situation for when to apply this special case is implemented
3618	// differently in other languages:
3619	// https://github.com/google/protobuf/blob/aff10976/src/google/protobuf/text_format.cc#L1560
3620	mset := false
3621	if extDesc.GetOptions().GetMessageSetWireFormat() && typeName[len(typeName)-1] == "message_set_extension" {
3622		typeName = typeName[:len(typeName)-1]
3623		mset = true
3624	}
3625
3626	// For text formatting, the package must be exactly what the .proto file declares,
3627	// ignoring overrides such as the go_package option, and with no dot/underscore mapping.
3628	extName := strings.Join(typeName, ".")
3629	if g.file.Package != nil {
3630		extName = *g.file.Package + "." + extName
3631	}
3632
3633	g.P("var ", ccTypeName, " = &", g.Pkg["proto"], ".ExtensionDesc{")
3634	g.In()
3635	g.P("ExtendedType: (", extendedType, ")(nil),")
3636	g.P("ExtensionType: (", fieldType, ")(nil),")
3637	g.P("Field: ", field.Number, ",")
3638	g.P(`Name: "`, extName, `",`)
3639	g.P("Tag: ", tag, ",")
3640	g.P(`Filename: "`, g.file.GetName(), `",`)
3641
3642	g.Out()
3643	g.P("}")
3644	g.P()
3645
3646	if mset {
3647		// Generate a bit more code to register with message_set.go.
3648		g.addInitf("%s.RegisterMessageSetType((%s)(nil), %d, %q)", g.Pkg["proto"], fieldType, *field.Number, extName)
3649		if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
3650			g.addInitf("%s.RegisterMessageSetType((%s)(nil), %d, %q)", g.Pkg["golang_proto"], fieldType, *field.Number, extName)
3651		}
3652	}
3653
3654	g.file.addExport(ext, constOrVarSymbol{ccTypeName, "var", ""})
3655}
3656
3657func (g *Generator) generateInitFunction() {
3658	for _, enum := range g.file.enum {
3659		g.generateEnumRegistration(enum)
3660	}
3661	for _, d := range g.file.desc {
3662		for _, ext := range d.ext {
3663			g.generateExtensionRegistration(ext)
3664		}
3665	}
3666	for _, ext := range g.file.ext {
3667		g.generateExtensionRegistration(ext)
3668	}
3669	if len(g.init) == 0 {
3670		return
3671	}
3672	g.P("func init() {")
3673	g.In()
3674	for _, l := range g.init {
3675		g.P(l)
3676	}
3677	g.Out()
3678	g.P("}")
3679	g.init = nil
3680}
3681
3682func (g *Generator) generateFileDescriptor(file *FileDescriptor) {
3683	// Make a copy and trim source_code_info data.
3684	// TODO: Trim this more when we know exactly what we need.
3685	pb := proto.Clone(file.FileDescriptorProto).(*descriptor.FileDescriptorProto)
3686	pb.SourceCodeInfo = nil
3687
3688	b, err := proto.Marshal(pb)
3689	if err != nil {
3690		g.Fail(err.Error())
3691	}
3692
3693	var buf bytes.Buffer
3694	w, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression)
3695	w.Write(b)
3696	w.Close()
3697	b = buf.Bytes()
3698
3699	v := file.VarName()
3700	g.P()
3701	g.P("func init() { ", g.Pkg["proto"], ".RegisterFile(", strconv.Quote(*file.Name), ", ", v, ") }")
3702	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
3703		g.P("func init() { ", g.Pkg["golang_proto"], ".RegisterFile(", strconv.Quote(*file.Name), ", ", v, ") }")
3704	}
3705	g.P("var ", v, " = []byte{")
3706	g.In()
3707	g.P("// ", len(b), " bytes of a gzipped FileDescriptorProto")
3708	for len(b) > 0 {
3709		n := 16
3710		if n > len(b) {
3711			n = len(b)
3712		}
3713
3714		s := ""
3715		for _, c := range b[:n] {
3716			s += fmt.Sprintf("0x%02x,", c)
3717		}
3718		g.P(s)
3719
3720		b = b[n:]
3721	}
3722	g.Out()
3723	g.P("}")
3724}
3725
3726func (g *Generator) generateEnumRegistration(enum *EnumDescriptor) {
3727	// // We always print the full (proto-world) package name here.
3728	pkg := enum.File().GetPackage()
3729	if pkg != "" {
3730		pkg += "."
3731	}
3732	// The full type name
3733	typeName := enum.TypeName()
3734	// The full type name, CamelCased.
3735	ccTypeName := CamelCaseSlice(typeName)
3736	g.addInitf("%s.RegisterEnum(%q, %[3]s_name, %[3]s_value)", g.Pkg["proto"], pkg+ccTypeName, ccTypeName)
3737	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
3738		g.addInitf("%s.RegisterEnum(%q, %[3]s_name, %[3]s_value)", g.Pkg["golang_proto"], pkg+ccTypeName, ccTypeName)
3739	}
3740}
3741
3742func (g *Generator) generateExtensionRegistration(ext *ExtensionDescriptor) {
3743	g.addInitf("%s.RegisterExtension(%s)", g.Pkg["proto"], ext.DescName())
3744	if gogoproto.ImportsGoGoProto(g.file.FileDescriptorProto) && gogoproto.RegistersGolangProto(g.file.FileDescriptorProto) {
3745		g.addInitf("%s.RegisterExtension(%s)", g.Pkg["golang_proto"], ext.DescName())
3746	}
3747}
3748
3749// And now lots of helper functions.
3750
3751// Is c an ASCII lower-case letter?
3752func isASCIILower(c byte) bool {
3753	return 'a' <= c && c <= 'z'
3754}
3755
3756// Is c an ASCII digit?
3757func isASCIIDigit(c byte) bool {
3758	return '0' <= c && c <= '9'
3759}
3760
3761// CamelCase returns the CamelCased name.
3762// If there is an interior underscore followed by a lower case letter,
3763// drop the underscore and convert the letter to upper case.
3764// There is a remote possibility of this rewrite causing a name collision,
3765// but it's so remote we're prepared to pretend it's nonexistent - since the
3766// C++ generator lowercases names, it's extremely unlikely to have two fields
3767// with different capitalizations.
3768// In short, _my_field_name_2 becomes XMyFieldName_2.
3769func CamelCase(s string) string {
3770	if s == "" {
3771		return ""
3772	}
3773	t := make([]byte, 0, 32)
3774	i := 0
3775	if s[0] == '_' {
3776		// Need a capital letter; drop the '_'.
3777		t = append(t, 'X')
3778		i++
3779	}
3780	// Invariant: if the next letter is lower case, it must be converted
3781	// to upper case.
3782	// That is, we process a word at a time, where words are marked by _ or
3783	// upper case letter. Digits are treated as words.
3784	for ; i < len(s); i++ {
3785		c := s[i]
3786		if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) {
3787			continue // Skip the underscore in s.
3788		}
3789		if isASCIIDigit(c) {
3790			t = append(t, c)
3791			continue
3792		}
3793		// Assume we have a letter now - if not, it's a bogus identifier.
3794		// The next word is a sequence of characters that must start upper case.
3795		if isASCIILower(c) {
3796			c ^= ' ' // Make it a capital letter.
3797		}
3798		t = append(t, c) // Guaranteed not lower case.
3799		// Accept lower case sequence that follows.
3800		for i+1 < len(s) && isASCIILower(s[i+1]) {
3801			i++
3802			t = append(t, s[i])
3803		}
3804	}
3805	return string(t)
3806}
3807
3808// CamelCaseSlice is like CamelCase, but the argument is a slice of strings to
3809// be joined with "_".
3810func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) }
3811
3812// dottedSlice turns a sliced name into a dotted name.
3813func dottedSlice(elem []string) string { return strings.Join(elem, ".") }
3814
3815// Is this field optional?
3816func isOptional(field *descriptor.FieldDescriptorProto) bool {
3817	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_OPTIONAL
3818}
3819
3820// Is this field required?
3821func isRequired(field *descriptor.FieldDescriptorProto) bool {
3822	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REQUIRED
3823}
3824
3825// Is this field repeated?
3826func isRepeated(field *descriptor.FieldDescriptorProto) bool {
3827	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED
3828}
3829
3830// Is this field a scalar numeric type?
3831func IsScalar(field *descriptor.FieldDescriptorProto) bool {
3832	if field.Type == nil {
3833		return false
3834	}
3835	switch *field.Type {
3836	case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
3837		descriptor.FieldDescriptorProto_TYPE_FLOAT,
3838		descriptor.FieldDescriptorProto_TYPE_INT64,
3839		descriptor.FieldDescriptorProto_TYPE_UINT64,
3840		descriptor.FieldDescriptorProto_TYPE_INT32,
3841		descriptor.FieldDescriptorProto_TYPE_FIXED64,
3842		descriptor.FieldDescriptorProto_TYPE_FIXED32,
3843		descriptor.FieldDescriptorProto_TYPE_BOOL,
3844		descriptor.FieldDescriptorProto_TYPE_UINT32,
3845		descriptor.FieldDescriptorProto_TYPE_ENUM,
3846		descriptor.FieldDescriptorProto_TYPE_SFIXED32,
3847		descriptor.FieldDescriptorProto_TYPE_SFIXED64,
3848		descriptor.FieldDescriptorProto_TYPE_SINT32,
3849		descriptor.FieldDescriptorProto_TYPE_SINT64:
3850		return true
3851	default:
3852		return false
3853	}
3854}
3855
3856func wireTypeName(field *descriptor.FieldDescriptorProto) string {
3857	switch *field.Type {
3858	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
3859		return "WireFixed64"
3860	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
3861		return "WireFixed32"
3862	case descriptor.FieldDescriptorProto_TYPE_INT64,
3863		descriptor.FieldDescriptorProto_TYPE_UINT64:
3864		return "WireVarint"
3865	case descriptor.FieldDescriptorProto_TYPE_INT32,
3866		descriptor.FieldDescriptorProto_TYPE_UINT32,
3867		descriptor.FieldDescriptorProto_TYPE_ENUM:
3868		return "WireVarint"
3869	case descriptor.FieldDescriptorProto_TYPE_FIXED64,
3870		descriptor.FieldDescriptorProto_TYPE_SFIXED64:
3871		return "WireFixed64"
3872	case descriptor.FieldDescriptorProto_TYPE_FIXED32,
3873		descriptor.FieldDescriptorProto_TYPE_SFIXED32:
3874		return "WireFixed32"
3875	case descriptor.FieldDescriptorProto_TYPE_BOOL:
3876		return "WireVarint"
3877	case descriptor.FieldDescriptorProto_TYPE_STRING:
3878		return "WireBytes"
3879	case descriptor.FieldDescriptorProto_TYPE_GROUP:
3880		return "WireStartGroup"
3881	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
3882		return "WireBytes"
3883	case descriptor.FieldDescriptorProto_TYPE_BYTES:
3884		return "WireBytes"
3885	case descriptor.FieldDescriptorProto_TYPE_SINT32:
3886		return "WireVarint"
3887	case descriptor.FieldDescriptorProto_TYPE_SINT64:
3888		return "WireVarint"
3889	default:
3890		return "WireVarint"
3891	}
3892}
3893
3894// badToUnderscore is the mapping function used to generate Go names from package names,
3895// which can be dotted in the input .proto file.  It replaces non-identifier characters such as
3896// dot or dash with underscore.
3897func badToUnderscore(r rune) rune {
3898	if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' {
3899		return r
3900	}
3901	return '_'
3902}
3903
3904// baseName returns the last path element of the name, with the last dotted suffix removed.
3905func baseName(name string) string {
3906	// First, find the last element
3907	if i := strings.LastIndex(name, "/"); i >= 0 {
3908		name = name[i+1:]
3909	}
3910	// Now drop the suffix
3911	if i := strings.LastIndex(name, "."); i >= 0 {
3912		name = name[0:i]
3913	}
3914	return name
3915}
3916
3917// The SourceCodeInfo message describes the location of elements of a parsed
3918// .proto file by way of a "path", which is a sequence of integers that
3919// describe the route from a FileDescriptorProto to the relevant submessage.
3920// The path alternates between a field number of a repeated field, and an index
3921// into that repeated field. The constants below define the field numbers that
3922// are used.
3923//
3924// See descriptor.proto for more information about this.
3925const (
3926	// tag numbers in FileDescriptorProto
3927	packagePath = 2 // package
3928	messagePath = 4 // message_type
3929	enumPath    = 5 // enum_type
3930	// tag numbers in DescriptorProto
3931	messageFieldPath   = 2 // field
3932	messageMessagePath = 3 // nested_type
3933	messageEnumPath    = 4 // enum_type
3934	messageOneofPath   = 8 // oneof_decl
3935	// tag numbers in EnumDescriptorProto
3936	enumValuePath = 2 // value
3937)
3938
3939var supportTypeAliases bool
3940
3941func init() {
3942	for _, tag := range build.Default.ReleaseTags {
3943		if tag == "go1.9" {
3944			supportTypeAliases = true
3945			return
3946		}
3947	}
3948}
3949