github.com/grpc-ecosystem/grpc-gateway/v2@v2.19.1/internal/descriptor/types.go (about)

     1  package descriptor
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/grpc-ecosystem/grpc-gateway/v2/internal/casing"
     8  	"github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule"
     9  	"google.golang.org/protobuf/types/descriptorpb"
    10  	"google.golang.org/protobuf/types/pluginpb"
    11  )
    12  
    13  // IsWellKnownType returns true if the provided fully qualified type name is considered 'well-known'.
    14  func IsWellKnownType(typeName string) bool {
    15  	_, ok := wellKnownTypeConv[typeName]
    16  	return ok
    17  }
    18  
    19  // GoPackage represents a golang package.
    20  type GoPackage struct {
    21  	// Path is the package path to the package.
    22  	Path string
    23  	// Name is the package name of the package
    24  	Name string
    25  	// Alias is an alias of the package unique within the current invocation of gRPC-Gateway generator.
    26  	Alias string
    27  }
    28  
    29  // Standard returns whether the import is a golang standard package.
    30  func (p GoPackage) Standard() bool {
    31  	return !strings.Contains(p.Path, ".")
    32  }
    33  
    34  // String returns a string representation of this package in the form of import line in golang.
    35  func (p GoPackage) String() string {
    36  	if p.Alias == "" {
    37  		return fmt.Sprintf("%q", p.Path)
    38  	}
    39  	return fmt.Sprintf("%s %q", p.Alias, p.Path)
    40  }
    41  
    42  // ResponseFile wraps pluginpb.CodeGeneratorResponse_File.
    43  type ResponseFile struct {
    44  	*pluginpb.CodeGeneratorResponse_File
    45  	// GoPkg is the Go package of the generated file.
    46  	GoPkg GoPackage
    47  }
    48  
    49  // File wraps descriptorpb.FileDescriptorProto for richer features.
    50  type File struct {
    51  	*descriptorpb.FileDescriptorProto
    52  	// GoPkg is the go package of the go file generated from this file.
    53  	GoPkg GoPackage
    54  	// GeneratedFilenamePrefix is used to construct filenames for generated
    55  	// files associated with this source file.
    56  	//
    57  	// For example, the source file "dir/foo.proto" might have a filename prefix
    58  	// of "dir/foo". Appending ".pb.go" produces an output file of "dir/foo.pb.go".
    59  	GeneratedFilenamePrefix string
    60  	// Messages is the list of messages defined in this file.
    61  	Messages []*Message
    62  	// Enums is the list of enums defined in this file.
    63  	Enums []*Enum
    64  	// Services is the list of services defined in this file.
    65  	Services []*Service
    66  }
    67  
    68  // Pkg returns package name or alias if it's present
    69  func (f *File) Pkg() string {
    70  	pkg := f.GoPkg.Name
    71  	if alias := f.GoPkg.Alias; alias != "" {
    72  		pkg = alias
    73  	}
    74  	return pkg
    75  }
    76  
    77  // proto2 determines if the syntax of the file is proto2.
    78  func (f *File) proto2() bool {
    79  	return f.Syntax == nil || f.GetSyntax() == "proto2"
    80  }
    81  
    82  // Message describes a protocol buffer message types.
    83  type Message struct {
    84  	*descriptorpb.DescriptorProto
    85  	// File is the file where the message is defined.
    86  	File *File
    87  	// Outers is a list of outer messages if this message is a nested type.
    88  	Outers []string
    89  	// Fields is a list of message fields.
    90  	Fields []*Field
    91  	// Index is proto path index of this message in File.
    92  	Index int
    93  	// ForcePrefixedName when set to true, prefixes a type with a package prefix.
    94  	ForcePrefixedName bool
    95  }
    96  
    97  // FQMN returns a fully qualified message name of this message.
    98  func (m *Message) FQMN() string {
    99  	components := []string{""}
   100  	if m.File.Package != nil {
   101  		components = append(components, m.File.GetPackage())
   102  	}
   103  	components = append(components, m.Outers...)
   104  	components = append(components, m.GetName())
   105  	return strings.Join(components, ".")
   106  }
   107  
   108  // GoType returns a go type name for the message type.
   109  // It prefixes the type name with the package alias if
   110  // its belonging package is not "currentPackage".
   111  func (m *Message) GoType(currentPackage string) string {
   112  	var components []string
   113  	components = append(components, m.Outers...)
   114  	components = append(components, m.GetName())
   115  
   116  	name := strings.Join(components, "_")
   117  	if !m.ForcePrefixedName && m.File.GoPkg.Path == currentPackage {
   118  		return name
   119  	}
   120  	return fmt.Sprintf("%s.%s", m.File.Pkg(), name)
   121  }
   122  
   123  // Enum describes a protocol buffer enum types.
   124  type Enum struct {
   125  	*descriptorpb.EnumDescriptorProto
   126  	// File is the file where the enum is defined
   127  	File *File
   128  	// Outers is a list of outer messages if this enum is a nested type.
   129  	Outers []string
   130  	// Index is a enum index value.
   131  	Index int
   132  	// ForcePrefixedName when set to true, prefixes a type with a package prefix.
   133  	ForcePrefixedName bool
   134  }
   135  
   136  // FQEN returns a fully qualified enum name of this enum.
   137  func (e *Enum) FQEN() string {
   138  	components := []string{""}
   139  	if e.File.Package != nil {
   140  		components = append(components, e.File.GetPackage())
   141  	}
   142  	components = append(components, e.Outers...)
   143  	components = append(components, e.GetName())
   144  	return strings.Join(components, ".")
   145  }
   146  
   147  // GoType returns a go type name for the enum type.
   148  // It prefixes the type name with the package alias if
   149  // its belonging package is not "currentPackage".
   150  func (e *Enum) GoType(currentPackage string) string {
   151  	var components []string
   152  	components = append(components, e.Outers...)
   153  	components = append(components, e.GetName())
   154  
   155  	name := strings.Join(components, "_")
   156  	if !e.ForcePrefixedName && e.File.GoPkg.Path == currentPackage {
   157  		return name
   158  	}
   159  	return fmt.Sprintf("%s.%s", e.File.Pkg(), name)
   160  }
   161  
   162  // Service wraps descriptorpb.ServiceDescriptorProto for richer features.
   163  type Service struct {
   164  	*descriptorpb.ServiceDescriptorProto
   165  	// File is the file where this service is defined.
   166  	File *File
   167  	// Methods is the list of methods defined in this service.
   168  	Methods []*Method
   169  	// ForcePrefixedName when set to true, prefixes a type with a package prefix.
   170  	ForcePrefixedName bool
   171  }
   172  
   173  // FQSN returns the fully qualified service name of this service.
   174  func (s *Service) FQSN() string {
   175  	components := []string{""}
   176  	if s.File.Package != nil {
   177  		components = append(components, s.File.GetPackage())
   178  	}
   179  	components = append(components, s.GetName())
   180  	return strings.Join(components, ".")
   181  }
   182  
   183  // InstanceName returns object name of the service with package prefix if needed
   184  func (s *Service) InstanceName() string {
   185  	if !s.ForcePrefixedName {
   186  		return s.GetName()
   187  	}
   188  	return fmt.Sprintf("%s.%s", s.File.Pkg(), s.GetName())
   189  }
   190  
   191  // ClientConstructorName returns name of the Client constructor with package prefix if needed
   192  func (s *Service) ClientConstructorName() string {
   193  	constructor := "New" + s.GetName() + "Client"
   194  	if !s.ForcePrefixedName {
   195  		return constructor
   196  	}
   197  	return fmt.Sprintf("%s.%s", s.File.Pkg(), constructor)
   198  }
   199  
   200  // Method wraps descriptorpb.MethodDescriptorProto for richer features.
   201  type Method struct {
   202  	*descriptorpb.MethodDescriptorProto
   203  	// Service is the service which this method belongs to.
   204  	Service *Service
   205  	// RequestType is the message type of requests to this method.
   206  	RequestType *Message
   207  	// ResponseType is the message type of responses from this method.
   208  	ResponseType *Message
   209  	Bindings     []*Binding
   210  }
   211  
   212  // FQMN returns a fully qualified rpc method name of this method.
   213  func (m *Method) FQMN() string {
   214  	var components []string
   215  	components = append(components, m.Service.FQSN())
   216  	components = append(components, m.GetName())
   217  	return strings.Join(components, ".")
   218  }
   219  
   220  // Binding describes how an HTTP endpoint is bound to a gRPC method.
   221  type Binding struct {
   222  	// Method is the method which the endpoint is bound to.
   223  	Method *Method
   224  	// Index is a zero-origin index of the binding in the target method
   225  	Index int
   226  	// PathTmpl is path template where this method is mapped to.
   227  	PathTmpl httprule.Template
   228  	// HTTPMethod is the HTTP method which this method is mapped to.
   229  	HTTPMethod string
   230  	// PathParams is the list of parameters provided in HTTP request paths.
   231  	PathParams []Parameter
   232  	// Body describes parameters provided in HTTP request body.
   233  	Body *Body
   234  	// ResponseBody describes field in response struct to marshal in HTTP response body.
   235  	ResponseBody *Body
   236  }
   237  
   238  // ExplicitParams returns a list of explicitly bound parameters of "b",
   239  // i.e. a union of field path for body and field paths for path parameters.
   240  func (b *Binding) ExplicitParams() []string {
   241  	var result []string
   242  	if b.Body != nil {
   243  		result = append(result, b.Body.FieldPath.String())
   244  	}
   245  	for _, p := range b.PathParams {
   246  		result = append(result, p.FieldPath.String())
   247  	}
   248  	return result
   249  }
   250  
   251  // Field wraps descriptorpb.FieldDescriptorProto for richer features.
   252  type Field struct {
   253  	*descriptorpb.FieldDescriptorProto
   254  	// Message is the message type which this field belongs to.
   255  	Message *Message
   256  	// FieldMessage is the message type of the field.
   257  	FieldMessage *Message
   258  	// ForcePrefixedName when set to true, prefixes a type with a package prefix.
   259  	ForcePrefixedName bool
   260  }
   261  
   262  // FQFN returns a fully qualified field name of this field.
   263  func (f *Field) FQFN() string {
   264  	return strings.Join([]string{f.Message.FQMN(), f.GetName()}, ".")
   265  }
   266  
   267  // Parameter is a parameter provided in http requests
   268  type Parameter struct {
   269  	// FieldPath is a path to a proto field which this parameter is mapped to.
   270  	FieldPath
   271  	// Target is the proto field which this parameter is mapped to.
   272  	Target *Field
   273  	// Method is the method which this parameter is used for.
   274  	Method *Method
   275  }
   276  
   277  // ConvertFuncExpr returns a go expression of a converter function.
   278  // The converter function converts a string into a value for the parameter.
   279  func (p Parameter) ConvertFuncExpr() (string, error) {
   280  	tbl := proto3ConvertFuncs
   281  	if !p.IsProto2() && p.IsRepeated() {
   282  		tbl = proto3RepeatedConvertFuncs
   283  	} else if !p.IsProto2() && p.IsOptionalProto3() {
   284  		tbl = proto3OptionalConvertFuncs
   285  	} else if p.IsProto2() && !p.IsRepeated() {
   286  		tbl = proto2ConvertFuncs
   287  	} else if p.IsProto2() && p.IsRepeated() {
   288  		tbl = proto2RepeatedConvertFuncs
   289  	}
   290  	typ := p.Target.GetType()
   291  	conv, ok := tbl[typ]
   292  	if !ok {
   293  		conv, ok = wellKnownTypeConv[p.Target.GetTypeName()]
   294  	}
   295  	if !ok {
   296  		return "", fmt.Errorf("unsupported field type %s of parameter %s in %s.%s", typ, p.FieldPath, p.Method.Service.GetName(), p.Method.GetName())
   297  	}
   298  	return conv, nil
   299  }
   300  
   301  // IsEnum returns true if the field is an enum type, otherwise false is returned.
   302  func (p Parameter) IsEnum() bool {
   303  	return p.Target.GetType() == descriptorpb.FieldDescriptorProto_TYPE_ENUM
   304  }
   305  
   306  // IsRepeated returns true if the field is repeated, otherwise false is returned.
   307  func (p Parameter) IsRepeated() bool {
   308  	return p.Target.GetLabel() == descriptorpb.FieldDescriptorProto_LABEL_REPEATED
   309  }
   310  
   311  // IsProto2 returns true if the field is proto2, otherwise false is returned.
   312  func (p Parameter) IsProto2() bool {
   313  	return p.Target.Message.File.proto2()
   314  }
   315  
   316  // Body describes a http (request|response) body to be sent to the (method|client).
   317  // This is used in body and response_body options in google.api.HttpRule
   318  type Body struct {
   319  	// FieldPath is a path to a proto field which the (request|response) body is mapped to.
   320  	// The (request|response) body is mapped to the (request|response) type itself if FieldPath is empty.
   321  	FieldPath FieldPath
   322  }
   323  
   324  // AssignableExpr returns an assignable expression in Go to be used to initialize method request object.
   325  // It starts with "msgExpr", which is the go expression of the method request object.
   326  func (b Body) AssignableExpr(msgExpr string, currentPackage string) string {
   327  	return b.FieldPath.AssignableExpr(msgExpr, currentPackage)
   328  }
   329  
   330  // AssignableExprPrep returns preparatory statements for an assignable expression to initialize the
   331  // method request object.
   332  func (b Body) AssignableExprPrep(msgExpr string, currentPackage string) string {
   333  	return b.FieldPath.AssignableExprPrep(msgExpr, currentPackage)
   334  }
   335  
   336  // FieldPath is a path to a field from a request message.
   337  type FieldPath []FieldPathComponent
   338  
   339  // String returns a string representation of the field path.
   340  func (p FieldPath) String() string {
   341  	components := make([]string, 0, len(p))
   342  	for _, c := range p {
   343  		components = append(components, c.Name)
   344  	}
   345  	return strings.Join(components, ".")
   346  }
   347  
   348  // IsNestedProto3 indicates whether the FieldPath is a nested Proto3 path.
   349  func (p FieldPath) IsNestedProto3() bool {
   350  	if len(p) > 1 && !p[0].Target.Message.File.proto2() {
   351  		return true
   352  	}
   353  	return false
   354  }
   355  
   356  // IsOptionalProto3 indicates whether the FieldPath is a proto3 optional field.
   357  func (p FieldPath) IsOptionalProto3() bool {
   358  	if len(p) == 0 {
   359  		return false
   360  	}
   361  	return p[0].Target.GetProto3Optional()
   362  }
   363  
   364  // AssignableExpr is an assignable expression in Go to be used to assign a value to the target field.
   365  // It starts with "msgExpr", which is the go expression of the method request object. Before using
   366  // such an expression the prep statements must be emitted first, in case the field path includes
   367  // a oneof. See FieldPath.AssignableExprPrep.
   368  func (p FieldPath) AssignableExpr(msgExpr string, currentPackage string) string {
   369  	l := len(p)
   370  	if l == 0 {
   371  		return msgExpr
   372  	}
   373  
   374  	components := msgExpr
   375  	for i, c := range p {
   376  		// We need to check if the target is not proto3_optional first.
   377  		// Under the hood, proto3_optional uses oneof to signal to old proto3 clients
   378  		// that presence is tracked for this field. This oneof is known as a "synthetic" oneof.
   379  		if !c.Target.GetProto3Optional() && c.Target.OneofIndex != nil {
   380  			index := c.Target.OneofIndex
   381  			msg := c.Target.Message
   382  			oneOfName := casing.Camel(msg.GetOneofDecl()[*index].GetName())
   383  			oneofFieldName := msg.GoType(currentPackage) + "_" + c.AssignableExpr()
   384  
   385  			if c.Target.ForcePrefixedName {
   386  				oneofFieldName = msg.File.Pkg() + "." + msg.GetName() + "_" + c.AssignableExpr()
   387  			}
   388  
   389  			components = components + "." + oneOfName + ".(*" + oneofFieldName + ")"
   390  		}
   391  
   392  		if i == l-1 {
   393  			components = components + "." + c.AssignableExpr()
   394  			continue
   395  		}
   396  		components = components + "." + c.ValueExpr()
   397  	}
   398  	return components
   399  }
   400  
   401  // AssignableExprPrep returns preparation statements for an assignable expression to assign a value
   402  // to the target field. The Go expression of the method request object is "msgExpr". This is only
   403  // needed for field paths that contain oneofs. Otherwise, an empty string is returned.
   404  func (p FieldPath) AssignableExprPrep(msgExpr string, currentPackage string) string {
   405  	l := len(p)
   406  	if l == 0 {
   407  		return ""
   408  	}
   409  
   410  	var preparations []string
   411  	components := msgExpr
   412  	for i, c := range p {
   413  		// We need to check if the target is not proto3_optional first.
   414  		// Under the hood, proto3_optional uses oneof to signal to old proto3 clients
   415  		// that presence is tracked for this field. This oneof is known as a "synthetic" oneof.
   416  		if !c.Target.GetProto3Optional() && c.Target.OneofIndex != nil {
   417  			index := c.Target.OneofIndex
   418  			msg := c.Target.Message
   419  			oneOfName := casing.Camel(msg.GetOneofDecl()[*index].GetName())
   420  			oneofFieldName := msg.GoType(currentPackage) + "_" + c.AssignableExpr()
   421  
   422  			if c.Target.ForcePrefixedName {
   423  				oneofFieldName = msg.File.Pkg() + "." + msg.GetName() + "_" + c.AssignableExpr()
   424  			}
   425  
   426  			components = components + "." + oneOfName
   427  			s := `if %s == nil {
   428  				%s =&%s{}
   429  			} else if _, ok := %s.(*%s); !ok {
   430  				return nil, metadata, status.Errorf(codes.InvalidArgument, "expect type: *%s, but: %%t\n",%s)
   431  			}`
   432  
   433  			preparations = append(preparations, fmt.Sprintf(s, components, components, oneofFieldName, components, oneofFieldName, oneofFieldName, components))
   434  			components = components + ".(*" + oneofFieldName + ")"
   435  		}
   436  
   437  		if i == l-1 {
   438  			components = components + "." + c.AssignableExpr()
   439  			continue
   440  		}
   441  		components = components + "." + c.ValueExpr()
   442  	}
   443  
   444  	return strings.Join(preparations, "\n")
   445  }
   446  
   447  // FieldPathComponent is a path component in FieldPath
   448  type FieldPathComponent struct {
   449  	// Name is a name of the proto field which this component corresponds to.
   450  	// TODO(yugui) is this necessary?
   451  	Name string
   452  	// Target is the proto field which this component corresponds to.
   453  	Target *Field
   454  }
   455  
   456  // AssignableExpr returns an assignable expression in go for this field.
   457  func (c FieldPathComponent) AssignableExpr() string {
   458  	return casing.Camel(c.Name)
   459  }
   460  
   461  // ValueExpr returns an expression in go for this field.
   462  func (c FieldPathComponent) ValueExpr() string {
   463  	if c.Target.Message.File.proto2() {
   464  		return fmt.Sprintf("Get%s()", casing.Camel(c.Name))
   465  	}
   466  	return casing.Camel(c.Name)
   467  }
   468  
   469  var (
   470  	proto3ConvertFuncs = map[descriptorpb.FieldDescriptorProto_Type]string{
   471  		descriptorpb.FieldDescriptorProto_TYPE_DOUBLE:  "runtime.Float64",
   472  		descriptorpb.FieldDescriptorProto_TYPE_FLOAT:   "runtime.Float32",
   473  		descriptorpb.FieldDescriptorProto_TYPE_INT64:   "runtime.Int64",
   474  		descriptorpb.FieldDescriptorProto_TYPE_UINT64:  "runtime.Uint64",
   475  		descriptorpb.FieldDescriptorProto_TYPE_INT32:   "runtime.Int32",
   476  		descriptorpb.FieldDescriptorProto_TYPE_FIXED64: "runtime.Uint64",
   477  		descriptorpb.FieldDescriptorProto_TYPE_FIXED32: "runtime.Uint32",
   478  		descriptorpb.FieldDescriptorProto_TYPE_BOOL:    "runtime.Bool",
   479  		descriptorpb.FieldDescriptorProto_TYPE_STRING:  "runtime.String",
   480  		// FieldDescriptorProto_TYPE_GROUP
   481  		// FieldDescriptorProto_TYPE_MESSAGE
   482  		descriptorpb.FieldDescriptorProto_TYPE_BYTES:    "runtime.Bytes",
   483  		descriptorpb.FieldDescriptorProto_TYPE_UINT32:   "runtime.Uint32",
   484  		descriptorpb.FieldDescriptorProto_TYPE_ENUM:     "runtime.Enum",
   485  		descriptorpb.FieldDescriptorProto_TYPE_SFIXED32: "runtime.Int32",
   486  		descriptorpb.FieldDescriptorProto_TYPE_SFIXED64: "runtime.Int64",
   487  		descriptorpb.FieldDescriptorProto_TYPE_SINT32:   "runtime.Int32",
   488  		descriptorpb.FieldDescriptorProto_TYPE_SINT64:   "runtime.Int64",
   489  	}
   490  
   491  	proto3OptionalConvertFuncs = func() map[descriptorpb.FieldDescriptorProto_Type]string {
   492  		result := make(map[descriptorpb.FieldDescriptorProto_Type]string)
   493  		for typ, converter := range proto3ConvertFuncs {
   494  			// TODO: this will use convert functions from proto2.
   495  			//       The converters returning pointers should be moved
   496  			//       to a more generic file.
   497  			result[typ] = converter + "P"
   498  		}
   499  		return result
   500  	}()
   501  
   502  	// TODO: replace it with a IIFE
   503  	proto3RepeatedConvertFuncs = map[descriptorpb.FieldDescriptorProto_Type]string{
   504  		descriptorpb.FieldDescriptorProto_TYPE_DOUBLE:  "runtime.Float64Slice",
   505  		descriptorpb.FieldDescriptorProto_TYPE_FLOAT:   "runtime.Float32Slice",
   506  		descriptorpb.FieldDescriptorProto_TYPE_INT64:   "runtime.Int64Slice",
   507  		descriptorpb.FieldDescriptorProto_TYPE_UINT64:  "runtime.Uint64Slice",
   508  		descriptorpb.FieldDescriptorProto_TYPE_INT32:   "runtime.Int32Slice",
   509  		descriptorpb.FieldDescriptorProto_TYPE_FIXED64: "runtime.Uint64Slice",
   510  		descriptorpb.FieldDescriptorProto_TYPE_FIXED32: "runtime.Uint32Slice",
   511  		descriptorpb.FieldDescriptorProto_TYPE_BOOL:    "runtime.BoolSlice",
   512  		descriptorpb.FieldDescriptorProto_TYPE_STRING:  "runtime.StringSlice",
   513  		// FieldDescriptorProto_TYPE_GROUP
   514  		// FieldDescriptorProto_TYPE_MESSAGE
   515  		descriptorpb.FieldDescriptorProto_TYPE_BYTES:    "runtime.BytesSlice",
   516  		descriptorpb.FieldDescriptorProto_TYPE_UINT32:   "runtime.Uint32Slice",
   517  		descriptorpb.FieldDescriptorProto_TYPE_ENUM:     "runtime.EnumSlice",
   518  		descriptorpb.FieldDescriptorProto_TYPE_SFIXED32: "runtime.Int32Slice",
   519  		descriptorpb.FieldDescriptorProto_TYPE_SFIXED64: "runtime.Int64Slice",
   520  		descriptorpb.FieldDescriptorProto_TYPE_SINT32:   "runtime.Int32Slice",
   521  		descriptorpb.FieldDescriptorProto_TYPE_SINT64:   "runtime.Int64Slice",
   522  	}
   523  
   524  	proto2ConvertFuncs = map[descriptorpb.FieldDescriptorProto_Type]string{
   525  		descriptorpb.FieldDescriptorProto_TYPE_DOUBLE:  "runtime.Float64P",
   526  		descriptorpb.FieldDescriptorProto_TYPE_FLOAT:   "runtime.Float32P",
   527  		descriptorpb.FieldDescriptorProto_TYPE_INT64:   "runtime.Int64P",
   528  		descriptorpb.FieldDescriptorProto_TYPE_UINT64:  "runtime.Uint64P",
   529  		descriptorpb.FieldDescriptorProto_TYPE_INT32:   "runtime.Int32P",
   530  		descriptorpb.FieldDescriptorProto_TYPE_FIXED64: "runtime.Uint64P",
   531  		descriptorpb.FieldDescriptorProto_TYPE_FIXED32: "runtime.Uint32P",
   532  		descriptorpb.FieldDescriptorProto_TYPE_BOOL:    "runtime.BoolP",
   533  		descriptorpb.FieldDescriptorProto_TYPE_STRING:  "runtime.StringP",
   534  		// FieldDescriptorProto_TYPE_GROUP
   535  		// FieldDescriptorProto_TYPE_MESSAGE
   536  		// FieldDescriptorProto_TYPE_BYTES
   537  		// TODO(yugui) Handle bytes
   538  		descriptorpb.FieldDescriptorProto_TYPE_UINT32:   "runtime.Uint32P",
   539  		descriptorpb.FieldDescriptorProto_TYPE_ENUM:     "runtime.EnumP",
   540  		descriptorpb.FieldDescriptorProto_TYPE_SFIXED32: "runtime.Int32P",
   541  		descriptorpb.FieldDescriptorProto_TYPE_SFIXED64: "runtime.Int64P",
   542  		descriptorpb.FieldDescriptorProto_TYPE_SINT32:   "runtime.Int32P",
   543  		descriptorpb.FieldDescriptorProto_TYPE_SINT64:   "runtime.Int64P",
   544  	}
   545  
   546  	proto2RepeatedConvertFuncs = map[descriptorpb.FieldDescriptorProto_Type]string{
   547  		descriptorpb.FieldDescriptorProto_TYPE_DOUBLE:  "runtime.Float64Slice",
   548  		descriptorpb.FieldDescriptorProto_TYPE_FLOAT:   "runtime.Float32Slice",
   549  		descriptorpb.FieldDescriptorProto_TYPE_INT64:   "runtime.Int64Slice",
   550  		descriptorpb.FieldDescriptorProto_TYPE_UINT64:  "runtime.Uint64Slice",
   551  		descriptorpb.FieldDescriptorProto_TYPE_INT32:   "runtime.Int32Slice",
   552  		descriptorpb.FieldDescriptorProto_TYPE_FIXED64: "runtime.Uint64Slice",
   553  		descriptorpb.FieldDescriptorProto_TYPE_FIXED32: "runtime.Uint32Slice",
   554  		descriptorpb.FieldDescriptorProto_TYPE_BOOL:    "runtime.BoolSlice",
   555  		descriptorpb.FieldDescriptorProto_TYPE_STRING:  "runtime.StringSlice",
   556  		// FieldDescriptorProto_TYPE_GROUP
   557  		// FieldDescriptorProto_TYPE_MESSAGE
   558  		// FieldDescriptorProto_TYPE_BYTES
   559  		// TODO(maros7) Handle bytes
   560  		descriptorpb.FieldDescriptorProto_TYPE_UINT32:   "runtime.Uint32Slice",
   561  		descriptorpb.FieldDescriptorProto_TYPE_ENUM:     "runtime.EnumSlice",
   562  		descriptorpb.FieldDescriptorProto_TYPE_SFIXED32: "runtime.Int32Slice",
   563  		descriptorpb.FieldDescriptorProto_TYPE_SFIXED64: "runtime.Int64Slice",
   564  		descriptorpb.FieldDescriptorProto_TYPE_SINT32:   "runtime.Int32Slice",
   565  		descriptorpb.FieldDescriptorProto_TYPE_SINT64:   "runtime.Int64Slice",
   566  	}
   567  
   568  	wellKnownTypeConv = map[string]string{
   569  		".google.protobuf.Timestamp":   "runtime.Timestamp",
   570  		".google.protobuf.Duration":    "runtime.Duration",
   571  		".google.protobuf.StringValue": "runtime.StringValue",
   572  		".google.protobuf.FloatValue":  "runtime.FloatValue",
   573  		".google.protobuf.DoubleValue": "runtime.DoubleValue",
   574  		".google.protobuf.BoolValue":   "runtime.BoolValue",
   575  		".google.protobuf.BytesValue":  "runtime.BytesValue",
   576  		".google.protobuf.Int32Value":  "runtime.Int32Value",
   577  		".google.protobuf.UInt32Value": "runtime.UInt32Value",
   578  		".google.protobuf.Int64Value":  "runtime.Int64Value",
   579  		".google.protobuf.UInt64Value": "runtime.UInt64Value",
   580  	}
   581  )