• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Go support for Protocol Buffers - Google's data interchange format
2//
3// Copyright 2010 The Go Authors.  All rights reserved.
4// https://github.com/golang/protobuf
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met:
9//
10//     * Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12//     * Redistributions in binary form must reproduce the above
13// copyright notice, this list of conditions and the following disclaimer
14// in the documentation and/or other materials provided with the
15// distribution.
16//     * Neither the name of Google Inc. nor the names of its
17// contributors may be used to endorse or promote products derived from
18// this software without specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32/*
33	The code generator for the plugin for the Google protocol buffer compiler.
34	It generates Go code from the protocol buffer description files read by the
35	main routine.
36*/
37package generator
38
39import (
40	"bufio"
41	"bytes"
42	"compress/gzip"
43	"crypto/sha256"
44	"encoding/hex"
45	"fmt"
46	"go/ast"
47	"go/build"
48	"go/parser"
49	"go/printer"
50	"go/token"
51	"log"
52	"os"
53	"path"
54	"sort"
55	"strconv"
56	"strings"
57	"unicode"
58	"unicode/utf8"
59
60	"github.com/golang/protobuf/proto"
61	"github.com/golang/protobuf/protoc-gen-go/generator/internal/remap"
62
63	"github.com/golang/protobuf/protoc-gen-go/descriptor"
64	plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
65)
66
67// generatedCodeVersion indicates a version of the generated code.
68// It is incremented whenever an incompatibility between the generated code and
69// proto package is introduced; the generated code references
70// a constant, proto.ProtoPackageIsVersionN (where N is generatedCodeVersion).
71const generatedCodeVersion = 3
72
73// A Plugin provides functionality to add to the output during Go code generation,
74// such as to produce RPC stubs.
75type Plugin interface {
76	// Name identifies the plugin.
77	Name() string
78	// Init is called once after data structures are built but before
79	// code generation begins.
80	Init(g *Generator)
81	// Generate produces the code generated by the plugin for this file,
82	// except for the imports, by calling the generator's methods P, In, and Out.
83	Generate(file *FileDescriptor)
84	// GenerateImports produces the import declarations for this file.
85	// It is called after Generate.
86	GenerateImports(file *FileDescriptor)
87}
88
89var plugins []Plugin
90
91// RegisterPlugin installs a (second-order) plugin to be run when the Go output is generated.
92// It is typically called during initialization.
93func RegisterPlugin(p Plugin) {
94	plugins = append(plugins, p)
95}
96
97// A GoImportPath is the import path of a Go package. e.g., "google.golang.org/genproto/protobuf".
98type GoImportPath string
99
100func (p GoImportPath) String() string { return strconv.Quote(string(p)) }
101
102// A GoPackageName is the name of a Go package. e.g., "protobuf".
103type GoPackageName string
104
105// Each type we import as a protocol buffer (other than FileDescriptorProto) needs
106// a pointer to the FileDescriptorProto that represents it.  These types achieve that
107// wrapping by placing each Proto inside a struct with the pointer to its File. The
108// structs have the same names as their contents, with "Proto" removed.
109// FileDescriptor is used to store the things that it points to.
110
111// The file and package name method are common to messages and enums.
112type common struct {
113	file *FileDescriptor // File this object comes from.
114}
115
116// GoImportPath is the import path of the Go package containing the type.
117func (c *common) GoImportPath() GoImportPath {
118	return c.file.importPath
119}
120
121func (c *common) File() *FileDescriptor { return c.file }
122
123func fileIsProto3(file *descriptor.FileDescriptorProto) bool {
124	return file.GetSyntax() == "proto3"
125}
126
127func (c *common) proto3() bool { return fileIsProto3(c.file.FileDescriptorProto) }
128
129// Descriptor represents a protocol buffer message.
130type Descriptor struct {
131	common
132	*descriptor.DescriptorProto
133	parent   *Descriptor            // The containing message, if any.
134	nested   []*Descriptor          // Inner messages, if any.
135	enums    []*EnumDescriptor      // Inner enums, if any.
136	ext      []*ExtensionDescriptor // Extensions, if any.
137	typename []string               // Cached typename vector.
138	index    int                    // The index into the container, whether the file or another message.
139	path     string                 // The SourceCodeInfo path as comma-separated integers.
140	group    bool
141}
142
143// TypeName returns the elements of the dotted type name.
144// The package name is not part of this name.
145func (d *Descriptor) TypeName() []string {
146	if d.typename != nil {
147		return d.typename
148	}
149	n := 0
150	for parent := d; parent != nil; parent = parent.parent {
151		n++
152	}
153	s := make([]string, n)
154	for parent := d; parent != nil; parent = parent.parent {
155		n--
156		s[n] = parent.GetName()
157	}
158	d.typename = s
159	return s
160}
161
162// EnumDescriptor describes an enum. If it's at top level, its parent will be nil.
163// Otherwise it will be the descriptor of the message in which it is defined.
164type EnumDescriptor struct {
165	common
166	*descriptor.EnumDescriptorProto
167	parent   *Descriptor // The containing message, if any.
168	typename []string    // Cached typename vector.
169	index    int         // The index into the container, whether the file or a message.
170	path     string      // The SourceCodeInfo path as comma-separated integers.
171}
172
173// TypeName returns the elements of the dotted type name.
174// The package name is not part of this name.
175func (e *EnumDescriptor) TypeName() (s []string) {
176	if e.typename != nil {
177		return e.typename
178	}
179	name := e.GetName()
180	if e.parent == nil {
181		s = make([]string, 1)
182	} else {
183		pname := e.parent.TypeName()
184		s = make([]string, len(pname)+1)
185		copy(s, pname)
186	}
187	s[len(s)-1] = name
188	e.typename = s
189	return s
190}
191
192// Everything but the last element of the full type name, CamelCased.
193// The values of type Foo.Bar are call Foo_value1... not Foo_Bar_value1... .
194func (e *EnumDescriptor) prefix() string {
195	if e.parent == nil {
196		// If the enum is not part of a message, the prefix is just the type name.
197		return CamelCase(*e.Name) + "_"
198	}
199	typeName := e.TypeName()
200	return CamelCaseSlice(typeName[0:len(typeName)-1]) + "_"
201}
202
203// The integer value of the named constant in this enumerated type.
204func (e *EnumDescriptor) integerValueAsString(name string) string {
205	for _, c := range e.Value {
206		if c.GetName() == name {
207			return fmt.Sprint(c.GetNumber())
208		}
209	}
210	log.Fatal("cannot find value for enum constant")
211	return ""
212}
213
214// ExtensionDescriptor describes an extension. If it's at top level, its parent will be nil.
215// Otherwise it will be the descriptor of the message in which it is defined.
216type ExtensionDescriptor struct {
217	common
218	*descriptor.FieldDescriptorProto
219	parent *Descriptor // The containing message, if any.
220}
221
222// TypeName returns the elements of the dotted type name.
223// The package name is not part of this name.
224func (e *ExtensionDescriptor) TypeName() (s []string) {
225	name := e.GetName()
226	if e.parent == nil {
227		// top-level extension
228		s = make([]string, 1)
229	} else {
230		pname := e.parent.TypeName()
231		s = make([]string, len(pname)+1)
232		copy(s, pname)
233	}
234	s[len(s)-1] = name
235	return s
236}
237
238// DescName returns the variable name used for the generated descriptor.
239func (e *ExtensionDescriptor) DescName() string {
240	// The full type name.
241	typeName := e.TypeName()
242	// Each scope of the extension is individually CamelCased, and all are joined with "_" with an "E_" prefix.
243	for i, s := range typeName {
244		typeName[i] = CamelCase(s)
245	}
246	return "E_" + strings.Join(typeName, "_")
247}
248
249// ImportedDescriptor describes a type that has been publicly imported from another file.
250type ImportedDescriptor struct {
251	common
252	o Object
253}
254
255func (id *ImportedDescriptor) TypeName() []string { return id.o.TypeName() }
256
257// FileDescriptor describes an protocol buffer descriptor file (.proto).
258// It includes slices of all the messages and enums defined within it.
259// Those slices are constructed by WrapTypes.
260type FileDescriptor struct {
261	*descriptor.FileDescriptorProto
262	desc []*Descriptor          // All the messages defined in this file.
263	enum []*EnumDescriptor      // All the enums defined in this file.
264	ext  []*ExtensionDescriptor // All the top-level extensions defined in this file.
265	imp  []*ImportedDescriptor  // All types defined in files publicly imported by this file.
266
267	// Comments, stored as a map of path (comma-separated integers) to the comment.
268	comments map[string]*descriptor.SourceCodeInfo_Location
269
270	// The full list of symbols that are exported,
271	// as a map from the exported object to its symbols.
272	// This is used for supporting public imports.
273	exported map[Object][]symbol
274
275	importPath  GoImportPath  // Import path of this file's package.
276	packageName GoPackageName // Name of this file's Go package.
277
278	proto3 bool // whether to generate proto3 code for this file
279}
280
281// VarName is the variable name we'll use in the generated code to refer
282// to the compressed bytes of this descriptor. It is not exported, so
283// it is only valid inside the generated package.
284func (d *FileDescriptor) VarName() string {
285	h := sha256.Sum256([]byte(d.GetName()))
286	return fmt.Sprintf("fileDescriptor_%s", hex.EncodeToString(h[:8]))
287}
288
289// goPackageOption interprets the file's go_package option.
290// If there is no go_package, it returns ("", "", false).
291// If there's a simple name, it returns ("", pkg, true).
292// If the option implies an import path, it returns (impPath, pkg, true).
293func (d *FileDescriptor) goPackageOption() (impPath GoImportPath, pkg GoPackageName, ok bool) {
294	opt := d.GetOptions().GetGoPackage()
295	if opt == "" {
296		return "", "", false
297	}
298	// A semicolon-delimited suffix delimits the import path and package name.
299	sc := strings.Index(opt, ";")
300	if sc >= 0 {
301		return GoImportPath(opt[:sc]), cleanPackageName(opt[sc+1:]), true
302	}
303	// The presence of a slash implies there's an import path.
304	slash := strings.LastIndex(opt, "/")
305	if slash >= 0 {
306		return GoImportPath(opt), cleanPackageName(opt[slash+1:]), true
307	}
308	return "", cleanPackageName(opt), true
309}
310
311// goFileName returns the output name for the generated Go file.
312func (d *FileDescriptor) goFileName(pathType pathType) string {
313	name := *d.Name
314	if ext := path.Ext(name); ext == ".proto" || ext == ".protodevel" {
315		name = name[:len(name)-len(ext)]
316	}
317	name += ".pb.go"
318
319	if pathType == pathTypeSourceRelative {
320		return name
321	}
322
323	// Does the file have a "go_package" option?
324	// If it does, it may override the filename.
325	if impPath, _, ok := d.goPackageOption(); ok && impPath != "" {
326		// Replace the existing dirname with the declared import path.
327		_, name = path.Split(name)
328		name = path.Join(string(impPath), name)
329		return name
330	}
331
332	return name
333}
334
335func (d *FileDescriptor) addExport(obj Object, sym symbol) {
336	d.exported[obj] = append(d.exported[obj], sym)
337}
338
339// symbol is an interface representing an exported Go symbol.
340type symbol interface {
341	// GenerateAlias should generate an appropriate alias
342	// for the symbol from the named package.
343	GenerateAlias(g *Generator, filename string, pkg GoPackageName)
344}
345
346type messageSymbol struct {
347	sym                         string
348	hasExtensions, isMessageSet bool
349	oneofTypes                  []string
350}
351
352type getterSymbol struct {
353	name     string
354	typ      string
355	typeName string // canonical name in proto world; empty for proto.Message and similar
356	genType  bool   // whether typ contains a generated type (message/group/enum)
357}
358
359func (ms *messageSymbol) GenerateAlias(g *Generator, filename string, pkg GoPackageName) {
360	g.P("// ", ms.sym, " from public import ", filename)
361	g.P("type ", ms.sym, " = ", pkg, ".", ms.sym)
362	for _, name := range ms.oneofTypes {
363		g.P("type ", name, " = ", pkg, ".", name)
364	}
365}
366
367type enumSymbol struct {
368	name   string
369	proto3 bool // Whether this came from a proto3 file.
370}
371
372func (es enumSymbol) GenerateAlias(g *Generator, filename string, pkg GoPackageName) {
373	s := es.name
374	g.P("// ", s, " from public import ", filename)
375	g.P("type ", s, " = ", pkg, ".", s)
376	g.P("var ", s, "_name = ", pkg, ".", s, "_name")
377	g.P("var ", s, "_value = ", pkg, ".", s, "_value")
378}
379
380type constOrVarSymbol struct {
381	sym  string
382	typ  string // either "const" or "var"
383	cast string // if non-empty, a type cast is required (used for enums)
384}
385
386func (cs constOrVarSymbol) GenerateAlias(g *Generator, filename string, pkg GoPackageName) {
387	v := string(pkg) + "." + cs.sym
388	if cs.cast != "" {
389		v = cs.cast + "(" + v + ")"
390	}
391	g.P(cs.typ, " ", cs.sym, " = ", v)
392}
393
394// Object is an interface abstracting the abilities shared by enums, messages, extensions and imported objects.
395type Object interface {
396	GoImportPath() GoImportPath
397	TypeName() []string
398	File() *FileDescriptor
399}
400
401// Generator is the type whose methods generate the output, stored in the associated response structure.
402type Generator struct {
403	*bytes.Buffer
404
405	Request  *plugin.CodeGeneratorRequest  // The input.
406	Response *plugin.CodeGeneratorResponse // The output.
407
408	Param             map[string]string // Command-line parameters.
409	PackageImportPath string            // Go import path of the package we're generating code for
410	ImportPrefix      string            // String to prefix to imported package file names.
411	ImportMap         map[string]string // Mapping from .proto file name to import path
412
413	Pkg map[string]string // The names under which we import support packages
414
415	outputImportPath GoImportPath                   // Package we're generating code for.
416	allFiles         []*FileDescriptor              // All files in the tree
417	allFilesByName   map[string]*FileDescriptor     // All files by filename.
418	genFiles         []*FileDescriptor              // Those files we will generate output for.
419	file             *FileDescriptor                // The file we are compiling now.
420	packageNames     map[GoImportPath]GoPackageName // Imported package names in the current file.
421	usedPackages     map[GoImportPath]bool          // Packages used in current file.
422	usedPackageNames map[GoPackageName]bool         // Package names used in the current file.
423	addedImports     map[GoImportPath]bool          // Additional imports to emit.
424	typeNameToObject map[string]Object              // Key is a fully-qualified name in input syntax.
425	init             []string                       // Lines to emit in the init function.
426	indent           string
427	pathType         pathType // How to generate output filenames.
428	writeOutput      bool
429	annotateCode     bool                                       // whether to store annotations
430	annotations      []*descriptor.GeneratedCodeInfo_Annotation // annotations to store
431}
432
433type pathType int
434
435const (
436	pathTypeImport pathType = iota
437	pathTypeSourceRelative
438)
439
440// New creates a new generator and allocates the request and response protobufs.
441func New() *Generator {
442	g := new(Generator)
443	g.Buffer = new(bytes.Buffer)
444	g.Request = new(plugin.CodeGeneratorRequest)
445	g.Response = new(plugin.CodeGeneratorResponse)
446	return g
447}
448
449// Error reports a problem, including an error, and exits the program.
450func (g *Generator) Error(err error, msgs ...string) {
451	s := strings.Join(msgs, " ") + ":" + err.Error()
452	log.Print("protoc-gen-go: error:", s)
453	os.Exit(1)
454}
455
456// Fail reports a problem and exits the program.
457func (g *Generator) Fail(msgs ...string) {
458	s := strings.Join(msgs, " ")
459	log.Print("protoc-gen-go: error:", s)
460	os.Exit(1)
461}
462
463// CommandLineParameters breaks the comma-separated list of key=value pairs
464// in the parameter (a member of the request protobuf) into a key/value map.
465// It then sets file name mappings defined by those entries.
466func (g *Generator) CommandLineParameters(parameter string) {
467	g.Param = make(map[string]string)
468	for _, p := range strings.Split(parameter, ",") {
469		if i := strings.Index(p, "="); i < 0 {
470			g.Param[p] = ""
471		} else {
472			g.Param[p[0:i]] = p[i+1:]
473		}
474	}
475
476	g.ImportMap = make(map[string]string)
477	pluginList := "none" // Default list of plugin names to enable (empty means all).
478	for k, v := range g.Param {
479		switch k {
480		case "import_prefix":
481			g.ImportPrefix = v
482		case "import_path":
483			g.PackageImportPath = v
484		case "paths":
485			switch v {
486			case "import":
487				g.pathType = pathTypeImport
488			case "source_relative":
489				g.pathType = pathTypeSourceRelative
490			default:
491				g.Fail(fmt.Sprintf(`Unknown path type %q: want "import" or "source_relative".`, v))
492			}
493		case "plugins":
494			pluginList = v
495		case "annotate_code":
496			if v == "true" {
497				g.annotateCode = true
498			}
499		default:
500			if len(k) > 0 && k[0] == 'M' {
501				g.ImportMap[k[1:]] = v
502			}
503		}
504	}
505	if pluginList != "" {
506		// Amend the set of plugins.
507		enabled := make(map[string]bool)
508		for _, name := range strings.Split(pluginList, "+") {
509			enabled[name] = true
510		}
511		var nplugins []Plugin
512		for _, p := range plugins {
513			if enabled[p.Name()] {
514				nplugins = append(nplugins, p)
515			}
516		}
517		plugins = nplugins
518	}
519}
520
521// DefaultPackageName returns the package name printed for the object.
522// If its file is in a different package, it returns the package name we're using for this file, plus ".".
523// Otherwise it returns the empty string.
524func (g *Generator) DefaultPackageName(obj Object) string {
525	importPath := obj.GoImportPath()
526	if importPath == g.outputImportPath {
527		return ""
528	}
529	return string(g.GoPackageName(importPath)) + "."
530}
531
532// GoPackageName returns the name used for a package.
533func (g *Generator) GoPackageName(importPath GoImportPath) GoPackageName {
534	if name, ok := g.packageNames[importPath]; ok {
535		return name
536	}
537	name := cleanPackageName(baseName(string(importPath)))
538	for i, orig := 1, name; g.usedPackageNames[name] || isGoPredeclaredIdentifier[string(name)]; i++ {
539		name = orig + GoPackageName(strconv.Itoa(i))
540	}
541	g.packageNames[importPath] = name
542	g.usedPackageNames[name] = true
543	return name
544}
545
546// AddImport adds a package to the generated file's import section.
547// It returns the name used for the package.
548func (g *Generator) AddImport(importPath GoImportPath) GoPackageName {
549	g.addedImports[importPath] = true
550	return g.GoPackageName(importPath)
551}
552
553var globalPackageNames = map[GoPackageName]bool{
554	"fmt":   true,
555	"math":  true,
556	"proto": true,
557}
558
559// Create and remember a guaranteed unique package name. Pkg is the candidate name.
560// The FileDescriptor parameter is unused.
561func RegisterUniquePackageName(pkg string, f *FileDescriptor) string {
562	name := cleanPackageName(pkg)
563	for i, orig := 1, name; globalPackageNames[name]; i++ {
564		name = orig + GoPackageName(strconv.Itoa(i))
565	}
566	globalPackageNames[name] = true
567	return string(name)
568}
569
570var isGoKeyword = map[string]bool{
571	"break":       true,
572	"case":        true,
573	"chan":        true,
574	"const":       true,
575	"continue":    true,
576	"default":     true,
577	"else":        true,
578	"defer":       true,
579	"fallthrough": true,
580	"for":         true,
581	"func":        true,
582	"go":          true,
583	"goto":        true,
584	"if":          true,
585	"import":      true,
586	"interface":   true,
587	"map":         true,
588	"package":     true,
589	"range":       true,
590	"return":      true,
591	"select":      true,
592	"struct":      true,
593	"switch":      true,
594	"type":        true,
595	"var":         true,
596}
597
598var isGoPredeclaredIdentifier = map[string]bool{
599	"append":     true,
600	"bool":       true,
601	"byte":       true,
602	"cap":        true,
603	"close":      true,
604	"complex":    true,
605	"complex128": true,
606	"complex64":  true,
607	"copy":       true,
608	"delete":     true,
609	"error":      true,
610	"false":      true,
611	"float32":    true,
612	"float64":    true,
613	"imag":       true,
614	"int":        true,
615	"int16":      true,
616	"int32":      true,
617	"int64":      true,
618	"int8":       true,
619	"iota":       true,
620	"len":        true,
621	"make":       true,
622	"new":        true,
623	"nil":        true,
624	"panic":      true,
625	"print":      true,
626	"println":    true,
627	"real":       true,
628	"recover":    true,
629	"rune":       true,
630	"string":     true,
631	"true":       true,
632	"uint":       true,
633	"uint16":     true,
634	"uint32":     true,
635	"uint64":     true,
636	"uint8":      true,
637	"uintptr":    true,
638}
639
640func cleanPackageName(name string) GoPackageName {
641	name = strings.Map(badToUnderscore, name)
642	// Identifier must not be keyword or predeclared identifier: insert _.
643	if isGoKeyword[name] {
644		name = "_" + name
645	}
646	// Identifier must not begin with digit: insert _.
647	if r, _ := utf8.DecodeRuneInString(name); unicode.IsDigit(r) {
648		name = "_" + name
649	}
650	return GoPackageName(name)
651}
652
653// defaultGoPackage returns the package name to use,
654// derived from the import path of the package we're building code for.
655func (g *Generator) defaultGoPackage() GoPackageName {
656	p := g.PackageImportPath
657	if i := strings.LastIndex(p, "/"); i >= 0 {
658		p = p[i+1:]
659	}
660	return cleanPackageName(p)
661}
662
663// SetPackageNames sets the package name for this run.
664// The package name must agree across all files being generated.
665// It also defines unique package names for all imported files.
666func (g *Generator) SetPackageNames() {
667	g.outputImportPath = g.genFiles[0].importPath
668
669	defaultPackageNames := make(map[GoImportPath]GoPackageName)
670	for _, f := range g.genFiles {
671		if _, p, ok := f.goPackageOption(); ok {
672			defaultPackageNames[f.importPath] = p
673		}
674	}
675	for _, f := range g.genFiles {
676		if _, p, ok := f.goPackageOption(); ok {
677			// Source file: option go_package = "quux/bar";
678			f.packageName = p
679		} else if p, ok := defaultPackageNames[f.importPath]; ok {
680			// A go_package option in another file in the same package.
681			//
682			// This is a poor choice in general, since every source file should
683			// contain a go_package option. Supported mainly for historical
684			// compatibility.
685			f.packageName = p
686		} else if p := g.defaultGoPackage(); p != "" {
687			// Command-line: import_path=quux/bar.
688			//
689			// The import_path flag sets a package name for files which don't
690			// contain a go_package option.
691			f.packageName = p
692		} else if p := f.GetPackage(); p != "" {
693			// Source file: package quux.bar;
694			f.packageName = cleanPackageName(p)
695		} else {
696			// Source filename.
697			f.packageName = cleanPackageName(baseName(f.GetName()))
698		}
699	}
700
701	// Check that all files have a consistent package name and import path.
702	for _, f := range g.genFiles[1:] {
703		if a, b := g.genFiles[0].importPath, f.importPath; a != b {
704			g.Fail(fmt.Sprintf("inconsistent package import paths: %v, %v", a, b))
705		}
706		if a, b := g.genFiles[0].packageName, f.packageName; a != b {
707			g.Fail(fmt.Sprintf("inconsistent package names: %v, %v", a, b))
708		}
709	}
710
711	// Names of support packages. These never vary (if there are conflicts,
712	// we rename the conflicting package), so this could be removed someday.
713	g.Pkg = map[string]string{
714		"fmt":   "fmt",
715		"math":  "math",
716		"proto": "proto",
717	}
718}
719
720// WrapTypes walks the incoming data, wrapping DescriptorProtos, EnumDescriptorProtos
721// and FileDescriptorProtos into file-referenced objects within the Generator.
722// It also creates the list of files to generate and so should be called before GenerateAllFiles.
723func (g *Generator) WrapTypes() {
724	g.allFiles = make([]*FileDescriptor, 0, len(g.Request.ProtoFile))
725	g.allFilesByName = make(map[string]*FileDescriptor, len(g.allFiles))
726	genFileNames := make(map[string]bool)
727	for _, n := range g.Request.FileToGenerate {
728		genFileNames[n] = true
729	}
730	for _, f := range g.Request.ProtoFile {
731		fd := &FileDescriptor{
732			FileDescriptorProto: f,
733			exported:            make(map[Object][]symbol),
734			proto3:              fileIsProto3(f),
735		}
736		// The import path may be set in a number of ways.
737		if substitution, ok := g.ImportMap[f.GetName()]; ok {
738			// Command-line: M=foo.proto=quux/bar.
739			//
740			// Explicit mapping of source file to import path.
741			fd.importPath = GoImportPath(substitution)
742		} else if genFileNames[f.GetName()] && g.PackageImportPath != "" {
743			// Command-line: import_path=quux/bar.
744			//
745			// The import_path flag sets the import path for every file that
746			// we generate code for.
747			fd.importPath = GoImportPath(g.PackageImportPath)
748		} else if p, _, _ := fd.goPackageOption(); p != "" {
749			// Source file: option go_package = "quux/bar";
750			//
751			// The go_package option sets the import path. Most users should use this.
752			fd.importPath = p
753		} else {
754			// Source filename.
755			//
756			// Last resort when nothing else is available.
757			fd.importPath = GoImportPath(path.Dir(f.GetName()))
758		}
759		// We must wrap the descriptors before we wrap the enums
760		fd.desc = wrapDescriptors(fd)
761		g.buildNestedDescriptors(fd.desc)
762		fd.enum = wrapEnumDescriptors(fd, fd.desc)
763		g.buildNestedEnums(fd.desc, fd.enum)
764		fd.ext = wrapExtensions(fd)
765		extractComments(fd)
766		g.allFiles = append(g.allFiles, fd)
767		g.allFilesByName[f.GetName()] = fd
768	}
769	for _, fd := range g.allFiles {
770		fd.imp = wrapImported(fd, g)
771	}
772
773	g.genFiles = make([]*FileDescriptor, 0, len(g.Request.FileToGenerate))
774	for _, fileName := range g.Request.FileToGenerate {
775		fd := g.allFilesByName[fileName]
776		if fd == nil {
777			g.Fail("could not find file named", fileName)
778		}
779		g.genFiles = append(g.genFiles, fd)
780	}
781}
782
783// Scan the descriptors in this file.  For each one, build the slice of nested descriptors
784func (g *Generator) buildNestedDescriptors(descs []*Descriptor) {
785	for _, desc := range descs {
786		if len(desc.NestedType) != 0 {
787			for _, nest := range descs {
788				if nest.parent == desc {
789					desc.nested = append(desc.nested, nest)
790				}
791			}
792			if len(desc.nested) != len(desc.NestedType) {
793				g.Fail("internal error: nesting failure for", desc.GetName())
794			}
795		}
796	}
797}
798
799func (g *Generator) buildNestedEnums(descs []*Descriptor, enums []*EnumDescriptor) {
800	for _, desc := range descs {
801		if len(desc.EnumType) != 0 {
802			for _, enum := range enums {
803				if enum.parent == desc {
804					desc.enums = append(desc.enums, enum)
805				}
806			}
807			if len(desc.enums) != len(desc.EnumType) {
808				g.Fail("internal error: enum nesting failure for", desc.GetName())
809			}
810		}
811	}
812}
813
814// Construct the Descriptor
815func newDescriptor(desc *descriptor.DescriptorProto, parent *Descriptor, file *FileDescriptor, index int) *Descriptor {
816	d := &Descriptor{
817		common:          common{file},
818		DescriptorProto: desc,
819		parent:          parent,
820		index:           index,
821	}
822	if parent == nil {
823		d.path = fmt.Sprintf("%d,%d", messagePath, index)
824	} else {
825		d.path = fmt.Sprintf("%s,%d,%d", parent.path, messageMessagePath, index)
826	}
827
828	// The only way to distinguish a group from a message is whether
829	// the containing message has a TYPE_GROUP field that matches.
830	if parent != nil {
831		parts := d.TypeName()
832		if file.Package != nil {
833			parts = append([]string{*file.Package}, parts...)
834		}
835		exp := "." + strings.Join(parts, ".")
836		for _, field := range parent.Field {
837			if field.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP && field.GetTypeName() == exp {
838				d.group = true
839				break
840			}
841		}
842	}
843
844	for _, field := range desc.Extension {
845		d.ext = append(d.ext, &ExtensionDescriptor{common{file}, field, d})
846	}
847
848	return d
849}
850
851// Return a slice of all the Descriptors defined within this file
852func wrapDescriptors(file *FileDescriptor) []*Descriptor {
853	sl := make([]*Descriptor, 0, len(file.MessageType)+10)
854	for i, desc := range file.MessageType {
855		sl = wrapThisDescriptor(sl, desc, nil, file, i)
856	}
857	return sl
858}
859
860// Wrap this Descriptor, recursively
861func wrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *FileDescriptor, index int) []*Descriptor {
862	sl = append(sl, newDescriptor(desc, parent, file, index))
863	me := sl[len(sl)-1]
864	for i, nested := range desc.NestedType {
865		sl = wrapThisDescriptor(sl, nested, me, file, i)
866	}
867	return sl
868}
869
870// Construct the EnumDescriptor
871func newEnumDescriptor(desc *descriptor.EnumDescriptorProto, parent *Descriptor, file *FileDescriptor, index int) *EnumDescriptor {
872	ed := &EnumDescriptor{
873		common:              common{file},
874		EnumDescriptorProto: desc,
875		parent:              parent,
876		index:               index,
877	}
878	if parent == nil {
879		ed.path = fmt.Sprintf("%d,%d", enumPath, index)
880	} else {
881		ed.path = fmt.Sprintf("%s,%d,%d", parent.path, messageEnumPath, index)
882	}
883	return ed
884}
885
886// Return a slice of all the EnumDescriptors defined within this file
887func wrapEnumDescriptors(file *FileDescriptor, descs []*Descriptor) []*EnumDescriptor {
888	sl := make([]*EnumDescriptor, 0, len(file.EnumType)+10)
889	// Top-level enums.
890	for i, enum := range file.EnumType {
891		sl = append(sl, newEnumDescriptor(enum, nil, file, i))
892	}
893	// Enums within messages. Enums within embedded messages appear in the outer-most message.
894	for _, nested := range descs {
895		for i, enum := range nested.EnumType {
896			sl = append(sl, newEnumDescriptor(enum, nested, file, i))
897		}
898	}
899	return sl
900}
901
902// Return a slice of all the top-level ExtensionDescriptors defined within this file.
903func wrapExtensions(file *FileDescriptor) []*ExtensionDescriptor {
904	var sl []*ExtensionDescriptor
905	for _, field := range file.Extension {
906		sl = append(sl, &ExtensionDescriptor{common{file}, field, nil})
907	}
908	return sl
909}
910
911// Return a slice of all the types that are publicly imported into this file.
912func wrapImported(file *FileDescriptor, g *Generator) (sl []*ImportedDescriptor) {
913	for _, index := range file.PublicDependency {
914		df := g.fileByName(file.Dependency[index])
915		for _, d := range df.desc {
916			if d.GetOptions().GetMapEntry() {
917				continue
918			}
919			sl = append(sl, &ImportedDescriptor{common{file}, d})
920		}
921		for _, e := range df.enum {
922			sl = append(sl, &ImportedDescriptor{common{file}, e})
923		}
924		for _, ext := range df.ext {
925			sl = append(sl, &ImportedDescriptor{common{file}, ext})
926		}
927	}
928	return
929}
930
931func extractComments(file *FileDescriptor) {
932	file.comments = make(map[string]*descriptor.SourceCodeInfo_Location)
933	for _, loc := range file.GetSourceCodeInfo().GetLocation() {
934		if loc.LeadingComments == nil {
935			continue
936		}
937		var p []string
938		for _, n := range loc.Path {
939			p = append(p, strconv.Itoa(int(n)))
940		}
941		file.comments[strings.Join(p, ",")] = loc
942	}
943}
944
945// BuildTypeNameMap builds the map from fully qualified type names to objects.
946// The key names for the map come from the input data, which puts a period at the beginning.
947// It should be called after SetPackageNames and before GenerateAllFiles.
948func (g *Generator) BuildTypeNameMap() {
949	g.typeNameToObject = make(map[string]Object)
950	for _, f := range g.allFiles {
951		// The names in this loop are defined by the proto world, not us, so the
952		// package name may be empty.  If so, the dotted package name of X will
953		// be ".X"; otherwise it will be ".pkg.X".
954		dottedPkg := "." + f.GetPackage()
955		if dottedPkg != "." {
956			dottedPkg += "."
957		}
958		for _, enum := range f.enum {
959			name := dottedPkg + dottedSlice(enum.TypeName())
960			g.typeNameToObject[name] = enum
961		}
962		for _, desc := range f.desc {
963			name := dottedPkg + dottedSlice(desc.TypeName())
964			g.typeNameToObject[name] = desc
965		}
966	}
967}
968
969// ObjectNamed, given a fully-qualified input type name as it appears in the input data,
970// returns the descriptor for the message or enum with that name.
971func (g *Generator) ObjectNamed(typeName string) Object {
972	o, ok := g.typeNameToObject[typeName]
973	if !ok {
974		g.Fail("can't find object with type", typeName)
975	}
976	return o
977}
978
979// AnnotatedAtoms is a list of atoms (as consumed by P) that records the file name and proto AST path from which they originated.
980type AnnotatedAtoms struct {
981	source string
982	path   string
983	atoms  []interface{}
984}
985
986// Annotate records the file name and proto AST path of a list of atoms
987// so that a later call to P can emit a link from each atom to its origin.
988func Annotate(file *FileDescriptor, path string, atoms ...interface{}) *AnnotatedAtoms {
989	return &AnnotatedAtoms{source: *file.Name, path: path, atoms: atoms}
990}
991
992// printAtom prints the (atomic, non-annotation) argument to the generated output.
993func (g *Generator) printAtom(v interface{}) {
994	switch v := v.(type) {
995	case string:
996		g.WriteString(v)
997	case *string:
998		g.WriteString(*v)
999	case bool:
1000		fmt.Fprint(g, v)
1001	case *bool:
1002		fmt.Fprint(g, *v)
1003	case int:
1004		fmt.Fprint(g, v)
1005	case *int32:
1006		fmt.Fprint(g, *v)
1007	case *int64:
1008		fmt.Fprint(g, *v)
1009	case float64:
1010		fmt.Fprint(g, v)
1011	case *float64:
1012		fmt.Fprint(g, *v)
1013	case GoPackageName:
1014		g.WriteString(string(v))
1015	case GoImportPath:
1016		g.WriteString(strconv.Quote(string(v)))
1017	default:
1018		g.Fail(fmt.Sprintf("unknown type in printer: %T", v))
1019	}
1020}
1021
1022// P prints the arguments to the generated output.  It handles strings and int32s, plus
1023// handling indirections because they may be *string, etc.  Any inputs of type AnnotatedAtoms may emit
1024// annotations in a .meta file in addition to outputting the atoms themselves (if g.annotateCode
1025// is true).
1026func (g *Generator) P(str ...interface{}) {
1027	if !g.writeOutput {
1028		return
1029	}
1030	g.WriteString(g.indent)
1031	for _, v := range str {
1032		switch v := v.(type) {
1033		case *AnnotatedAtoms:
1034			begin := int32(g.Len())
1035			for _, v := range v.atoms {
1036				g.printAtom(v)
1037			}
1038			if g.annotateCode {
1039				end := int32(g.Len())
1040				var path []int32
1041				for _, token := range strings.Split(v.path, ",") {
1042					val, err := strconv.ParseInt(token, 10, 32)
1043					if err != nil {
1044						g.Fail("could not parse proto AST path: ", err.Error())
1045					}
1046					path = append(path, int32(val))
1047				}
1048				g.annotations = append(g.annotations, &descriptor.GeneratedCodeInfo_Annotation{
1049					Path:       path,
1050					SourceFile: &v.source,
1051					Begin:      &begin,
1052					End:        &end,
1053				})
1054			}
1055		default:
1056			g.printAtom(v)
1057		}
1058	}
1059	g.WriteByte('\n')
1060}
1061
1062// addInitf stores the given statement to be printed inside the file's init function.
1063// The statement is given as a format specifier and arguments.
1064func (g *Generator) addInitf(stmt string, a ...interface{}) {
1065	g.init = append(g.init, fmt.Sprintf(stmt, a...))
1066}
1067
1068// In Indents the output one tab stop.
1069func (g *Generator) In() { g.indent += "\t" }
1070
1071// Out unindents the output one tab stop.
1072func (g *Generator) Out() {
1073	if len(g.indent) > 0 {
1074		g.indent = g.indent[1:]
1075	}
1076}
1077
1078// GenerateAllFiles generates the output for all the files we're outputting.
1079func (g *Generator) GenerateAllFiles() {
1080	// Initialize the plugins
1081	for _, p := range plugins {
1082		p.Init(g)
1083	}
1084	// Generate the output. The generator runs for every file, even the files
1085	// that we don't generate output for, so that we can collate the full list
1086	// of exported symbols to support public imports.
1087	genFileMap := make(map[*FileDescriptor]bool, len(g.genFiles))
1088	for _, file := range g.genFiles {
1089		genFileMap[file] = true
1090	}
1091	for _, file := range g.allFiles {
1092		g.Reset()
1093		g.annotations = nil
1094		g.writeOutput = genFileMap[file]
1095		g.generate(file)
1096		if !g.writeOutput {
1097			continue
1098		}
1099		fname := file.goFileName(g.pathType)
1100		g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{
1101			Name:    proto.String(fname),
1102			Content: proto.String(g.String()),
1103		})
1104		if g.annotateCode {
1105			// Store the generated code annotations in text, as the protoc plugin protocol requires that
1106			// strings contain valid UTF-8.
1107			g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{
1108				Name:    proto.String(file.goFileName(g.pathType) + ".meta"),
1109				Content: proto.String(proto.CompactTextString(&descriptor.GeneratedCodeInfo{Annotation: g.annotations})),
1110			})
1111		}
1112	}
1113}
1114
1115// Run all the plugins associated with the file.
1116func (g *Generator) runPlugins(file *FileDescriptor) {
1117	for _, p := range plugins {
1118		p.Generate(file)
1119	}
1120}
1121
1122// Fill the response protocol buffer with the generated output for all the files we're
1123// supposed to generate.
1124func (g *Generator) generate(file *FileDescriptor) {
1125	g.file = file
1126	g.usedPackages = make(map[GoImportPath]bool)
1127	g.packageNames = make(map[GoImportPath]GoPackageName)
1128	g.usedPackageNames = make(map[GoPackageName]bool)
1129	g.addedImports = make(map[GoImportPath]bool)
1130	for name := range globalPackageNames {
1131		g.usedPackageNames[name] = true
1132	}
1133
1134	g.P("// This is a compile-time assertion to ensure that this generated file")
1135	g.P("// is compatible with the proto package it is being compiled against.")
1136	g.P("// A compilation error at this line likely means your copy of the")
1137	g.P("// proto package needs to be updated.")
1138	g.P("const _ = ", g.Pkg["proto"], ".ProtoPackageIsVersion", generatedCodeVersion, " // please upgrade the proto package")
1139	g.P()
1140
1141	for _, td := range g.file.imp {
1142		g.generateImported(td)
1143	}
1144	for _, enum := range g.file.enum {
1145		g.generateEnum(enum)
1146	}
1147	for _, desc := range g.file.desc {
1148		// Don't generate virtual messages for maps.
1149		if desc.GetOptions().GetMapEntry() {
1150			continue
1151		}
1152		g.generateMessage(desc)
1153	}
1154	for _, ext := range g.file.ext {
1155		g.generateExtension(ext)
1156	}
1157	g.generateInitFunction()
1158	g.generateFileDescriptor(file)
1159
1160	// Run the plugins before the imports so we know which imports are necessary.
1161	g.runPlugins(file)
1162
1163	// Generate header and imports last, though they appear first in the output.
1164	rem := g.Buffer
1165	remAnno := g.annotations
1166	g.Buffer = new(bytes.Buffer)
1167	g.annotations = nil
1168	g.generateHeader()
1169	g.generateImports()
1170	if !g.writeOutput {
1171		return
1172	}
1173	// Adjust the offsets for annotations displaced by the header and imports.
1174	for _, anno := range remAnno {
1175		*anno.Begin += int32(g.Len())
1176		*anno.End += int32(g.Len())
1177		g.annotations = append(g.annotations, anno)
1178	}
1179	g.Write(rem.Bytes())
1180
1181	// Reformat generated code and patch annotation locations.
1182	fset := token.NewFileSet()
1183	original := g.Bytes()
1184	if g.annotateCode {
1185		// make a copy independent of g; we'll need it after Reset.
1186		original = append([]byte(nil), original...)
1187	}
1188	fileAST, err := parser.ParseFile(fset, "", original, parser.ParseComments)
1189	if err != nil {
1190		// Print out the bad code with line numbers.
1191		// This should never happen in practice, but it can while changing generated code,
1192		// so consider this a debugging aid.
1193		var src bytes.Buffer
1194		s := bufio.NewScanner(bytes.NewReader(original))
1195		for line := 1; s.Scan(); line++ {
1196			fmt.Fprintf(&src, "%5d\t%s\n", line, s.Bytes())
1197		}
1198		g.Fail("bad Go source code was generated:", err.Error(), "\n"+src.String())
1199	}
1200	ast.SortImports(fset, fileAST)
1201	g.Reset()
1202	err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(g, fset, fileAST)
1203	if err != nil {
1204		g.Fail("generated Go source code could not be reformatted:", err.Error())
1205	}
1206	if g.annotateCode {
1207		m, err := remap.Compute(original, g.Bytes())
1208		if err != nil {
1209			g.Fail("formatted generated Go source code could not be mapped back to the original code:", err.Error())
1210		}
1211		for _, anno := range g.annotations {
1212			new, ok := m.Find(int(*anno.Begin), int(*anno.End))
1213			if !ok {
1214				g.Fail("span in formatted generated Go source code could not be mapped back to the original code")
1215			}
1216			*anno.Begin = int32(new.Pos)
1217			*anno.End = int32(new.End)
1218		}
1219	}
1220}
1221
1222// Generate the header, including package definition
1223func (g *Generator) generateHeader() {
1224	g.P("// Code generated by protoc-gen-go. DO NOT EDIT.")
1225	if g.file.GetOptions().GetDeprecated() {
1226		g.P("// ", g.file.Name, " is a deprecated file.")
1227	} else {
1228		g.P("// source: ", g.file.Name)
1229	}
1230	g.P()
1231	g.PrintComments(strconv.Itoa(packagePath))
1232	g.P()
1233	g.P("package ", g.file.packageName)
1234	g.P()
1235}
1236
1237// deprecationComment is the standard comment added to deprecated
1238// messages, fields, enums, and enum values.
1239var deprecationComment = "// Deprecated: Do not use."
1240
1241// PrintComments prints any comments from the source .proto file.
1242// The path is a comma-separated list of integers.
1243// It returns an indication of whether any comments were printed.
1244// See descriptor.proto for its format.
1245func (g *Generator) PrintComments(path string) bool {
1246	if !g.writeOutput {
1247		return false
1248	}
1249	if c, ok := g.makeComments(path); ok {
1250		g.P(c)
1251		return true
1252	}
1253	return false
1254}
1255
1256// makeComments generates the comment string for the field, no "\n" at the end
1257func (g *Generator) makeComments(path string) (string, bool) {
1258	loc, ok := g.file.comments[path]
1259	if !ok {
1260		return "", false
1261	}
1262	w := new(bytes.Buffer)
1263	nl := ""
1264	for _, line := range strings.Split(strings.TrimSuffix(loc.GetLeadingComments(), "\n"), "\n") {
1265		fmt.Fprintf(w, "%s//%s", nl, line)
1266		nl = "\n"
1267	}
1268	return w.String(), true
1269}
1270
1271func (g *Generator) fileByName(filename string) *FileDescriptor {
1272	return g.allFilesByName[filename]
1273}
1274
1275// weak returns whether the ith import of the current file is a weak import.
1276func (g *Generator) weak(i int32) bool {
1277	for _, j := range g.file.WeakDependency {
1278		if j == i {
1279			return true
1280		}
1281	}
1282	return false
1283}
1284
1285// Generate the imports
1286func (g *Generator) generateImports() {
1287	imports := make(map[GoImportPath]GoPackageName)
1288	for i, s := range g.file.Dependency {
1289		fd := g.fileByName(s)
1290		importPath := fd.importPath
1291		// Do not import our own package.
1292		if importPath == g.file.importPath {
1293			continue
1294		}
1295		// Do not import weak imports.
1296		if g.weak(int32(i)) {
1297			continue
1298		}
1299		// Do not import a package twice.
1300		if _, ok := imports[importPath]; ok {
1301			continue
1302		}
1303		// We need to import all the dependencies, even if we don't reference them,
1304		// because other code and tools depend on having the full transitive closure
1305		// of protocol buffer types in the binary.
1306		packageName := g.GoPackageName(importPath)
1307		if _, ok := g.usedPackages[importPath]; !ok {
1308			packageName = "_"
1309		}
1310		imports[importPath] = packageName
1311	}
1312	for importPath := range g.addedImports {
1313		imports[importPath] = g.GoPackageName(importPath)
1314	}
1315	// We almost always need a proto import.  Rather than computing when we
1316	// do, which is tricky when there's a plugin, just import it and
1317	// reference it later. The same argument applies to the fmt and math packages.
1318	g.P("import (")
1319	g.P(g.Pkg["fmt"] + ` "fmt"`)
1320	g.P(g.Pkg["math"] + ` "math"`)
1321	g.P(g.Pkg["proto"]+" ", GoImportPath(g.ImportPrefix)+"github.com/golang/protobuf/proto")
1322	for importPath, packageName := range imports {
1323		g.P(packageName, " ", GoImportPath(g.ImportPrefix)+importPath)
1324	}
1325	g.P(")")
1326	g.P()
1327	// TODO: may need to worry about uniqueness across plugins
1328	for _, p := range plugins {
1329		p.GenerateImports(g.file)
1330		g.P()
1331	}
1332	g.P("// Reference imports to suppress errors if they are not otherwise used.")
1333	g.P("var _ = ", g.Pkg["proto"], ".Marshal")
1334	g.P("var _ = ", g.Pkg["fmt"], ".Errorf")
1335	g.P("var _ = ", g.Pkg["math"], ".Inf")
1336	g.P()
1337}
1338
1339func (g *Generator) generateImported(id *ImportedDescriptor) {
1340	df := id.o.File()
1341	filename := *df.Name
1342	if df.importPath == g.file.importPath {
1343		// Don't generate type aliases for files in the same Go package as this one.
1344		return
1345	}
1346	if !supportTypeAliases {
1347		g.Fail(fmt.Sprintf("%s: public imports require at least go1.9", filename))
1348	}
1349	g.usedPackages[df.importPath] = true
1350
1351	for _, sym := range df.exported[id.o] {
1352		sym.GenerateAlias(g, filename, g.GoPackageName(df.importPath))
1353	}
1354
1355	g.P()
1356}
1357
1358// Generate the enum definitions for this EnumDescriptor.
1359func (g *Generator) generateEnum(enum *EnumDescriptor) {
1360	// The full type name
1361	typeName := enum.TypeName()
1362	// The full type name, CamelCased.
1363	ccTypeName := CamelCaseSlice(typeName)
1364	ccPrefix := enum.prefix()
1365
1366	deprecatedEnum := ""
1367	if enum.GetOptions().GetDeprecated() {
1368		deprecatedEnum = deprecationComment
1369	}
1370	g.PrintComments(enum.path)
1371	g.P("type ", Annotate(enum.file, enum.path, ccTypeName), " int32", deprecatedEnum)
1372	g.file.addExport(enum, enumSymbol{ccTypeName, enum.proto3()})
1373	g.P("const (")
1374	for i, e := range enum.Value {
1375		etorPath := fmt.Sprintf("%s,%d,%d", enum.path, enumValuePath, i)
1376		g.PrintComments(etorPath)
1377
1378		deprecatedValue := ""
1379		if e.GetOptions().GetDeprecated() {
1380			deprecatedValue = deprecationComment
1381		}
1382
1383		name := ccPrefix + *e.Name
1384		g.P(Annotate(enum.file, etorPath, name), " ", ccTypeName, " = ", e.Number, " ", deprecatedValue)
1385		g.file.addExport(enum, constOrVarSymbol{name, "const", ccTypeName})
1386	}
1387	g.P(")")
1388	g.P()
1389	g.P("var ", ccTypeName, "_name = map[int32]string{")
1390	generated := make(map[int32]bool) // avoid duplicate values
1391	for _, e := range enum.Value {
1392		duplicate := ""
1393		if _, present := generated[*e.Number]; present {
1394			duplicate = "// Duplicate value: "
1395		}
1396		g.P(duplicate, e.Number, ": ", strconv.Quote(*e.Name), ",")
1397		generated[*e.Number] = true
1398	}
1399	g.P("}")
1400	g.P()
1401	g.P("var ", ccTypeName, "_value = map[string]int32{")
1402	for _, e := range enum.Value {
1403		g.P(strconv.Quote(*e.Name), ": ", e.Number, ",")
1404	}
1405	g.P("}")
1406	g.P()
1407
1408	if !enum.proto3() {
1409		g.P("func (x ", ccTypeName, ") Enum() *", ccTypeName, " {")
1410		g.P("p := new(", ccTypeName, ")")
1411		g.P("*p = x")
1412		g.P("return p")
1413		g.P("}")
1414		g.P()
1415	}
1416
1417	g.P("func (x ", ccTypeName, ") String() string {")
1418	g.P("return ", g.Pkg["proto"], ".EnumName(", ccTypeName, "_name, int32(x))")
1419	g.P("}")
1420	g.P()
1421
1422	if !enum.proto3() {
1423		g.P("func (x *", ccTypeName, ") UnmarshalJSON(data []byte) error {")
1424		g.P("value, err := ", g.Pkg["proto"], ".UnmarshalJSONEnum(", ccTypeName, `_value, data, "`, ccTypeName, `")`)
1425		g.P("if err != nil {")
1426		g.P("return err")
1427		g.P("}")
1428		g.P("*x = ", ccTypeName, "(value)")
1429		g.P("return nil")
1430		g.P("}")
1431		g.P()
1432	}
1433
1434	var indexes []string
1435	for m := enum.parent; m != nil; m = m.parent {
1436		// XXX: skip groups?
1437		indexes = append([]string{strconv.Itoa(m.index)}, indexes...)
1438	}
1439	indexes = append(indexes, strconv.Itoa(enum.index))
1440	g.P("func (", ccTypeName, ") EnumDescriptor() ([]byte, []int) {")
1441	g.P("return ", g.file.VarName(), ", []int{", strings.Join(indexes, ", "), "}")
1442	g.P("}")
1443	g.P()
1444	if enum.file.GetPackage() == "google.protobuf" && enum.GetName() == "NullValue" {
1445		g.P("func (", ccTypeName, `) XXX_WellKnownType() string { return "`, enum.GetName(), `" }`)
1446		g.P()
1447	}
1448
1449	g.generateEnumRegistration(enum)
1450}
1451
1452// The tag is a string like "varint,2,opt,name=fieldname,def=7" that
1453// identifies details of the field for the protocol buffer marshaling and unmarshaling
1454// code.  The fields are:
1455//	wire encoding
1456//	protocol tag number
1457//	opt,req,rep for optional, required, or repeated
1458//	packed whether the encoding is "packed" (optional; repeated primitives only)
1459//	name= the original declared name
1460//	enum= the name of the enum type if it is an enum-typed field.
1461//	proto3 if this field is in a proto3 message
1462//	def= string representation of the default value, if any.
1463// The default value must be in a representation that can be used at run-time
1464// to generate the default value. Thus bools become 0 and 1, for instance.
1465func (g *Generator) goTag(message *Descriptor, field *descriptor.FieldDescriptorProto, wiretype string) string {
1466	optrepreq := ""
1467	switch {
1468	case isOptional(field):
1469		optrepreq = "opt"
1470	case isRequired(field):
1471		optrepreq = "req"
1472	case isRepeated(field):
1473		optrepreq = "rep"
1474	}
1475	var defaultValue string
1476	if dv := field.DefaultValue; dv != nil { // set means an explicit default
1477		defaultValue = *dv
1478		// Some types need tweaking.
1479		switch *field.Type {
1480		case descriptor.FieldDescriptorProto_TYPE_BOOL:
1481			if defaultValue == "true" {
1482				defaultValue = "1"
1483			} else {
1484				defaultValue = "0"
1485			}
1486		case descriptor.FieldDescriptorProto_TYPE_STRING,
1487			descriptor.FieldDescriptorProto_TYPE_BYTES:
1488			// Nothing to do. Quoting is done for the whole tag.
1489		case descriptor.FieldDescriptorProto_TYPE_ENUM:
1490			// For enums we need to provide the integer constant.
1491			obj := g.ObjectNamed(field.GetTypeName())
1492			if id, ok := obj.(*ImportedDescriptor); ok {
1493				// It is an enum that was publicly imported.
1494				// We need the underlying type.
1495				obj = id.o
1496			}
1497			enum, ok := obj.(*EnumDescriptor)
1498			if !ok {
1499				log.Printf("obj is a %T", obj)
1500				if id, ok := obj.(*ImportedDescriptor); ok {
1501					log.Printf("id.o is a %T", id.o)
1502				}
1503				g.Fail("unknown enum type", CamelCaseSlice(obj.TypeName()))
1504			}
1505			defaultValue = enum.integerValueAsString(defaultValue)
1506		case descriptor.FieldDescriptorProto_TYPE_FLOAT:
1507			if def := defaultValue; def != "inf" && def != "-inf" && def != "nan" {
1508				if f, err := strconv.ParseFloat(defaultValue, 32); err == nil {
1509					defaultValue = fmt.Sprint(float32(f))
1510				}
1511			}
1512		case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
1513			if def := defaultValue; def != "inf" && def != "-inf" && def != "nan" {
1514				if f, err := strconv.ParseFloat(defaultValue, 64); err == nil {
1515					defaultValue = fmt.Sprint(f)
1516				}
1517			}
1518		}
1519		defaultValue = ",def=" + defaultValue
1520	}
1521	enum := ""
1522	if *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM {
1523		// We avoid using obj.GoPackageName(), because we want to use the
1524		// original (proto-world) package name.
1525		obj := g.ObjectNamed(field.GetTypeName())
1526		if id, ok := obj.(*ImportedDescriptor); ok {
1527			obj = id.o
1528		}
1529		enum = ",enum="
1530		if pkg := obj.File().GetPackage(); pkg != "" {
1531			enum += pkg + "."
1532		}
1533		enum += CamelCaseSlice(obj.TypeName())
1534	}
1535	packed := ""
1536	if (field.Options != nil && field.Options.GetPacked()) ||
1537		// Per https://developers.google.com/protocol-buffers/docs/proto3#simple:
1538		// "In proto3, repeated fields of scalar numeric types use packed encoding by default."
1539		(message.proto3() && (field.Options == nil || field.Options.Packed == nil) &&
1540			isRepeated(field) && isScalar(field)) {
1541		packed = ",packed"
1542	}
1543	fieldName := field.GetName()
1544	name := fieldName
1545	if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP {
1546		// We must use the type name for groups instead of
1547		// the field name to preserve capitalization.
1548		// type_name in FieldDescriptorProto is fully-qualified,
1549		// but we only want the local part.
1550		name = *field.TypeName
1551		if i := strings.LastIndex(name, "."); i >= 0 {
1552			name = name[i+1:]
1553		}
1554	}
1555	if json := field.GetJsonName(); field.Extendee == nil && json != "" && json != name {
1556		// TODO: escaping might be needed, in which case
1557		// perhaps this should be in its own "json" tag.
1558		name += ",json=" + json
1559	}
1560	name = ",name=" + name
1561	if message.proto3() {
1562		name += ",proto3"
1563	}
1564	oneof := ""
1565	if field.OneofIndex != nil {
1566		oneof = ",oneof"
1567	}
1568	return strconv.Quote(fmt.Sprintf("%s,%d,%s%s%s%s%s%s",
1569		wiretype,
1570		field.GetNumber(),
1571		optrepreq,
1572		packed,
1573		name,
1574		enum,
1575		oneof,
1576		defaultValue))
1577}
1578
1579func needsStar(typ descriptor.FieldDescriptorProto_Type) bool {
1580	switch typ {
1581	case descriptor.FieldDescriptorProto_TYPE_GROUP:
1582		return false
1583	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
1584		return false
1585	case descriptor.FieldDescriptorProto_TYPE_BYTES:
1586		return false
1587	}
1588	return true
1589}
1590
1591// TypeName is the printed name appropriate for an item. If the object is in the current file,
1592// TypeName drops the package name and underscores the rest.
1593// Otherwise the object is from another package; and the result is the underscored
1594// package name followed by the item name.
1595// The result always has an initial capital.
1596func (g *Generator) TypeName(obj Object) string {
1597	return g.DefaultPackageName(obj) + CamelCaseSlice(obj.TypeName())
1598}
1599
1600// GoType returns a string representing the type name, and the wire type
1601func (g *Generator) GoType(message *Descriptor, field *descriptor.FieldDescriptorProto) (typ string, wire string) {
1602	// TODO: Options.
1603	switch *field.Type {
1604	case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
1605		typ, wire = "float64", "fixed64"
1606	case descriptor.FieldDescriptorProto_TYPE_FLOAT:
1607		typ, wire = "float32", "fixed32"
1608	case descriptor.FieldDescriptorProto_TYPE_INT64:
1609		typ, wire = "int64", "varint"
1610	case descriptor.FieldDescriptorProto_TYPE_UINT64:
1611		typ, wire = "uint64", "varint"
1612	case descriptor.FieldDescriptorProto_TYPE_INT32:
1613		typ, wire = "int32", "varint"
1614	case descriptor.FieldDescriptorProto_TYPE_UINT32:
1615		typ, wire = "uint32", "varint"
1616	case descriptor.FieldDescriptorProto_TYPE_FIXED64:
1617		typ, wire = "uint64", "fixed64"
1618	case descriptor.FieldDescriptorProto_TYPE_FIXED32:
1619		typ, wire = "uint32", "fixed32"
1620	case descriptor.FieldDescriptorProto_TYPE_BOOL:
1621		typ, wire = "bool", "varint"
1622	case descriptor.FieldDescriptorProto_TYPE_STRING:
1623		typ, wire = "string", "bytes"
1624	case descriptor.FieldDescriptorProto_TYPE_GROUP:
1625		desc := g.ObjectNamed(field.GetTypeName())
1626		typ, wire = "*"+g.TypeName(desc), "group"
1627	case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
1628		desc := g.ObjectNamed(field.GetTypeName())
1629		typ, wire = "*"+g.TypeName(desc), "bytes"
1630	case descriptor.FieldDescriptorProto_TYPE_BYTES:
1631		typ, wire = "[]byte", "bytes"
1632	case descriptor.FieldDescriptorProto_TYPE_ENUM:
1633		desc := g.ObjectNamed(field.GetTypeName())
1634		typ, wire = g.TypeName(desc), "varint"
1635	case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
1636		typ, wire = "int32", "fixed32"
1637	case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
1638		typ, wire = "int64", "fixed64"
1639	case descriptor.FieldDescriptorProto_TYPE_SINT32:
1640		typ, wire = "int32", "zigzag32"
1641	case descriptor.FieldDescriptorProto_TYPE_SINT64:
1642		typ, wire = "int64", "zigzag64"
1643	default:
1644		g.Fail("unknown type for", field.GetName())
1645	}
1646	if isRepeated(field) {
1647		typ = "[]" + typ
1648	} else if message != nil && message.proto3() {
1649		return
1650	} else if field.OneofIndex != nil && message != nil {
1651		return
1652	} else if needsStar(*field.Type) {
1653		typ = "*" + typ
1654	}
1655	return
1656}
1657
1658func (g *Generator) RecordTypeUse(t string) {
1659	if _, ok := g.typeNameToObject[t]; !ok {
1660		return
1661	}
1662	importPath := g.ObjectNamed(t).GoImportPath()
1663	if importPath == g.outputImportPath {
1664		// Don't record use of objects in our package.
1665		return
1666	}
1667	g.AddImport(importPath)
1668	g.usedPackages[importPath] = true
1669}
1670
1671// Method names that may be generated.  Fields with these names get an
1672// underscore appended. Any change to this set is a potential incompatible
1673// API change because it changes generated field names.
1674var methodNames = [...]string{
1675	"Reset",
1676	"String",
1677	"ProtoMessage",
1678	"Marshal",
1679	"Unmarshal",
1680	"ExtensionRangeArray",
1681	"ExtensionMap",
1682	"Descriptor",
1683}
1684
1685// Names of messages in the `google.protobuf` package for which
1686// we will generate XXX_WellKnownType methods.
1687var wellKnownTypes = map[string]bool{
1688	"Any":       true,
1689	"Duration":  true,
1690	"Empty":     true,
1691	"Struct":    true,
1692	"Timestamp": true,
1693
1694	"Value":       true,
1695	"ListValue":   true,
1696	"DoubleValue": true,
1697	"FloatValue":  true,
1698	"Int64Value":  true,
1699	"UInt64Value": true,
1700	"Int32Value":  true,
1701	"UInt32Value": true,
1702	"BoolValue":   true,
1703	"StringValue": true,
1704	"BytesValue":  true,
1705}
1706
1707// getterDefault finds the default value for the field to return from a getter,
1708// regardless of if it's a built in default or explicit from the source. Returns e.g. "nil", `""`, "Default_MessageType_FieldName"
1709func (g *Generator) getterDefault(field *descriptor.FieldDescriptorProto, goMessageType string) string {
1710	if isRepeated(field) {
1711		return "nil"
1712	}
1713	if def := field.GetDefaultValue(); def != "" {
1714		defaultConstant := g.defaultConstantName(goMessageType, field.GetName())
1715		if *field.Type != descriptor.FieldDescriptorProto_TYPE_BYTES {
1716			return defaultConstant
1717		}
1718		return "append([]byte(nil), " + defaultConstant + "...)"
1719	}
1720	switch *field.Type {
1721	case descriptor.FieldDescriptorProto_TYPE_BOOL:
1722		return "false"
1723	case descriptor.FieldDescriptorProto_TYPE_STRING:
1724		return `""`
1725	case descriptor.FieldDescriptorProto_TYPE_GROUP, descriptor.FieldDescriptorProto_TYPE_MESSAGE, descriptor.FieldDescriptorProto_TYPE_BYTES:
1726		return "nil"
1727	case descriptor.FieldDescriptorProto_TYPE_ENUM:
1728		obj := g.ObjectNamed(field.GetTypeName())
1729		var enum *EnumDescriptor
1730		if id, ok := obj.(*ImportedDescriptor); ok {
1731			// The enum type has been publicly imported.
1732			enum, _ = id.o.(*EnumDescriptor)
1733		} else {
1734			enum, _ = obj.(*EnumDescriptor)
1735		}
1736		if enum == nil {
1737			log.Printf("don't know how to generate getter for %s", field.GetName())
1738			return "nil"
1739		}
1740		if len(enum.Value) == 0 {
1741			return "0 // empty enum"
1742		}
1743		first := enum.Value[0].GetName()
1744		return g.DefaultPackageName(obj) + enum.prefix() + first
1745	default:
1746		return "0"
1747	}
1748}
1749
1750// defaultConstantName builds the name of the default constant from the message
1751// type name and the untouched field name, e.g. "Default_MessageType_FieldName"
1752func (g *Generator) defaultConstantName(goMessageType, protoFieldName string) string {
1753	return "Default_" + goMessageType + "_" + CamelCase(protoFieldName)
1754}
1755
1756// The different types of fields in a message and how to actually print them
1757// Most of the logic for generateMessage is in the methods of these types.
1758//
1759// Note that the content of the field is irrelevant, a simpleField can contain
1760// anything from a scalar to a group (which is just a message).
1761//
1762// Extension fields (and message sets) are however handled separately.
1763//
1764// simpleField - a field that is neiter weak nor oneof, possibly repeated
1765// oneofField - field containing list of subfields:
1766// - oneofSubField - a field within the oneof
1767
1768// msgCtx contains the context for the generator functions.
1769type msgCtx struct {
1770	goName  string      // Go struct name of the message, e.g. MessageName
1771	message *Descriptor // The descriptor for the message
1772}
1773
1774// fieldCommon contains data common to all types of fields.
1775type fieldCommon struct {
1776	goName     string // Go name of field, e.g. "FieldName" or "Descriptor_"
1777	protoName  string // Name of field in proto language, e.g. "field_name" or "descriptor"
1778	getterName string // Name of the getter, e.g. "GetFieldName" or "GetDescriptor_"
1779	goType     string // The Go type as a string, e.g. "*int32" or "*OtherMessage"
1780	tags       string // The tag string/annotation for the type, e.g. `protobuf:"varint,8,opt,name=region_id,json=regionId"`
1781	fullPath   string // The full path of the field as used by Annotate etc, e.g. "4,0,2,0"
1782}
1783
1784// getProtoName gets the proto name of a field, e.g. "field_name" or "descriptor".
1785func (f *fieldCommon) getProtoName() string {
1786	return f.protoName
1787}
1788
1789// getGoType returns the go type of the field  as a string, e.g. "*int32".
1790func (f *fieldCommon) getGoType() string {
1791	return f.goType
1792}
1793
1794// simpleField is not weak, not a oneof, not an extension. Can be required, optional or repeated.
1795type simpleField struct {
1796	fieldCommon
1797	protoTypeName string                               // Proto type name, empty if primitive, e.g. ".google.protobuf.Duration"
1798	protoType     descriptor.FieldDescriptorProto_Type // Actual type enum value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64
1799	deprecated    string                               // Deprecation comment, if any, e.g. "// Deprecated: Do not use."
1800	getterDef     string                               // Default for getters, e.g. "nil", `""` or "Default_MessageType_FieldName"
1801	protoDef      string                               // Default value as defined in the proto file, e.g "yoshi" or "5"
1802	comment       string                               // The full comment for the field, e.g. "// Useful information"
1803}
1804
1805// decl prints the declaration of the field in the struct (if any).
1806func (f *simpleField) decl(g *Generator, mc *msgCtx) {
1807	g.P(f.comment, Annotate(mc.message.file, f.fullPath, f.goName), "\t", f.goType, "\t`", f.tags, "`", f.deprecated)
1808}
1809
1810// getter prints the getter for the field.
1811func (f *simpleField) getter(g *Generator, mc *msgCtx) {
1812	star := ""
1813	tname := f.goType
1814	if needsStar(f.protoType) && tname[0] == '*' {
1815		tname = tname[1:]
1816		star = "*"
1817	}
1818	if f.deprecated != "" {
1819		g.P(f.deprecated)
1820	}
1821	g.P("func (m *", mc.goName, ") ", Annotate(mc.message.file, f.fullPath, f.getterName), "() "+tname+" {")
1822	if f.getterDef == "nil" { // Simpler getter
1823		g.P("if m != nil {")
1824		g.P("return m." + f.goName)
1825		g.P("}")
1826		g.P("return nil")
1827		g.P("}")
1828		g.P()
1829		return
1830	}
1831	if mc.message.proto3() {
1832		g.P("if m != nil {")
1833	} else {
1834		g.P("if m != nil && m." + f.goName + " != nil {")
1835	}
1836	g.P("return " + star + "m." + f.goName)
1837	g.P("}")
1838	g.P("return ", f.getterDef)
1839	g.P("}")
1840	g.P()
1841}
1842
1843// setter prints the setter method of the field.
1844func (f *simpleField) setter(g *Generator, mc *msgCtx) {
1845	// No setter for regular fields yet
1846}
1847
1848// getProtoDef returns the default value explicitly stated in the proto file, e.g "yoshi" or "5".
1849func (f *simpleField) getProtoDef() string {
1850	return f.protoDef
1851}
1852
1853// getProtoTypeName returns the protobuf type name for the field as returned by field.GetTypeName(), e.g. ".google.protobuf.Duration".
1854func (f *simpleField) getProtoTypeName() string {
1855	return f.protoTypeName
1856}
1857
1858// getProtoType returns the *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64.
1859func (f *simpleField) getProtoType() descriptor.FieldDescriptorProto_Type {
1860	return f.protoType
1861}
1862
1863// oneofSubFields are kept slize held by each oneofField. They do not appear in the top level slize of fields for the message.
1864type oneofSubField struct {
1865	fieldCommon
1866	protoTypeName string                               // Proto type name, empty if primitive, e.g. ".google.protobuf.Duration"
1867	protoType     descriptor.FieldDescriptorProto_Type // Actual type enum value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64
1868	oneofTypeName string                               // Type name of the enclosing struct, e.g. "MessageName_FieldName"
1869	fieldNumber   int                                  // Actual field number, as defined in proto, e.g. 12
1870	getterDef     string                               // Default for getters, e.g. "nil", `""` or "Default_MessageType_FieldName"
1871	protoDef      string                               // Default value as defined in the proto file, e.g "yoshi" or "5"
1872	deprecated    string                               // Deprecation comment, if any.
1873}
1874
1875// typedNil prints a nil casted to the pointer to this field.
1876// - for XXX_OneofWrappers
1877func (f *oneofSubField) typedNil(g *Generator) {
1878	g.P("(*", f.oneofTypeName, ")(nil),")
1879}
1880
1881// getProtoDef returns the default value explicitly stated in the proto file, e.g "yoshi" or "5".
1882func (f *oneofSubField) getProtoDef() string {
1883	return f.protoDef
1884}
1885
1886// getProtoTypeName returns the protobuf type name for the field as returned by field.GetTypeName(), e.g. ".google.protobuf.Duration".
1887func (f *oneofSubField) getProtoTypeName() string {
1888	return f.protoTypeName
1889}
1890
1891// getProtoType returns the *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64.
1892func (f *oneofSubField) getProtoType() descriptor.FieldDescriptorProto_Type {
1893	return f.protoType
1894}
1895
1896// oneofField represents the oneof on top level.
1897// The alternative fields within the oneof are represented by oneofSubField.
1898type oneofField struct {
1899	fieldCommon
1900	subFields []*oneofSubField // All the possible oneof fields
1901	comment   string           // The full comment for the field, e.g. "// Types that are valid to be assigned to MyOneof:\n\\"
1902}
1903
1904// decl prints the declaration of the field in the struct (if any).
1905func (f *oneofField) decl(g *Generator, mc *msgCtx) {
1906	comment := f.comment
1907	for _, sf := range f.subFields {
1908		comment += "//\t*" + sf.oneofTypeName + "\n"
1909	}
1910	g.P(comment, Annotate(mc.message.file, f.fullPath, f.goName), " ", f.goType, " `", f.tags, "`")
1911}
1912
1913// getter for a oneof field will print additional discriminators and interfaces for the oneof,
1914// also it prints all the getters for the sub fields.
1915func (f *oneofField) getter(g *Generator, mc *msgCtx) {
1916	// The discriminator type
1917	g.P("type ", f.goType, " interface {")
1918	g.P(f.goType, "()")
1919	g.P("}")
1920	g.P()
1921	// The subField types, fulfilling the discriminator type contract
1922	for _, sf := range f.subFields {
1923		g.P("type ", Annotate(mc.message.file, sf.fullPath, sf.oneofTypeName), " struct {")
1924		g.P(Annotate(mc.message.file, sf.fullPath, sf.goName), " ", sf.goType, " `", sf.tags, "`")
1925		g.P("}")
1926		g.P()
1927	}
1928	for _, sf := range f.subFields {
1929		g.P("func (*", sf.oneofTypeName, ") ", f.goType, "() {}")
1930		g.P()
1931	}
1932	// Getter for the oneof field
1933	g.P("func (m *", mc.goName, ") ", Annotate(mc.message.file, f.fullPath, f.getterName), "() ", f.goType, " {")
1934	g.P("if m != nil { return m.", f.goName, " }")
1935	g.P("return nil")
1936	g.P("}")
1937	g.P()
1938	// Getters for each oneof
1939	for _, sf := range f.subFields {
1940		if sf.deprecated != "" {
1941			g.P(sf.deprecated)
1942		}
1943		g.P("func (m *", mc.goName, ") ", Annotate(mc.message.file, sf.fullPath, sf.getterName), "() "+sf.goType+" {")
1944		g.P("if x, ok := m.", f.getterName, "().(*", sf.oneofTypeName, "); ok {")
1945		g.P("return x.", sf.goName)
1946		g.P("}")
1947		g.P("return ", sf.getterDef)
1948		g.P("}")
1949		g.P()
1950	}
1951}
1952
1953// setter prints the setter method of the field.
1954func (f *oneofField) setter(g *Generator, mc *msgCtx) {
1955	// No setters for oneof yet
1956}
1957
1958// topLevelField interface implemented by all types of fields on the top level (not oneofSubField).
1959type topLevelField interface {
1960	decl(g *Generator, mc *msgCtx)   // print declaration within the struct
1961	getter(g *Generator, mc *msgCtx) // print getter
1962	setter(g *Generator, mc *msgCtx) // print setter if applicable
1963}
1964
1965// defField interface implemented by all types of fields that can have defaults (not oneofField, but instead oneofSubField).
1966type defField interface {
1967	getProtoDef() string                                // default value explicitly stated in the proto file, e.g "yoshi" or "5"
1968	getProtoName() string                               // proto name of a field, e.g. "field_name" or "descriptor"
1969	getGoType() string                                  // go type of the field  as a string, e.g. "*int32"
1970	getProtoTypeName() string                           // protobuf type name for the field, e.g. ".google.protobuf.Duration"
1971	getProtoType() descriptor.FieldDescriptorProto_Type // *field.Type value, e.g. descriptor.FieldDescriptorProto_TYPE_FIXED64
1972}
1973
1974// generateDefaultConstants adds constants for default values if needed, which is only if the default value is.
1975// explicit in the proto.
1976func (g *Generator) generateDefaultConstants(mc *msgCtx, topLevelFields []topLevelField) {
1977	// Collect fields that can have defaults
1978	dFields := []defField{}
1979	for _, pf := range topLevelFields {
1980		if f, ok := pf.(*oneofField); ok {
1981			for _, osf := range f.subFields {
1982				dFields = append(dFields, osf)
1983			}
1984			continue
1985		}
1986		dFields = append(dFields, pf.(defField))
1987	}
1988	for _, df := range dFields {
1989		def := df.getProtoDef()
1990		if def == "" {
1991			continue
1992		}
1993		fieldname := g.defaultConstantName(mc.goName, df.getProtoName())
1994		typename := df.getGoType()
1995		if typename[0] == '*' {
1996			typename = typename[1:]
1997		}
1998		kind := "const "
1999		switch {
2000		case typename == "bool":
2001		case typename == "string":
2002			def = strconv.Quote(def)
2003		case typename == "[]byte":
2004			def = "[]byte(" + strconv.Quote(unescape(def)) + ")"
2005			kind = "var "
2006		case def == "inf", def == "-inf", def == "nan":
2007			// These names are known to, and defined by, the protocol language.
2008			switch def {
2009			case "inf":
2010				def = "math.Inf(1)"
2011			case "-inf":
2012				def = "math.Inf(-1)"
2013			case "nan":
2014				def = "math.NaN()"
2015			}
2016			if df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_FLOAT {
2017				def = "float32(" + def + ")"
2018			}
2019			kind = "var "
2020		case df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_FLOAT:
2021			if f, err := strconv.ParseFloat(def, 32); err == nil {
2022				def = fmt.Sprint(float32(f))
2023			}
2024		case df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_DOUBLE:
2025			if f, err := strconv.ParseFloat(def, 64); err == nil {
2026				def = fmt.Sprint(f)
2027			}
2028		case df.getProtoType() == descriptor.FieldDescriptorProto_TYPE_ENUM:
2029			// Must be an enum.  Need to construct the prefixed name.
2030			obj := g.ObjectNamed(df.getProtoTypeName())
2031			var enum *EnumDescriptor
2032			if id, ok := obj.(*ImportedDescriptor); ok {
2033				// The enum type has been publicly imported.
2034				enum, _ = id.o.(*EnumDescriptor)
2035			} else {
2036				enum, _ = obj.(*EnumDescriptor)
2037			}
2038			if enum == nil {
2039				log.Printf("don't know how to generate constant for %s", fieldname)
2040				continue
2041			}
2042			def = g.DefaultPackageName(obj) + enum.prefix() + def
2043		}
2044		g.P(kind, fieldname, " ", typename, " = ", def)
2045		g.file.addExport(mc.message, constOrVarSymbol{fieldname, kind, ""})
2046	}
2047	g.P()
2048}
2049
2050// generateInternalStructFields just adds the XXX_<something> fields to the message struct.
2051func (g *Generator) generateInternalStructFields(mc *msgCtx, topLevelFields []topLevelField) {
2052	g.P("XXX_NoUnkeyedLiteral\tstruct{} `json:\"-\"`") // prevent unkeyed struct literals
2053	if len(mc.message.ExtensionRange) > 0 {
2054		messageset := ""
2055		if opts := mc.message.Options; opts != nil && opts.GetMessageSetWireFormat() {
2056			messageset = "protobuf_messageset:\"1\" "
2057		}
2058		g.P(g.Pkg["proto"], ".XXX_InternalExtensions `", messageset, "json:\"-\"`")
2059	}
2060	g.P("XXX_unrecognized\t[]byte `json:\"-\"`")
2061	g.P("XXX_sizecache\tint32 `json:\"-\"`")
2062
2063}
2064
2065// generateOneofFuncs adds all the utility functions for oneof, including marshaling, unmarshaling and sizer.
2066func (g *Generator) generateOneofFuncs(mc *msgCtx, topLevelFields []topLevelField) {
2067	ofields := []*oneofField{}
2068	for _, f := range topLevelFields {
2069		if o, ok := f.(*oneofField); ok {
2070			ofields = append(ofields, o)
2071		}
2072	}
2073	if len(ofields) == 0 {
2074		return
2075	}
2076
2077	// OneofFuncs
2078	g.P("// XXX_OneofWrappers is for the internal use of the proto package.")
2079	g.P("func (*", mc.goName, ") XXX_OneofWrappers() []interface{} {")
2080	g.P("return []interface{}{")
2081	for _, of := range ofields {
2082		for _, sf := range of.subFields {
2083			sf.typedNil(g)
2084		}
2085	}
2086	g.P("}")
2087	g.P("}")
2088	g.P()
2089}
2090
2091// generateMessageStruct adds the actual struct with it's members (but not methods) to the output.
2092func (g *Generator) generateMessageStruct(mc *msgCtx, topLevelFields []topLevelField) {
2093	comments := g.PrintComments(mc.message.path)
2094
2095	// Guarantee deprecation comments appear after user-provided comments.
2096	if mc.message.GetOptions().GetDeprecated() {
2097		if comments {
2098			// Convention: Separate deprecation comments from original
2099			// comments with an empty line.
2100			g.P("//")
2101		}
2102		g.P(deprecationComment)
2103	}
2104
2105	g.P("type ", Annotate(mc.message.file, mc.message.path, mc.goName), " struct {")
2106	for _, pf := range topLevelFields {
2107		pf.decl(g, mc)
2108	}
2109	g.generateInternalStructFields(mc, topLevelFields)
2110	g.P("}")
2111}
2112
2113// generateGetters adds getters for all fields, including oneofs and weak fields when applicable.
2114func (g *Generator) generateGetters(mc *msgCtx, topLevelFields []topLevelField) {
2115	for _, pf := range topLevelFields {
2116		pf.getter(g, mc)
2117	}
2118}
2119
2120// generateSetters add setters for all fields, including oneofs and weak fields when applicable.
2121func (g *Generator) generateSetters(mc *msgCtx, topLevelFields []topLevelField) {
2122	for _, pf := range topLevelFields {
2123		pf.setter(g, mc)
2124	}
2125}
2126
2127// generateCommonMethods adds methods to the message that are not on a per field basis.
2128func (g *Generator) generateCommonMethods(mc *msgCtx) {
2129	// Reset, String and ProtoMessage methods.
2130	g.P("func (m *", mc.goName, ") Reset() { *m = ", mc.goName, "{} }")
2131	g.P("func (m *", mc.goName, ") String() string { return ", g.Pkg["proto"], ".CompactTextString(m) }")
2132	g.P("func (*", mc.goName, ") ProtoMessage() {}")
2133	var indexes []string
2134	for m := mc.message; m != nil; m = m.parent {
2135		indexes = append([]string{strconv.Itoa(m.index)}, indexes...)
2136	}
2137	g.P("func (*", mc.goName, ") Descriptor() ([]byte, []int) {")
2138	g.P("return ", g.file.VarName(), ", []int{", strings.Join(indexes, ", "), "}")
2139	g.P("}")
2140	g.P()
2141	// TODO: Revisit the decision to use a XXX_WellKnownType method
2142	// if we change proto.MessageName to work with multiple equivalents.
2143	if mc.message.file.GetPackage() == "google.protobuf" && wellKnownTypes[mc.message.GetName()] {
2144		g.P("func (*", mc.goName, `) XXX_WellKnownType() string { return "`, mc.message.GetName(), `" }`)
2145		g.P()
2146	}
2147
2148	// Extension support methods
2149	if len(mc.message.ExtensionRange) > 0 {
2150		g.P()
2151		g.P("var extRange_", mc.goName, " = []", g.Pkg["proto"], ".ExtensionRange{")
2152		for _, r := range mc.message.ExtensionRange {
2153			end := fmt.Sprint(*r.End - 1) // make range inclusive on both ends
2154			g.P("{Start: ", r.Start, ", End: ", end, "},")
2155		}
2156		g.P("}")
2157		g.P("func (*", mc.goName, ") ExtensionRangeArray() []", g.Pkg["proto"], ".ExtensionRange {")
2158		g.P("return extRange_", mc.goName)
2159		g.P("}")
2160		g.P()
2161	}
2162
2163	// TODO: It does not scale to keep adding another method for every
2164	// operation on protos that we want to switch over to using the
2165	// table-driven approach. Instead, we should only add a single method
2166	// that allows getting access to the *InternalMessageInfo struct and then
2167	// calling Unmarshal, Marshal, Merge, Size, and Discard directly on that.
2168
2169	// Wrapper for table-driven marshaling and unmarshaling.
2170	g.P("func (m *", mc.goName, ") XXX_Unmarshal(b []byte) error {")
2171	g.P("return xxx_messageInfo_", mc.goName, ".Unmarshal(m, b)")
2172	g.P("}")
2173
2174	g.P("func (m *", mc.goName, ") XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {")
2175	g.P("return xxx_messageInfo_", mc.goName, ".Marshal(b, m, deterministic)")
2176	g.P("}")
2177
2178	g.P("func (m *", mc.goName, ") XXX_Merge(src ", g.Pkg["proto"], ".Message) {")
2179	g.P("xxx_messageInfo_", mc.goName, ".Merge(m, src)")
2180	g.P("}")
2181
2182	g.P("func (m *", mc.goName, ") XXX_Size() int {") // avoid name clash with "Size" field in some message
2183	g.P("return xxx_messageInfo_", mc.goName, ".Size(m)")
2184	g.P("}")
2185
2186	g.P("func (m *", mc.goName, ") XXX_DiscardUnknown() {")
2187	g.P("xxx_messageInfo_", mc.goName, ".DiscardUnknown(m)")
2188	g.P("}")
2189
2190	g.P("var xxx_messageInfo_", mc.goName, " ", g.Pkg["proto"], ".InternalMessageInfo")
2191	g.P()
2192}
2193
2194// Generate the type, methods and default constant definitions for this Descriptor.
2195func (g *Generator) generateMessage(message *Descriptor) {
2196	topLevelFields := []topLevelField{}
2197	oFields := make(map[int32]*oneofField)
2198	// The full type name
2199	typeName := message.TypeName()
2200	// The full type name, CamelCased.
2201	goTypeName := CamelCaseSlice(typeName)
2202
2203	usedNames := make(map[string]bool)
2204	for _, n := range methodNames {
2205		usedNames[n] = true
2206	}
2207
2208	// allocNames finds a conflict-free variation of the given strings,
2209	// consistently mutating their suffixes.
2210	// It returns the same number of strings.
2211	allocNames := func(ns ...string) []string {
2212	Loop:
2213		for {
2214			for _, n := range ns {
2215				if usedNames[n] {
2216					for i := range ns {
2217						ns[i] += "_"
2218					}
2219					continue Loop
2220				}
2221			}
2222			for _, n := range ns {
2223				usedNames[n] = true
2224			}
2225			return ns
2226		}
2227	}
2228
2229	mapFieldTypes := make(map[*descriptor.FieldDescriptorProto]string) // keep track of the map fields to be added later
2230
2231	// Build a structure more suitable for generating the text in one pass
2232	for i, field := range message.Field {
2233		// Allocate the getter and the field at the same time so name
2234		// collisions create field/method consistent names.
2235		// TODO: This allocation occurs based on the order of the fields
2236		// in the proto file, meaning that a change in the field
2237		// ordering can change generated Method/Field names.
2238		base := CamelCase(*field.Name)
2239		ns := allocNames(base, "Get"+base)
2240		fieldName, fieldGetterName := ns[0], ns[1]
2241		typename, wiretype := g.GoType(message, field)
2242		jsonName := *field.Name
2243		tag := fmt.Sprintf("protobuf:%s json:%q", g.goTag(message, field, wiretype), jsonName+",omitempty")
2244
2245		oneof := field.OneofIndex != nil
2246		if oneof && oFields[*field.OneofIndex] == nil {
2247			odp := message.OneofDecl[int(*field.OneofIndex)]
2248			base := CamelCase(odp.GetName())
2249			fname := allocNames(base)[0]
2250
2251			// This is the first field of a oneof we haven't seen before.
2252			// Generate the union field.
2253			oneofFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageOneofPath, *field.OneofIndex)
2254			c, ok := g.makeComments(oneofFullPath)
2255			if ok {
2256				c += "\n//\n"
2257			}
2258			c += "// Types that are valid to be assigned to " + fname + ":\n"
2259			// Generate the rest of this comment later,
2260			// when we've computed any disambiguation.
2261
2262			dname := "is" + goTypeName + "_" + fname
2263			tag := `protobuf_oneof:"` + odp.GetName() + `"`
2264			of := oneofField{
2265				fieldCommon: fieldCommon{
2266					goName:     fname,
2267					getterName: "Get" + fname,
2268					goType:     dname,
2269					tags:       tag,
2270					protoName:  odp.GetName(),
2271					fullPath:   oneofFullPath,
2272				},
2273				comment: c,
2274			}
2275			topLevelFields = append(topLevelFields, &of)
2276			oFields[*field.OneofIndex] = &of
2277		}
2278
2279		if *field.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE {
2280			desc := g.ObjectNamed(field.GetTypeName())
2281			if d, ok := desc.(*Descriptor); ok && d.GetOptions().GetMapEntry() {
2282				// Figure out the Go types and tags for the key and value types.
2283				keyField, valField := d.Field[0], d.Field[1]
2284				keyType, keyWire := g.GoType(d, keyField)
2285				valType, valWire := g.GoType(d, valField)
2286				keyTag, valTag := g.goTag(d, keyField, keyWire), g.goTag(d, valField, valWire)
2287
2288				// We don't use stars, except for message-typed values.
2289				// Message and enum types are the only two possibly foreign types used in maps,
2290				// so record their use. They are not permitted as map keys.
2291				keyType = strings.TrimPrefix(keyType, "*")
2292				switch *valField.Type {
2293				case descriptor.FieldDescriptorProto_TYPE_ENUM:
2294					valType = strings.TrimPrefix(valType, "*")
2295					g.RecordTypeUse(valField.GetTypeName())
2296				case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2297					g.RecordTypeUse(valField.GetTypeName())
2298				default:
2299					valType = strings.TrimPrefix(valType, "*")
2300				}
2301
2302				typename = fmt.Sprintf("map[%s]%s", keyType, valType)
2303				mapFieldTypes[field] = typename // record for the getter generation
2304
2305				tag += fmt.Sprintf(" protobuf_key:%s protobuf_val:%s", keyTag, valTag)
2306			}
2307		}
2308
2309		fieldDeprecated := ""
2310		if field.GetOptions().GetDeprecated() {
2311			fieldDeprecated = deprecationComment
2312		}
2313
2314		dvalue := g.getterDefault(field, goTypeName)
2315		if oneof {
2316			tname := goTypeName + "_" + fieldName
2317			// It is possible for this to collide with a message or enum
2318			// nested in this message. Check for collisions.
2319			for {
2320				ok := true
2321				for _, desc := range message.nested {
2322					if CamelCaseSlice(desc.TypeName()) == tname {
2323						ok = false
2324						break
2325					}
2326				}
2327				for _, enum := range message.enums {
2328					if CamelCaseSlice(enum.TypeName()) == tname {
2329						ok = false
2330						break
2331					}
2332				}
2333				if !ok {
2334					tname += "_"
2335					continue
2336				}
2337				break
2338			}
2339
2340			oneofField := oFields[*field.OneofIndex]
2341			tag := "protobuf:" + g.goTag(message, field, wiretype)
2342			sf := oneofSubField{
2343				fieldCommon: fieldCommon{
2344					goName:     fieldName,
2345					getterName: fieldGetterName,
2346					goType:     typename,
2347					tags:       tag,
2348					protoName:  field.GetName(),
2349					fullPath:   fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i),
2350				},
2351				protoTypeName: field.GetTypeName(),
2352				fieldNumber:   int(*field.Number),
2353				protoType:     *field.Type,
2354				getterDef:     dvalue,
2355				protoDef:      field.GetDefaultValue(),
2356				oneofTypeName: tname,
2357				deprecated:    fieldDeprecated,
2358			}
2359			oneofField.subFields = append(oneofField.subFields, &sf)
2360			g.RecordTypeUse(field.GetTypeName())
2361			continue
2362		}
2363
2364		fieldFullPath := fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i)
2365		c, ok := g.makeComments(fieldFullPath)
2366		if ok {
2367			c += "\n"
2368		}
2369		rf := simpleField{
2370			fieldCommon: fieldCommon{
2371				goName:     fieldName,
2372				getterName: fieldGetterName,
2373				goType:     typename,
2374				tags:       tag,
2375				protoName:  field.GetName(),
2376				fullPath:   fieldFullPath,
2377			},
2378			protoTypeName: field.GetTypeName(),
2379			protoType:     *field.Type,
2380			deprecated:    fieldDeprecated,
2381			getterDef:     dvalue,
2382			protoDef:      field.GetDefaultValue(),
2383			comment:       c,
2384		}
2385		var pf topLevelField = &rf
2386
2387		topLevelFields = append(topLevelFields, pf)
2388		g.RecordTypeUse(field.GetTypeName())
2389	}
2390
2391	mc := &msgCtx{
2392		goName:  goTypeName,
2393		message: message,
2394	}
2395
2396	g.generateMessageStruct(mc, topLevelFields)
2397	g.P()
2398	g.generateCommonMethods(mc)
2399	g.P()
2400	g.generateDefaultConstants(mc, topLevelFields)
2401	g.P()
2402	g.generateGetters(mc, topLevelFields)
2403	g.P()
2404	g.generateSetters(mc, topLevelFields)
2405	g.P()
2406	g.generateOneofFuncs(mc, topLevelFields)
2407	g.P()
2408
2409	var oneofTypes []string
2410	for _, f := range topLevelFields {
2411		if of, ok := f.(*oneofField); ok {
2412			for _, osf := range of.subFields {
2413				oneofTypes = append(oneofTypes, osf.oneofTypeName)
2414			}
2415		}
2416	}
2417
2418	opts := message.Options
2419	ms := &messageSymbol{
2420		sym:           goTypeName,
2421		hasExtensions: len(message.ExtensionRange) > 0,
2422		isMessageSet:  opts != nil && opts.GetMessageSetWireFormat(),
2423		oneofTypes:    oneofTypes,
2424	}
2425	g.file.addExport(message, ms)
2426
2427	for _, ext := range message.ext {
2428		g.generateExtension(ext)
2429	}
2430
2431	fullName := strings.Join(message.TypeName(), ".")
2432	if g.file.Package != nil {
2433		fullName = *g.file.Package + "." + fullName
2434	}
2435
2436	g.addInitf("%s.RegisterType((*%s)(nil), %q)", g.Pkg["proto"], goTypeName, fullName)
2437	// Register types for native map types.
2438	for _, k := range mapFieldKeys(mapFieldTypes) {
2439		fullName := strings.TrimPrefix(*k.TypeName, ".")
2440		g.addInitf("%s.RegisterMapType((%s)(nil), %q)", g.Pkg["proto"], mapFieldTypes[k], fullName)
2441	}
2442
2443}
2444
2445type byTypeName []*descriptor.FieldDescriptorProto
2446
2447func (a byTypeName) Len() int           { return len(a) }
2448func (a byTypeName) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
2449func (a byTypeName) Less(i, j int) bool { return *a[i].TypeName < *a[j].TypeName }
2450
2451// mapFieldKeys returns the keys of m in a consistent order.
2452func mapFieldKeys(m map[*descriptor.FieldDescriptorProto]string) []*descriptor.FieldDescriptorProto {
2453	keys := make([]*descriptor.FieldDescriptorProto, 0, len(m))
2454	for k := range m {
2455		keys = append(keys, k)
2456	}
2457	sort.Sort(byTypeName(keys))
2458	return keys
2459}
2460
2461var escapeChars = [256]byte{
2462	'a': '\a', 'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t', 'v': '\v', '\\': '\\', '"': '"', '\'': '\'', '?': '?',
2463}
2464
2465// unescape reverses the "C" escaping that protoc does for default values of bytes fields.
2466// It is best effort in that it effectively ignores malformed input. Seemingly invalid escape
2467// sequences are conveyed, unmodified, into the decoded result.
2468func unescape(s string) string {
2469	// NB: Sadly, we can't use strconv.Unquote because protoc will escape both
2470	// single and double quotes, but strconv.Unquote only allows one or the
2471	// other (based on actual surrounding quotes of its input argument).
2472
2473	var out []byte
2474	for len(s) > 0 {
2475		// regular character, or too short to be valid escape
2476		if s[0] != '\\' || len(s) < 2 {
2477			out = append(out, s[0])
2478			s = s[1:]
2479		} else if c := escapeChars[s[1]]; c != 0 {
2480			// escape sequence
2481			out = append(out, c)
2482			s = s[2:]
2483		} else if s[1] == 'x' || s[1] == 'X' {
2484			// hex escape, e.g. "\x80
2485			if len(s) < 4 {
2486				// too short to be valid
2487				out = append(out, s[:2]...)
2488				s = s[2:]
2489				continue
2490			}
2491			v, err := strconv.ParseUint(s[2:4], 16, 8)
2492			if err != nil {
2493				out = append(out, s[:4]...)
2494			} else {
2495				out = append(out, byte(v))
2496			}
2497			s = s[4:]
2498		} else if '0' <= s[1] && s[1] <= '7' {
2499			// octal escape, can vary from 1 to 3 octal digits; e.g., "\0" "\40" or "\164"
2500			// so consume up to 2 more bytes or up to end-of-string
2501			n := len(s[1:]) - len(strings.TrimLeft(s[1:], "01234567"))
2502			if n > 3 {
2503				n = 3
2504			}
2505			v, err := strconv.ParseUint(s[1:1+n], 8, 8)
2506			if err != nil {
2507				out = append(out, s[:1+n]...)
2508			} else {
2509				out = append(out, byte(v))
2510			}
2511			s = s[1+n:]
2512		} else {
2513			// bad escape, just propagate the slash as-is
2514			out = append(out, s[0])
2515			s = s[1:]
2516		}
2517	}
2518
2519	return string(out)
2520}
2521
2522func (g *Generator) generateExtension(ext *ExtensionDescriptor) {
2523	ccTypeName := ext.DescName()
2524
2525	extObj := g.ObjectNamed(*ext.Extendee)
2526	var extDesc *Descriptor
2527	if id, ok := extObj.(*ImportedDescriptor); ok {
2528		// This is extending a publicly imported message.
2529		// We need the underlying type for goTag.
2530		extDesc = id.o.(*Descriptor)
2531	} else {
2532		extDesc = extObj.(*Descriptor)
2533	}
2534	extendedType := "*" + g.TypeName(extObj) // always use the original
2535	field := ext.FieldDescriptorProto
2536	fieldType, wireType := g.GoType(ext.parent, field)
2537	tag := g.goTag(extDesc, field, wireType)
2538	g.RecordTypeUse(*ext.Extendee)
2539	if n := ext.FieldDescriptorProto.TypeName; n != nil {
2540		// foreign extension type
2541		g.RecordTypeUse(*n)
2542	}
2543
2544	typeName := ext.TypeName()
2545
2546	// Special case for proto2 message sets: If this extension is extending
2547	// proto2.bridge.MessageSet, and its final name component is "message_set_extension",
2548	// then drop that last component.
2549	//
2550	// TODO: This should be implemented in the text formatter rather than the generator.
2551	// In addition, the situation for when to apply this special case is implemented
2552	// differently in other languages:
2553	// https://github.com/google/protobuf/blob/aff10976/src/google/protobuf/text_format.cc#L1560
2554	if extDesc.GetOptions().GetMessageSetWireFormat() && typeName[len(typeName)-1] == "message_set_extension" {
2555		typeName = typeName[:len(typeName)-1]
2556	}
2557
2558	// For text formatting, the package must be exactly what the .proto file declares,
2559	// ignoring overrides such as the go_package option, and with no dot/underscore mapping.
2560	extName := strings.Join(typeName, ".")
2561	if g.file.Package != nil {
2562		extName = *g.file.Package + "." + extName
2563	}
2564
2565	g.P("var ", ccTypeName, " = &", g.Pkg["proto"], ".ExtensionDesc{")
2566	g.P("ExtendedType: (", extendedType, ")(nil),")
2567	g.P("ExtensionType: (", fieldType, ")(nil),")
2568	g.P("Field: ", field.Number, ",")
2569	g.P(`Name: "`, extName, `",`)
2570	g.P("Tag: ", tag, ",")
2571	g.P(`Filename: "`, g.file.GetName(), `",`)
2572
2573	g.P("}")
2574	g.P()
2575
2576	g.addInitf("%s.RegisterExtension(%s)", g.Pkg["proto"], ext.DescName())
2577
2578	g.file.addExport(ext, constOrVarSymbol{ccTypeName, "var", ""})
2579}
2580
2581func (g *Generator) generateInitFunction() {
2582	if len(g.init) == 0 {
2583		return
2584	}
2585	g.P("func init() {")
2586	for _, l := range g.init {
2587		g.P(l)
2588	}
2589	g.P("}")
2590	g.init = nil
2591}
2592
2593func (g *Generator) generateFileDescriptor(file *FileDescriptor) {
2594	// Make a copy and trim source_code_info data.
2595	// TODO: Trim this more when we know exactly what we need.
2596	pb := proto.Clone(file.FileDescriptorProto).(*descriptor.FileDescriptorProto)
2597	pb.SourceCodeInfo = nil
2598
2599	b, err := proto.Marshal(pb)
2600	if err != nil {
2601		g.Fail(err.Error())
2602	}
2603
2604	var buf bytes.Buffer
2605	w, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression)
2606	w.Write(b)
2607	w.Close()
2608	b = buf.Bytes()
2609
2610	v := file.VarName()
2611	g.P()
2612	g.P("func init() {")
2613	g.P(g.Pkg["proto"], ".RegisterFile(", strconv.Quote(*file.Name), ", ", v, ")")
2614	g.P("}")
2615	g.P("var ", v, " = []byte{")
2616	g.P("// ", len(b), " bytes of a gzipped FileDescriptorProto")
2617	for len(b) > 0 {
2618		n := 16
2619		if n > len(b) {
2620			n = len(b)
2621		}
2622
2623		s := ""
2624		for _, c := range b[:n] {
2625			s += fmt.Sprintf("0x%02x,", c)
2626		}
2627		g.P(s)
2628
2629		b = b[n:]
2630	}
2631	g.P("}")
2632}
2633
2634func (g *Generator) generateEnumRegistration(enum *EnumDescriptor) {
2635	// // We always print the full (proto-world) package name here.
2636	pkg := enum.File().GetPackage()
2637	if pkg != "" {
2638		pkg += "."
2639	}
2640	// The full type name
2641	typeName := enum.TypeName()
2642	// The full type name, CamelCased.
2643	ccTypeName := CamelCaseSlice(typeName)
2644	g.addInitf("%s.RegisterEnum(%q, %[3]s_name, %[3]s_value)", g.Pkg["proto"], pkg+ccTypeName, ccTypeName)
2645}
2646
2647// And now lots of helper functions.
2648
2649// Is c an ASCII lower-case letter?
2650func isASCIILower(c byte) bool {
2651	return 'a' <= c && c <= 'z'
2652}
2653
2654// Is c an ASCII digit?
2655func isASCIIDigit(c byte) bool {
2656	return '0' <= c && c <= '9'
2657}
2658
2659// CamelCase returns the CamelCased name.
2660// If there is an interior underscore followed by a lower case letter,
2661// drop the underscore and convert the letter to upper case.
2662// There is a remote possibility of this rewrite causing a name collision,
2663// but it's so remote we're prepared to pretend it's nonexistent - since the
2664// C++ generator lowercases names, it's extremely unlikely to have two fields
2665// with different capitalizations.
2666// In short, _my_field_name_2 becomes XMyFieldName_2.
2667func CamelCase(s string) string {
2668	if s == "" {
2669		return ""
2670	}
2671	t := make([]byte, 0, 32)
2672	i := 0
2673	if s[0] == '_' {
2674		// Need a capital letter; drop the '_'.
2675		t = append(t, 'X')
2676		i++
2677	}
2678	// Invariant: if the next letter is lower case, it must be converted
2679	// to upper case.
2680	// That is, we process a word at a time, where words are marked by _ or
2681	// upper case letter. Digits are treated as words.
2682	for ; i < len(s); i++ {
2683		c := s[i]
2684		if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) {
2685			continue // Skip the underscore in s.
2686		}
2687		if isASCIIDigit(c) {
2688			t = append(t, c)
2689			continue
2690		}
2691		// Assume we have a letter now - if not, it's a bogus identifier.
2692		// The next word is a sequence of characters that must start upper case.
2693		if isASCIILower(c) {
2694			c ^= ' ' // Make it a capital letter.
2695		}
2696		t = append(t, c) // Guaranteed not lower case.
2697		// Accept lower case sequence that follows.
2698		for i+1 < len(s) && isASCIILower(s[i+1]) {
2699			i++
2700			t = append(t, s[i])
2701		}
2702	}
2703	return string(t)
2704}
2705
2706// CamelCaseSlice is like CamelCase, but the argument is a slice of strings to
2707// be joined with "_".
2708func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) }
2709
2710// dottedSlice turns a sliced name into a dotted name.
2711func dottedSlice(elem []string) string { return strings.Join(elem, ".") }
2712
2713// Is this field optional?
2714func isOptional(field *descriptor.FieldDescriptorProto) bool {
2715	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_OPTIONAL
2716}
2717
2718// Is this field required?
2719func isRequired(field *descriptor.FieldDescriptorProto) bool {
2720	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REQUIRED
2721}
2722
2723// Is this field repeated?
2724func isRepeated(field *descriptor.FieldDescriptorProto) bool {
2725	return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED
2726}
2727
2728// Is this field a scalar numeric type?
2729func isScalar(field *descriptor.FieldDescriptorProto) bool {
2730	if field.Type == nil {
2731		return false
2732	}
2733	switch *field.Type {
2734	case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
2735		descriptor.FieldDescriptorProto_TYPE_FLOAT,
2736		descriptor.FieldDescriptorProto_TYPE_INT64,
2737		descriptor.FieldDescriptorProto_TYPE_UINT64,
2738		descriptor.FieldDescriptorProto_TYPE_INT32,
2739		descriptor.FieldDescriptorProto_TYPE_FIXED64,
2740		descriptor.FieldDescriptorProto_TYPE_FIXED32,
2741		descriptor.FieldDescriptorProto_TYPE_BOOL,
2742		descriptor.FieldDescriptorProto_TYPE_UINT32,
2743		descriptor.FieldDescriptorProto_TYPE_ENUM,
2744		descriptor.FieldDescriptorProto_TYPE_SFIXED32,
2745		descriptor.FieldDescriptorProto_TYPE_SFIXED64,
2746		descriptor.FieldDescriptorProto_TYPE_SINT32,
2747		descriptor.FieldDescriptorProto_TYPE_SINT64:
2748		return true
2749	default:
2750		return false
2751	}
2752}
2753
2754// badToUnderscore is the mapping function used to generate Go names from package names,
2755// which can be dotted in the input .proto file.  It replaces non-identifier characters such as
2756// dot or dash with underscore.
2757func badToUnderscore(r rune) rune {
2758	if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' {
2759		return r
2760	}
2761	return '_'
2762}
2763
2764// baseName returns the last path element of the name, with the last dotted suffix removed.
2765func baseName(name string) string {
2766	// First, find the last element
2767	if i := strings.LastIndex(name, "/"); i >= 0 {
2768		name = name[i+1:]
2769	}
2770	// Now drop the suffix
2771	if i := strings.LastIndex(name, "."); i >= 0 {
2772		name = name[0:i]
2773	}
2774	return name
2775}
2776
2777// The SourceCodeInfo message describes the location of elements of a parsed
2778// .proto file by way of a "path", which is a sequence of integers that
2779// describe the route from a FileDescriptorProto to the relevant submessage.
2780// The path alternates between a field number of a repeated field, and an index
2781// into that repeated field. The constants below define the field numbers that
2782// are used.
2783//
2784// See descriptor.proto for more information about this.
2785const (
2786	// tag numbers in FileDescriptorProto
2787	packagePath = 2 // package
2788	messagePath = 4 // message_type
2789	enumPath    = 5 // enum_type
2790	// tag numbers in DescriptorProto
2791	messageFieldPath   = 2 // field
2792	messageMessagePath = 3 // nested_type
2793	messageEnumPath    = 4 // enum_type
2794	messageOneofPath   = 8 // oneof_decl
2795	// tag numbers in EnumDescriptorProto
2796	enumValuePath = 2 // value
2797)
2798
2799var supportTypeAliases bool
2800
2801func init() {
2802	for _, tag := range build.Default.ReleaseTags {
2803		if tag == "go1.9" {
2804			supportTypeAliases = true
2805			return
2806		}
2807	}
2808}
2809