github.com/aavshr/aws-sdk-go@v1.41.3/private/model/api/shape.go (about) 1 //go:build codegen 2 // +build codegen 3 4 package api 5 6 import ( 7 "bytes" 8 "fmt" 9 "path" 10 "regexp" 11 "sort" 12 "strings" 13 "text/template" 14 15 "github.com/aavshr/aws-sdk-go/private/protocol" 16 ) 17 18 // ErrorInfo represents the error block of a shape's structure 19 type ErrorInfo struct { 20 Type string 21 Code string 22 HTTPStatusCode int 23 } 24 25 // A XMLInfo defines URL and prefix for Shapes when rendered as XML 26 type XMLInfo struct { 27 Prefix string 28 URI string 29 } 30 31 // A ShapeRef defines the usage of a shape within the API. 32 type ShapeRef struct { 33 API *API `json:"-"` 34 Shape *Shape `json:"-"` 35 Documentation string `json:"-"` 36 ShapeName string `json:"shape"` 37 Location string 38 LocationName string 39 QueryName string 40 Flattened bool 41 Streaming bool 42 XMLAttribute bool 43 // Ignore, if set, will not be sent over the wire 44 Ignore bool 45 XMLNamespace XMLInfo 46 Payload string 47 IdempotencyToken bool `json:"idempotencyToken"` 48 TimestampFormat string `json:"timestampFormat"` 49 JSONValue bool `json:"jsonvalue"` 50 Deprecated bool `json:"deprecated"` 51 DeprecatedMsg string `json:"deprecatedMessage"` 52 EndpointDiscoveryID bool `json:"endpointdiscoveryid"` 53 HostLabel bool `json:"hostLabel"` 54 55 OrigShapeName string `json:"-"` 56 57 GenerateGetter bool 58 59 IsEventPayload bool `json:"eventpayload"` 60 IsEventHeader bool `json:"eventheader"` 61 62 // Collection of custom tags the shape reference includes. 63 CustomTags ShapeTags 64 65 // Flags whether the member reference is a endpoint ARN 66 EndpointARN bool 67 68 // Flags whether the member reference is a Outpost ID 69 OutpostIDMember bool 70 71 // Flag whether the member reference is a Account ID when endpoint shape ARN is present 72 AccountIDMemberWithARN bool 73 } 74 75 // A Shape defines the definition of a shape type 76 type Shape struct { 77 API *API `json:"-"` 78 ShapeName string 79 Documentation string `json:"-"` 80 MemberRefs map[string]*ShapeRef `json:"members"` 81 MemberRef ShapeRef `json:"member"` // List ref 82 KeyRef ShapeRef `json:"key"` // map key ref 83 ValueRef ShapeRef `json:"value"` // map value ref 84 Required []string 85 Payload string 86 Type string 87 Exception bool 88 Enum []string 89 EnumConsts []string 90 Flattened bool 91 Streaming bool 92 Location string 93 LocationName string 94 IdempotencyToken bool `json:"idempotencyToken"` 95 TimestampFormat string `json:"timestampFormat"` 96 XMLNamespace XMLInfo 97 Min float64 // optional Minimum length (string, list) or value (number) 98 99 OutputEventStreamAPI *EventStreamAPI 100 EventStream *EventStream 101 EventFor map[string]*EventStream `json:"-"` 102 103 IsInputEventStream bool `json:"-"` 104 IsOutputEventStream bool `json:"-"` 105 106 IsEventStream bool `json:"eventstream"` 107 IsEvent bool `json:"event"` 108 109 refs []*ShapeRef // References to this shape 110 resolvePkg string // use this package in the goType() if present 111 112 OrigShapeName string `json:"-"` 113 114 // Defines if the shape is a placeholder and should not be used directly 115 Placeholder bool 116 117 Deprecated bool `json:"deprecated"` 118 DeprecatedMsg string `json:"deprecatedMessage"` 119 120 Validations ShapeValidations 121 122 // Error information that is set if the shape is an error shape. 123 ErrorInfo ErrorInfo `json:"error"` 124 125 // Flags that the shape cannot be rename. Prevents the shape from being 126 // renamed further by the Input/Output. 127 AliasedShapeName bool 128 129 // Sensitive types should not be logged by SDK type loggers. 130 Sensitive bool `json:"sensitive"` 131 132 // Flags that a member of the shape is an EndpointARN 133 HasEndpointARNMember bool 134 135 // Flags that a member of the shape is an OutpostIDMember 136 HasOutpostIDMember bool 137 138 // Flags that the shape has an account id member along with EndpointARN member 139 HasAccountIdMemberWithARN bool 140 141 // Indicates the Shape is used as an operation input 142 UsedAsInput bool 143 144 // Indicates the Shape is used as an operation output 145 UsedAsOutput bool 146 147 // Indicates a structure shape is a document type 148 Document bool `json:"document"` 149 } 150 151 // CanBeEmpty returns if the shape value can sent request as an empty value. 152 // String, blob, list, and map are types must not be empty when the member is 153 // serialized to the URI path, or decorated with HostLabel. 154 func (ref *ShapeRef) CanBeEmpty() bool { 155 switch ref.Shape.Type { 156 case "string": 157 return !(ref.Location == "uri" || ref.HostLabel) 158 case "blob", "map", "list": 159 return !(ref.Location == "uri") 160 default: 161 return true 162 } 163 } 164 165 // ErrorCodeName will return the error shape's name formated for 166 // error code const. 167 func (s *Shape) ErrorCodeName() string { 168 return "ErrCode" + s.ShapeName 169 } 170 171 // ErrorName will return the shape's name or error code if available based 172 // on the API's protocol. This is the error code string returned by the service. 173 func (s *Shape) ErrorName() string { 174 name := s.ErrorInfo.Type 175 switch s.API.Metadata.Protocol { 176 case "query", "ec2query", "rest-xml": 177 if len(s.ErrorInfo.Code) > 0 { 178 name = s.ErrorInfo.Code 179 } 180 } 181 182 if len(name) == 0 { 183 name = s.OrigShapeName 184 } 185 if len(name) == 0 { 186 name = s.ShapeName 187 } 188 189 return name 190 } 191 192 // PayloadRefName returns the payload member of the shape if there is one 193 // modeled. If no payload is modeled, empty string will be returned. 194 func (s *Shape) PayloadRefName() string { 195 if name := s.Payload; len(name) != 0 { 196 // Root shape 197 return name 198 } 199 200 for name, ref := range s.MemberRefs { 201 if ref.IsEventPayload { 202 return name 203 } 204 } 205 206 return "" 207 } 208 209 // GoTags returns the struct tags for a shape. 210 func (s *Shape) GoTags(root, required bool) string { 211 ref := &ShapeRef{ShapeName: s.ShapeName, API: s.API, Shape: s} 212 return ref.GoTags(root, required) 213 } 214 215 // Rename changes the name of the Shape to newName. Also updates 216 // the associated API's reference to use newName. 217 func (s *Shape) Rename(newName string) { 218 if s.AliasedShapeName { 219 panic(fmt.Sprintf("attempted to rename %s, but flagged as aliased", 220 s.ShapeName)) 221 } 222 223 for _, r := range s.refs { 224 r.ShapeName = newName 225 } 226 227 delete(s.API.Shapes, s.ShapeName) 228 s.API.Shapes[newName] = s 229 s.ShapeName = newName 230 } 231 232 // MemberNames returns a slice of struct member names. 233 func (s *Shape) MemberNames() []string { 234 i, names := 0, make([]string, len(s.MemberRefs)) 235 for n := range s.MemberRefs { 236 names[i] = n 237 i++ 238 } 239 sort.Strings(names) 240 return names 241 } 242 243 // HasMember will return whether or not the shape has a given 244 // member by name. 245 func (s *Shape) HasMember(name string) bool { 246 _, ok := s.MemberRefs[name] 247 return ok 248 } 249 250 // GoTypeWithPkgName returns a shape's type as a string with the package name in 251 // <packageName>.<type> format. Package naming only applies to structures. 252 func (s *Shape) GoTypeWithPkgName() string { 253 return goType(s, true) 254 } 255 256 // GoTypeWithPkgNameElem returns the shapes type as a string with the "*" 257 // removed if there was one preset. 258 func (s *Shape) GoTypeWithPkgNameElem() string { 259 t := goType(s, true) 260 if strings.HasPrefix(t, "*") { 261 return t[1:] 262 } 263 return t 264 } 265 266 // UseIndirection returns if the shape's reference should use indirection or not. 267 func (s *ShapeRef) UseIndirection() bool { 268 switch s.Shape.Type { 269 case "map", "list", "blob", "structure", "jsonvalue": 270 return false 271 } 272 273 if s.Streaming || s.Shape.Streaming { 274 return false 275 } 276 277 if s.JSONValue { 278 return false 279 } 280 281 return true 282 } 283 284 func (s Shape) GetTimestampFormat() string { 285 format := s.TimestampFormat 286 287 if len(format) > 0 && !protocol.IsKnownTimestampFormat(format) { 288 panic(fmt.Sprintf("Unknown timestampFormat %s, for %s", 289 format, s.ShapeName)) 290 } 291 292 return format 293 } 294 295 func (ref ShapeRef) GetTimestampFormat() string { 296 format := ref.TimestampFormat 297 298 if len(format) == 0 { 299 format = ref.Shape.TimestampFormat 300 } 301 302 if len(format) > 0 && !protocol.IsKnownTimestampFormat(format) { 303 panic(fmt.Sprintf("Unknown timestampFormat %s, for %s", 304 format, ref.ShapeName)) 305 } 306 307 return format 308 } 309 310 // GoStructValueType returns the Shape's Go type value instead of a pointer 311 // for the type. 312 func (s *Shape) GoStructValueType(name string, ref *ShapeRef) string { 313 v := s.GoStructType(name, ref) 314 315 if ref.UseIndirection() && v[0] == '*' { 316 return v[1:] 317 } 318 319 return v 320 } 321 322 // GoStructType returns the type of a struct field based on the API 323 // model definition. 324 func (s *Shape) GoStructType(name string, ref *ShapeRef) string { 325 if (ref.Streaming || ref.Shape.Streaming) && s.Payload == name { 326 rtype := "io.ReadSeeker" 327 if strings.HasSuffix(s.ShapeName, "Output") { 328 rtype = "io.ReadCloser" 329 } 330 331 s.API.imports["io"] = true 332 return rtype 333 } 334 335 if ref.JSONValue { 336 s.API.AddSDKImport("aws") 337 return "aws.JSONValue" 338 } 339 340 for _, v := range s.Validations { 341 // TODO move this to shape validation resolution 342 if (v.Ref.Shape.Type == "map" || v.Ref.Shape.Type == "list") && v.Type == ShapeValidationNested { 343 s.API.imports["fmt"] = true 344 } 345 } 346 347 return ref.GoType() 348 } 349 350 // GoType returns a shape's Go type 351 func (s *Shape) GoType() string { 352 return goType(s, false) 353 } 354 355 // GoType returns a shape ref's Go type. 356 func (ref *ShapeRef) GoType() string { 357 if ref.Shape == nil { 358 panic(fmt.Errorf("missing shape definition on reference for %#v", ref)) 359 } 360 361 return ref.Shape.GoType() 362 } 363 364 // GoTypeWithPkgName returns a shape's type as a string with the package name in 365 // <packageName>.<type> format. Package naming only applies to structures. 366 func (ref *ShapeRef) GoTypeWithPkgName() string { 367 if ref.Shape == nil { 368 panic(fmt.Errorf("missing shape definition on reference for %#v", ref)) 369 } 370 371 return ref.Shape.GoTypeWithPkgName() 372 } 373 374 // Returns a string version of the Shape's type. 375 // If withPkgName is true, the package name will be added as a prefix 376 func goType(s *Shape, withPkgName bool) string { 377 switch s.Type { 378 case "structure": 379 if withPkgName || s.resolvePkg != "" { 380 pkg := s.resolvePkg 381 if pkg != "" { 382 s.API.imports[pkg] = true 383 pkg = path.Base(pkg) 384 } else { 385 pkg = s.API.PackageName() 386 } 387 return fmt.Sprintf("*%s.%s", pkg, s.ShapeName) 388 } 389 return "*" + s.ShapeName 390 case "map": 391 return "map[string]" + goType(s.ValueRef.Shape, withPkgName) 392 case "jsonvalue": 393 return "aws.JSONValue" 394 case "list": 395 return "[]" + goType(s.MemberRef.Shape, withPkgName) 396 case "boolean": 397 return "*bool" 398 case "string", "character": 399 return "*string" 400 case "blob": 401 return "[]byte" 402 case "byte", "short", "integer", "long": 403 return "*int64" 404 case "float", "double": 405 return "*float64" 406 case "timestamp": 407 s.API.imports["time"] = true 408 return "*time.Time" 409 default: 410 panic("Unsupported shape type: " + s.Type) 411 } 412 } 413 414 // GoTypeElem returns the Go type for the Shape. If the shape type is a pointer just 415 // the type will be returned minus the pointer *. 416 func (s *Shape) GoTypeElem() string { 417 t := s.GoType() 418 if strings.HasPrefix(t, "*") { 419 return t[1:] 420 } 421 return t 422 } 423 424 // GoTypeElem returns the Go type for the Shape. If the shape type is a pointer just 425 // the type will be returned minus the pointer *. 426 func (ref *ShapeRef) GoTypeElem() string { 427 if ref.Shape == nil { 428 panic(fmt.Errorf("missing shape definition on reference for %#v", ref)) 429 } 430 431 return ref.Shape.GoTypeElem() 432 } 433 434 // ShapeTag is a struct tag that will be applied to a shape's generated code 435 type ShapeTag struct { 436 Key, Val string 437 } 438 439 // String returns the string representation of the shape tag 440 func (s ShapeTag) String() string { 441 return fmt.Sprintf(`%s:"%s"`, s.Key, s.Val) 442 } 443 444 // ShapeTags is a collection of shape tags and provides serialization of the 445 // tags in an ordered list. 446 type ShapeTags []ShapeTag 447 448 // Join returns an ordered serialization of the shape tags with the provided 449 // separator. 450 func (s ShapeTags) Join(sep string) string { 451 o := &bytes.Buffer{} 452 for i, t := range s { 453 o.WriteString(t.String()) 454 if i < len(s)-1 { 455 o.WriteString(sep) 456 } 457 } 458 459 return o.String() 460 } 461 462 // String is an alias for Join with the empty space separator. 463 func (s ShapeTags) String() string { 464 return s.Join(" ") 465 } 466 467 // GoTags returns the rendered tags string for the ShapeRef 468 func (ref *ShapeRef) GoTags(toplevel bool, isRequired bool) string { 469 tags := append(ShapeTags{}, ref.CustomTags...) 470 471 if ref.Location != "" { 472 tags = append(tags, ShapeTag{"location", ref.Location}) 473 } else if ref.Shape.Location != "" { 474 tags = append(tags, ShapeTag{"location", ref.Shape.Location}) 475 } else if ref.IsEventHeader { 476 tags = append(tags, ShapeTag{"location", "header"}) 477 } 478 479 if ref.LocationName != "" { 480 tags = append(tags, ShapeTag{"locationName", ref.LocationName}) 481 } else if ref.Shape.LocationName != "" { 482 tags = append(tags, ShapeTag{"locationName", ref.Shape.LocationName}) 483 } else if len(ref.Shape.EventFor) != 0 && ref.API.Metadata.Protocol == "rest-xml" { 484 // RPC JSON events need to have location name modeled for round trip testing. 485 tags = append(tags, ShapeTag{"locationName", ref.Shape.OrigShapeName}) 486 } 487 488 if ref.QueryName != "" { 489 tags = append(tags, ShapeTag{"queryName", ref.QueryName}) 490 } 491 if ref.Shape.MemberRef.LocationName != "" { 492 tags = append(tags, ShapeTag{"locationNameList", ref.Shape.MemberRef.LocationName}) 493 } 494 if ref.Shape.KeyRef.LocationName != "" { 495 tags = append(tags, ShapeTag{"locationNameKey", ref.Shape.KeyRef.LocationName}) 496 } 497 if ref.Shape.ValueRef.LocationName != "" { 498 tags = append(tags, ShapeTag{"locationNameValue", ref.Shape.ValueRef.LocationName}) 499 } 500 if ref.Shape.Min > 0 { 501 tags = append(tags, ShapeTag{"min", fmt.Sprintf("%v", ref.Shape.Min)}) 502 } 503 504 if ref.Deprecated || ref.Shape.Deprecated { 505 tags = append(tags, ShapeTag{"deprecated", "true"}) 506 } 507 508 // All shapes have a type 509 tags = append(tags, ShapeTag{"type", ref.Shape.Type}) 510 511 // embed the timestamp type for easier lookups 512 if ref.Shape.Type == "timestamp" { 513 if format := ref.GetTimestampFormat(); len(format) > 0 { 514 tags = append(tags, ShapeTag{ 515 Key: "timestampFormat", 516 Val: format, 517 }) 518 } 519 } 520 521 if ref.Shape.Flattened || ref.Flattened { 522 tags = append(tags, ShapeTag{"flattened", "true"}) 523 } 524 if ref.XMLAttribute { 525 tags = append(tags, ShapeTag{"xmlAttribute", "true"}) 526 } 527 if isRequired { 528 tags = append(tags, ShapeTag{"required", "true"}) 529 } 530 if ref.Shape.IsEnum() { 531 tags = append(tags, ShapeTag{"enum", ref.ShapeName}) 532 } 533 534 if toplevel { 535 if name := ref.Shape.PayloadRefName(); len(name) > 0 { 536 tags = append(tags, ShapeTag{"payload", name}) 537 } 538 if !ref.Shape.HasPayloadMembers() && ref.API.Metadata.Protocol == "rest-json" { 539 tags = append(tags, ShapeTag{"nopayload", "true"}) 540 } 541 } 542 543 if ref.XMLNamespace.Prefix != "" { 544 tags = append(tags, ShapeTag{"xmlPrefix", ref.XMLNamespace.Prefix}) 545 } else if ref.Shape.XMLNamespace.Prefix != "" { 546 tags = append(tags, ShapeTag{"xmlPrefix", ref.Shape.XMLNamespace.Prefix}) 547 } 548 549 if ref.XMLNamespace.URI != "" { 550 tags = append(tags, ShapeTag{"xmlURI", ref.XMLNamespace.URI}) 551 } else if ref.Shape.XMLNamespace.URI != "" { 552 tags = append(tags, ShapeTag{"xmlURI", ref.Shape.XMLNamespace.URI}) 553 } 554 555 if ref.IdempotencyToken || ref.Shape.IdempotencyToken { 556 tags = append(tags, ShapeTag{"idempotencyToken", "true"}) 557 } 558 559 if ref.Ignore { 560 tags = append(tags, ShapeTag{"ignore", "true"}) 561 } 562 563 if ref.Shape.Sensitive { 564 tags = append(tags, ShapeTag{"sensitive", "true"}) 565 } 566 567 return fmt.Sprintf("`%s`", tags) 568 } 569 570 // HasPayloadMembers returns if the shape has any members that will be 571 // serialized to the payload of a API message. 572 func (s *Shape) HasPayloadMembers() bool { 573 for _, ref := range s.MemberRefs { 574 if ref.Location == "" && ref.Shape.Location == "" { 575 return true 576 } 577 } 578 579 return false 580 } 581 582 // Docstring returns the godocs formated documentation 583 func (ref *ShapeRef) Docstring() string { 584 if ref.Documentation != "" { 585 return strings.Trim(ref.Documentation, "\n ") 586 } 587 return ref.Shape.Docstring() 588 } 589 590 // Docstring returns the godocs formated documentation 591 func (s *Shape) Docstring() string { 592 return strings.Trim(s.Documentation, "\n ") 593 } 594 595 // IndentedDocstring is the indented form of the doc string. 596 func (ref *ShapeRef) IndentedDocstring() string { 597 doc := ref.Docstring() 598 return strings.Replace(doc, "// ", "// ", -1) 599 } 600 601 var goCodeStringerTmpl = template.Must(template.New("goCodeStringerTmpl").Parse(` 602 // String returns the string representation. 603 // 604 // API parameter values that are decorated as "sensitive" in the API will not 605 // be included in the string output. The member name will be present, but the 606 // value will be replaced with "sensitive". 607 func (s {{ $.ShapeName }}) String() string { 608 return awsutil.Prettify(s) 609 } 610 // GoString returns the string representation. 611 // 612 // API parameter values that are decorated as "sensitive" in the API will not 613 // be included in the string output. The member name will be present, but the 614 // value will be replaced with "sensitive". 615 func (s {{ $.ShapeName }}) GoString() string { 616 return s.String() 617 } 618 `)) 619 620 // GoCodeStringers renders the Stringers for API input/output shapes 621 func (s *Shape) GoCodeStringers() string { 622 w := bytes.Buffer{} 623 if err := goCodeStringerTmpl.Execute(&w, s); err != nil { 624 panic(fmt.Sprintln("Unexpected error executing GoCodeStringers template", err)) 625 } 626 627 return w.String() 628 } 629 630 var enumStrip = regexp.MustCompile(`[^a-zA-Z0-9_:\./-]`) 631 var enumDelims = regexp.MustCompile(`[-_:\./]+`) 632 var enumCamelCase = regexp.MustCompile(`([a-z])([A-Z])`) 633 634 // EnumName returns the Nth enum in the shapes Enum list 635 func (s *Shape) EnumName(n int) string { 636 enum := s.Enum[n] 637 enum = enumStrip.ReplaceAllLiteralString(enum, "") 638 enum = enumCamelCase.ReplaceAllString(enum, "$1-$2") 639 parts := enumDelims.Split(enum, -1) 640 for i, v := range parts { 641 v = strings.ToLower(v) 642 parts[i] = "" 643 if len(v) > 0 { 644 parts[i] = strings.ToUpper(v[0:1]) 645 } 646 if len(v) > 1 { 647 parts[i] += v[1:] 648 } 649 } 650 enum = strings.Join(parts, "") 651 enum = strings.ToUpper(enum[0:1]) + enum[1:] 652 return enum 653 } 654 655 // NestedShape returns the shape pointer value for the shape which is nested 656 // under the current shape. If the shape is not nested nil will be returned. 657 // 658 // strucutures, the current shape is returned 659 // map: the value shape of the map is returned 660 // list: the element shape of the list is returned 661 func (s *Shape) NestedShape() *Shape { 662 var nestedShape *Shape 663 switch s.Type { 664 case "structure": 665 nestedShape = s 666 case "map": 667 nestedShape = s.ValueRef.Shape 668 case "list": 669 nestedShape = s.MemberRef.Shape 670 } 671 672 return nestedShape 673 } 674 675 var structShapeTmpl = func() *template.Template { 676 shapeTmpl := template.Must( 677 template.New("structShapeTmpl"). 678 Funcs(template.FuncMap{ 679 "GetDeprecatedMsg": getDeprecatedMessage, 680 "TrimExportedMembers": func(s *Shape) map[string]*ShapeRef { 681 members := map[string]*ShapeRef{} 682 for name, ref := range s.MemberRefs { 683 if ref.Shape.IsEventStream { 684 continue 685 } 686 members[name] = ref 687 } 688 return members 689 }, 690 }). 691 Parse(structShapeTmplDef), 692 ) 693 694 template.Must( 695 shapeTmpl.AddParseTree( 696 "eventStreamEventShapeTmpl", eventStreamEventShapeTmpl.Tree), 697 ) 698 template.Must( 699 shapeTmpl.AddParseTree( 700 "exceptionShapeMethodTmpl", 701 exceptionShapeMethodTmpl.Tree), 702 ) 703 shapeTmpl.Funcs(eventStreamEventShapeTmplFuncs) 704 705 template.Must( 706 shapeTmpl.AddParseTree( 707 "hostLabelsShapeTmpl", 708 hostLabelsShapeTmpl.Tree), 709 ) 710 711 template.Must( 712 shapeTmpl.AddParseTree( 713 "endpointARNShapeTmpl", 714 endpointARNShapeTmpl.Tree), 715 ) 716 717 template.Must( 718 shapeTmpl.AddParseTree( 719 "outpostIDShapeTmpl", 720 outpostIDShapeTmpl.Tree), 721 ) 722 723 template.Must( 724 shapeTmpl.AddParseTree( 725 "accountIDWithARNShapeTmpl", 726 accountIDWithARNShapeTmpl.Tree), 727 ) 728 729 return shapeTmpl 730 }() 731 732 const structShapeTmplDef = ` 733 {{ $.Docstring }} 734 {{ if $.Deprecated -}} 735 {{ if $.Docstring -}} 736 // 737 {{ end -}} 738 // Deprecated: {{ GetDeprecatedMsg $.DeprecatedMsg $.ShapeName }} 739 {{ end -}} 740 type {{ $.ShapeName }} struct { 741 _ struct{} {{ $.GoTags true false }} 742 743 {{- if $.Exception }} 744 {{- $_ := $.API.AddSDKImport "private/protocol" }} 745 RespMetadata protocol.ResponseMetadata` + "`json:\"-\" xml:\"-\"`" + ` 746 {{- end }} 747 748 {{- if $.OutputEventStreamAPI }} 749 750 {{ $.OutputEventStreamAPI.OutputMemberName }} *{{ $.OutputEventStreamAPI.Name }} 751 {{- end }} 752 753 {{- range $name, $elem := (TrimExportedMembers $) }} 754 755 {{ $isBlob := $.WillRefBeBase64Encoded $name -}} 756 {{ $isRequired := $.IsRequired $name -}} 757 {{ $isSensitive := $elem.Shape.Sensitive -}} 758 {{ $doc := $elem.Docstring -}} 759 760 {{ if $doc -}} 761 {{ $doc }} 762 {{ if $elem.Deprecated -}} 763 // 764 // Deprecated: {{ GetDeprecatedMsg $elem.DeprecatedMsg $name }} 765 {{ end -}} 766 {{ end -}} 767 {{ if $isSensitive -}} 768 {{ if $doc -}} 769 // 770 {{ end -}} 771 // {{ $name }} is a sensitive parameter and its value will be 772 // replaced with "sensitive" in string returned by {{ $.ShapeName }}'s 773 // String and GoString methods. 774 {{ end -}} 775 {{ if $isBlob -}} 776 {{ if $isSensitive -}} 777 // 778 {{ end -}} 779 // {{ $name }} is automatically base64 encoded/decoded by the SDK. 780 {{ end -}} 781 {{ if $isRequired -}} 782 {{ if or $doc $isBlob -}} 783 // 784 {{ end -}} 785 // {{ $name }} is a required field 786 {{ end -}} 787 {{ $name }} {{ $.GoStructType $name $elem }} {{ $elem.GoTags false $isRequired }} 788 {{- end }} 789 } 790 791 {{- if not $.API.NoStringerMethods }} 792 {{ $.GoCodeStringers }} 793 {{- end }} 794 795 {{- if not (or $.API.NoValidataShapeMethods $.Exception) }} 796 {{- if $.Validations }} 797 {{ $.Validations.GoCode $ }} 798 {{- end }} 799 {{- end }} 800 801 {{- if not (or $.API.NoGenStructFieldAccessors $.Exception) }} 802 {{- $builderShapeName := print $.ShapeName }} 803 804 {{- range $name, $elem := (TrimExportedMembers $) }} 805 // Set{{ $name }} sets the {{ $name }} field's value. 806 func (s *{{ $builderShapeName }}) Set{{ $name }}(v {{ $.GoStructValueType $name $elem }}) *{{ $builderShapeName }} { 807 {{- if $elem.UseIndirection }} 808 s.{{ $name }} = &v 809 {{- else }} 810 s.{{ $name }} = v 811 {{- end }} 812 return s 813 } 814 815 {{- if $elem.GenerateGetter }} 816 817 func (s *{{ $builderShapeName }}) get{{ $name }}() (v {{ $.GoStructValueType $name $elem }}) { 818 {{- if $elem.UseIndirection }} 819 if s.{{ $name }} == nil { 820 return v 821 } 822 return *s.{{ $name }} 823 {{- else }} 824 return s.{{ $name }} 825 {{- end }} 826 } 827 {{- end }} 828 {{- end }} 829 {{- end }} 830 831 {{- if $.OutputEventStreamAPI }} 832 {{- $esMemberName := $.OutputEventStreamAPI.OutputMemberName }} 833 {{- if $.OutputEventStreamAPI.Legacy }} 834 func (s *{{ $.ShapeName }}) Set{{ $esMemberName }}(v *{{ $.OutputEventStreamAPI.Name }}) *{{ $.ShapeName }} { 835 s.{{ $esMemberName }} = v 836 return s 837 } 838 func (s *{{ $.ShapeName }}) Get{{ $esMemberName }}() *{{ $.OutputEventStreamAPI.Name }} { 839 return s.{{ $esMemberName }} 840 } 841 {{- end }} 842 843 // GetStream returns the type to interact with the event stream. 844 func (s *{{ $.ShapeName }}) GetStream() *{{ $.OutputEventStreamAPI.Name }} { 845 return s.{{ $esMemberName }} 846 } 847 {{- end }} 848 849 {{- if $.EventFor }} 850 {{ template "eventStreamEventShapeTmpl" $ }} 851 {{- end }} 852 853 {{- if and $.Exception (or $.API.WithGeneratedTypedErrors $.EventFor) }} 854 {{ template "exceptionShapeMethodTmpl" $ }} 855 {{- end }} 856 857 {{- if $.HasHostLabelMembers }} 858 {{ template "hostLabelsShapeTmpl" $ }} 859 {{- end }} 860 861 {{- if $.HasEndpointARNMember }} 862 {{ template "endpointARNShapeTmpl" $ }} 863 {{- end }} 864 865 {{- if $.HasOutpostIDMember }} 866 {{ template "outpostIDShapeTmpl" $ }} 867 {{- end }} 868 869 {{- if $.HasAccountIdMemberWithARN }} 870 {{ template "accountIDWithARNShapeTmpl" $ }} 871 {{- end }} 872 873 ` 874 875 var exceptionShapeMethodTmpl = template.Must( 876 template.New("exceptionShapeMethodTmpl").Parse(` 877 {{- $_ := $.API.AddImport "fmt" }} 878 {{/* TODO allow service custom input to be used */}} 879 func newError{{ $.ShapeName }}(v protocol.ResponseMetadata) error { 880 return &{{ $.ShapeName }}{ 881 RespMetadata: v, 882 } 883 } 884 885 // Code returns the exception type name. 886 func (s *{{ $.ShapeName }}) Code() string { 887 return "{{ $.ErrorName }}" 888 } 889 890 // Message returns the exception's message. 891 func (s *{{ $.ShapeName }}) Message() string { 892 {{- if index $.MemberRefs "Message_" }} 893 if s.Message_ != nil { 894 return *s.Message_ 895 } 896 {{ end -}} 897 return "" 898 } 899 900 // OrigErr always returns nil, satisfies awserr.Error interface. 901 func (s *{{ $.ShapeName }}) OrigErr() error { 902 return nil 903 } 904 905 func (s *{{ $.ShapeName }}) Error() string { 906 {{- if or (and (eq (len $.MemberRefs) 1) (not (index $.MemberRefs "Message_"))) (gt (len $.MemberRefs) 1) }} 907 return fmt.Sprintf("%s: %s\n%s", s.Code(), s.Message(), s.String()) 908 {{- else }} 909 return fmt.Sprintf("%s: %s", s.Code(), s.Message()) 910 {{- end }} 911 } 912 913 // Status code returns the HTTP status code for the request's response error. 914 func (s *{{ $.ShapeName }}) StatusCode() int { 915 return s.RespMetadata.StatusCode 916 } 917 918 // RequestID returns the service's response RequestID for request. 919 func (s *{{ $.ShapeName }}) RequestID() string { 920 return s.RespMetadata.RequestID 921 } 922 `)) 923 924 var enumShapeTmpl = template.Must(template.New("EnumShape").Parse(` 925 {{ $.Docstring }} 926 const ( 927 {{ range $index, $elem := $.Enum -}} 928 {{ $name := index $.EnumConsts $index -}} 929 // {{ $name }} is a {{ $.ShapeName }} enum value 930 {{ $name }} = "{{ $elem }}" 931 932 {{ end }} 933 ) 934 935 {{/* Enum iterators use non-idomatic _Values suffix to avoid naming collisions with other generated types, and enum values */}} 936 // {{ $.ShapeName }}_Values returns all elements of the {{ $.ShapeName }} enum 937 func {{ $.ShapeName }}_Values() []string { 938 return []string{ 939 {{ range $index, $elem := $.Enum -}} 940 {{ index $.EnumConsts $index }}, 941 {{ end }} 942 } 943 } 944 `)) 945 946 // GoCode returns the rendered Go code for the Shape. 947 func (s *Shape) GoCode() string { 948 w := &bytes.Buffer{} 949 950 switch { 951 case s.IsEventStream: 952 if err := renderEventStreamShape(w, s); err != nil { 953 panic( 954 fmt.Sprintf( 955 "failed to generate eventstream API shape, %s, %v", 956 s.ShapeName, err), 957 ) 958 } 959 case s.Type == "structure": 960 if err := structShapeTmpl.Execute(w, s); err != nil { 961 panic( 962 fmt.Sprintf( 963 "Failed to generate struct shape %s, %v", 964 s.ShapeName, err), 965 ) 966 } 967 case s.IsEnum(): 968 if err := enumShapeTmpl.Execute(w, s); err != nil { 969 panic( 970 fmt.Sprintf( 971 "Failed to generate enum shape %s, %v", 972 s.ShapeName, err), 973 ) 974 } 975 default: 976 panic(fmt.Sprintln("Cannot generate toplevel shape for", s.Type)) 977 } 978 979 return w.String() 980 } 981 982 // IsEnum returns whether this shape is an enum list 983 func (s *Shape) IsEnum() bool { 984 return s.Type == "string" && len(s.Enum) > 0 985 } 986 987 // IsRequired returns if member is a required field. Required fields are fields 988 // marked as required, hostLabels, or location of uri path. 989 func (s *Shape) IsRequired(member string) bool { 990 ref, ok := s.MemberRefs[member] 991 if !ok { 992 panic(fmt.Sprintf( 993 "attempted to check required for unknown member, %s.%s", 994 s.ShapeName, member, 995 )) 996 } 997 if ref.IdempotencyToken || ref.Shape.IdempotencyToken { 998 return false 999 } 1000 if ref.Location == "uri" || ref.HostLabel { 1001 return true 1002 } 1003 for _, n := range s.Required { 1004 if n == member { 1005 if ref.Shape.IsEventStream { 1006 return false 1007 } 1008 return true 1009 } 1010 } 1011 return false 1012 } 1013 1014 // IsInternal returns whether the shape was defined in this package 1015 func (s *Shape) IsInternal() bool { 1016 return s.resolvePkg == "" 1017 } 1018 1019 // removeRef removes a shape reference from the list of references this 1020 // shape is used in. 1021 func (s *Shape) removeRef(ref *ShapeRef) { 1022 r := s.refs 1023 for i := 0; i < len(r); i++ { 1024 if r[i] == ref { 1025 j := i + 1 1026 copy(r[i:], r[j:]) 1027 for k, n := len(r)-j+i, len(r); k < n; k++ { 1028 r[k] = nil // free up the end of the list 1029 } // for k 1030 s.refs = r[:len(r)-j+i] 1031 break 1032 } 1033 } 1034 } 1035 1036 func (s *Shape) WillRefBeBase64Encoded(refName string) bool { 1037 payloadRefName := s.Payload 1038 if payloadRefName == refName { 1039 return false 1040 } 1041 1042 ref, ok := s.MemberRefs[refName] 1043 if !ok { 1044 panic(fmt.Sprintf("shape %s does not contain %q refName", s.ShapeName, refName)) 1045 } 1046 1047 return ref.Shape.Type == "blob" 1048 } 1049 1050 // Clone returns a cloned version of the shape with all references clones. 1051 // 1052 // Does not clone EventStream or Validate related values. 1053 func (s *Shape) Clone(newName string) *Shape { 1054 if s.AliasedShapeName { 1055 panic(fmt.Sprintf("attempted to clone and rename %s, but flagged as aliased", 1056 s.ShapeName)) 1057 } 1058 1059 n := new(Shape) 1060 *n = *s 1061 1062 debugLogger.Logln("cloning", s.ShapeName, "to", newName) 1063 1064 n.MemberRefs = map[string]*ShapeRef{} 1065 for k, r := range s.MemberRefs { 1066 nr := new(ShapeRef) 1067 *nr = *r 1068 nr.Shape.refs = append(nr.Shape.refs, nr) 1069 n.MemberRefs[k] = nr 1070 } 1071 1072 if n.MemberRef.Shape != nil { 1073 n.MemberRef.Shape.refs = append(n.MemberRef.Shape.refs, &n.MemberRef) 1074 } 1075 if n.KeyRef.Shape != nil { 1076 n.KeyRef.Shape.refs = append(n.KeyRef.Shape.refs, &n.KeyRef) 1077 } 1078 if n.ValueRef.Shape != nil { 1079 n.ValueRef.Shape.refs = append(n.ValueRef.Shape.refs, &n.ValueRef) 1080 } 1081 1082 n.refs = []*ShapeRef{} 1083 1084 n.Required = append([]string{}, n.Required...) 1085 n.Enum = append([]string{}, n.Enum...) 1086 n.EnumConsts = append([]string{}, n.EnumConsts...) 1087 1088 n.API.Shapes[newName] = n 1089 n.ShapeName = newName 1090 n.OrigShapeName = s.OrigShapeName 1091 1092 return n 1093 }