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