1 // Go support for Protocol Buffers - Google's data interchange format
3 // Copyright 2010 The Go Authors. All rights reserved.
4 // https://github.com/golang/protobuf
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are
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
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.
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.
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
55 "github.com/golang/protobuf/proto"
57 "github.com/golang/protobuf/protoc-gen-go/descriptor"
58 plugin "github.com/golang/protobuf/protoc-gen-go/plugin"
61 // generatedCodeVersion indicates a version of the generated code.
62 // It is incremented whenever an incompatibility between the generated code and
63 // proto package is introduced; the generated code references
64 // a constant, proto.ProtoPackageIsVersionN (where N is generatedCodeVersion).
65 const generatedCodeVersion = 2
67 // A Plugin provides functionality to add to the output during Go code generation,
68 // such as to produce RPC stubs.
69 type Plugin interface {
70 // Name identifies the plugin.
72 // Init is called once after data structures are built but before
73 // code generation begins.
75 // Generate produces the code generated by the plugin for this file,
76 // except for the imports, by calling the generator's methods P, In, and Out.
77 Generate(file *FileDescriptor)
78 // GenerateImports produces the import declarations for this file.
79 // It is called after Generate.
80 GenerateImports(file *FileDescriptor)
85 // RegisterPlugin installs a (second-order) plugin to be run when the Go output is generated.
86 // It is typically called during initialization.
87 func RegisterPlugin(p Plugin) {
88 plugins = append(plugins, p)
91 // Each type we import as a protocol buffer (other than FileDescriptorProto) needs
92 // a pointer to the FileDescriptorProto that represents it. These types achieve that
93 // wrapping by placing each Proto inside a struct with the pointer to its File. The
94 // structs have the same names as their contents, with "Proto" removed.
95 // FileDescriptor is used to store the things that it points to.
97 // The file and package name method are common to messages and enums.
99 file *descriptor.FileDescriptorProto // File this object comes from.
102 // PackageName is name in the package clause in the generated file.
103 func (c *common) PackageName() string { return uniquePackageOf(c.file) }
105 func (c *common) File() *descriptor.FileDescriptorProto { return c.file }
107 func fileIsProto3(file *descriptor.FileDescriptorProto) bool {
108 return file.GetSyntax() == "proto3"
111 func (c *common) proto3() bool { return fileIsProto3(c.file) }
113 // Descriptor represents a protocol buffer message.
114 type Descriptor struct {
116 *descriptor.DescriptorProto
117 parent *Descriptor // The containing message, if any.
118 nested []*Descriptor // Inner messages, if any.
119 enums []*EnumDescriptor // Inner enums, if any.
120 ext []*ExtensionDescriptor // Extensions, if any.
121 typename []string // Cached typename vector.
122 index int // The index into the container, whether the file or another message.
123 path string // The SourceCodeInfo path as comma-separated integers.
127 // TypeName returns the elements of the dotted type name.
128 // The package name is not part of this name.
129 func (d *Descriptor) TypeName() []string {
130 if d.typename != nil {
134 for parent := d; parent != nil; parent = parent.parent {
137 s := make([]string, n, n)
138 for parent := d; parent != nil; parent = parent.parent {
140 s[n] = parent.GetName()
146 // EnumDescriptor describes an enum. If it's at top level, its parent will be nil.
147 // Otherwise it will be the descriptor of the message in which it is defined.
148 type EnumDescriptor struct {
150 *descriptor.EnumDescriptorProto
151 parent *Descriptor // The containing message, if any.
152 typename []string // Cached typename vector.
153 index int // The index into the container, whether the file or a message.
154 path string // The SourceCodeInfo path as comma-separated integers.
157 // TypeName returns the elements of the dotted type name.
158 // The package name is not part of this name.
159 func (e *EnumDescriptor) TypeName() (s []string) {
160 if e.typename != nil {
165 s = make([]string, 1)
167 pname := e.parent.TypeName()
168 s = make([]string, len(pname)+1)
176 // Everything but the last element of the full type name, CamelCased.
177 // The values of type Foo.Bar are call Foo_value1... not Foo_Bar_value1... .
178 func (e *EnumDescriptor) prefix() string {
180 // If the enum is not part of a message, the prefix is just the type name.
181 return CamelCase(*e.Name) + "_"
183 typeName := e.TypeName()
184 return CamelCaseSlice(typeName[0:len(typeName)-1]) + "_"
187 // The integer value of the named constant in this enumerated type.
188 func (e *EnumDescriptor) integerValueAsString(name string) string {
189 for _, c := range e.Value {
190 if c.GetName() == name {
191 return fmt.Sprint(c.GetNumber())
194 log.Fatal("cannot find value for enum constant")
198 // ExtensionDescriptor describes an extension. If it's at top level, its parent will be nil.
199 // Otherwise it will be the descriptor of the message in which it is defined.
200 type ExtensionDescriptor struct {
202 *descriptor.FieldDescriptorProto
203 parent *Descriptor // The containing message, if any.
206 // TypeName returns the elements of the dotted type name.
207 // The package name is not part of this name.
208 func (e *ExtensionDescriptor) TypeName() (s []string) {
211 // top-level extension
212 s = make([]string, 1)
214 pname := e.parent.TypeName()
215 s = make([]string, len(pname)+1)
222 // DescName returns the variable name used for the generated descriptor.
223 func (e *ExtensionDescriptor) DescName() string {
224 // The full type name.
225 typeName := e.TypeName()
226 // Each scope of the extension is individually CamelCased, and all are joined with "_" with an "E_" prefix.
227 for i, s := range typeName {
228 typeName[i] = CamelCase(s)
230 return "E_" + strings.Join(typeName, "_")
233 // ImportedDescriptor describes a type that has been publicly imported from another file.
234 type ImportedDescriptor struct {
239 func (id *ImportedDescriptor) TypeName() []string { return id.o.TypeName() }
241 // FileDescriptor describes an protocol buffer descriptor file (.proto).
242 // It includes slices of all the messages and enums defined within it.
243 // Those slices are constructed by WrapTypes.
244 type FileDescriptor struct {
245 *descriptor.FileDescriptorProto
246 desc []*Descriptor // All the messages defined in this file.
247 enum []*EnumDescriptor // All the enums defined in this file.
248 ext []*ExtensionDescriptor // All the top-level extensions defined in this file.
249 imp []*ImportedDescriptor // All types defined in files publicly imported by this file.
251 // Comments, stored as a map of path (comma-separated integers) to the comment.
252 comments map[string]*descriptor.SourceCodeInfo_Location
254 // The full list of symbols that are exported,
255 // as a map from the exported object to its symbols.
256 // This is used for supporting public imports.
257 exported map[Object][]symbol
259 index int // The index of this file in the list of files to generate code for
261 proto3 bool // whether to generate proto3 code for this file
264 // PackageName is the package name we'll use in the generated code to refer to this file.
265 func (d *FileDescriptor) PackageName() string { return uniquePackageOf(d.FileDescriptorProto) }
267 // VarName is the variable name we'll use in the generated code to refer
268 // to the compressed bytes of this descriptor. It is not exported, so
269 // it is only valid inside the generated package.
270 func (d *FileDescriptor) VarName() string { return fmt.Sprintf("fileDescriptor%d", d.index) }
272 // goPackageOption interprets the file's go_package option.
273 // If there is no go_package, it returns ("", "", false).
274 // If there's a simple name, it returns ("", pkg, true).
275 // If the option implies an import path, it returns (impPath, pkg, true).
276 func (d *FileDescriptor) goPackageOption() (impPath, pkg string, ok bool) {
277 pkg = d.GetOptions().GetGoPackage()
282 // The presence of a slash implies there's an import path.
283 slash := strings.LastIndex(pkg, "/")
287 impPath, pkg = pkg, pkg[slash+1:]
288 // A semicolon-delimited suffix overrides the package name.
289 sc := strings.IndexByte(impPath, ';')
293 impPath, pkg = impPath[:sc], impPath[sc+1:]
297 // goPackageName returns the Go package name to use in the
298 // generated Go file. The result explicit reports whether the name
299 // came from an option go_package statement. If explicit is false,
300 // the name was derived from the protocol buffer's package statement
301 // or the input file name.
302 func (d *FileDescriptor) goPackageName() (name string, explicit bool) {
303 // Does the file have a "go_package" option?
304 if _, pkg, ok := d.goPackageOption(); ok {
308 // Does the file have a package clause?
309 if pkg := d.GetPackage(); pkg != "" {
312 // Use the file base name.
313 return baseName(d.GetName()), false
316 // goFileName returns the output name for the generated Go file.
317 func (d *FileDescriptor) goFileName() string {
319 if ext := path.Ext(name); ext == ".proto" || ext == ".protodevel" {
320 name = name[:len(name)-len(ext)]
324 // Does the file have a "go_package" option?
325 // If it does, it may override the filename.
326 if impPath, _, ok := d.goPackageOption(); ok && impPath != "" {
327 // Replace the existing dirname with the declared import path.
328 _, name = path.Split(name)
329 name = path.Join(impPath, name)
336 func (d *FileDescriptor) addExport(obj Object, sym symbol) {
337 d.exported[obj] = append(d.exported[obj], sym)
340 // symbol is an interface representing an exported Go symbol.
341 type symbol interface {
342 // GenerateAlias should generate an appropriate alias
343 // for the symbol from the named package.
344 GenerateAlias(g *Generator, pkg string)
347 type messageSymbol struct {
349 hasExtensions, isMessageSet bool
351 getters []getterSymbol
354 type getterSymbol struct {
357 typeName string // canonical name in proto world; empty for proto.Message and similar
358 genType bool // whether typ contains a generated type (message/group/enum)
361 func (ms *messageSymbol) GenerateAlias(g *Generator, pkg string) {
362 remoteSym := pkg + "." + ms.sym
364 g.P("type ", ms.sym, " ", remoteSym)
365 g.P("func (m *", ms.sym, ") Reset() { (*", remoteSym, ")(m).Reset() }")
366 g.P("func (m *", ms.sym, ") String() string { return (*", remoteSym, ")(m).String() }")
367 g.P("func (*", ms.sym, ") ProtoMessage() {}")
368 if ms.hasExtensions {
369 g.P("func (*", ms.sym, ") ExtensionRangeArray() []", g.Pkg["proto"], ".ExtensionRange ",
370 "{ return (*", remoteSym, ")(nil).ExtensionRangeArray() }")
372 g.P("func (m *", ms.sym, ") Marshal() ([]byte, error) ",
373 "{ return (*", remoteSym, ")(m).Marshal() }")
374 g.P("func (m *", ms.sym, ") Unmarshal(buf []byte) error ",
375 "{ return (*", remoteSym, ")(m).Unmarshal(buf) }")
379 // Oneofs and public imports do not mix well.
380 // We can make them work okay for the binary format,
381 // but they're going to break weirdly for text/JSON.
382 enc := "_" + ms.sym + "_OneofMarshaler"
383 dec := "_" + ms.sym + "_OneofUnmarshaler"
384 size := "_" + ms.sym + "_OneofSizer"
385 encSig := "(msg " + g.Pkg["proto"] + ".Message, b *" + g.Pkg["proto"] + ".Buffer) error"
386 decSig := "(msg " + g.Pkg["proto"] + ".Message, tag, wire int, b *" + g.Pkg["proto"] + ".Buffer) (bool, error)"
387 sizeSig := "(msg " + g.Pkg["proto"] + ".Message) int"
388 g.P("func (m *", ms.sym, ") XXX_OneofFuncs() (func", encSig, ", func", decSig, ", func", sizeSig, ", []interface{}) {")
389 g.P("return ", enc, ", ", dec, ", ", size, ", nil")
392 g.P("func ", enc, encSig, " {")
393 g.P("m := msg.(*", ms.sym, ")")
394 g.P("m0 := (*", remoteSym, ")(m)")
395 g.P("enc, _, _, _ := m0.XXX_OneofFuncs()")
396 g.P("return enc(m0, b)")
399 g.P("func ", dec, decSig, " {")
400 g.P("m := msg.(*", ms.sym, ")")
401 g.P("m0 := (*", remoteSym, ")(m)")
402 g.P("_, dec, _, _ := m0.XXX_OneofFuncs()")
403 g.P("return dec(m0, tag, wire, b)")
406 g.P("func ", size, sizeSig, " {")
407 g.P("m := msg.(*", ms.sym, ")")
408 g.P("m0 := (*", remoteSym, ")(m)")
409 g.P("_, _, size, _ := m0.XXX_OneofFuncs()")
410 g.P("return size(m0)")
413 for _, get := range ms.getters {
415 if get.typeName != "" {
416 g.RecordTypeUse(get.typeName)
419 val := "(*" + remoteSym + ")(m)." + get.name + "()"
421 // typ will be "*pkg.T" (message/group) or "pkg.T" (enum)
422 // or "map[t]*pkg.T" (map to message/enum).
423 // The first two of those might have a "[]" prefix if it is repeated.
424 // Drop any package qualifier since we have hoisted the type into this package.
425 rep := strings.HasPrefix(typ, "[]")
429 isMap := strings.HasPrefix(typ, "map[")
430 star := typ[0] == '*'
431 if !isMap { // map types handled lower down
432 typ = typ[strings.Index(typ, ".")+1:]
438 // Go does not permit conversion between slice types where both
439 // element types are named. That means we need to generate a bit
440 // of code in this situation.
441 // typ is the element type.
442 // val is the expression to get the slice from the imported type.
444 ctyp := typ // conversion type expression; "Foo" or "(*Foo)"
446 ctyp = "(" + typ + ")"
449 g.P("func (m *", ms.sym, ") ", get.name, "() []", typ, " {")
457 g.P("s := make([]", typ, ", len(o))")
458 g.P("for i, x := range o {")
460 g.P("s[i] = ", ctyp, "(x)")
469 // Split map[keyTyp]valTyp.
470 bra, ket := strings.Index(typ, "["), strings.Index(typ, "]")
471 keyTyp, valTyp := typ[bra+1:ket], typ[ket+1:]
472 // Drop any package qualifier.
473 // Only the value type may be foreign.
474 star := valTyp[0] == '*'
475 valTyp = valTyp[strings.Index(valTyp, ".")+1:]
477 valTyp = "*" + valTyp
480 typ := "map[" + keyTyp + "]" + valTyp
481 g.P("func (m *", ms.sym, ") ", get.name, "() ", typ, " {")
483 g.P("if o == nil { return nil }")
484 g.P("s := make(", typ, ", len(o))")
485 g.P("for k, v := range o {")
486 g.P("s[k] = (", valTyp, ")(v)")
492 // Convert imported type into the forwarding type.
493 val = "(" + typ + ")(" + val + ")"
496 g.P("func (m *", ms.sym, ") ", get.name, "() ", typ, " { return ", val, " }")
501 type enumSymbol struct {
503 proto3 bool // Whether this came from a proto3 file.
506 func (es enumSymbol) GenerateAlias(g *Generator, pkg string) {
508 g.P("type ", s, " ", pkg, ".", s)
509 g.P("var ", s, "_name = ", pkg, ".", s, "_name")
510 g.P("var ", s, "_value = ", pkg, ".", s, "_value")
511 g.P("func (x ", s, ") String() string { return (", pkg, ".", s, ")(x).String() }")
513 g.P("func (x ", s, ") Enum() *", s, "{ return (*", s, ")((", pkg, ".", s, ")(x).Enum()) }")
514 g.P("func (x *", s, ") UnmarshalJSON(data []byte) error { return (*", pkg, ".", s, ")(x).UnmarshalJSON(data) }")
518 type constOrVarSymbol struct {
520 typ string // either "const" or "var"
521 cast string // if non-empty, a type cast is required (used for enums)
524 func (cs constOrVarSymbol) GenerateAlias(g *Generator, pkg string) {
525 v := pkg + "." + cs.sym
527 v = cs.cast + "(" + v + ")"
529 g.P(cs.typ, " ", cs.sym, " = ", v)
532 // Object is an interface abstracting the abilities shared by enums, messages, extensions and imported objects.
533 type Object interface {
534 PackageName() string // The name we use in our output (a_b_c), possibly renamed for uniqueness.
536 File() *descriptor.FileDescriptorProto
539 // Each package name we generate must be unique. The package we're generating
540 // gets its own name but every other package must have a unique name that does
541 // not conflict in the code we generate. These names are chosen globally (although
542 // they don't have to be, it simplifies things to do them globally).
543 func uniquePackageOf(fd *descriptor.FileDescriptorProto) string {
544 s, ok := uniquePackageName[fd]
546 log.Fatal("internal error: no package name defined for " + fd.GetName())
551 // Generator is the type whose methods generate the output, stored in the associated response structure.
552 type Generator struct {
555 Request *plugin.CodeGeneratorRequest // The input.
556 Response *plugin.CodeGeneratorResponse // The output.
558 Param map[string]string // Command-line parameters.
559 PackageImportPath string // Go import path of the package we're generating code for
560 ImportPrefix string // String to prefix to imported package file names.
561 ImportMap map[string]string // Mapping from .proto file name to import path
563 Pkg map[string]string // The names under which we import support packages
565 packageName string // What we're calling ourselves.
566 allFiles []*FileDescriptor // All files in the tree
567 allFilesByName map[string]*FileDescriptor // All files by filename.
568 genFiles []*FileDescriptor // Those files we will generate output for.
569 file *FileDescriptor // The file we are compiling now.
570 usedPackages map[string]bool // Names of packages used in current file.
571 typeNameToObject map[string]Object // Key is a fully-qualified name in input syntax.
572 init []string // Lines to emit in the init function.
577 // New creates a new generator and allocates the request and response protobufs.
578 func New() *Generator {
580 g.Buffer = new(bytes.Buffer)
581 g.Request = new(plugin.CodeGeneratorRequest)
582 g.Response = new(plugin.CodeGeneratorResponse)
586 // Error reports a problem, including an error, and exits the program.
587 func (g *Generator) Error(err error, msgs ...string) {
588 s := strings.Join(msgs, " ") + ":" + err.Error()
589 log.Print("protoc-gen-go: error:", s)
593 // Fail reports a problem and exits the program.
594 func (g *Generator) Fail(msgs ...string) {
595 s := strings.Join(msgs, " ")
596 log.Print("protoc-gen-go: error:", s)
600 // CommandLineParameters breaks the comma-separated list of key=value pairs
601 // in the parameter (a member of the request protobuf) into a key/value map.
602 // It then sets file name mappings defined by those entries.
603 func (g *Generator) CommandLineParameters(parameter string) {
604 g.Param = make(map[string]string)
605 for _, p := range strings.Split(parameter, ",") {
606 if i := strings.Index(p, "="); i < 0 {
609 g.Param[p[0:i]] = p[i+1:]
613 g.ImportMap = make(map[string]string)
614 pluginList := "none" // Default list of plugin names to enable (empty means all).
615 for k, v := range g.Param {
617 case "import_prefix":
620 g.PackageImportPath = v
624 if len(k) > 0 && k[0] == 'M' {
625 g.ImportMap[k[1:]] = v
629 if pluginList != "" {
630 // Amend the set of plugins.
631 enabled := make(map[string]bool)
632 for _, name := range strings.Split(pluginList, "+") {
635 var nplugins []Plugin
636 for _, p := range plugins {
637 if enabled[p.Name()] {
638 nplugins = append(nplugins, p)
645 // DefaultPackageName returns the package name printed for the object.
646 // If its file is in a different package, it returns the package name we're using for this file, plus ".".
647 // Otherwise it returns the empty string.
648 func (g *Generator) DefaultPackageName(obj Object) string {
649 pkg := obj.PackageName()
650 if pkg == g.packageName {
656 // For each input file, the unique package name to use, underscored.
657 var uniquePackageName = make(map[*descriptor.FileDescriptorProto]string)
659 // Package names already registered. Key is the name from the .proto file;
660 // value is the name that appears in the generated code.
661 var pkgNamesInUse = make(map[string]bool)
663 // Create and remember a guaranteed unique package name for this file descriptor.
664 // Pkg is the candidate name. If f is nil, it's a builtin package like "proto" and
665 // has no file descriptor.
666 func RegisterUniquePackageName(pkg string, f *FileDescriptor) string {
667 // Convert dots to underscores before finding a unique alias.
668 pkg = strings.Map(badToUnderscore, pkg)
670 for i, orig := 1, pkg; pkgNamesInUse[pkg]; i++ {
671 // It's a duplicate; must rename.
672 pkg = orig + strconv.Itoa(i)
675 pkgNamesInUse[pkg] = true
677 uniquePackageName[f.FileDescriptorProto] = pkg
682 var isGoKeyword = map[string]bool{
710 // defaultGoPackage returns the package name to use,
711 // derived from the import path of the package we're building code for.
712 func (g *Generator) defaultGoPackage() string {
713 p := g.PackageImportPath
714 if i := strings.LastIndex(p, "/"); i >= 0 {
721 p = strings.Map(badToUnderscore, p)
722 // Identifier must not be keyword: insert _.
726 // Identifier must not begin with digit: insert _.
727 if r, _ := utf8.DecodeRuneInString(p); unicode.IsDigit(r) {
733 // SetPackageNames sets the package name for this run.
734 // The package name must agree across all files being generated.
735 // It also defines unique package names for all imported files.
736 func (g *Generator) SetPackageNames() {
737 // Register the name for this package. It will be the first name
738 // registered so is guaranteed to be unmodified.
739 pkg, explicit := g.genFiles[0].goPackageName()
741 // Check all files for an explicit go_package option.
742 for _, f := range g.genFiles {
743 thisPkg, thisExplicit := f.goPackageName()
746 // Let this file's go_package option serve for all input files.
747 pkg, explicit = thisPkg, true
748 } else if thisPkg != pkg {
749 g.Fail("inconsistent package names:", thisPkg, pkg)
754 // If we don't have an explicit go_package option but we have an
755 // import path, use that.
757 p := g.defaultGoPackage()
759 pkg, explicit = p, true
763 // If there was no go_package and no import path to use,
764 // double-check that all the inputs have the same implicit
767 for _, f := range g.genFiles {
768 thisPkg, _ := f.goPackageName()
770 g.Fail("inconsistent package names:", thisPkg, pkg)
775 g.packageName = RegisterUniquePackageName(pkg, g.genFiles[0])
777 // Register the support package names. They might collide with the
778 // name of a package we import.
779 g.Pkg = map[string]string{
780 "fmt": RegisterUniquePackageName("fmt", nil),
781 "math": RegisterUniquePackageName("math", nil),
782 "proto": RegisterUniquePackageName("proto", nil),
786 for _, f := range g.allFiles {
787 for _, genf := range g.genFiles {
789 // In this package already.
790 uniquePackageName[f.FileDescriptorProto] = g.packageName
794 // The file is a dependency, so we want to ignore its go_package option
795 // because that is only relevant for its specific generated output.
796 pkg := f.GetPackage()
798 pkg = baseName(*f.Name)
800 RegisterUniquePackageName(pkg, f)
804 // WrapTypes walks the incoming data, wrapping DescriptorProtos, EnumDescriptorProtos
805 // and FileDescriptorProtos into file-referenced objects within the Generator.
806 // It also creates the list of files to generate and so should be called before GenerateAllFiles.
807 func (g *Generator) WrapTypes() {
808 g.allFiles = make([]*FileDescriptor, 0, len(g.Request.ProtoFile))
809 g.allFilesByName = make(map[string]*FileDescriptor, len(g.allFiles))
810 for _, f := range g.Request.ProtoFile {
811 // We must wrap the descriptors before we wrap the enums
812 descs := wrapDescriptors(f)
813 g.buildNestedDescriptors(descs)
814 enums := wrapEnumDescriptors(f, descs)
815 g.buildNestedEnums(descs, enums)
816 exts := wrapExtensions(f)
817 fd := &FileDescriptor{
818 FileDescriptorProto: f,
822 exported: make(map[Object][]symbol),
823 proto3: fileIsProto3(f),
826 g.allFiles = append(g.allFiles, fd)
827 g.allFilesByName[f.GetName()] = fd
829 for _, fd := range g.allFiles {
830 fd.imp = wrapImported(fd.FileDescriptorProto, g)
833 g.genFiles = make([]*FileDescriptor, 0, len(g.Request.FileToGenerate))
834 for _, fileName := range g.Request.FileToGenerate {
835 fd := g.allFilesByName[fileName]
837 g.Fail("could not find file named", fileName)
839 fd.index = len(g.genFiles)
840 g.genFiles = append(g.genFiles, fd)
844 // Scan the descriptors in this file. For each one, build the slice of nested descriptors
845 func (g *Generator) buildNestedDescriptors(descs []*Descriptor) {
846 for _, desc := range descs {
847 if len(desc.NestedType) != 0 {
848 for _, nest := range descs {
849 if nest.parent == desc {
850 desc.nested = append(desc.nested, nest)
853 if len(desc.nested) != len(desc.NestedType) {
854 g.Fail("internal error: nesting failure for", desc.GetName())
860 func (g *Generator) buildNestedEnums(descs []*Descriptor, enums []*EnumDescriptor) {
861 for _, desc := range descs {
862 if len(desc.EnumType) != 0 {
863 for _, enum := range enums {
864 if enum.parent == desc {
865 desc.enums = append(desc.enums, enum)
868 if len(desc.enums) != len(desc.EnumType) {
869 g.Fail("internal error: enum nesting failure for", desc.GetName())
875 // Construct the Descriptor
876 func newDescriptor(desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) *Descriptor {
878 common: common{file},
879 DescriptorProto: desc,
884 d.path = fmt.Sprintf("%d,%d", messagePath, index)
886 d.path = fmt.Sprintf("%s,%d,%d", parent.path, messageMessagePath, index)
889 // The only way to distinguish a group from a message is whether
890 // the containing message has a TYPE_GROUP field that matches.
892 parts := d.TypeName()
893 if file.Package != nil {
894 parts = append([]string{*file.Package}, parts...)
896 exp := "." + strings.Join(parts, ".")
897 for _, field := range parent.Field {
898 if field.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP && field.GetTypeName() == exp {
905 for _, field := range desc.Extension {
906 d.ext = append(d.ext, &ExtensionDescriptor{common{file}, field, d})
912 // Return a slice of all the Descriptors defined within this file
913 func wrapDescriptors(file *descriptor.FileDescriptorProto) []*Descriptor {
914 sl := make([]*Descriptor, 0, len(file.MessageType)+10)
915 for i, desc := range file.MessageType {
916 sl = wrapThisDescriptor(sl, desc, nil, file, i)
921 // Wrap this Descriptor, recursively
922 func wrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) []*Descriptor {
923 sl = append(sl, newDescriptor(desc, parent, file, index))
925 for i, nested := range desc.NestedType {
926 sl = wrapThisDescriptor(sl, nested, me, file, i)
931 // Construct the EnumDescriptor
932 func newEnumDescriptor(desc *descriptor.EnumDescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) *EnumDescriptor {
933 ed := &EnumDescriptor{
934 common: common{file},
935 EnumDescriptorProto: desc,
940 ed.path = fmt.Sprintf("%d,%d", enumPath, index)
942 ed.path = fmt.Sprintf("%s,%d,%d", parent.path, messageEnumPath, index)
947 // Return a slice of all the EnumDescriptors defined within this file
948 func wrapEnumDescriptors(file *descriptor.FileDescriptorProto, descs []*Descriptor) []*EnumDescriptor {
949 sl := make([]*EnumDescriptor, 0, len(file.EnumType)+10)
951 for i, enum := range file.EnumType {
952 sl = append(sl, newEnumDescriptor(enum, nil, file, i))
954 // Enums within messages. Enums within embedded messages appear in the outer-most message.
955 for _, nested := range descs {
956 for i, enum := range nested.EnumType {
957 sl = append(sl, newEnumDescriptor(enum, nested, file, i))
963 // Return a slice of all the top-level ExtensionDescriptors defined within this file.
964 func wrapExtensions(file *descriptor.FileDescriptorProto) []*ExtensionDescriptor {
965 var sl []*ExtensionDescriptor
966 for _, field := range file.Extension {
967 sl = append(sl, &ExtensionDescriptor{common{file}, field, nil})
972 // Return a slice of all the types that are publicly imported into this file.
973 func wrapImported(file *descriptor.FileDescriptorProto, g *Generator) (sl []*ImportedDescriptor) {
974 for _, index := range file.PublicDependency {
975 df := g.fileByName(file.Dependency[index])
976 for _, d := range df.desc {
977 if d.GetOptions().GetMapEntry() {
980 sl = append(sl, &ImportedDescriptor{common{file}, d})
982 for _, e := range df.enum {
983 sl = append(sl, &ImportedDescriptor{common{file}, e})
985 for _, ext := range df.ext {
986 sl = append(sl, &ImportedDescriptor{common{file}, ext})
992 func extractComments(file *FileDescriptor) {
993 file.comments = make(map[string]*descriptor.SourceCodeInfo_Location)
994 for _, loc := range file.GetSourceCodeInfo().GetLocation() {
995 if loc.LeadingComments == nil {
999 for _, n := range loc.Path {
1000 p = append(p, strconv.Itoa(int(n)))
1002 file.comments[strings.Join(p, ",")] = loc
1006 // BuildTypeNameMap builds the map from fully qualified type names to objects.
1007 // The key names for the map come from the input data, which puts a period at the beginning.
1008 // It should be called after SetPackageNames and before GenerateAllFiles.
1009 func (g *Generator) BuildTypeNameMap() {
1010 g.typeNameToObject = make(map[string]Object)
1011 for _, f := range g.allFiles {
1012 // The names in this loop are defined by the proto world, not us, so the
1013 // package name may be empty. If so, the dotted package name of X will
1014 // be ".X"; otherwise it will be ".pkg.X".
1015 dottedPkg := "." + f.GetPackage()
1016 if dottedPkg != "." {
1019 for _, enum := range f.enum {
1020 name := dottedPkg + dottedSlice(enum.TypeName())
1021 g.typeNameToObject[name] = enum
1023 for _, desc := range f.desc {
1024 name := dottedPkg + dottedSlice(desc.TypeName())
1025 g.typeNameToObject[name] = desc
1030 // ObjectNamed, given a fully-qualified input type name as it appears in the input data,
1031 // returns the descriptor for the message or enum with that name.
1032 func (g *Generator) ObjectNamed(typeName string) Object {
1033 o, ok := g.typeNameToObject[typeName]
1035 g.Fail("can't find object with type", typeName)
1038 // If the file of this object isn't a direct dependency of the current file,
1039 // or in the current file, then this object has been publicly imported into
1040 // a dependency of the current file.
1041 // We should return the ImportedDescriptor object for it instead.
1042 direct := *o.File().Name == *g.file.Name
1044 for _, dep := range g.file.Dependency {
1045 if *g.fileByName(dep).Name == *o.File().Name {
1054 for _, dep := range g.file.Dependency {
1055 df := g.fileByName(*g.fileByName(dep).Name)
1056 for _, td := range df.imp {
1066 log.Printf("protoc-gen-go: WARNING: failed finding publicly imported dependency for %v, used in %v", typeName, *g.file.Name)
1073 // P prints the arguments to the generated output. It handles strings and int32s, plus
1074 // handling indirections because they may be *string, etc.
1075 func (g *Generator) P(str ...interface{}) {
1079 g.WriteString(g.indent)
1080 for _, v := range str {
1081 switch s := v.(type) {
1087 fmt.Fprintf(g, "%t", s)
1089 fmt.Fprintf(g, "%t", *s)
1091 fmt.Fprintf(g, "%d", s)
1093 fmt.Fprintf(g, "%d", *s)
1095 fmt.Fprintf(g, "%d", *s)
1097 fmt.Fprintf(g, "%g", s)
1099 fmt.Fprintf(g, "%g", *s)
1101 g.Fail(fmt.Sprintf("unknown type in printer: %T", v))
1107 // addInitf stores the given statement to be printed inside the file's init function.
1108 // The statement is given as a format specifier and arguments.
1109 func (g *Generator) addInitf(stmt string, a ...interface{}) {
1110 g.init = append(g.init, fmt.Sprintf(stmt, a...))
1113 // In Indents the output one tab stop.
1114 func (g *Generator) In() { g.indent += "\t" }
1116 // Out unindents the output one tab stop.
1117 func (g *Generator) Out() {
1118 if len(g.indent) > 0 {
1119 g.indent = g.indent[1:]
1123 // GenerateAllFiles generates the output for all the files we're outputting.
1124 func (g *Generator) GenerateAllFiles() {
1125 // Initialize the plugins
1126 for _, p := range plugins {
1129 // Generate the output. The generator runs for every file, even the files
1130 // that we don't generate output for, so that we can collate the full list
1131 // of exported symbols to support public imports.
1132 genFileMap := make(map[*FileDescriptor]bool, len(g.genFiles))
1133 for _, file := range g.genFiles {
1134 genFileMap[file] = true
1136 for _, file := range g.allFiles {
1138 g.writeOutput = genFileMap[file]
1143 g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{
1144 Name: proto.String(file.goFileName()),
1145 Content: proto.String(g.String()),
1150 // Run all the plugins associated with the file.
1151 func (g *Generator) runPlugins(file *FileDescriptor) {
1152 for _, p := range plugins {
1157 // FileOf return the FileDescriptor for this FileDescriptorProto.
1158 func (g *Generator) FileOf(fd *descriptor.FileDescriptorProto) *FileDescriptor {
1159 for _, file := range g.allFiles {
1160 if file.FileDescriptorProto == fd {
1164 g.Fail("could not find file in table:", fd.GetName())
1168 // Fill the response protocol buffer with the generated output for all the files we're
1169 // supposed to generate.
1170 func (g *Generator) generate(file *FileDescriptor) {
1171 g.file = g.FileOf(file.FileDescriptorProto)
1172 g.usedPackages = make(map[string]bool)
1174 if g.file.index == 0 {
1175 // For one file in the package, assert version compatibility.
1176 g.P("// This is a compile-time assertion to ensure that this generated file")
1177 g.P("// is compatible with the proto package it is being compiled against.")
1178 g.P("// A compilation error at this line likely means your copy of the")
1179 g.P("// proto package needs to be updated.")
1180 g.P("const _ = ", g.Pkg["proto"], ".ProtoPackageIsVersion", generatedCodeVersion, " // please upgrade the proto package")
1183 for _, td := range g.file.imp {
1184 g.generateImported(td)
1186 for _, enum := range g.file.enum {
1187 g.generateEnum(enum)
1189 for _, desc := range g.file.desc {
1190 // Don't generate virtual messages for maps.
1191 if desc.GetOptions().GetMapEntry() {
1194 g.generateMessage(desc)
1196 for _, ext := range g.file.ext {
1197 g.generateExtension(ext)
1199 g.generateInitFunction()
1201 // Run the plugins before the imports so we know which imports are necessary.
1204 g.generateFileDescriptor(file)
1206 // Generate header and imports last, though they appear first in the output.
1208 g.Buffer = new(bytes.Buffer)
1214 g.Write(rem.Bytes())
1216 // Reformat generated code.
1217 fset := token.NewFileSet()
1219 ast, err := parser.ParseFile(fset, "", g, parser.ParseComments)
1221 // Print out the bad code with line numbers.
1222 // This should never happen in practice, but it can while changing generated code,
1223 // so consider this a debugging aid.
1224 var src bytes.Buffer
1225 s := bufio.NewScanner(bytes.NewReader(raw))
1226 for line := 1; s.Scan(); line++ {
1227 fmt.Fprintf(&src, "%5d\t%s\n", line, s.Bytes())
1229 g.Fail("bad Go source code was generated:", err.Error(), "\n"+src.String())
1232 err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(g, fset, ast)
1234 g.Fail("generated Go source code could not be reformatted:", err.Error())
1238 // Generate the header, including package definition
1239 func (g *Generator) generateHeader() {
1240 g.P("// Code generated by protoc-gen-go. DO NOT EDIT.")
1241 g.P("// source: ", g.file.Name)
1244 name := g.file.PackageName()
1246 if g.file.index == 0 {
1247 // Generate package docs for the first file in the package.
1249 g.P("Package ", name, " is a generated protocol buffer package.")
1251 if loc, ok := g.file.comments[strconv.Itoa(packagePath)]; ok {
1252 // not using g.PrintComments because this is a /* */ comment block.
1253 text := strings.TrimSuffix(loc.GetLeadingComments(), "\n")
1254 for _, line := range strings.Split(text, "\n") {
1255 line = strings.TrimPrefix(line, " ")
1256 // ensure we don't escape from the block comment
1257 line = strings.Replace(line, "*/", "* /", -1)
1262 var topMsgs []string
1263 g.P("It is generated from these files:")
1264 for _, f := range g.genFiles {
1266 for _, msg := range f.desc {
1267 if msg.parent != nil {
1270 topMsgs = append(topMsgs, CamelCaseSlice(msg.TypeName()))
1274 g.P("It has these top-level messages:")
1275 for _, msg := range topMsgs {
1281 g.P("package ", name)
1285 // PrintComments prints any comments from the source .proto file.
1286 // The path is a comma-separated list of integers.
1287 // It returns an indication of whether any comments were printed.
1288 // See descriptor.proto for its format.
1289 func (g *Generator) PrintComments(path string) bool {
1293 if loc, ok := g.file.comments[path]; ok {
1294 text := strings.TrimSuffix(loc.GetLeadingComments(), "\n")
1295 for _, line := range strings.Split(text, "\n") {
1296 g.P("// ", strings.TrimPrefix(line, " "))
1303 func (g *Generator) fileByName(filename string) *FileDescriptor {
1304 return g.allFilesByName[filename]
1307 // weak returns whether the ith import of the current file is a weak import.
1308 func (g *Generator) weak(i int32) bool {
1309 for _, j := range g.file.WeakDependency {
1317 // Generate the imports
1318 func (g *Generator) generateImports() {
1319 // We almost always need a proto import. Rather than computing when we
1320 // do, which is tricky when there's a plugin, just import it and
1321 // reference it later. The same argument applies to the fmt and math packages.
1322 g.P("import " + g.Pkg["proto"] + " " + strconv.Quote(g.ImportPrefix+"github.com/golang/protobuf/proto"))
1323 g.P("import " + g.Pkg["fmt"] + ` "fmt"`)
1324 g.P("import " + g.Pkg["math"] + ` "math"`)
1325 for i, s := range g.file.Dependency {
1326 fd := g.fileByName(s)
1327 // Do not import our own package.
1328 if fd.PackageName() == g.packageName {
1331 filename := fd.goFileName()
1332 // By default, import path is the dirname of the Go filename.
1333 importPath := path.Dir(filename)
1334 if substitution, ok := g.ImportMap[s]; ok {
1335 importPath = substitution
1337 importPath = g.ImportPrefix + importPath
1338 // Skip weak imports.
1339 if g.weak(int32(i)) {
1340 g.P("// skipping weak import ", fd.PackageName(), " ", strconv.Quote(importPath))
1343 // We need to import all the dependencies, even if we don't reference them,
1344 // because other code and tools depend on having the full transitive closure
1345 // of protocol buffer types in the binary.
1346 pname := fd.PackageName()
1347 if _, ok := g.usedPackages[pname]; !ok {
1350 g.P("import ", pname, " ", strconv.Quote(importPath))
1353 // TODO: may need to worry about uniqueness across plugins
1354 for _, p := range plugins {
1355 p.GenerateImports(g.file)
1358 g.P("// Reference imports to suppress errors if they are not otherwise used.")
1359 g.P("var _ = ", g.Pkg["proto"], ".Marshal")
1360 g.P("var _ = ", g.Pkg["fmt"], ".Errorf")
1361 g.P("var _ = ", g.Pkg["math"], ".Inf")
1365 func (g *Generator) generateImported(id *ImportedDescriptor) {
1366 // Don't generate public import symbols for files that we are generating
1367 // code for, since those symbols will already be in this package.
1368 // We can't simply avoid creating the ImportedDescriptor objects,
1369 // because g.genFiles isn't populated at that stage.
1372 df := g.FileOf(id.o.File())
1373 filename := *df.Name
1374 for _, fd := range g.genFiles {
1375 if *fd.Name == filename {
1376 g.P("// Ignoring public import of ", sn, " from ", filename)
1381 g.P("// ", sn, " from public import ", filename)
1382 g.usedPackages[df.PackageName()] = true
1384 for _, sym := range df.exported[id.o] {
1385 sym.GenerateAlias(g, df.PackageName())
1391 // Generate the enum definitions for this EnumDescriptor.
1392 func (g *Generator) generateEnum(enum *EnumDescriptor) {
1393 // The full type name
1394 typeName := enum.TypeName()
1395 // The full type name, CamelCased.
1396 ccTypeName := CamelCaseSlice(typeName)
1397 ccPrefix := enum.prefix()
1399 g.PrintComments(enum.path)
1400 g.P("type ", ccTypeName, " int32")
1401 g.file.addExport(enum, enumSymbol{ccTypeName, enum.proto3()})
1404 for i, e := range enum.Value {
1405 g.PrintComments(fmt.Sprintf("%s,%d,%d", enum.path, enumValuePath, i))
1407 name := ccPrefix + *e.Name
1408 g.P(name, " ", ccTypeName, " = ", e.Number)
1409 g.file.addExport(enum, constOrVarSymbol{name, "const", ccTypeName})
1413 g.P("var ", ccTypeName, "_name = map[int32]string{")
1415 generated := make(map[int32]bool) // avoid duplicate values
1416 for _, e := range enum.Value {
1418 if _, present := generated[*e.Number]; present {
1419 duplicate = "// Duplicate value: "
1421 g.P(duplicate, e.Number, ": ", strconv.Quote(*e.Name), ",")
1422 generated[*e.Number] = true
1426 g.P("var ", ccTypeName, "_value = map[string]int32{")
1428 for _, e := range enum.Value {
1429 g.P(strconv.Quote(*e.Name), ": ", e.Number, ",")
1435 g.P("func (x ", ccTypeName, ") Enum() *", ccTypeName, " {")
1437 g.P("p := new(", ccTypeName, ")")
1444 g.P("func (x ", ccTypeName, ") String() string {")
1446 g.P("return ", g.Pkg["proto"], ".EnumName(", ccTypeName, "_name, int32(x))")
1451 g.P("func (x *", ccTypeName, ") UnmarshalJSON(data []byte) error {")
1453 g.P("value, err := ", g.Pkg["proto"], ".UnmarshalJSONEnum(", ccTypeName, `_value, data, "`, ccTypeName, `")`)
1454 g.P("if err != nil {")
1459 g.P("*x = ", ccTypeName, "(value)")
1465 var indexes []string
1466 for m := enum.parent; m != nil; m = m.parent {
1467 // XXX: skip groups?
1468 indexes = append([]string{strconv.Itoa(m.index)}, indexes...)
1470 indexes = append(indexes, strconv.Itoa(enum.index))
1471 g.P("func (", ccTypeName, ") EnumDescriptor() ([]byte, []int) { return ", g.file.VarName(), ", []int{", strings.Join(indexes, ", "), "} }")
1472 if enum.file.GetPackage() == "google.protobuf" && enum.GetName() == "NullValue" {
1473 g.P("func (", ccTypeName, `) XXX_WellKnownType() string { return "`, enum.GetName(), `" }`)
1479 // The tag is a string like "varint,2,opt,name=fieldname,def=7" that
1480 // identifies details of the field for the protocol buffer marshaling and unmarshaling
1481 // code. The fields are:
1483 // protocol tag number
1484 // opt,req,rep for optional, required, or repeated
1485 // packed whether the encoding is "packed" (optional; repeated primitives only)
1486 // name= the original declared name
1487 // enum= the name of the enum type if it is an enum-typed field.
1488 // proto3 if this field is in a proto3 message
1489 // def= string representation of the default value, if any.
1490 // The default value must be in a representation that can be used at run-time
1491 // to generate the default value. Thus bools become 0 and 1, for instance.
1492 func (g *Generator) goTag(message *Descriptor, field *descriptor.FieldDescriptorProto, wiretype string) string {
1495 case isOptional(field):
1497 case isRequired(field):
1499 case isRepeated(field):
1502 var defaultValue string
1503 if dv := field.DefaultValue; dv != nil { // set means an explicit default
1505 // Some types need tweaking.
1506 switch *field.Type {
1507 case descriptor.FieldDescriptorProto_TYPE_BOOL:
1508 if defaultValue == "true" {
1513 case descriptor.FieldDescriptorProto_TYPE_STRING,
1514 descriptor.FieldDescriptorProto_TYPE_BYTES:
1515 // Nothing to do. Quoting is done for the whole tag.
1516 case descriptor.FieldDescriptorProto_TYPE_ENUM:
1517 // For enums we need to provide the integer constant.
1518 obj := g.ObjectNamed(field.GetTypeName())
1519 if id, ok := obj.(*ImportedDescriptor); ok {
1520 // It is an enum that was publicly imported.
1521 // We need the underlying type.
1524 enum, ok := obj.(*EnumDescriptor)
1526 log.Printf("obj is a %T", obj)
1527 if id, ok := obj.(*ImportedDescriptor); ok {
1528 log.Printf("id.o is a %T", id.o)
1530 g.Fail("unknown enum type", CamelCaseSlice(obj.TypeName()))
1532 defaultValue = enum.integerValueAsString(defaultValue)
1534 defaultValue = ",def=" + defaultValue
1537 if *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM {
1538 // We avoid using obj.PackageName(), because we want to use the
1539 // original (proto-world) package name.
1540 obj := g.ObjectNamed(field.GetTypeName())
1541 if id, ok := obj.(*ImportedDescriptor); ok {
1545 if pkg := obj.File().GetPackage(); pkg != "" {
1548 enum += CamelCaseSlice(obj.TypeName())
1551 if (field.Options != nil && field.Options.GetPacked()) ||
1552 // Per https://developers.google.com/protocol-buffers/docs/proto3#simple:
1553 // "In proto3, repeated fields of scalar numeric types use packed encoding by default."
1554 (message.proto3() && (field.Options == nil || field.Options.Packed == nil) &&
1555 isRepeated(field) && isScalar(field)) {
1558 fieldName := field.GetName()
1560 if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP {
1561 // We must use the type name for groups instead of
1562 // the field name to preserve capitalization.
1563 // type_name in FieldDescriptorProto is fully-qualified,
1564 // but we only want the local part.
1565 name = *field.TypeName
1566 if i := strings.LastIndex(name, "."); i >= 0 {
1570 if json := field.GetJsonName(); json != "" && json != name {
1571 // TODO: escaping might be needed, in which case
1572 // perhaps this should be in its own "json" tag.
1573 name += ",json=" + json
1575 name = ",name=" + name
1576 if message.proto3() {
1577 // We only need the extra tag for []byte fields;
1578 // no need to add noise for the others.
1579 if *field.Type == descriptor.FieldDescriptorProto_TYPE_BYTES {
1585 if field.OneofIndex != nil {
1588 return strconv.Quote(fmt.Sprintf("%s,%d,%s%s%s%s%s%s",
1599 func needsStar(typ descriptor.FieldDescriptorProto_Type) bool {
1601 case descriptor.FieldDescriptorProto_TYPE_GROUP:
1603 case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
1605 case descriptor.FieldDescriptorProto_TYPE_BYTES:
1611 // TypeName is the printed name appropriate for an item. If the object is in the current file,
1612 // TypeName drops the package name and underscores the rest.
1613 // Otherwise the object is from another package; and the result is the underscored
1614 // package name followed by the item name.
1615 // The result always has an initial capital.
1616 func (g *Generator) TypeName(obj Object) string {
1617 return g.DefaultPackageName(obj) + CamelCaseSlice(obj.TypeName())
1620 // TypeNameWithPackage is like TypeName, but always includes the package
1621 // name even if the object is in our own package.
1622 func (g *Generator) TypeNameWithPackage(obj Object) string {
1623 return obj.PackageName() + CamelCaseSlice(obj.TypeName())
1626 // GoType returns a string representing the type name, and the wire type
1627 func (g *Generator) GoType(message *Descriptor, field *descriptor.FieldDescriptorProto) (typ string, wire string) {
1629 switch *field.Type {
1630 case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
1631 typ, wire = "float64", "fixed64"
1632 case descriptor.FieldDescriptorProto_TYPE_FLOAT:
1633 typ, wire = "float32", "fixed32"
1634 case descriptor.FieldDescriptorProto_TYPE_INT64:
1635 typ, wire = "int64", "varint"
1636 case descriptor.FieldDescriptorProto_TYPE_UINT64:
1637 typ, wire = "uint64", "varint"
1638 case descriptor.FieldDescriptorProto_TYPE_INT32:
1639 typ, wire = "int32", "varint"
1640 case descriptor.FieldDescriptorProto_TYPE_UINT32:
1641 typ, wire = "uint32", "varint"
1642 case descriptor.FieldDescriptorProto_TYPE_FIXED64:
1643 typ, wire = "uint64", "fixed64"
1644 case descriptor.FieldDescriptorProto_TYPE_FIXED32:
1645 typ, wire = "uint32", "fixed32"
1646 case descriptor.FieldDescriptorProto_TYPE_BOOL:
1647 typ, wire = "bool", "varint"
1648 case descriptor.FieldDescriptorProto_TYPE_STRING:
1649 typ, wire = "string", "bytes"
1650 case descriptor.FieldDescriptorProto_TYPE_GROUP:
1651 desc := g.ObjectNamed(field.GetTypeName())
1652 typ, wire = "*"+g.TypeName(desc), "group"
1653 case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
1654 desc := g.ObjectNamed(field.GetTypeName())
1655 typ, wire = "*"+g.TypeName(desc), "bytes"
1656 case descriptor.FieldDescriptorProto_TYPE_BYTES:
1657 typ, wire = "[]byte", "bytes"
1658 case descriptor.FieldDescriptorProto_TYPE_ENUM:
1659 desc := g.ObjectNamed(field.GetTypeName())
1660 typ, wire = g.TypeName(desc), "varint"
1661 case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
1662 typ, wire = "int32", "fixed32"
1663 case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
1664 typ, wire = "int64", "fixed64"
1665 case descriptor.FieldDescriptorProto_TYPE_SINT32:
1666 typ, wire = "int32", "zigzag32"
1667 case descriptor.FieldDescriptorProto_TYPE_SINT64:
1668 typ, wire = "int64", "zigzag64"
1670 g.Fail("unknown type for", field.GetName())
1672 if isRepeated(field) {
1674 } else if message != nil && message.proto3() {
1676 } else if field.OneofIndex != nil && message != nil {
1678 } else if needsStar(*field.Type) {
1684 func (g *Generator) RecordTypeUse(t string) {
1685 if obj, ok := g.typeNameToObject[t]; ok {
1686 // Call ObjectNamed to get the true object to record the use.
1687 obj = g.ObjectNamed(t)
1688 g.usedPackages[obj.PackageName()] = true
1692 // Method names that may be generated. Fields with these names get an
1693 // underscore appended. Any change to this set is a potential incompatible
1694 // API change because it changes generated field names.
1695 var methodNames = [...]string{
1701 "ExtensionRangeArray",
1706 // Names of messages in the `google.protobuf` package for which
1707 // we will generate XXX_WellKnownType methods.
1708 var wellKnownTypes = map[string]bool{
1717 "DoubleValue": true,
1720 "UInt64Value": true,
1722 "UInt32Value": true,
1724 "StringValue": true,
1728 // Generate the type and default constant definitions for this Descriptor.
1729 func (g *Generator) generateMessage(message *Descriptor) {
1730 // The full type name
1731 typeName := message.TypeName()
1732 // The full type name, CamelCased.
1733 ccTypeName := CamelCaseSlice(typeName)
1735 usedNames := make(map[string]bool)
1736 for _, n := range methodNames {
1739 fieldNames := make(map[*descriptor.FieldDescriptorProto]string)
1740 fieldGetterNames := make(map[*descriptor.FieldDescriptorProto]string)
1741 fieldTypes := make(map[*descriptor.FieldDescriptorProto]string)
1742 mapFieldTypes := make(map[*descriptor.FieldDescriptorProto]string)
1744 oneofFieldName := make(map[int32]string) // indexed by oneof_index field of FieldDescriptorProto
1745 oneofDisc := make(map[int32]string) // name of discriminator method
1746 oneofTypeName := make(map[*descriptor.FieldDescriptorProto]string) // without star
1747 oneofInsertPoints := make(map[int32]int) // oneof_index => offset of g.Buffer
1749 g.PrintComments(message.path)
1750 g.P("type ", ccTypeName, " struct {")
1753 // allocNames finds a conflict-free variation of the given strings,
1754 // consistently mutating their suffixes.
1755 // It returns the same number of strings.
1756 allocNames := func(ns ...string) []string {
1759 for _, n := range ns {
1767 for _, n := range ns {
1774 for i, field := range message.Field {
1775 // Allocate the getter and the field at the same time so name
1776 // collisions create field/method consistent names.
1777 // TODO: This allocation occurs based on the order of the fields
1778 // in the proto file, meaning that a change in the field
1779 // ordering can change generated Method/Field names.
1780 base := CamelCase(*field.Name)
1781 ns := allocNames(base, "Get"+base)
1782 fieldName, fieldGetterName := ns[0], ns[1]
1783 typename, wiretype := g.GoType(message, field)
1784 jsonName := *field.Name
1785 tag := fmt.Sprintf("protobuf:%s json:%q", g.goTag(message, field, wiretype), jsonName+",omitempty")
1787 fieldNames[field] = fieldName
1788 fieldGetterNames[field] = fieldGetterName
1790 oneof := field.OneofIndex != nil
1791 if oneof && oneofFieldName[*field.OneofIndex] == "" {
1792 odp := message.OneofDecl[int(*field.OneofIndex)]
1793 fname := allocNames(CamelCase(odp.GetName()))[0]
1795 // This is the first field of a oneof we haven't seen before.
1796 // Generate the union field.
1797 com := g.PrintComments(fmt.Sprintf("%s,%d,%d", message.path, messageOneofPath, *field.OneofIndex))
1801 g.P("// Types that are valid to be assigned to ", fname, ":")
1802 // Generate the rest of this comment later,
1803 // when we've computed any disambiguation.
1804 oneofInsertPoints[*field.OneofIndex] = g.Buffer.Len()
1806 dname := "is" + ccTypeName + "_" + fname
1807 oneofFieldName[*field.OneofIndex] = fname
1808 oneofDisc[*field.OneofIndex] = dname
1809 tag := `protobuf_oneof:"` + odp.GetName() + `"`
1810 g.P(fname, " ", dname, " `", tag, "`")
1813 if *field.Type == descriptor.FieldDescriptorProto_TYPE_MESSAGE {
1814 desc := g.ObjectNamed(field.GetTypeName())
1815 if d, ok := desc.(*Descriptor); ok && d.GetOptions().GetMapEntry() {
1816 // Figure out the Go types and tags for the key and value types.
1817 keyField, valField := d.Field[0], d.Field[1]
1818 keyType, keyWire := g.GoType(d, keyField)
1819 valType, valWire := g.GoType(d, valField)
1820 keyTag, valTag := g.goTag(d, keyField, keyWire), g.goTag(d, valField, valWire)
1822 // We don't use stars, except for message-typed values.
1823 // Message and enum types are the only two possibly foreign types used in maps,
1824 // so record their use. They are not permitted as map keys.
1825 keyType = strings.TrimPrefix(keyType, "*")
1826 switch *valField.Type {
1827 case descriptor.FieldDescriptorProto_TYPE_ENUM:
1828 valType = strings.TrimPrefix(valType, "*")
1829 g.RecordTypeUse(valField.GetTypeName())
1830 case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
1831 g.RecordTypeUse(valField.GetTypeName())
1833 valType = strings.TrimPrefix(valType, "*")
1836 typename = fmt.Sprintf("map[%s]%s", keyType, valType)
1837 mapFieldTypes[field] = typename // record for the getter generation
1839 tag += fmt.Sprintf(" protobuf_key:%s protobuf_val:%s", keyTag, valTag)
1843 fieldTypes[field] = typename
1846 tname := ccTypeName + "_" + fieldName
1847 // It is possible for this to collide with a message or enum
1848 // nested in this message. Check for collisions.
1851 for _, desc := range message.nested {
1852 if CamelCaseSlice(desc.TypeName()) == tname {
1857 for _, enum := range message.enums {
1858 if CamelCaseSlice(enum.TypeName()) == tname {
1870 oneofTypeName[field] = tname
1874 g.PrintComments(fmt.Sprintf("%s,%d,%d", message.path, messageFieldPath, i))
1875 g.P(fieldName, "\t", typename, "\t`", tag, "`")
1876 g.RecordTypeUse(field.GetTypeName())
1878 if len(message.ExtensionRange) > 0 {
1879 g.P(g.Pkg["proto"], ".XXX_InternalExtensions `json:\"-\"`")
1881 if !message.proto3() {
1882 g.P("XXX_unrecognized\t[]byte `json:\"-\"`")
1887 // Update g.Buffer to list valid oneof types.
1888 // We do this down here, after we've disambiguated the oneof type names.
1889 // We go in reverse order of insertion point to avoid invalidating offsets.
1890 for oi := int32(len(message.OneofDecl)); oi >= 0; oi-- {
1891 ip := oneofInsertPoints[oi]
1892 all := g.Buffer.Bytes()
1894 g.Buffer = bytes.NewBuffer(all[:ip:ip]) // set cap so we don't scribble on rem
1895 for _, field := range message.Field {
1896 if field.OneofIndex == nil || *field.OneofIndex != oi {
1899 g.P("//\t*", oneofTypeName[field])
1904 // Reset, String and ProtoMessage methods.
1905 g.P("func (m *", ccTypeName, ") Reset() { *m = ", ccTypeName, "{} }")
1906 g.P("func (m *", ccTypeName, ") String() string { return ", g.Pkg["proto"], ".CompactTextString(m) }")
1907 g.P("func (*", ccTypeName, ") ProtoMessage() {}")
1908 var indexes []string
1909 for m := message; m != nil; m = m.parent {
1910 indexes = append([]string{strconv.Itoa(m.index)}, indexes...)
1912 g.P("func (*", ccTypeName, ") Descriptor() ([]byte, []int) { return ", g.file.VarName(), ", []int{", strings.Join(indexes, ", "), "} }")
1913 // TODO: Revisit the decision to use a XXX_WellKnownType method
1914 // if we change proto.MessageName to work with multiple equivalents.
1915 if message.file.GetPackage() == "google.protobuf" && wellKnownTypes[message.GetName()] {
1916 g.P("func (*", ccTypeName, `) XXX_WellKnownType() string { return "`, message.GetName(), `" }`)
1919 // Extension support methods
1920 var hasExtensions, isMessageSet bool
1921 if len(message.ExtensionRange) > 0 {
1922 hasExtensions = true
1923 // message_set_wire_format only makes sense when extensions are defined.
1924 if opts := message.Options; opts != nil && opts.GetMessageSetWireFormat() {
1927 g.P("func (m *", ccTypeName, ") Marshal() ([]byte, error) {")
1929 g.P("return ", g.Pkg["proto"], ".MarshalMessageSet(&m.XXX_InternalExtensions)")
1932 g.P("func (m *", ccTypeName, ") Unmarshal(buf []byte) error {")
1934 g.P("return ", g.Pkg["proto"], ".UnmarshalMessageSet(buf, &m.XXX_InternalExtensions)")
1937 g.P("func (m *", ccTypeName, ") MarshalJSON() ([]byte, error) {")
1939 g.P("return ", g.Pkg["proto"], ".MarshalMessageSetJSON(&m.XXX_InternalExtensions)")
1942 g.P("func (m *", ccTypeName, ") UnmarshalJSON(buf []byte) error {")
1944 g.P("return ", g.Pkg["proto"], ".UnmarshalMessageSetJSON(buf, &m.XXX_InternalExtensions)")
1947 g.P("// ensure ", ccTypeName, " satisfies proto.Marshaler and proto.Unmarshaler")
1948 g.P("var _ ", g.Pkg["proto"], ".Marshaler = (*", ccTypeName, ")(nil)")
1949 g.P("var _ ", g.Pkg["proto"], ".Unmarshaler = (*", ccTypeName, ")(nil)")
1953 g.P("var extRange_", ccTypeName, " = []", g.Pkg["proto"], ".ExtensionRange{")
1955 for _, r := range message.ExtensionRange {
1956 end := fmt.Sprint(*r.End - 1) // make range inclusive on both ends
1957 g.P("{", r.Start, ", ", end, "},")
1961 g.P("func (*", ccTypeName, ") ExtensionRangeArray() []", g.Pkg["proto"], ".ExtensionRange {")
1963 g.P("return extRange_", ccTypeName)
1968 // Default constants
1969 defNames := make(map[*descriptor.FieldDescriptorProto]string)
1970 for _, field := range message.Field {
1971 def := field.GetDefaultValue()
1975 fieldname := "Default_" + ccTypeName + "_" + CamelCase(*field.Name)
1976 defNames[field] = fieldname
1977 typename, _ := g.GoType(message, field)
1978 if typename[0] == '*' {
1979 typename = typename[1:]
1983 case typename == "bool":
1984 case typename == "string":
1985 def = strconv.Quote(def)
1986 case typename == "[]byte":
1987 def = "[]byte(" + strconv.Quote(unescape(def)) + ")"
1989 case def == "inf", def == "-inf", def == "nan":
1990 // These names are known to, and defined by, the protocol language.
1995 def = "math.Inf(-1)"
1999 if *field.Type == descriptor.FieldDescriptorProto_TYPE_FLOAT {
2000 def = "float32(" + def + ")"
2003 case *field.Type == descriptor.FieldDescriptorProto_TYPE_ENUM:
2004 // Must be an enum. Need to construct the prefixed name.
2005 obj := g.ObjectNamed(field.GetTypeName())
2006 var enum *EnumDescriptor
2007 if id, ok := obj.(*ImportedDescriptor); ok {
2008 // The enum type has been publicly imported.
2009 enum, _ = id.o.(*EnumDescriptor)
2011 enum, _ = obj.(*EnumDescriptor)
2014 log.Printf("don't know how to generate constant for %s", fieldname)
2017 def = g.DefaultPackageName(obj) + enum.prefix() + def
2019 g.P(kind, fieldname, " ", typename, " = ", def)
2020 g.file.addExport(message, constOrVarSymbol{fieldname, kind, ""})
2024 // Oneof per-field types, discriminants and getters.
2026 // Generate unexported named types for the discriminant interfaces.
2027 // We shouldn't have to do this, but there was (~19 Aug 2015) a compiler/linker bug
2028 // that was triggered by using anonymous interfaces here.
2029 // TODO: Revisit this and consider reverting back to anonymous interfaces.
2030 for oi := range message.OneofDecl {
2031 dname := oneofDisc[int32(oi)]
2032 g.P("type ", dname, " interface { ", dname, "() }")
2035 for _, field := range message.Field {
2036 if field.OneofIndex == nil {
2039 _, wiretype := g.GoType(message, field)
2040 tag := "protobuf:" + g.goTag(message, field, wiretype)
2041 g.P("type ", oneofTypeName[field], " struct{ ", fieldNames[field], " ", fieldTypes[field], " `", tag, "` }")
2042 g.RecordTypeUse(field.GetTypeName())
2045 for _, field := range message.Field {
2046 if field.OneofIndex == nil {
2049 g.P("func (*", oneofTypeName[field], ") ", oneofDisc[*field.OneofIndex], "() {}")
2052 for oi := range message.OneofDecl {
2053 fname := oneofFieldName[int32(oi)]
2054 g.P("func (m *", ccTypeName, ") Get", fname, "() ", oneofDisc[int32(oi)], " {")
2055 g.P("if m != nil { return m.", fname, " }")
2062 var getters []getterSymbol
2063 for _, field := range message.Field {
2064 oneof := field.OneofIndex != nil
2066 fname := fieldNames[field]
2067 typename, _ := g.GoType(message, field)
2068 if t, ok := mapFieldTypes[field]; ok {
2071 mname := fieldGetterNames[field]
2073 if needsStar(*field.Type) && typename[0] == '*' {
2074 typename = typename[1:]
2078 // Only export getter symbols for basic types,
2079 // and for messages and enums in the same package.
2080 // Groups are not exported.
2081 // Foreign types can't be hoisted through a public import because
2082 // the importer may not already be importing the defining .proto.
2083 // As an example, imagine we have an import tree like this:
2084 // A.proto -> B.proto -> C.proto
2085 // If A publicly imports B, we need to generate the getters from B in A's output,
2086 // but if one such getter returns something from C then we cannot do that
2087 // because A is not importing C already.
2088 var getter, genType bool
2089 switch *field.Type {
2090 case descriptor.FieldDescriptorProto_TYPE_GROUP:
2092 case descriptor.FieldDescriptorProto_TYPE_MESSAGE, descriptor.FieldDescriptorProto_TYPE_ENUM:
2093 // Only export getter if its return type is in this package.
2094 getter = g.ObjectNamed(field.GetTypeName()).PackageName() == message.PackageName()
2100 getters = append(getters, getterSymbol{
2103 typeName: field.GetTypeName(),
2108 g.P("func (m *", ccTypeName, ") "+mname+"() "+typename+" {")
2110 def, hasDef := defNames[field]
2111 typeDefaultIsNil := false // whether this field type's default value is a literal nil unless specified
2112 switch *field.Type {
2113 case descriptor.FieldDescriptorProto_TYPE_BYTES:
2114 typeDefaultIsNil = !hasDef
2115 case descriptor.FieldDescriptorProto_TYPE_GROUP, descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2116 typeDefaultIsNil = true
2118 if isRepeated(field) {
2119 typeDefaultIsNil = true
2121 if typeDefaultIsNil && !oneof {
2122 // A bytes field with no explicit default needs less generated code,
2123 // as does a message or group field, or a repeated field.
2124 g.P("if m != nil {")
2126 g.P("return m." + fname)
2136 if message.proto3() {
2137 g.P("if m != nil {")
2139 g.P("if m != nil && m." + fname + " != nil {")
2142 g.P("return " + star + "m." + fname)
2146 uname := oneofFieldName[*field.OneofIndex]
2147 tname := oneofTypeName[field]
2148 g.P("if x, ok := m.Get", uname, "().(*", tname, "); ok {")
2149 g.P("return x.", fname)
2153 if *field.Type != descriptor.FieldDescriptorProto_TYPE_BYTES {
2154 g.P("return " + def)
2156 // The default is a []byte var.
2157 // Make a copy when returning it to be safe.
2158 g.P("return append([]byte(nil), ", def, "...)")
2161 switch *field.Type {
2162 case descriptor.FieldDescriptorProto_TYPE_BOOL:
2164 case descriptor.FieldDescriptorProto_TYPE_STRING:
2166 case descriptor.FieldDescriptorProto_TYPE_GROUP,
2167 descriptor.FieldDescriptorProto_TYPE_MESSAGE,
2168 descriptor.FieldDescriptorProto_TYPE_BYTES:
2169 // This is only possible for oneof fields.
2171 case descriptor.FieldDescriptorProto_TYPE_ENUM:
2172 // The default default for an enum is the first value in the enum,
2174 obj := g.ObjectNamed(field.GetTypeName())
2175 var enum *EnumDescriptor
2176 if id, ok := obj.(*ImportedDescriptor); ok {
2177 // The enum type has been publicly imported.
2178 enum, _ = id.o.(*EnumDescriptor)
2180 enum, _ = obj.(*EnumDescriptor)
2183 log.Printf("don't know how to generate getter for %s", field.GetName())
2186 if len(enum.Value) == 0 {
2187 g.P("return 0 // empty enum")
2189 first := enum.Value[0].GetName()
2190 g.P("return ", g.DefaultPackageName(obj)+enum.prefix()+first)
2202 ms := &messageSymbol{
2204 hasExtensions: hasExtensions,
2205 isMessageSet: isMessageSet,
2206 hasOneof: len(message.OneofDecl) > 0,
2209 g.file.addExport(message, ms)
2213 if len(message.OneofDecl) > 0 {
2214 fieldWire := make(map[*descriptor.FieldDescriptorProto]string)
2217 enc := "_" + ccTypeName + "_OneofMarshaler"
2218 dec := "_" + ccTypeName + "_OneofUnmarshaler"
2219 size := "_" + ccTypeName + "_OneofSizer"
2220 encSig := "(msg " + g.Pkg["proto"] + ".Message, b *" + g.Pkg["proto"] + ".Buffer) error"
2221 decSig := "(msg " + g.Pkg["proto"] + ".Message, tag, wire int, b *" + g.Pkg["proto"] + ".Buffer) (bool, error)"
2222 sizeSig := "(msg " + g.Pkg["proto"] + ".Message) (n int)"
2224 g.P("// XXX_OneofFuncs is for the internal use of the proto package.")
2225 g.P("func (*", ccTypeName, ") XXX_OneofFuncs() (func", encSig, ", func", decSig, ", func", sizeSig, ", []interface{}) {")
2226 g.P("return ", enc, ", ", dec, ", ", size, ", []interface{}{")
2227 for _, field := range message.Field {
2228 if field.OneofIndex == nil {
2231 g.P("(*", oneofTypeName[field], ")(nil),")
2238 g.P("func ", enc, encSig, " {")
2239 g.P("m := msg.(*", ccTypeName, ")")
2240 for oi, odp := range message.OneofDecl {
2241 g.P("// ", odp.GetName())
2242 fname := oneofFieldName[int32(oi)]
2243 g.P("switch x := m.", fname, ".(type) {")
2244 for _, field := range message.Field {
2245 if field.OneofIndex == nil || int(*field.OneofIndex) != oi {
2248 g.P("case *", oneofTypeName[field], ":")
2249 var wire, pre, post string
2250 val := "x." + fieldNames[field] // overridden for TYPE_BOOL
2251 canFail := false // only TYPE_MESSAGE and TYPE_GROUP can fail
2252 switch *field.Type {
2253 case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
2254 wire = "WireFixed64"
2255 pre = "b.EncodeFixed64(" + g.Pkg["math"] + ".Float64bits("
2257 case descriptor.FieldDescriptorProto_TYPE_FLOAT:
2258 wire = "WireFixed32"
2259 pre = "b.EncodeFixed32(uint64(" + g.Pkg["math"] + ".Float32bits("
2261 case descriptor.FieldDescriptorProto_TYPE_INT64,
2262 descriptor.FieldDescriptorProto_TYPE_UINT64:
2264 pre, post = "b.EncodeVarint(uint64(", "))"
2265 case descriptor.FieldDescriptorProto_TYPE_INT32,
2266 descriptor.FieldDescriptorProto_TYPE_UINT32,
2267 descriptor.FieldDescriptorProto_TYPE_ENUM:
2269 pre, post = "b.EncodeVarint(uint64(", "))"
2270 case descriptor.FieldDescriptorProto_TYPE_FIXED64,
2271 descriptor.FieldDescriptorProto_TYPE_SFIXED64:
2272 wire = "WireFixed64"
2273 pre, post = "b.EncodeFixed64(uint64(", "))"
2274 case descriptor.FieldDescriptorProto_TYPE_FIXED32,
2275 descriptor.FieldDescriptorProto_TYPE_SFIXED32:
2276 wire = "WireFixed32"
2277 pre, post = "b.EncodeFixed32(uint64(", "))"
2278 case descriptor.FieldDescriptorProto_TYPE_BOOL:
2279 // bool needs special handling.
2280 g.P("t := uint64(0)")
2281 g.P("if ", val, " { t = 1 }")
2284 pre, post = "b.EncodeVarint(", ")"
2285 case descriptor.FieldDescriptorProto_TYPE_STRING:
2287 pre, post = "b.EncodeStringBytes(", ")"
2288 case descriptor.FieldDescriptorProto_TYPE_GROUP:
2289 wire = "WireStartGroup"
2290 pre, post = "b.Marshal(", ")"
2292 case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2294 pre, post = "b.EncodeMessage(", ")"
2296 case descriptor.FieldDescriptorProto_TYPE_BYTES:
2298 pre, post = "b.EncodeRawBytes(", ")"
2299 case descriptor.FieldDescriptorProto_TYPE_SINT32:
2301 pre, post = "b.EncodeZigzag32(uint64(", "))"
2302 case descriptor.FieldDescriptorProto_TYPE_SINT64:
2304 pre, post = "b.EncodeZigzag64(uint64(", "))"
2306 g.Fail("unhandled oneof field type ", field.Type.String())
2308 fieldWire[field] = wire
2309 g.P("b.EncodeVarint(", field.Number, "<<3|", g.Pkg["proto"], ".", wire, ")")
2313 g.P("if err := ", pre, val, post, "; err != nil {")
2317 if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP {
2318 g.P("b.EncodeVarint(", field.Number, "<<3|", g.Pkg["proto"], ".WireEndGroup)")
2322 g.P("default: return ", g.Pkg["fmt"], `.Errorf("`, ccTypeName, ".", fname, ` has unexpected type %T", x)`)
2330 g.P("func ", dec, decSig, " {")
2331 g.P("m := msg.(*", ccTypeName, ")")
2333 for _, field := range message.Field {
2334 if field.OneofIndex == nil {
2337 odp := message.OneofDecl[int(*field.OneofIndex)]
2338 g.P("case ", field.Number, ": // ", odp.GetName(), ".", *field.Name)
2339 g.P("if wire != ", g.Pkg["proto"], ".", fieldWire[field], " {")
2340 g.P("return true, ", g.Pkg["proto"], ".ErrInternalBadWireType")
2342 lhs := "x, err" // overridden for TYPE_MESSAGE and TYPE_GROUP
2343 var dec, cast, cast2 string
2344 switch *field.Type {
2345 case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
2346 dec, cast = "b.DecodeFixed64()", g.Pkg["math"]+".Float64frombits"
2347 case descriptor.FieldDescriptorProto_TYPE_FLOAT:
2348 dec, cast, cast2 = "b.DecodeFixed32()", "uint32", g.Pkg["math"]+".Float32frombits"
2349 case descriptor.FieldDescriptorProto_TYPE_INT64:
2350 dec, cast = "b.DecodeVarint()", "int64"
2351 case descriptor.FieldDescriptorProto_TYPE_UINT64:
2352 dec = "b.DecodeVarint()"
2353 case descriptor.FieldDescriptorProto_TYPE_INT32:
2354 dec, cast = "b.DecodeVarint()", "int32"
2355 case descriptor.FieldDescriptorProto_TYPE_FIXED64:
2356 dec = "b.DecodeFixed64()"
2357 case descriptor.FieldDescriptorProto_TYPE_FIXED32:
2358 dec, cast = "b.DecodeFixed32()", "uint32"
2359 case descriptor.FieldDescriptorProto_TYPE_BOOL:
2360 dec = "b.DecodeVarint()"
2361 // handled specially below
2362 case descriptor.FieldDescriptorProto_TYPE_STRING:
2363 dec = "b.DecodeStringBytes()"
2364 case descriptor.FieldDescriptorProto_TYPE_GROUP:
2365 g.P("msg := new(", fieldTypes[field][1:], ")") // drop star
2367 dec = "b.DecodeGroup(msg)"
2368 // handled specially below
2369 case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2370 g.P("msg := new(", fieldTypes[field][1:], ")") // drop star
2372 dec = "b.DecodeMessage(msg)"
2373 // handled specially below
2374 case descriptor.FieldDescriptorProto_TYPE_BYTES:
2375 dec = "b.DecodeRawBytes(true)"
2376 case descriptor.FieldDescriptorProto_TYPE_UINT32:
2377 dec, cast = "b.DecodeVarint()", "uint32"
2378 case descriptor.FieldDescriptorProto_TYPE_ENUM:
2379 dec, cast = "b.DecodeVarint()", fieldTypes[field]
2380 case descriptor.FieldDescriptorProto_TYPE_SFIXED32:
2381 dec, cast = "b.DecodeFixed32()", "int32"
2382 case descriptor.FieldDescriptorProto_TYPE_SFIXED64:
2383 dec, cast = "b.DecodeFixed64()", "int64"
2384 case descriptor.FieldDescriptorProto_TYPE_SINT32:
2385 dec, cast = "b.DecodeZigzag32()", "int32"
2386 case descriptor.FieldDescriptorProto_TYPE_SINT64:
2387 dec, cast = "b.DecodeZigzag64()", "int64"
2389 g.Fail("unhandled oneof field type ", field.Type.String())
2391 g.P(lhs, " := ", dec)
2394 val = cast + "(" + val + ")"
2397 val = cast2 + "(" + val + ")"
2399 switch *field.Type {
2400 case descriptor.FieldDescriptorProto_TYPE_BOOL:
2402 case descriptor.FieldDescriptorProto_TYPE_GROUP,
2403 descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2406 g.P("m.", oneofFieldName[*field.OneofIndex], " = &", oneofTypeName[field], "{", val, "}")
2407 g.P("return true, err")
2409 g.P("default: return false, nil")
2415 g.P("func ", size, sizeSig, " {")
2416 g.P("m := msg.(*", ccTypeName, ")")
2417 for oi, odp := range message.OneofDecl {
2418 g.P("// ", odp.GetName())
2419 fname := oneofFieldName[int32(oi)]
2420 g.P("switch x := m.", fname, ".(type) {")
2421 for _, field := range message.Field {
2422 if field.OneofIndex == nil || int(*field.OneofIndex) != oi {
2425 g.P("case *", oneofTypeName[field], ":")
2426 val := "x." + fieldNames[field]
2427 var wire, varint, fixed string
2428 switch *field.Type {
2429 case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
2430 wire = "WireFixed64"
2432 case descriptor.FieldDescriptorProto_TYPE_FLOAT:
2433 wire = "WireFixed32"
2435 case descriptor.FieldDescriptorProto_TYPE_INT64,
2436 descriptor.FieldDescriptorProto_TYPE_UINT64,
2437 descriptor.FieldDescriptorProto_TYPE_INT32,
2438 descriptor.FieldDescriptorProto_TYPE_UINT32,
2439 descriptor.FieldDescriptorProto_TYPE_ENUM:
2442 case descriptor.FieldDescriptorProto_TYPE_FIXED64,
2443 descriptor.FieldDescriptorProto_TYPE_SFIXED64:
2444 wire = "WireFixed64"
2446 case descriptor.FieldDescriptorProto_TYPE_FIXED32,
2447 descriptor.FieldDescriptorProto_TYPE_SFIXED32:
2448 wire = "WireFixed32"
2450 case descriptor.FieldDescriptorProto_TYPE_BOOL:
2453 case descriptor.FieldDescriptorProto_TYPE_STRING:
2455 fixed = "len(" + val + ")"
2457 case descriptor.FieldDescriptorProto_TYPE_GROUP:
2458 wire = "WireStartGroup"
2459 fixed = g.Pkg["proto"] + ".Size(" + val + ")"
2460 case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
2462 g.P("s := ", g.Pkg["proto"], ".Size(", val, ")")
2465 case descriptor.FieldDescriptorProto_TYPE_BYTES:
2467 fixed = "len(" + val + ")"
2469 case descriptor.FieldDescriptorProto_TYPE_SINT32:
2471 varint = "(uint32(" + val + ") << 1) ^ uint32((int32(" + val + ") >> 31))"
2472 case descriptor.FieldDescriptorProto_TYPE_SINT64:
2474 varint = "uint64(" + val + " << 1) ^ uint64((int64(" + val + ") >> 63))"
2476 g.Fail("unhandled oneof field type ", field.Type.String())
2478 g.P("n += ", g.Pkg["proto"], ".SizeVarint(", field.Number, "<<3|", g.Pkg["proto"], ".", wire, ")")
2480 g.P("n += ", g.Pkg["proto"], ".SizeVarint(uint64(", varint, "))")
2485 if *field.Type == descriptor.FieldDescriptorProto_TYPE_GROUP {
2486 g.P("n += ", g.Pkg["proto"], ".SizeVarint(", field.Number, "<<3|", g.Pkg["proto"], ".WireEndGroup)")
2491 g.P("panic(", g.Pkg["fmt"], ".Sprintf(\"proto: unexpected type %T in oneof\", x))")
2499 for _, ext := range message.ext {
2500 g.generateExtension(ext)
2503 fullName := strings.Join(message.TypeName(), ".")
2504 if g.file.Package != nil {
2505 fullName = *g.file.Package + "." + fullName
2508 g.addInitf("%s.RegisterType((*%s)(nil), %q)", g.Pkg["proto"], ccTypeName, fullName)
2511 var escapeChars = [256]byte{
2512 'a': '\a', 'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t', 'v': '\v', '\\': '\\', '"': '"', '\'': '\'', '?': '?',
2515 // unescape reverses the "C" escaping that protoc does for default values of bytes fields.
2516 // It is best effort in that it effectively ignores malformed input. Seemingly invalid escape
2517 // sequences are conveyed, unmodified, into the decoded result.
2518 func unescape(s string) string {
2519 // NB: Sadly, we can't use strconv.Unquote because protoc will escape both
2520 // single and double quotes, but strconv.Unquote only allows one or the
2521 // other (based on actual surrounding quotes of its input argument).
2525 // regular character, or too short to be valid escape
2526 if s[0] != '\\' || len(s) < 2 {
2527 out = append(out, s[0])
2529 } else if c := escapeChars[s[1]]; c != 0 {
2531 out = append(out, c)
2533 } else if s[1] == 'x' || s[1] == 'X' {
2534 // hex escape, e.g. "\x80
2536 // too short to be valid
2537 out = append(out, s[:2]...)
2541 v, err := strconv.ParseUint(s[2:4], 16, 8)
2543 out = append(out, s[:4]...)
2545 out = append(out, byte(v))
2548 } else if '0' <= s[1] && s[1] <= '7' {
2549 // octal escape, can vary from 1 to 3 octal digits; e.g., "\0" "\40" or "\164"
2550 // so consume up to 2 more bytes or up to end-of-string
2551 n := len(s[1:]) - len(strings.TrimLeft(s[1:], "01234567"))
2555 v, err := strconv.ParseUint(s[1:1+n], 8, 8)
2557 out = append(out, s[:1+n]...)
2559 out = append(out, byte(v))
2563 // bad escape, just propagate the slash as-is
2564 out = append(out, s[0])
2572 func (g *Generator) generateExtension(ext *ExtensionDescriptor) {
2573 ccTypeName := ext.DescName()
2575 extObj := g.ObjectNamed(*ext.Extendee)
2576 var extDesc *Descriptor
2577 if id, ok := extObj.(*ImportedDescriptor); ok {
2578 // This is extending a publicly imported message.
2579 // We need the underlying type for goTag.
2580 extDesc = id.o.(*Descriptor)
2582 extDesc = extObj.(*Descriptor)
2584 extendedType := "*" + g.TypeName(extObj) // always use the original
2585 field := ext.FieldDescriptorProto
2586 fieldType, wireType := g.GoType(ext.parent, field)
2587 tag := g.goTag(extDesc, field, wireType)
2588 g.RecordTypeUse(*ext.Extendee)
2589 if n := ext.FieldDescriptorProto.TypeName; n != nil {
2590 // foreign extension type
2594 typeName := ext.TypeName()
2596 // Special case for proto2 message sets: If this extension is extending
2597 // proto2_bridge.MessageSet, and its final name component is "message_set_extension",
2598 // then drop that last component.
2600 if extendedType == "*proto2_bridge.MessageSet" && typeName[len(typeName)-1] == "message_set_extension" {
2601 typeName = typeName[:len(typeName)-1]
2605 // For text formatting, the package must be exactly what the .proto file declares,
2606 // ignoring overrides such as the go_package option, and with no dot/underscore mapping.
2607 extName := strings.Join(typeName, ".")
2608 if g.file.Package != nil {
2609 extName = *g.file.Package + "." + extName
2612 g.P("var ", ccTypeName, " = &", g.Pkg["proto"], ".ExtensionDesc{")
2614 g.P("ExtendedType: (", extendedType, ")(nil),")
2615 g.P("ExtensionType: (", fieldType, ")(nil),")
2616 g.P("Field: ", field.Number, ",")
2617 g.P(`Name: "`, extName, `",`)
2618 g.P("Tag: ", tag, ",")
2619 g.P(`Filename: "`, g.file.GetName(), `",`)
2626 // Generate a bit more code to register with message_set.go.
2627 g.addInitf("%s.RegisterMessageSetType((%s)(nil), %d, %q)", g.Pkg["proto"], fieldType, *field.Number, extName)
2630 g.file.addExport(ext, constOrVarSymbol{ccTypeName, "var", ""})
2633 func (g *Generator) generateInitFunction() {
2634 for _, enum := range g.file.enum {
2635 g.generateEnumRegistration(enum)
2637 for _, d := range g.file.desc {
2638 for _, ext := range d.ext {
2639 g.generateExtensionRegistration(ext)
2642 for _, ext := range g.file.ext {
2643 g.generateExtensionRegistration(ext)
2645 if len(g.init) == 0 {
2648 g.P("func init() {")
2650 for _, l := range g.init {
2658 func (g *Generator) generateFileDescriptor(file *FileDescriptor) {
2659 // Make a copy and trim source_code_info data.
2660 // TODO: Trim this more when we know exactly what we need.
2661 pb := proto.Clone(file.FileDescriptorProto).(*descriptor.FileDescriptorProto)
2662 pb.SourceCodeInfo = nil
2664 b, err := proto.Marshal(pb)
2669 var buf bytes.Buffer
2670 w, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression)
2677 g.P("func init() { ", g.Pkg["proto"], ".RegisterFile(", strconv.Quote(*file.Name), ", ", v, ") }")
2678 g.P("var ", v, " = []byte{")
2680 g.P("// ", len(b), " bytes of a gzipped FileDescriptorProto")
2688 for _, c := range b[:n] {
2689 s += fmt.Sprintf("0x%02x,", c)
2699 func (g *Generator) generateEnumRegistration(enum *EnumDescriptor) {
2700 // // We always print the full (proto-world) package name here.
2701 pkg := enum.File().GetPackage()
2705 // The full type name
2706 typeName := enum.TypeName()
2707 // The full type name, CamelCased.
2708 ccTypeName := CamelCaseSlice(typeName)
2709 g.addInitf("%s.RegisterEnum(%q, %[3]s_name, %[3]s_value)", g.Pkg["proto"], pkg+ccTypeName, ccTypeName)
2712 func (g *Generator) generateExtensionRegistration(ext *ExtensionDescriptor) {
2713 g.addInitf("%s.RegisterExtension(%s)", g.Pkg["proto"], ext.DescName())
2716 // And now lots of helper functions.
2718 // Is c an ASCII lower-case letter?
2719 func isASCIILower(c byte) bool {
2720 return 'a' <= c && c <= 'z'
2723 // Is c an ASCII digit?
2724 func isASCIIDigit(c byte) bool {
2725 return '0' <= c && c <= '9'
2728 // CamelCase returns the CamelCased name.
2729 // If there is an interior underscore followed by a lower case letter,
2730 // drop the underscore and convert the letter to upper case.
2731 // There is a remote possibility of this rewrite causing a name collision,
2732 // but it's so remote we're prepared to pretend it's nonexistent - since the
2733 // C++ generator lowercases names, it's extremely unlikely to have two fields
2734 // with different capitalizations.
2735 // In short, _my_field_name_2 becomes XMyFieldName_2.
2736 func CamelCase(s string) string {
2740 t := make([]byte, 0, 32)
2743 // Need a capital letter; drop the '_'.
2747 // Invariant: if the next letter is lower case, it must be converted
2749 // That is, we process a word at a time, where words are marked by _ or
2750 // upper case letter. Digits are treated as words.
2751 for ; i < len(s); i++ {
2753 if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) {
2754 continue // Skip the underscore in s.
2756 if isASCIIDigit(c) {
2760 // Assume we have a letter now - if not, it's a bogus identifier.
2761 // The next word is a sequence of characters that must start upper case.
2762 if isASCIILower(c) {
2763 c ^= ' ' // Make it a capital letter.
2765 t = append(t, c) // Guaranteed not lower case.
2766 // Accept lower case sequence that follows.
2767 for i+1 < len(s) && isASCIILower(s[i+1]) {
2775 // CamelCaseSlice is like CamelCase, but the argument is a slice of strings to
2776 // be joined with "_".
2777 func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) }
2779 // dottedSlice turns a sliced name into a dotted name.
2780 func dottedSlice(elem []string) string { return strings.Join(elem, ".") }
2782 // Is this field optional?
2783 func isOptional(field *descriptor.FieldDescriptorProto) bool {
2784 return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_OPTIONAL
2787 // Is this field required?
2788 func isRequired(field *descriptor.FieldDescriptorProto) bool {
2789 return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REQUIRED
2792 // Is this field repeated?
2793 func isRepeated(field *descriptor.FieldDescriptorProto) bool {
2794 return field.Label != nil && *field.Label == descriptor.FieldDescriptorProto_LABEL_REPEATED
2797 // Is this field a scalar numeric type?
2798 func isScalar(field *descriptor.FieldDescriptorProto) bool {
2799 if field.Type == nil {
2802 switch *field.Type {
2803 case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
2804 descriptor.FieldDescriptorProto_TYPE_FLOAT,
2805 descriptor.FieldDescriptorProto_TYPE_INT64,
2806 descriptor.FieldDescriptorProto_TYPE_UINT64,
2807 descriptor.FieldDescriptorProto_TYPE_INT32,
2808 descriptor.FieldDescriptorProto_TYPE_FIXED64,
2809 descriptor.FieldDescriptorProto_TYPE_FIXED32,
2810 descriptor.FieldDescriptorProto_TYPE_BOOL,
2811 descriptor.FieldDescriptorProto_TYPE_UINT32,
2812 descriptor.FieldDescriptorProto_TYPE_ENUM,
2813 descriptor.FieldDescriptorProto_TYPE_SFIXED32,
2814 descriptor.FieldDescriptorProto_TYPE_SFIXED64,
2815 descriptor.FieldDescriptorProto_TYPE_SINT32,
2816 descriptor.FieldDescriptorProto_TYPE_SINT64:
2823 // badToUnderscore is the mapping function used to generate Go names from package names,
2824 // which can be dotted in the input .proto file. It replaces non-identifier characters such as
2825 // dot or dash with underscore.
2826 func badToUnderscore(r rune) rune {
2827 if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' {
2833 // baseName returns the last path element of the name, with the last dotted suffix removed.
2834 func baseName(name string) string {
2835 // First, find the last element
2836 if i := strings.LastIndex(name, "/"); i >= 0 {
2839 // Now drop the suffix
2840 if i := strings.LastIndex(name, "."); i >= 0 {
2846 // The SourceCodeInfo message describes the location of elements of a parsed
2847 // .proto file by way of a "path", which is a sequence of integers that
2848 // describe the route from a FileDescriptorProto to the relevant submessage.
2849 // The path alternates between a field number of a repeated field, and an index
2850 // into that repeated field. The constants below define the field numbers that
2853 // See descriptor.proto for more information about this.
2855 // tag numbers in FileDescriptorProto
2856 packagePath = 2 // package
2857 messagePath = 4 // message_type
2858 enumPath = 5 // enum_type
2859 // tag numbers in DescriptorProto
2860 messageFieldPath = 2 // field
2861 messageMessagePath = 3 // nested_type
2862 messageEnumPath = 4 // enum_type
2863 messageOneofPath = 8 // oneof_decl
2864 // tag numbers in EnumDescriptorProto
2865 enumValuePath = 2 // value