1// +build codegen 2 3package api 4 5import ( 6 "bytes" 7 "fmt" 8 "regexp" 9 "sort" 10 "strings" 11 "text/template" 12) 13 14// An Operation defines a specific API Operation. 15type Operation struct { 16 API *API `json:"-"` 17 ExportedName string 18 Name string 19 Documentation string 20 HTTP HTTPInfo 21 Host string `json:"host"` 22 InputRef ShapeRef `json:"input"` 23 OutputRef ShapeRef `json:"output"` 24 ErrorRefs []ShapeRef `json:"errors"` 25 Paginator *Paginator 26 Deprecated bool `json:"deprecated"` 27 DeprecatedMsg string `json:"deprecatedMessage"` 28 AuthType AuthType `json:"authtype"` 29 imports map[string]bool 30 CustomBuildHandlers []string 31 32 EventStreamAPI *EventStreamAPI 33 34 IsEndpointDiscoveryOp bool `json:"endpointoperation"` 35 EndpointDiscovery *EndpointDiscovery `json:"endpointdiscovery"` 36 Endpoint *EndpointTrait `json:"endpoint"` 37} 38 39// EndpointTrait provides the structure of the modeled enpdoint trait, and its 40// properties. 41type EndpointTrait struct { 42 // Specifies the hostPrefix template to prepend to the operation's request 43 // endpoint host. 44 HostPrefix string `json:"hostPrefix"` 45} 46 47// EndpointDiscovery represents a map of key values pairs that represents 48// metadata about how a given API will make a call to the discovery endpoint. 49type EndpointDiscovery struct { 50 // Required indicates that for a given operation that endpoint is required. 51 // Any required endpoint discovery operation cannot have endpoint discovery 52 // turned off. 53 Required bool `json:"required"` 54} 55 56// OperationForMethod returns the API operation name that corresponds to the 57// client method name provided. 58func (a *API) OperationForMethod(name string) *Operation { 59 for _, op := range a.Operations { 60 for _, m := range op.Methods() { 61 if m == name { 62 return op 63 } 64 } 65 } 66 67 return nil 68} 69 70// A HTTPInfo defines the method of HTTP request for the Operation. 71type HTTPInfo struct { 72 Method string 73 RequestURI string 74 ResponseCode uint 75} 76 77// Methods Returns a list of method names that will be generated. 78func (o *Operation) Methods() []string { 79 methods := []string{ 80 o.ExportedName, 81 o.ExportedName + "Request", 82 o.ExportedName + "WithContext", 83 } 84 85 if o.Paginator != nil { 86 methods = append(methods, []string{ 87 o.ExportedName + "Pages", 88 o.ExportedName + "PagesWithContext", 89 }...) 90 } 91 92 return methods 93} 94 95// HasInput returns if the Operation accepts an input paramater 96func (o *Operation) HasInput() bool { 97 return o.InputRef.ShapeName != "" 98} 99 100// HasOutput returns if the Operation accepts an output parameter 101func (o *Operation) HasOutput() bool { 102 return o.OutputRef.ShapeName != "" 103} 104 105// AuthType provides the enumeration of AuthType trait. 106type AuthType string 107 108// Enumeration values for AuthType trait 109const ( 110 NoneAuthType AuthType = "none" 111 V4UnsignedBodyAuthType AuthType = "v4-unsigned-body" 112) 113 114// GetSigner returns the signer that should be used for a API request. 115func (o *Operation) GetSigner() string { 116 buf := bytes.NewBuffer(nil) 117 118 switch o.AuthType { 119 case NoneAuthType: 120 o.API.AddSDKImport("aws/credentials") 121 122 buf.WriteString("req.Config.Credentials = credentials.AnonymousCredentials") 123 case V4UnsignedBodyAuthType: 124 o.API.AddSDKImport("aws/signer/v4") 125 126 buf.WriteString("req.Handlers.Sign.Remove(v4.SignRequestHandler)\n") 127 buf.WriteString("handler := v4.BuildNamedHandler(\"v4.CustomSignerHandler\", v4.WithUnsignedPayload)\n") 128 buf.WriteString("req.Handlers.Sign.PushFrontNamed(handler)") 129 } 130 131 buf.WriteString("\n") 132 return buf.String() 133} 134 135// operationTmpl defines a template for rendering an API Operation 136var operationTmpl = template.Must(template.New("operation").Funcs(template.FuncMap{ 137 "GetCrosslinkURL": GetCrosslinkURL, 138 "EnableStopOnSameToken": enableStopOnSameToken, 139 "GetDeprecatedMsg": getDeprecatedMessage, 140}).Parse(` 141const op{{ .ExportedName }} = "{{ .Name }}" 142 143// {{ .ExportedName }}Request generates a "aws/request.Request" representing the 144// client's request for the {{ .ExportedName }} operation. The "output" return 145// value will be populated with the request's response once the request completes 146// successfully. 147// 148// Use "Send" method on the returned Request to send the API call to the service. 149// the "output" return value is not valid until after Send returns without error. 150// 151// See {{ .ExportedName }} for more information on using the {{ .ExportedName }} 152// API call, and error handling. 153// 154// This method is useful when you want to inject custom logic or configuration 155// into the SDK's request lifecycle. Such as custom headers, or retry logic. 156// 157// 158// // Example sending a request using the {{ .ExportedName }}Request method. 159// req, resp := client.{{ .ExportedName }}Request(params) 160// 161// err := req.Send() 162// if err == nil { // resp is now filled 163// fmt.Println(resp) 164// } 165{{ $crosslinkURL := GetCrosslinkURL $.API.BaseCrosslinkURL $.API.Metadata.UID $.ExportedName -}} 166{{ if ne $crosslinkURL "" -}} 167// 168// See also, {{ $crosslinkURL }} 169{{ end -}} 170{{- if .Deprecated }}// 171// Deprecated: {{ GetDeprecatedMsg .DeprecatedMsg .ExportedName }} 172{{ end -}} 173func (c *{{ .API.StructName }}) {{ .ExportedName }}Request(` + 174 `input {{ .InputRef.GoType }}) (req *request.Request, output {{ .OutputRef.GoType }}) { 175 {{ if (or .Deprecated (or .InputRef.Deprecated .OutputRef.Deprecated)) }}if c.Client.Config.Logger != nil { 176 c.Client.Config.Logger.Log("This operation, {{ .ExportedName }}, has been deprecated") 177 } 178 op := &request.Operation{ {{ else }} op := &request.Operation{ {{ end }} 179 Name: op{{ .ExportedName }}, 180 {{ if ne .HTTP.Method "" }}HTTPMethod: "{{ .HTTP.Method }}", 181 {{ end }}HTTPPath: {{ if ne .HTTP.RequestURI "" }}"{{ .HTTP.RequestURI }}"{{ else }}"/"{{ end }}, 182 {{ if .Paginator }}Paginator: &request.Paginator{ 183 InputTokens: {{ .Paginator.InputTokensString }}, 184 OutputTokens: {{ .Paginator.OutputTokensString }}, 185 LimitToken: "{{ .Paginator.LimitKey }}", 186 TruncationToken: "{{ .Paginator.MoreResults }}", 187 }, 188 {{ end }} 189 } 190 191 if input == nil { 192 input = &{{ .InputRef.GoTypeElem }}{} 193 } 194 195 output = &{{ .OutputRef.GoTypeElem }}{} 196 req = c.newRequest(op, input, output) 197 {{ if ne .AuthType "" }}{{ .GetSigner }}{{ end }} 198 {{- if .ShouldDiscardResponse -}} 199 {{- $_ := .API.AddSDKImport "private/protocol" -}} 200 {{- $_ := .API.AddSDKImport "private/protocol" .API.ProtocolPackage -}} 201 req.Handlers.Unmarshal.Swap({{ .API.ProtocolPackage }}.UnmarshalHandler.Name, protocol.UnmarshalDiscardBodyHandler) 202 {{ else if .OutputRef.Shape.EventStreamsMemberName -}} 203 {{- $_ := .API.AddSDKImport "private/protocol" .API.ProtocolPackage -}} 204 {{- $_ := .API.AddSDKImport "private/protocol/rest" -}} 205 req.Handlers.Send.Swap(client.LogHTTPResponseHandler.Name, client.LogHTTPResponseHeaderHandler) 206 req.Handlers.Unmarshal.Swap({{ .API.ProtocolPackage }}.UnmarshalHandler.Name, rest.UnmarshalHandler) 207 req.Handlers.Unmarshal.PushBack(output.runEventStreamLoop) 208 {{ if eq .API.Metadata.Protocol "json" -}} 209 req.Handlers.Unmarshal.PushBack(output.unmarshalInitialResponse) 210 {{ end -}} 211 {{ end -}} 212 {{ if .EndpointDiscovery -}} 213 {{if not .EndpointDiscovery.Required -}} 214 if aws.BoolValue(req.Config.EnableEndpointDiscovery) { 215 {{end -}} 216 de := discoverer{{ .API.EndpointDiscoveryOp.Name }}{ 217 Required: {{ .EndpointDiscovery.Required }}, 218 EndpointCache: c.endpointCache, 219 Params: map[string]*string{ 220 "op": aws.String(req.Operation.Name), 221 {{ range $key, $ref := .InputRef.Shape.MemberRefs -}} 222 {{ if $ref.EndpointDiscoveryID -}} 223 "{{ $ref.OrigShapeName }}": input.{{ $key }}, 224 {{ end -}} 225 {{- end }} 226 }, 227 Client: c, 228 } 229 230 for k, v := range de.Params { 231 if v == nil { 232 delete(de.Params, k) 233 } 234 } 235 236 req.Handlers.Build.PushFrontNamed(request.NamedHandler{ 237 Name: "crr.endpointdiscovery", 238 Fn: de.Handler, 239 }) 240 {{if not .EndpointDiscovery.Required -}} 241 } 242 {{ end -}} 243 {{ end -}} 244 {{- range $_, $handler := $.CustomBuildHandlers -}} 245 req.Handlers.Build.PushBackNamed({{ $handler }}) 246 {{ end -}} 247 return 248} 249 250// {{ .ExportedName }} API operation for {{ .API.Metadata.ServiceFullName }}. 251{{ if .Documentation -}} 252// 253{{ .Documentation }} 254{{ end -}} 255// 256// Returns awserr.Error for service API and SDK errors. Use runtime type assertions 257// with awserr.Error's Code and Message methods to get detailed information about 258// the error. 259// 260// See the AWS API reference guide for {{ .API.Metadata.ServiceFullName }}'s 261// API operation {{ .ExportedName }} for usage and error information. 262{{ if .ErrorRefs -}} 263// 264// Returned Error Codes: 265{{ range $_, $err := .ErrorRefs -}} 266// * {{ $err.Shape.ErrorCodeName }} "{{ $err.Shape.ErrorName}}" 267{{ if $err.Docstring -}} 268{{ $err.IndentedDocstring }} 269{{ end -}} 270// 271{{ end -}} 272{{ end -}} 273{{ $crosslinkURL := GetCrosslinkURL $.API.BaseCrosslinkURL $.API.Metadata.UID $.ExportedName -}} 274{{ if ne $crosslinkURL "" -}} 275// See also, {{ $crosslinkURL }} 276{{ end -}} 277{{- if .Deprecated }}// 278// Deprecated: {{ GetDeprecatedMsg .DeprecatedMsg .ExportedName }} 279{{ end -}} 280func (c *{{ .API.StructName }}) {{ .ExportedName }}(` + 281 `input {{ .InputRef.GoType }}) ({{ .OutputRef.GoType }}, error) { 282 req, out := c.{{ .ExportedName }}Request(input) 283 return out, req.Send() 284} 285 286// {{ .ExportedName }}WithContext is the same as {{ .ExportedName }} with the addition of 287// the ability to pass a context and additional request options. 288// 289// See {{ .ExportedName }} for details on how to use this API operation. 290// 291// The context must be non-nil and will be used for request cancellation. If 292// the context is nil a panic will occur. In the future the SDK may create 293// sub-contexts for http.Requests. See https://golang.org/pkg/context/ 294// for more information on using Contexts. 295{{ if .Deprecated }}// 296// Deprecated: {{ GetDeprecatedMsg .DeprecatedMsg (printf "%s%s" .ExportedName "WithContext") }} 297{{ end -}} 298func (c *{{ .API.StructName }}) {{ .ExportedName }}WithContext(` + 299 `ctx aws.Context, input {{ .InputRef.GoType }}, opts ...request.Option) ` + 300 `({{ .OutputRef.GoType }}, error) { 301 req, out := c.{{ .ExportedName }}Request(input) 302 req.SetContext(ctx) 303 req.ApplyOptions(opts...) 304 return out, req.Send() 305} 306 307{{ if .Paginator }} 308// {{ .ExportedName }}Pages iterates over the pages of a {{ .ExportedName }} operation, 309// calling the "fn" function with the response data for each page. To stop 310// iterating, return false from the fn function. 311// 312// See {{ .ExportedName }} method for more information on how to use this operation. 313// 314// Note: This operation can generate multiple requests to a service. 315// 316// // Example iterating over at most 3 pages of a {{ .ExportedName }} operation. 317// pageNum := 0 318// err := client.{{ .ExportedName }}Pages(params, 319// func(page {{ .OutputRef.Shape.GoTypeWithPkgName }}, lastPage bool) bool { 320// pageNum++ 321// fmt.Println(page) 322// return pageNum <= 3 323// }) 324// 325{{ if .Deprecated }}// 326// Deprecated: {{ GetDeprecatedMsg .DeprecatedMsg (printf "%s%s" .ExportedName "Pages") }} 327{{ end -}} 328func (c *{{ .API.StructName }}) {{ .ExportedName }}Pages(` + 329 `input {{ .InputRef.GoType }}, fn func({{ .OutputRef.GoType }}, bool) bool) error { 330 return c.{{ .ExportedName }}PagesWithContext(aws.BackgroundContext(), input, fn) 331} 332 333// {{ .ExportedName }}PagesWithContext same as {{ .ExportedName }}Pages except 334// it takes a Context and allows setting request options on the pages. 335// 336// The context must be non-nil and will be used for request cancellation. If 337// the context is nil a panic will occur. In the future the SDK may create 338// sub-contexts for http.Requests. See https://golang.org/pkg/context/ 339// for more information on using Contexts. 340{{ if .Deprecated }}// 341// Deprecated: {{ GetDeprecatedMsg .DeprecatedMsg (printf "%s%s" .ExportedName "PagesWithContext") }} 342{{ end -}} 343func (c *{{ .API.StructName }}) {{ .ExportedName }}PagesWithContext(` + 344 `ctx aws.Context, ` + 345 `input {{ .InputRef.GoType }}, ` + 346 `fn func({{ .OutputRef.GoType }}, bool) bool, ` + 347 `opts ...request.Option) error { 348 p := request.Pagination { 349 {{ if EnableStopOnSameToken .API.PackageName -}}EndPageOnSameToken: true, 350 {{ end -}} 351 NewRequest: func() (*request.Request, error) { 352 var inCpy {{ .InputRef.GoType }} 353 if input != nil { 354 tmp := *input 355 inCpy = &tmp 356 } 357 req, _ := c.{{ .ExportedName }}Request(inCpy) 358 req.SetContext(ctx) 359 req.ApplyOptions(opts...) 360 return req, nil 361 }, 362 } 363 364 cont := true 365 for p.Next() && cont { 366 cont = fn(p.Page().({{ .OutputRef.GoType }}), !p.HasNextPage()) 367 } 368 return p.Err() 369} 370{{ end }} 371 372{{ if .IsEndpointDiscoveryOp -}} 373 374type discoverer{{ .ExportedName }} struct { 375 Client *{{ .API.StructName }} 376 Required bool 377 EndpointCache *crr.EndpointCache 378 Params map[string]*string 379 Key string 380} 381 382func (d *discoverer{{ .ExportedName }}) Discover() (crr.Endpoint, error) { 383 input := &{{ .API.EndpointDiscoveryOp.InputRef.ShapeName }}{ 384 {{ if .API.EndpointDiscoveryOp.InputRef.Shape.HasMember "Operation" -}} 385 Operation: d.Params["op"], 386 {{ end -}} 387 {{ if .API.EndpointDiscoveryOp.InputRef.Shape.HasMember "Identifiers" -}} 388 Identifiers: d.Params, 389 {{ end -}} 390 } 391 392 resp, err := d.Client.{{ .API.EndpointDiscoveryOp.Name }}(input) 393 if err != nil { 394 return crr.Endpoint{}, err 395 } 396 397 endpoint := crr.Endpoint{ 398 Key: d.Key, 399 } 400 401 for _, e := range resp.Endpoints { 402 if e.Address == nil { 403 continue 404 } 405 406 cachedInMinutes := aws.Int64Value(e.CachePeriodInMinutes) 407 u, err := url.Parse(*e.Address) 408 if err != nil { 409 continue 410 } 411 412 addr := crr.WeightedAddress{ 413 URL: u, 414 Expired: time.Now().Add(time.Duration(cachedInMinutes) * time.Minute), 415 } 416 417 endpoint.Add(addr) 418 } 419 420 d.EndpointCache.Add(endpoint) 421 422 return endpoint, nil 423} 424 425func (d *discoverer{{ .ExportedName }}) Handler(r *request.Request) { 426 endpointKey := crr.BuildEndpointKey(d.Params) 427 d.Key = endpointKey 428 429 endpoint, err := d.EndpointCache.Get(d, endpointKey, d.Required) 430 if err != nil { 431 r.Error = err 432 return 433 } 434 435 if endpoint.URL != nil && len(endpoint.URL.String()) > 0 { 436 r.HTTPRequest.URL = endpoint.URL 437 } 438} 439{{ end -}} 440 441`)) 442 443// GoCode returns a string of rendered GoCode for this Operation 444func (o *Operation) GoCode() string { 445 var buf bytes.Buffer 446 447 if len(o.OutputRef.Shape.EventStreamsMemberName) != 0 { 448 o.API.AddSDKImport("aws/client") 449 o.API.AddSDKImport("private/protocol") 450 o.API.AddSDKImport("private/protocol/rest") 451 o.API.AddSDKImport("private/protocol", o.API.ProtocolPackage()) 452 } 453 454 if o.API.EndpointDiscoveryOp != nil { 455 o.API.AddSDKImport("aws/crr") 456 o.API.AddImport("time") 457 o.API.AddImport("net/url") 458 } 459 460 if o.Endpoint != nil && len(o.Endpoint.HostPrefix) != 0 { 461 setupEndpointHostPrefix(o) 462 } 463 464 err := operationTmpl.Execute(&buf, o) 465 if err != nil { 466 panic(err) 467 } 468 469 return strings.TrimSpace(buf.String()) 470} 471 472// tplInfSig defines the template for rendering an Operation's signature within an Interface definition. 473var tplInfSig = template.Must(template.New("opsig").Parse(` 474{{ .ExportedName }}({{ .InputRef.GoTypeWithPkgName }}) ({{ .OutputRef.GoTypeWithPkgName }}, error) 475{{ .ExportedName }}WithContext(aws.Context, {{ .InputRef.GoTypeWithPkgName }}, ...request.Option) ({{ .OutputRef.GoTypeWithPkgName }}, error) 476{{ .ExportedName }}Request({{ .InputRef.GoTypeWithPkgName }}) (*request.Request, {{ .OutputRef.GoTypeWithPkgName }}) 477 478{{ if .Paginator -}} 479{{ .ExportedName }}Pages({{ .InputRef.GoTypeWithPkgName }}, func({{ .OutputRef.GoTypeWithPkgName }}, bool) bool) error 480{{ .ExportedName }}PagesWithContext(aws.Context, {{ .InputRef.GoTypeWithPkgName }}, func({{ .OutputRef.GoTypeWithPkgName }}, bool) bool, ...request.Option) error 481{{- end }} 482`)) 483 484// InterfaceSignature returns a string representing the Operation's interface{} 485// functional signature. 486func (o *Operation) InterfaceSignature() string { 487 var buf bytes.Buffer 488 err := tplInfSig.Execute(&buf, o) 489 if err != nil { 490 panic(err) 491 } 492 493 return strings.TrimSpace(buf.String()) 494} 495 496// tplExample defines the template for rendering an Operation example 497var tplExample = template.Must(template.New("operationExample").Parse(` 498func Example{{ .API.StructName }}_{{ .ExportedName }}() { 499 sess := session.Must(session.NewSession()) 500 501 svc := {{ .API.PackageName }}.New(sess) 502 503 {{ .ExampleInput }} 504 resp, err := svc.{{ .ExportedName }}(params) 505 506 if err != nil { 507 // Print the error, cast err to awserr.Error to get the Code and 508 // Message from an error. 509 fmt.Println(err.Error()) 510 return 511 } 512 513 // Pretty-print the response data. 514 fmt.Println(resp) 515} 516`)) 517 518// Example returns a string of the rendered Go code for the Operation 519func (o *Operation) Example() string { 520 var buf bytes.Buffer 521 err := tplExample.Execute(&buf, o) 522 if err != nil { 523 panic(err) 524 } 525 526 return strings.TrimSpace(buf.String()) 527} 528 529// ExampleInput return a string of the rendered Go code for an example's input parameters 530func (o *Operation) ExampleInput() string { 531 if len(o.InputRef.Shape.MemberRefs) == 0 { 532 if strings.Contains(o.InputRef.GoTypeElem(), ".") { 533 o.imports[SDKImportRoot+"service/"+strings.Split(o.InputRef.GoTypeElem(), ".")[0]] = true 534 return fmt.Sprintf("var params *%s", o.InputRef.GoTypeElem()) 535 } 536 return fmt.Sprintf("var params *%s.%s", 537 o.API.PackageName(), o.InputRef.GoTypeElem()) 538 } 539 e := example{o, map[string]int{}} 540 return "params := " + e.traverseAny(o.InputRef.Shape, false, false) 541} 542 543// ShouldDiscardResponse returns if the operation should discard the response 544// returned by the service. 545func (o *Operation) ShouldDiscardResponse() bool { 546 s := o.OutputRef.Shape 547 return s.Placeholder || len(s.MemberRefs) == 0 548} 549 550// A example provides 551type example struct { 552 *Operation 553 visited map[string]int 554} 555 556// traverseAny returns rendered Go code for the shape. 557func (e *example) traverseAny(s *Shape, required, payload bool) string { 558 str := "" 559 e.visited[s.ShapeName]++ 560 561 switch s.Type { 562 case "structure": 563 str = e.traverseStruct(s, required, payload) 564 case "list": 565 str = e.traverseList(s, required, payload) 566 case "map": 567 str = e.traverseMap(s, required, payload) 568 case "jsonvalue": 569 str = "aws.JSONValue{\"key\": \"value\"}" 570 if required { 571 str += " // Required" 572 } 573 default: 574 str = e.traverseScalar(s, required, payload) 575 } 576 577 e.visited[s.ShapeName]-- 578 579 return str 580} 581 582var reType = regexp.MustCompile(`\b([A-Z])`) 583 584// traverseStruct returns rendered Go code for a structure type shape. 585func (e *example) traverseStruct(s *Shape, required, payload bool) string { 586 var buf bytes.Buffer 587 588 if s.resolvePkg != "" { 589 e.imports[s.resolvePkg] = true 590 buf.WriteString("&" + s.GoTypeElem() + "{") 591 } else { 592 buf.WriteString("&" + s.API.PackageName() + "." + s.GoTypeElem() + "{") 593 } 594 595 if required { 596 buf.WriteString(" // Required") 597 } 598 buf.WriteString("\n") 599 600 req := make([]string, len(s.Required)) 601 copy(req, s.Required) 602 sort.Strings(req) 603 604 if e.visited[s.ShapeName] < 2 { 605 for _, n := range req { 606 m := s.MemberRefs[n].Shape 607 p := n == s.Payload && (s.MemberRefs[n].Streaming || m.Streaming) 608 buf.WriteString(n + ": " + e.traverseAny(m, true, p) + ",") 609 if m.Type != "list" && m.Type != "structure" && m.Type != "map" { 610 buf.WriteString(" // Required") 611 } 612 buf.WriteString("\n") 613 } 614 615 for _, n := range s.MemberNames() { 616 if s.IsRequired(n) { 617 continue 618 } 619 m := s.MemberRefs[n].Shape 620 p := n == s.Payload && (s.MemberRefs[n].Streaming || m.Streaming) 621 buf.WriteString(n + ": " + e.traverseAny(m, false, p) + ",\n") 622 } 623 } else { 624 buf.WriteString("// Recursive values...\n") 625 } 626 627 buf.WriteString("}") 628 return buf.String() 629} 630 631// traverseMap returns rendered Go code for a map type shape. 632func (e *example) traverseMap(s *Shape, required, payload bool) string { 633 var buf bytes.Buffer 634 635 t := "" 636 if s.resolvePkg != "" { 637 e.imports[s.resolvePkg] = true 638 t = s.GoTypeElem() 639 } else { 640 t = reType.ReplaceAllString(s.GoTypeElem(), s.API.PackageName()+".$1") 641 } 642 buf.WriteString(t + "{") 643 if required { 644 buf.WriteString(" // Required") 645 } 646 buf.WriteString("\n") 647 648 if e.visited[s.ShapeName] < 2 { 649 m := s.ValueRef.Shape 650 buf.WriteString("\"Key\": " + e.traverseAny(m, true, false) + ",") 651 if m.Type != "list" && m.Type != "structure" && m.Type != "map" { 652 buf.WriteString(" // Required") 653 } 654 buf.WriteString("\n// More values...\n") 655 } else { 656 buf.WriteString("// Recursive values...\n") 657 } 658 buf.WriteString("}") 659 660 return buf.String() 661} 662 663// traverseList returns rendered Go code for a list type shape. 664func (e *example) traverseList(s *Shape, required, payload bool) string { 665 var buf bytes.Buffer 666 t := "" 667 if s.resolvePkg != "" { 668 e.imports[s.resolvePkg] = true 669 t = s.GoTypeElem() 670 } else { 671 t = reType.ReplaceAllString(s.GoTypeElem(), s.API.PackageName()+".$1") 672 } 673 674 buf.WriteString(t + "{") 675 if required { 676 buf.WriteString(" // Required") 677 } 678 buf.WriteString("\n") 679 680 if e.visited[s.ShapeName] < 2 { 681 m := s.MemberRef.Shape 682 buf.WriteString(e.traverseAny(m, true, false) + ",") 683 if m.Type != "list" && m.Type != "structure" && m.Type != "map" { 684 buf.WriteString(" // Required") 685 } 686 buf.WriteString("\n// More values...\n") 687 } else { 688 buf.WriteString("// Recursive values...\n") 689 } 690 buf.WriteString("}") 691 692 return buf.String() 693} 694 695// traverseScalar returns an AWS Type string representation initialized to a value. 696// Will panic if s is an unsupported shape type. 697func (e *example) traverseScalar(s *Shape, required, payload bool) string { 698 str := "" 699 switch s.Type { 700 case "integer", "long": 701 str = `aws.Int64(1)` 702 case "float", "double": 703 str = `aws.Float64(1.0)` 704 case "string", "character": 705 str = `aws.String("` + s.ShapeName + `")` 706 case "blob": 707 if payload { 708 str = `bytes.NewReader([]byte("PAYLOAD"))` 709 } else { 710 str = `[]byte("PAYLOAD")` 711 } 712 case "boolean": 713 str = `aws.Bool(true)` 714 case "timestamp": 715 str = `aws.Time(time.Now())` 716 default: 717 panic("unsupported shape " + s.Type) 718 } 719 720 return str 721} 722