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 )