rbd: add aws-sts-metdata encryption type

With Amazon STS and kubernetes cluster is configured with
OIDC identity provider, credentials to access Amazon KMS
can be fetched using oidc-token(serviceaccount token).
Each tenant/namespace needs to create a secret with aws region,
role and CMK ARN.
Ceph-CSI will assume the given role with oidc token and access
aws KMS, with given CMK to encrypt/decrypt DEK which will stored
in the image metdata.

Refer: https://docs.aws.amazon.com/STS/latest/APIReference/welcome.html
Resolves: #2879

Signed-off-by: Rakshith R <rar@redhat.com>
This commit is contained in:
Rakshith R
2022-03-02 16:00:48 +05:30
committed by mergify[bot]
parent 13dcc89ac8
commit 4f0bb2315b
217 changed files with 24757 additions and 72 deletions

22
vendor/github.com/aws/smithy-go/.gitignore generated vendored Normal file
View File

@ -0,0 +1,22 @@
# Eclipse
.classpath
.project
.settings/
# Intellij
.idea/
*.iml
*.iws
# Mac
.DS_Store
# Maven
target/
**/dependency-reduced-pom.xml
# Gradle
/.gradle
build/
*/out/
*/*/out/

28
vendor/github.com/aws/smithy-go/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,28 @@
language: go
sudo: true
dist: bionic
branches:
only:
- main
os:
- linux
- osx
# Travis doesn't work with windows and Go tip
#- windows
go:
- tip
matrix:
allow_failures:
- go: tip
before_install:
- if [ "$TRAVIS_OS_NAME" = "windows" ]; then choco install make; fi
- (cd /tmp/; go get golang.org/x/lint/golint)
script:
- make go test -v ./...;

111
vendor/github.com/aws/smithy-go/CHANGELOG.md generated vendored Normal file
View File

@ -0,0 +1,111 @@
# Release (v1.11.0)
## Module Highlights
* `github.com/aws/smithy-go`: v1.11.0
* **Feature**: Updates deserialization of header list to supported quoted strings
# Release (v1.10.0)
## Module Highlights
* `github.com/aws/smithy-go`: v1.10.0
* **Feature**: Add `ptr.Duration`, `ptr.ToDuration`, `ptr.DurationSlice`, `ptr.ToDurationSlice`, `ptr.DurationMap`, and `ptr.ToDurationMap` functions for the `time.Duration` type.
# Release (v1.9.1)
## Module Highlights
* `github.com/aws/smithy-go`: v1.9.1
* **Documentation**: Fixes various typos in Go package documentation.
# Release (v1.9.0)
## Module Highlights
* `github.com/aws/smithy-go`: v1.9.0
* **Feature**: sync: OnceErr, can be used to concurrently record a signal when an error has occurred.
* **Bug Fix**: `transport/http`: CloseResponseBody and ErrorCloseResponseBody middleware have been updated to ensure that the body is fully drained before closing.
# Release v1.8.1
### Smithy Go Module
* **Bug Fix**: Fixed an issue that would cause the HTTP Content-Length to be set to 0 if the stream body was not set.
* Fixes [aws/aws-sdk-go-v2#1418](https://github.com/aws/aws-sdk-go-v2/issues/1418)
# Release v1.8.0
### Smithy Go Module
* `time`: Add support for parsing additional DateTime timestamp format ([#324](https://github.com/aws/smithy-go/pull/324))
* Adds support for parsing DateTime timestamp formatted time similar to RFC 3339, but without the `Z` character, nor UTC offset.
* Fixes [#1387](https://github.com/aws/aws-sdk-go-v2/issues/1387)
# Release v1.7.0
### Smithy Go Module
* `ptr`: Handle error for deferred file close call ([#314](https://github.com/aws/smithy-go/pull/314))
* Handle error for defer close call
* `middleware`: Add Clone to Metadata ([#318](https://github.com/aws/smithy-go/pull/318))
* Adds a new Clone method to the middleware Metadata type. This provides a shallow clone of the entries in the Metadata.
* `document`: Add new package for document shape serialization support ([#310](https://github.com/aws/smithy-go/pull/310))
### Codegen
* Add Smithy Document Shape Support ([#310](https://github.com/aws/smithy-go/pull/310))
* Adds support for Smithy Document shapes and supporting types for protocols to implement support
# Release v1.6.0 (2021-07-15)
### Smithy Go Module
* `encoding/httpbinding`: Support has been added for encoding `float32` and `float64` values that are `NaN`, `Infinity`, or `-Infinity`. ([#316](https://github.com/aws/smithy-go/pull/316))
### Codegen
* Adds support for handling `float32` and `float64` `NaN` values in HTTP Protocol Unit Tests. ([#316](https://github.com/aws/smithy-go/pull/316))
* Adds support protocol generator implementations to override the error code string returned by `ErrorCode` methods on generated error types. ([#315](https://github.com/aws/smithy-go/pull/315))
# Release v1.5.0 (2021-06-25)
### Smithy Go module
* `time`: Update time parsing to not be as strict for HTTPDate and DateTime ([#307](https://github.com/aws/smithy-go/pull/307))
* Fixes [#302](https://github.com/aws/smithy-go/issues/302) by changing time to UTC before formatting so no local offset time is lost.
### Codegen
* Adds support for integrating client members via plugins ([#301](https://github.com/aws/smithy-go/pull/301))
* Fix serialization of enum types marked with payload trait ([#296](https://github.com/aws/smithy-go/pull/296))
* Update generation of API client modules to include a manifest of files generated ([#283](https://github.com/aws/smithy-go/pull/283))
* Update Group Java group ID for smithy-go generator ([#298](https://github.com/aws/smithy-go/pull/298))
* Support the delegation of determining the errors that can occur for an operation ([#304](https://github.com/aws/smithy-go/pull/304))
* Support for marking and documenting deprecated client config fields. ([#303](https://github.com/aws/smithy-go/pull/303))
# Release v1.4.0 (2021-05-06)
### Smithy Go module
* `encoding/xml`: Fix escaping of Next Line and Line Start in XML Encoder ([#267](https://github.com/aws/smithy-go/pull/267))
### Codegen
* Add support for Smithy 1.7 ([#289](https://github.com/aws/smithy-go/pull/289))
* Add support for httpQueryParams location
* Add support for model renaming conflict resolution with service closure
# Release v1.3.1 (2021-04-08)
### Smithy Go module
* `transport/http`: Loosen endpoint hostname validation to allow specifying port numbers. ([#279](https://github.com/aws/smithy-go/pull/279))
* `io`: Fix RingBuffer panics due to out of bounds index. ([#282](https://github.com/aws/smithy-go/pull/282))
# Release v1.3.0 (2021-04-01)
### Smithy Go module
* `transport/http`: Add utility to safely join string to url path, and url raw query.
### Codegen
* Update HttpBindingProtocolGenerator to use http/transport JoinPath and JoinQuery utility.
# Release v1.2.0 (2021-03-12)
### Smithy Go module
* Fix support for parsing shortened year format in HTTP Date header.
* Fix GitHub APIDiff action workflow to get gorelease tool correctly.
* Fix codegen artifact unit test for Go 1.16
### Codegen
* Fix generating paginator nil parameter handling before usage.
* Fix Serialize unboxed members decorated as required.
* Add ability to define resolvers at both client construction and operation invocation.
* Support for extending paginators with custom runtime trait

4
vendor/github.com/aws/smithy-go/CODE_OF_CONDUCT.md generated vendored Normal file
View File

@ -0,0 +1,4 @@
## Code of Conduct
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
opensource-codeofconduct@amazon.com with any additional questions or comments.

59
vendor/github.com/aws/smithy-go/CONTRIBUTING.md generated vendored Normal file
View File

@ -0,0 +1,59 @@
# Contributing Guidelines
Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional
documentation, we greatly value feedback and contributions from our community.
Please read through this document before submitting any issues or pull requests to ensure we have all the necessary
information to effectively respond to your bug report or contribution.
## Reporting Bugs/Feature Requests
We welcome you to use the GitHub issue tracker to report bugs or suggest features.
When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already
reported the issue. Please try to include as much information as you can. Details like these are incredibly useful:
* A reproducible test case or series of steps
* The version of our code being used
* Any modifications you've made relevant to the bug
* Anything unusual about your environment or deployment
## Contributing via Pull Requests
Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that:
1. You are working against the latest source on the *main* branch.
2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
3. You open an issue to discuss any significant work - we would hate for your time to be wasted.
To send us a pull request, please:
1. Fork the repository.
2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
3. Ensure local tests pass.
4. Commit to your fork using clear commit messages.
5. Send us a pull request, answering any default questions in the pull request interface.
6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation.
GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and
[creating a pull request](https://help.github.com/articles/creating-a-pull-request/).
## Finding contributions to work on
Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start.
## Code of Conduct
This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct).
For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact
opensource-codeofconduct@amazon.com with any additional questions or comments.
## Security issue notifications
If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue.
## Licensing
See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution.

175
vendor/github.com/aws/smithy-go/LICENSE generated vendored Normal file
View File

@ -0,0 +1,175 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

63
vendor/github.com/aws/smithy-go/Makefile generated vendored Normal file
View File

@ -0,0 +1,63 @@
PRE_RELEASE_VERSION ?=
RELEASE_MANIFEST_FILE ?=
RELEASE_CHGLOG_DESC_FILE ?=
REPOTOOLS_VERSION ?= latest
REPOTOOLS_MODULE = github.com/awslabs/aws-go-multi-module-repository-tools
REPOTOOLS_CMD_CALCULATE_RELEASE = ${REPOTOOLS_MODULE}/cmd/calculaterelease@${REPOTOOLS_VERSION}
REPOTOOLS_CMD_CALCULATE_RELEASE_ADDITIONAL_ARGS ?=
REPOTOOLS_CMD_UPDATE_REQUIRES = ${REPOTOOLS_MODULE}/cmd/updaterequires@${REPOTOOLS_VERSION}
REPOTOOLS_CMD_UPDATE_MODULE_METADATA = ${REPOTOOLS_MODULE}/cmd/updatemodulemeta@${REPOTOOLS_VERSION}
REPOTOOLS_CMD_GENERATE_CHANGELOG = ${REPOTOOLS_MODULE}/cmd/generatechangelog@${REPOTOOLS_VERSION}
REPOTOOLS_CMD_CHANGELOG = ${REPOTOOLS_MODULE}/cmd/changelog@${REPOTOOLS_VERSION}
REPOTOOLS_CMD_TAG_RELEASE = ${REPOTOOLS_MODULE}/cmd/tagrelease@${REPOTOOLS_VERSION}
REPOTOOLS_CMD_MODULE_VERSION = ${REPOTOOLS_MODULE}/cmd/moduleversion@${REPOTOOLS_VERSION}
ifneq ($(PRE_RELEASE_VERSION),)
REPOTOOLS_CMD_CALCULATE_RELEASE_ADDITIONAL_ARGS += -preview=${PRE_RELEASE_VERSION}
endif
smithy-publish-local:
cd codegen && ./gradlew publishToMavenLocal
smithy-build:
cd codegen && ./gradlew build
smithy-clean:
cd codegen && ./gradlew clean
#####################
# Release Process #
#####################
.PHONY: preview-release pre-release-validation release
preview-release:
go run ${REPOTOOLS_CMD_CALCULATE_RELEASE} ${REPOTOOLS_CMD_CALCULATE_RELEASE_ADDITIONAL_ARGS}
pre-release-validation:
@if [[ -z "${RELEASE_MANIFEST_FILE}" ]]; then \
echo "RELEASE_MANIFEST_FILE is required to specify the file to write the release manifest" && false; \
fi
@if [[ -z "${RELEASE_CHGLOG_DESC_FILE}" ]]; then \
echo "RELEASE_CHGLOG_DESC_FILE is required to specify the file to write the release notes" && false; \
fi
release: pre-release-validation
go run ${REPOTOOLS_CMD_CALCULATE_RELEASE} -o ${RELEASE_MANIFEST_FILE} ${REPOTOOLS_CMD_CALCULATE_RELEASE_ADDITIONAL_ARGS}
go run ${REPOTOOLS_CMD_UPDATE_REQUIRES} -release ${RELEASE_MANIFEST_FILE}
go run ${REPOTOOLS_CMD_UPDATE_MODULE_METADATA} -release ${RELEASE_MANIFEST_FILE}
go run ${REPOTOOLS_CMD_GENERATE_CHANGELOG} -release ${RELEASE_MANIFEST_FILE} -o ${RELEASE_CHGLOG_DESC_FILE}
go run ${REPOTOOLS_CMD_CHANGELOG} rm -all
go run ${REPOTOOLS_CMD_TAG_RELEASE} -release ${RELEASE_MANIFEST_FILE}
module-version:
@go run ${REPOTOOLS_CMD_MODULE_VERSION} .
##############
# Repo Tools #
##############
.PHONY: install-changelog
install-changelog:
go install ${REPOTOOLS_MODULE}/cmd/changelog@${REPOTOOLS_VERSION}

1
vendor/github.com/aws/smithy-go/NOTICE generated vendored Normal file
View File

@ -0,0 +1 @@
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.

12
vendor/github.com/aws/smithy-go/README.md generated vendored Normal file
View File

@ -0,0 +1,12 @@
## Smithy Go
[![Go Build Status](https://github.com/aws/smithy-go/actions/workflows/go.yml/badge.svg?branch=main)](https://github.com/aws/smithy-go/actions/workflows/go.yml)[![Codegen Build Status](https://github.com/aws/smithy-go/actions/workflows/codegen.yml/badge.svg?branch=main)](https://github.com/aws/smithy-go/actions/workflows/codegen.yml)
Smithy code generators for Go.
**WARNING: All interfaces are subject to change.**
## License
This project is licensed under the Apache-2.0 License.

2
vendor/github.com/aws/smithy-go/doc.go generated vendored Normal file
View File

@ -0,0 +1,2 @@
// Package smithy provides the core components for a Smithy SDK.
package smithy

10
vendor/github.com/aws/smithy-go/document.go generated vendored Normal file
View File

@ -0,0 +1,10 @@
package smithy
// Document provides access to loosely structured data in a document-like
// format.
//
// Deprecated: See the github.com/aws/smithy-go/document package.
type Document interface {
UnmarshalDocument(interface{}) error
GetValue() (interface{}, error)
}

12
vendor/github.com/aws/smithy-go/document/doc.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
// Package document provides interface definitions and error types for document types.
//
// A document is a protocol-agnostic type which supports a JSON-like data-model. You can use this type to send
// UTF-8 strings, arbitrary precision numbers, booleans, nulls, a list of these values, and a map of UTF-8
// strings to these values.
//
// API Clients expose document constructors in their respective client document packages which must be used to
// Marshal and Unmarshal Go types to and from their respective protocol representations.
//
// See the Marshaler and Unmarshaler type documentation for more details on how to Go types can be converted to and from
// document types.
package document

153
vendor/github.com/aws/smithy-go/document/document.go generated vendored Normal file
View File

@ -0,0 +1,153 @@
package document
import (
"fmt"
"math/big"
"strconv"
)
// Marshaler is an interface for a type that marshals a document to its protocol-specific byte representation and
// returns the resulting bytes. A non-nil error will be returned if an error is encountered during marshaling.
//
// Marshal supports basic scalars (int,uint,float,bool,string), big.Int, and big.Float, maps, slices, and structs.
// Anonymous nested types are flattened based on Go anonymous type visibility.
//
// When defining struct types. the `document` struct tag can be used to control how the value will be
// marshaled into the resulting protocol document.
//
// // Field is ignored
// Field int `document:"-"`
//
// // Field object of key "myName"
// Field int `document:"myName"`
//
// // Field object key of key "myName", and
// // Field is omitted if the field is a zero value for the type.
// Field int `document:"myName,omitempty"`
//
// // Field object key of "Field", and
// // Field is omitted if the field is a zero value for the type.
// Field int `document:",omitempty"`
//
// All struct fields, including anonymous fields, are marshaled unless the
// any of the following conditions are meet.
//
// - the field is not exported
// - document field tag is "-"
// - document field tag specifies "omitempty", and is a zero value.
//
// Pointer and interface values are encoded as the value pointed to or
// contained in the interface. A nil value encodes as a null
// value unless `omitempty` struct tag is provided.
//
// Channel, complex, and function values are not encoded and will be skipped
// when walking the value to be marshaled.
//
// time.Time is not supported and will cause the Marshaler to return an error. These values should be represented
// by your application as a string or numerical representation.
//
// Errors that occur when marshaling will stop the marshaler, and return the error.
//
// Marshal cannot represent cyclic data structures and will not handle them.
// Passing cyclic structures to Marshal will result in an infinite recursion.
type Marshaler interface {
MarshalSmithyDocument() ([]byte, error)
}
// Unmarshaler is an interface for a type that unmarshals a document from its protocol-specific representation, and
// stores the result into the value pointed by v. If v is nil or not a pointer then InvalidUnmarshalError will be
// returned.
//
// Unmarshaler supports the same encodings produced by a document Marshaler. This includes support for the `document`
// struct field tag for controlling how struct fields are unmarshaled.
//
// Both generic interface{} and concrete types are valid unmarshal destination types. When unmarshaling a document
// into an empty interface the Unmarshaler will store one of these values:
// bool, for boolean values
// document.Number, for arbitrary-precision numbers (int64, float64, big.Int, big.Float)
// string, for string values
// []interface{}, for array values
// map[string]interface{}, for objects
// nil, for null values
//
// When unmarshaling, any error that occurs will halt the unmarshal and return the error.
type Unmarshaler interface {
UnmarshalSmithyDocument(v interface{}) error
}
type noSerde interface {
noSmithyDocumentSerde()
}
// NoSerde is a sentinel value to indicate that a given type should not be marshaled or unmarshaled
// into a protocol document.
type NoSerde struct{}
func (n NoSerde) noSmithyDocumentSerde() {}
var _ noSerde = (*NoSerde)(nil)
// IsNoSerde returns whether the given type implements the no smithy document serde interface.
func IsNoSerde(x interface{}) bool {
_, ok := x.(noSerde)
return ok
}
// Number is an arbitrary precision numerical value
type Number string
// Int64 returns the number as a string.
func (n Number) String() string {
return string(n)
}
// Int64 returns the number as an int64.
func (n Number) Int64() (int64, error) {
return n.intOfBitSize(64)
}
func (n Number) intOfBitSize(bitSize int) (int64, error) {
return strconv.ParseInt(string(n), 10, bitSize)
}
// Uint64 returns the number as a uint64.
func (n Number) Uint64() (uint64, error) {
return n.uintOfBitSize(64)
}
func (n Number) uintOfBitSize(bitSize int) (uint64, error) {
return strconv.ParseUint(string(n), 10, bitSize)
}
// Float32 returns the number parsed as a 32-bit float, returns a float64.
func (n Number) Float32() (float64, error) {
return n.floatOfBitSize(32)
}
// Float64 returns the number as a float64.
func (n Number) Float64() (float64, error) {
return n.floatOfBitSize(64)
}
// Float64 returns the number as a float64.
func (n Number) floatOfBitSize(bitSize int) (float64, error) {
return strconv.ParseFloat(string(n), bitSize)
}
// BigFloat attempts to convert the number to a big.Float, returns an error if the operation fails.
func (n Number) BigFloat() (*big.Float, error) {
f, ok := (&big.Float{}).SetString(string(n))
if !ok {
return nil, fmt.Errorf("failed to convert to big.Float")
}
return f, nil
}
// BigInt attempts to convert the number to a big.Int, returns an error if the operation fails.
func (n Number) BigInt() (*big.Int, error) {
f, ok := (&big.Int{}).SetString(string(n), 10)
if !ok {
return nil, fmt.Errorf("failed to convert to big.Float")
}
return f, nil
}

75
vendor/github.com/aws/smithy-go/document/errors.go generated vendored Normal file
View File

@ -0,0 +1,75 @@
package document
import (
"fmt"
"reflect"
)
// UnmarshalTypeError is an error type representing an error
// unmarshaling a Smithy document to a Go value type. This is different
// from UnmarshalError in that it does not wrap an underlying error type.
type UnmarshalTypeError struct {
Value string
Type reflect.Type
}
// Error returns the string representation of the error.
// Satisfying the error interface.
func (e *UnmarshalTypeError) Error() string {
return fmt.Sprintf("unmarshal failed, cannot unmarshal %s into Go value type %s",
e.Value, e.Type.String())
}
// An InvalidUnmarshalError is an error type representing an invalid type
// encountered while unmarshaling a Smithy document to a Go value type.
type InvalidUnmarshalError struct {
Type reflect.Type
}
// Error returns the string representation of the error.
// Satisfying the error interface.
func (e *InvalidUnmarshalError) Error() string {
var msg string
if e.Type == nil {
msg = "cannot unmarshal to nil value"
} else if e.Type.Kind() != reflect.Ptr {
msg = fmt.Sprintf("cannot unmarshal to non-pointer value, got %s", e.Type.String())
} else {
msg = fmt.Sprintf("cannot unmarshal to nil value, %s", e.Type.String())
}
return fmt.Sprintf("unmarshal failed, %s", msg)
}
// An UnmarshalError wraps an error that occurred while unmarshaling a
// Smithy document into a Go type. This is different from
// UnmarshalTypeError in that it wraps the underlying error that occurred.
type UnmarshalError struct {
Err error
Value string
Type reflect.Type
}
// Unwrap returns the underlying unmarshaling error
func (e *UnmarshalError) Unwrap() error {
return e.Err
}
// Error returns the string representation of the error.
// Satisfying the error interface.
func (e *UnmarshalError) Error() string {
return fmt.Sprintf("unmarshal failed, cannot unmarshal %q into %s, %v",
e.Value, e.Type.String(), e.Err)
}
// An InvalidMarshalError is an error type representing an error
// occurring when marshaling a Go value type.
type InvalidMarshalError struct {
Message string
}
// Error returns the string representation of the error.
// Satisfying the error interface.
func (e *InvalidMarshalError) Error() string {
return fmt.Sprintf("marshal failed, %s", e.Message)
}

4
vendor/github.com/aws/smithy-go/encoding/doc.go generated vendored Normal file
View File

@ -0,0 +1,4 @@
// Package encoding provides utilities for encoding values for specific
// document encodings.
package encoding

40
vendor/github.com/aws/smithy-go/encoding/encoding.go generated vendored Normal file
View File

@ -0,0 +1,40 @@
package encoding
import (
"fmt"
"math"
"strconv"
)
// EncodeFloat encodes a float value as per the stdlib encoder for json and xml protocol
// This encodes a float value into dst while attempting to conform to ES6 ToString for Numbers
//
// Based on encoding/json floatEncoder from the Go Standard Library
// https://golang.org/src/encoding/json/encode.go
func EncodeFloat(dst []byte, v float64, bits int) []byte {
if math.IsInf(v, 0) || math.IsNaN(v) {
panic(fmt.Sprintf("invalid float value: %s", strconv.FormatFloat(v, 'g', -1, bits)))
}
abs := math.Abs(v)
fmt := byte('f')
if abs != 0 {
if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
fmt = 'e'
}
}
dst = strconv.AppendFloat(dst, v, fmt, -1, bits)
if fmt == 'e' {
// clean up e-09 to e-9
n := len(dst)
if n >= 4 && dst[n-4] == 'e' && dst[n-3] == '-' && dst[n-2] == '0' {
dst[n-2] = dst[n-1]
dst = dst[:n-1]
}
}
return dst
}

View File

@ -0,0 +1,116 @@
package httpbinding
import (
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
)
const (
contentLengthHeader = "Content-Length"
floatNaN = "NaN"
floatInfinity = "Infinity"
floatNegInfinity = "-Infinity"
)
// An Encoder provides encoding of REST URI path, query, and header components
// of an HTTP request. Can also encode a stream as the payload.
//
// Does not support SetFields.
type Encoder struct {
path, rawPath, pathBuffer []byte
query url.Values
header http.Header
}
// NewEncoder creates a new encoder from the passed in request. All query and
// header values will be added on top of the request's existing values. Overwriting
// duplicate values.
func NewEncoder(path, query string, headers http.Header) (*Encoder, error) {
parseQuery, err := url.ParseQuery(query)
if err != nil {
return nil, fmt.Errorf("failed to parse query string: %w", err)
}
e := &Encoder{
path: []byte(path),
rawPath: []byte(path),
query: parseQuery,
header: headers.Clone(),
}
return e, nil
}
// Encode returns a REST protocol encoder for encoding HTTP bindings.
//
// Due net/http requiring `Content-Length` to be specified on the http.Request#ContentLength directly. Encode
// will look for whether the header is present, and if so will remove it and set the respective value on http.Request.
//
// Returns any error occurring during encoding.
func (e *Encoder) Encode(req *http.Request) (*http.Request, error) {
req.URL.Path, req.URL.RawPath = string(e.path), string(e.rawPath)
req.URL.RawQuery = e.query.Encode()
// net/http ignores Content-Length header and requires it to be set on http.Request
if v := e.header.Get(contentLengthHeader); len(v) > 0 {
iv, err := strconv.ParseInt(v, 10, 64)
if err != nil {
return nil, err
}
req.ContentLength = iv
e.header.Del(contentLengthHeader)
}
req.Header = e.header
return req, nil
}
// AddHeader returns a HeaderValue for appending to the given header name
func (e *Encoder) AddHeader(key string) HeaderValue {
return newHeaderValue(e.header, key, true)
}
// SetHeader returns a HeaderValue for setting the given header name
func (e *Encoder) SetHeader(key string) HeaderValue {
return newHeaderValue(e.header, key, false)
}
// Headers returns a Header used for encoding headers with the given prefix
func (e *Encoder) Headers(prefix string) Headers {
return Headers{
header: e.header,
prefix: strings.TrimSpace(prefix),
}
}
// HasHeader returns if a header with the key specified exists with one or
// more value.
func (e Encoder) HasHeader(key string) bool {
return len(e.header[key]) != 0
}
// SetURI returns a URIValue used for setting the given path key
func (e *Encoder) SetURI(key string) URIValue {
return newURIValue(&e.path, &e.rawPath, &e.pathBuffer, key)
}
// SetQuery returns a QueryValue used for setting the given query key
func (e *Encoder) SetQuery(key string) QueryValue {
return NewQueryValue(e.query, key, false)
}
// AddQuery returns a QueryValue used for appending the given query key
func (e *Encoder) AddQuery(key string) QueryValue {
return NewQueryValue(e.query, key, true)
}
// HasQuery returns if a query with the key specified exists with one or
// more values.
func (e *Encoder) HasQuery(key string) bool {
return len(e.query.Get(key)) != 0
}

View File

@ -0,0 +1,122 @@
package httpbinding
import (
"encoding/base64"
"math"
"math/big"
"net/http"
"strconv"
"strings"
)
// Headers is used to encode header keys using a provided prefix
type Headers struct {
header http.Header
prefix string
}
// AddHeader returns a HeaderValue used to append values to prefix+key
func (h Headers) AddHeader(key string) HeaderValue {
return h.newHeaderValue(key, true)
}
// SetHeader returns a HeaderValue used to set the value of prefix+key
func (h Headers) SetHeader(key string) HeaderValue {
return h.newHeaderValue(key, false)
}
func (h Headers) newHeaderValue(key string, append bool) HeaderValue {
return newHeaderValue(h.header, h.prefix+strings.TrimSpace(key), append)
}
// HeaderValue is used to encode values to an HTTP header
type HeaderValue struct {
header http.Header
key string
append bool
}
func newHeaderValue(header http.Header, key string, append bool) HeaderValue {
return HeaderValue{header: header, key: strings.TrimSpace(key), append: append}
}
func (h HeaderValue) modifyHeader(value string) {
if h.append {
h.header[h.key] = append(h.header[h.key], value)
} else {
h.header[h.key] = append(h.header[h.key][:0], value)
}
}
// String encodes the value v as the header string value
func (h HeaderValue) String(v string) {
h.modifyHeader(v)
}
// Byte encodes the value v as a query string value
func (h HeaderValue) Byte(v int8) {
h.Long(int64(v))
}
// Short encodes the value v as a query string value
func (h HeaderValue) Short(v int16) {
h.Long(int64(v))
}
// Integer encodes the value v as the header string value
func (h HeaderValue) Integer(v int32) {
h.Long(int64(v))
}
// Long encodes the value v as the header string value
func (h HeaderValue) Long(v int64) {
h.modifyHeader(strconv.FormatInt(v, 10))
}
// Boolean encodes the value v as a query string value
func (h HeaderValue) Boolean(v bool) {
h.modifyHeader(strconv.FormatBool(v))
}
// Float encodes the value v as a query string value
func (h HeaderValue) Float(v float32) {
h.float(float64(v), 32)
}
// Double encodes the value v as a query string value
func (h HeaderValue) Double(v float64) {
h.float(v, 64)
}
func (h HeaderValue) float(v float64, bitSize int) {
switch {
case math.IsNaN(v):
h.String(floatNaN)
case math.IsInf(v, 1):
h.String(floatInfinity)
case math.IsInf(v, -1):
h.String(floatNegInfinity)
default:
h.modifyHeader(strconv.FormatFloat(v, 'f', -1, bitSize))
}
}
// BigInteger encodes the value v as a query string value
func (h HeaderValue) BigInteger(v *big.Int) {
h.modifyHeader(v.String())
}
// BigDecimal encodes the value v as a query string value
func (h HeaderValue) BigDecimal(v *big.Float) {
if i, accuracy := v.Int64(); accuracy == big.Exact {
h.Long(i)
return
}
h.modifyHeader(v.Text('e', -1))
}
// Blob encodes the value v as a base64 header string value
func (h HeaderValue) Blob(v []byte) {
encodeToString := base64.StdEncoding.EncodeToString(v)
h.modifyHeader(encodeToString)
}

View File

@ -0,0 +1,108 @@
package httpbinding
import (
"bytes"
"fmt"
)
const (
uriTokenStart = '{'
uriTokenStop = '}'
uriTokenSkip = '+'
)
func bufCap(b []byte, n int) []byte {
if cap(b) < n {
return make([]byte, 0, n)
}
return b[0:0]
}
// replacePathElement replaces a single element in the path []byte.
// Escape is used to control whether the value will be escaped using Amazon path escape style.
func replacePathElement(path, fieldBuf []byte, key, val string, escape bool) ([]byte, []byte, error) {
fieldBuf = bufCap(fieldBuf, len(key)+3) // { <key> [+] }
fieldBuf = append(fieldBuf, uriTokenStart)
fieldBuf = append(fieldBuf, key...)
start := bytes.Index(path, fieldBuf)
end := start + len(fieldBuf)
if start < 0 || len(path[end:]) == 0 {
// TODO what to do about error?
return path, fieldBuf, fmt.Errorf("invalid path index, start=%d,end=%d. %s", start, end, path)
}
encodeSep := true
if path[end] == uriTokenSkip {
// '+' token means do not escape slashes
encodeSep = false
end++
}
if escape {
val = EscapePath(val, encodeSep)
}
if path[end] != uriTokenStop {
return path, fieldBuf, fmt.Errorf("invalid path element, does not contain token stop, %s", path)
}
end++
fieldBuf = bufCap(fieldBuf, len(val))
fieldBuf = append(fieldBuf, val...)
keyLen := end - start
valLen := len(fieldBuf)
if keyLen == valLen {
copy(path[start:], fieldBuf)
return path, fieldBuf, nil
}
newLen := len(path) + (valLen - keyLen)
if len(path) < newLen {
path = path[:cap(path)]
}
if cap(path) < newLen {
newURI := make([]byte, newLen)
copy(newURI, path)
path = newURI
}
// shift
copy(path[start+valLen:], path[end:])
path = path[:newLen]
copy(path[start:], fieldBuf)
return path, fieldBuf, nil
}
// EscapePath escapes part of a URL path in Amazon style.
func EscapePath(path string, encodeSep bool) string {
var buf bytes.Buffer
for i := 0; i < len(path); i++ {
c := path[i]
if noEscape[c] || (c == '/' && !encodeSep) {
buf.WriteByte(c)
} else {
fmt.Fprintf(&buf, "%%%02X", c)
}
}
return buf.String()
}
var noEscape [256]bool
func init() {
for i := 0; i < len(noEscape); i++ {
// AWS expects every character except these to be escaped
noEscape[i] = (i >= 'A' && i <= 'Z') ||
(i >= 'a' && i <= 'z') ||
(i >= '0' && i <= '9') ||
i == '-' ||
i == '.' ||
i == '_' ||
i == '~'
}
}

View File

@ -0,0 +1,107 @@
package httpbinding
import (
"encoding/base64"
"math"
"math/big"
"net/url"
"strconv"
)
// QueryValue is used to encode query key values
type QueryValue struct {
query url.Values
key string
append bool
}
// NewQueryValue creates a new QueryValue which enables encoding
// a query value into the given url.Values.
func NewQueryValue(query url.Values, key string, append bool) QueryValue {
return QueryValue{
query: query,
key: key,
append: append,
}
}
func (qv QueryValue) updateKey(value string) {
if qv.append {
qv.query.Add(qv.key, value)
} else {
qv.query.Set(qv.key, value)
}
}
// Blob encodes v as a base64 query string value
func (qv QueryValue) Blob(v []byte) {
encodeToString := base64.StdEncoding.EncodeToString(v)
qv.updateKey(encodeToString)
}
// Boolean encodes v as a query string value
func (qv QueryValue) Boolean(v bool) {
qv.updateKey(strconv.FormatBool(v))
}
// String encodes v as a query string value
func (qv QueryValue) String(v string) {
qv.updateKey(v)
}
// Byte encodes v as a query string value
func (qv QueryValue) Byte(v int8) {
qv.Long(int64(v))
}
// Short encodes v as a query string value
func (qv QueryValue) Short(v int16) {
qv.Long(int64(v))
}
// Integer encodes v as a query string value
func (qv QueryValue) Integer(v int32) {
qv.Long(int64(v))
}
// Long encodes v as a query string value
func (qv QueryValue) Long(v int64) {
qv.updateKey(strconv.FormatInt(v, 10))
}
// Float encodes v as a query string value
func (qv QueryValue) Float(v float32) {
qv.float(float64(v), 32)
}
// Double encodes v as a query string value
func (qv QueryValue) Double(v float64) {
qv.float(v, 64)
}
func (qv QueryValue) float(v float64, bitSize int) {
switch {
case math.IsNaN(v):
qv.String(floatNaN)
case math.IsInf(v, 1):
qv.String(floatInfinity)
case math.IsInf(v, -1):
qv.String(floatNegInfinity)
default:
qv.updateKey(strconv.FormatFloat(v, 'f', -1, bitSize))
}
}
// BigInteger encodes v as a query string value
func (qv QueryValue) BigInteger(v *big.Int) {
qv.updateKey(v.String())
}
// BigDecimal encodes v as a query string value
func (qv QueryValue) BigDecimal(v *big.Float) {
if i, accuracy := v.Int64(); accuracy == big.Exact {
qv.Long(i)
return
}
qv.updateKey(v.Text('e', -1))
}

View File

@ -0,0 +1,108 @@
package httpbinding
import (
"math"
"math/big"
"strconv"
"strings"
)
// URIValue is used to encode named URI parameters
type URIValue struct {
path, rawPath, buffer *[]byte
key string
}
func newURIValue(path *[]byte, rawPath *[]byte, buffer *[]byte, key string) URIValue {
return URIValue{path: path, rawPath: rawPath, buffer: buffer, key: key}
}
func (u URIValue) modifyURI(value string) (err error) {
*u.path, *u.buffer, err = replacePathElement(*u.path, *u.buffer, u.key, value, false)
*u.rawPath, *u.buffer, err = replacePathElement(*u.rawPath, *u.buffer, u.key, value, true)
return err
}
// Boolean encodes v as a URI string value
func (u URIValue) Boolean(v bool) error {
return u.modifyURI(strconv.FormatBool(v))
}
// String encodes v as a URI string value
func (u URIValue) String(v string) error {
return u.modifyURI(v)
}
// Byte encodes v as a URI string value
func (u URIValue) Byte(v int8) error {
return u.Long(int64(v))
}
// Short encodes v as a URI string value
func (u URIValue) Short(v int16) error {
return u.Long(int64(v))
}
// Integer encodes v as a URI string value
func (u URIValue) Integer(v int32) error {
return u.Long(int64(v))
}
// Long encodes v as a URI string value
func (u URIValue) Long(v int64) error {
return u.modifyURI(strconv.FormatInt(v, 10))
}
// Float encodes v as a query string value
func (u URIValue) Float(v float32) error {
return u.float(float64(v), 32)
}
// Double encodes v as a query string value
func (u URIValue) Double(v float64) error {
return u.float(v, 64)
}
func (u URIValue) float(v float64, bitSize int) error {
switch {
case math.IsNaN(v):
return u.String(floatNaN)
case math.IsInf(v, 1):
return u.String(floatInfinity)
case math.IsInf(v, -1):
return u.String(floatNegInfinity)
default:
return u.modifyURI(strconv.FormatFloat(v, 'f', -1, bitSize))
}
}
// BigInteger encodes v as a query string value
func (u URIValue) BigInteger(v *big.Int) error {
return u.modifyURI(v.String())
}
// BigDecimal encodes v as a query string value
func (u URIValue) BigDecimal(v *big.Float) error {
if i, accuracy := v.Int64(); accuracy == big.Exact {
return u.Long(i)
}
return u.modifyURI(v.Text('e', -1))
}
// SplitURI parses a Smithy HTTP binding trait URI
func SplitURI(uri string) (path, query string) {
queryStart := strings.IndexRune(uri, '?')
if queryStart == -1 {
path = uri
return path, query
}
path = uri[:queryStart]
if queryStart+1 >= len(uri) {
return path, query
}
query = uri[queryStart+1:]
return path, query
}

49
vendor/github.com/aws/smithy-go/encoding/xml/array.go generated vendored Normal file
View File

@ -0,0 +1,49 @@
package xml
// arrayMemberWrapper is the default member wrapper tag name for XML Array type
var arrayMemberWrapper = StartElement{
Name: Name{Local: "member"},
}
// Array represents the encoding of a XML array type
type Array struct {
w writer
scratch *[]byte
// member start element is the array member wrapper start element
memberStartElement StartElement
// isFlattened indicates if the array is a flattened array.
isFlattened bool
}
// newArray returns an array encoder.
// It also takes in the member start element, array start element.
// It takes in a isFlattened bool, indicating that an array is flattened array.
//
// A wrapped array ["value1", "value2"] is represented as
// `<List><member>value1</member><member>value2</member></List>`.
// A flattened array `someList: ["value1", "value2"]` is represented as
// `<someList>value1</someList><someList>value2</someList>`.
func newArray(w writer, scratch *[]byte, memberStartElement StartElement, arrayStartElement StartElement, isFlattened bool) *Array {
var memberWrapper = memberStartElement
if isFlattened {
memberWrapper = arrayStartElement
}
return &Array{
w: w,
scratch: scratch,
memberStartElement: memberWrapper,
isFlattened: isFlattened,
}
}
// Member adds a new member to the XML array.
// It returns a Value encoder.
func (a *Array) Member() Value {
v := newValue(a.w, a.scratch, a.memberStartElement)
v.isFlattened = a.isFlattened
return v
}

View File

@ -0,0 +1,10 @@
package xml
const (
leftAngleBracket = '<'
rightAngleBracket = '>'
forwardSlash = '/'
colon = ':'
equals = '='
quote = '"'
)

49
vendor/github.com/aws/smithy-go/encoding/xml/doc.go generated vendored Normal file
View File

@ -0,0 +1,49 @@
/*
Package xml holds the XMl encoder utility. This utility is written in accordance to our design to delegate to
shape serializer function in which a xml.Value will be passed around.
Resources followed: https://awslabs.github.io/smithy/1.0/spec/core/xml-traits.html#
Member Element
Member element should be used to encode xml shapes into xml elements except for flattened xml shapes. Member element
write their own element start tag. These elements should always be closed.
Flattened Element
Flattened element should be used to encode shapes marked with flattened trait into xml elements. Flattened element
do not write a start tag, and thus should not be closed.
Simple types encoding
All simple type methods on value such as String(), Long() etc; auto close the associated member element.
Array
Array returns the collection encoder. It has two modes, wrapped and flattened encoding.
Wrapped arrays have two methods Array() and ArrayWithCustomName() which facilitate array member wrapping.
By default, a wrapped array members are wrapped with `member` named start element.
<wrappedArray><member>apple</member><member>tree</member></wrappedArray>
Flattened arrays rely on Value being marked as flattened.
If a shape is marked as flattened, Array() will use the shape element name as wrapper for array elements.
<flattenedAarray>apple</flattenedArray><flattenedArray>tree</flattenedArray>
Map
Map is the map encoder. It has two modes, wrapped and flattened encoding.
Wrapped map has Array() method, which facilitate map member wrapping.
By default, a wrapped map members are wrapped with `entry` named start element.
<wrappedMap><entry><Key>apple</Key><Value>tree</Value></entry><entry><Key>snow</Key><Value>ice</Value></entry></wrappedMap>
Flattened map rely on Value being marked as flattened.
If a shape is marked as flattened, Map() will use the shape element name as wrapper for map entry elements.
<flattenedMap><Key>apple</Key><Value>tree</Value></flattenedMap><flattenedMap><Key>snow</Key><Value>ice</Value></flattenedMap>
*/
package xml

View File

@ -0,0 +1,91 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Copied and modified from Go 1.14 stdlib's encoding/xml
package xml
// A Name represents an XML name (Local) annotated
// with a name space identifier (Space).
// In tokens returned by Decoder.Token, the Space identifier
// is given as a canonical URL, not the short prefix used
// in the document being parsed.
type Name struct {
Space, Local string
}
// An Attr represents an attribute in an XML element (Name=Value).
type Attr struct {
Name Name
Value string
}
/*
NewAttribute returns a pointer to an attribute.
It takes in a local name aka attribute name, and value
representing the attribute value.
*/
func NewAttribute(local, value string) Attr {
return Attr{
Name: Name{
Local: local,
},
Value: value,
}
}
/*
NewNamespaceAttribute returns a pointer to an attribute.
It takes in a local name aka attribute name, and value
representing the attribute value.
NewNamespaceAttribute appends `xmlns:` in front of namespace
prefix.
For creating a name space attribute representing
`xmlns:prefix="http://example.com`, the breakdown would be:
local = "prefix"
value = "http://example.com"
*/
func NewNamespaceAttribute(local, value string) Attr {
attr := NewAttribute(local, value)
// default name space identifier
attr.Name.Space = "xmlns"
return attr
}
// A StartElement represents an XML start element.
type StartElement struct {
Name Name
Attr []Attr
}
// Copy creates a new copy of StartElement.
func (e StartElement) Copy() StartElement {
attrs := make([]Attr, len(e.Attr))
copy(attrs, e.Attr)
e.Attr = attrs
return e
}
// End returns the corresponding XML end element.
func (e StartElement) End() EndElement {
return EndElement{e.Name}
}
// returns true if start element local name is empty
func (e StartElement) isZero() bool {
return len(e.Name.Local) == 0
}
// An EndElement represents an XML end element.
type EndElement struct {
Name Name
}
// returns true if end element local name is empty
func (e EndElement) isZero() bool {
return len(e.Name.Local) == 0
}

View File

@ -0,0 +1,51 @@
package xml
// writer interface used by the xml encoder to write an encoded xml
// document in a writer.
type writer interface {
// Write takes in a byte slice and returns number of bytes written and error
Write(p []byte) (n int, err error)
// WriteRune takes in a rune and returns number of bytes written and error
WriteRune(r rune) (n int, err error)
// WriteString takes in a string and returns number of bytes written and error
WriteString(s string) (n int, err error)
// String method returns a string
String() string
// Bytes return a byte slice.
Bytes() []byte
}
// Encoder is an XML encoder that supports construction of XML values
// using methods. The encoder takes in a writer and maintains a scratch buffer.
type Encoder struct {
w writer
scratch *[]byte
}
// NewEncoder returns an XML encoder
func NewEncoder(w writer) *Encoder {
scratch := make([]byte, 64)
return &Encoder{w: w, scratch: &scratch}
}
// String returns the string output of the XML encoder
func (e Encoder) String() string {
return e.w.String()
}
// Bytes returns the []byte slice of the XML encoder
func (e Encoder) Bytes() []byte {
return e.w.Bytes()
}
// RootElement builds a root element encoding
// It writes it's start element tag. The value should be closed.
func (e Encoder) RootElement(element StartElement) Value {
return newValue(e.w, e.scratch, element)
}

View File

@ -0,0 +1,51 @@
package xml
import (
"encoding/xml"
"fmt"
"io"
)
// ErrorComponents represents the error response fields
// that will be deserialized from an xml error response body
type ErrorComponents struct {
Code string
Message string
}
// GetErrorResponseComponents returns the error fields from an xml error response body
func GetErrorResponseComponents(r io.Reader, noErrorWrapping bool) (ErrorComponents, error) {
if noErrorWrapping {
var errResponse noWrappedErrorResponse
if err := xml.NewDecoder(r).Decode(&errResponse); err != nil && err != io.EOF {
return ErrorComponents{}, fmt.Errorf("error while deserializing xml error response: %w", err)
}
return ErrorComponents{
Code: errResponse.Code,
Message: errResponse.Message,
}, nil
}
var errResponse wrappedErrorResponse
if err := xml.NewDecoder(r).Decode(&errResponse); err != nil && err != io.EOF {
return ErrorComponents{}, fmt.Errorf("error while deserializing xml error response: %w", err)
}
return ErrorComponents{
Code: errResponse.Code,
Message: errResponse.Message,
}, nil
}
// noWrappedErrorResponse represents the error response body with
// no internal <Error></Error wrapping
type noWrappedErrorResponse struct {
Code string `xml:"Code"`
Message string `xml:"Message"`
}
// wrappedErrorResponse represents the error response body
// wrapped within <Error>...</Error>
type wrappedErrorResponse struct {
Code string `xml:"Error>Code"`
Message string `xml:"Error>Message"`
}

137
vendor/github.com/aws/smithy-go/encoding/xml/escape.go generated vendored Normal file
View File

@ -0,0 +1,137 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Copied and modified from Go 1.14 stdlib's encoding/xml
package xml
import (
"unicode/utf8"
)
// Copied from Go 1.14 stdlib's encoding/xml
var (
escQuot = []byte("&#34;") // shorter than "&quot;"
escApos = []byte("&#39;") // shorter than "&apos;"
escAmp = []byte("&amp;")
escLT = []byte("&lt;")
escGT = []byte("&gt;")
escTab = []byte("&#x9;")
escNL = []byte("&#xA;")
escCR = []byte("&#xD;")
escFFFD = []byte("\uFFFD") // Unicode replacement character
// Additional Escapes
escNextLine = []byte("&#x85;")
escLS = []byte("&#x2028;")
)
// Decide whether the given rune is in the XML Character Range, per
// the Char production of https://www.xml.com/axml/testaxml.htm,
// Section 2.2 Characters.
func isInCharacterRange(r rune) (inrange bool) {
return r == 0x09 ||
r == 0x0A ||
r == 0x0D ||
r >= 0x20 && r <= 0xD7FF ||
r >= 0xE000 && r <= 0xFFFD ||
r >= 0x10000 && r <= 0x10FFFF
}
// TODO: When do we need to escape the string?
// Based on encoding/xml escapeString from the Go Standard Library.
// https://golang.org/src/encoding/xml/xml.go
func escapeString(e writer, s string) {
var esc []byte
last := 0
for i := 0; i < len(s); {
r, width := utf8.DecodeRuneInString(s[i:])
i += width
switch r {
case '"':
esc = escQuot
case '\'':
esc = escApos
case '&':
esc = escAmp
case '<':
esc = escLT
case '>':
esc = escGT
case '\t':
esc = escTab
case '\n':
esc = escNL
case '\r':
esc = escCR
case '\u0085':
// Not escaped by stdlib
esc = escNextLine
case '\u2028':
// Not escaped by stdlib
esc = escLS
default:
if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
esc = escFFFD
break
}
continue
}
e.WriteString(s[last : i-width])
e.Write(esc)
last = i
}
e.WriteString(s[last:])
}
// escapeText writes to w the properly escaped XML equivalent
// of the plain text data s. If escapeNewline is true, newline
// characters will be escaped.
//
// Based on encoding/xml escapeText from the Go Standard Library.
// https://golang.org/src/encoding/xml/xml.go
func escapeText(e writer, s []byte) {
var esc []byte
last := 0
for i := 0; i < len(s); {
r, width := utf8.DecodeRune(s[i:])
i += width
switch r {
case '"':
esc = escQuot
case '\'':
esc = escApos
case '&':
esc = escAmp
case '<':
esc = escLT
case '>':
esc = escGT
case '\t':
esc = escTab
case '\n':
// This always escapes newline, which is different than stdlib's optional
// escape of new line.
esc = escNL
case '\r':
esc = escCR
case '\u0085':
// Not escaped by stdlib
esc = escNextLine
case '\u2028':
// Not escaped by stdlib
esc = escLS
default:
if !isInCharacterRange(r) || (r == 0xFFFD && width == 1) {
esc = escFFFD
break
}
continue
}
e.Write(s[last : i-width])
e.Write(esc)
last = i
}
e.Write(s[last:])
}

53
vendor/github.com/aws/smithy-go/encoding/xml/map.go generated vendored Normal file
View File

@ -0,0 +1,53 @@
package xml
// mapEntryWrapper is the default member wrapper start element for XML Map entry
var mapEntryWrapper = StartElement{
Name: Name{Local: "entry"},
}
// Map represents the encoding of a XML map type
type Map struct {
w writer
scratch *[]byte
// member start element is the map entry wrapper start element
memberStartElement StartElement
// isFlattened returns true if the map is a flattened map
isFlattened bool
}
// newMap returns a map encoder which sets the default map
// entry wrapper to `entry`.
//
// A map `someMap : {{key:"abc", value:"123"}}` is represented as
// `<someMap><entry><key>abc<key><value>123</value></entry></someMap>`.
func newMap(w writer, scratch *[]byte) *Map {
return &Map{
w: w,
scratch: scratch,
memberStartElement: mapEntryWrapper,
}
}
// newFlattenedMap returns a map encoder which sets the map
// entry wrapper to the passed in memberWrapper`.
//
// A flattened map `someMap : {{key:"abc", value:"123"}}` is represented as
// `<someMap><key>abc<key><value>123</value></someMap>`.
func newFlattenedMap(w writer, scratch *[]byte, memberWrapper StartElement) *Map {
return &Map{
w: w,
scratch: scratch,
memberStartElement: memberWrapper,
isFlattened: true,
}
}
// Entry returns a Value encoder with map's element.
// It writes the member wrapper start tag for each entry.
func (m *Map) Entry() Value {
v := newValue(m.w, m.scratch, m.memberStartElement)
v.isFlattened = m.isFlattened
return v
}

302
vendor/github.com/aws/smithy-go/encoding/xml/value.go generated vendored Normal file
View File

@ -0,0 +1,302 @@
package xml
import (
"encoding/base64"
"fmt"
"math/big"
"strconv"
"github.com/aws/smithy-go/encoding"
)
// Value represents an XML Value type
// XML Value types: Object, Array, Map, String, Number, Boolean.
type Value struct {
w writer
scratch *[]byte
// xml start element is the associated start element for the Value
startElement StartElement
// indicates if the Value represents a flattened shape
isFlattened bool
}
// newFlattenedValue returns a Value encoder. newFlattenedValue does NOT write the start element tag
func newFlattenedValue(w writer, scratch *[]byte, startElement StartElement) Value {
return Value{
w: w,
scratch: scratch,
startElement: startElement,
}
}
// newValue writes the start element xml tag and returns a Value
func newValue(w writer, scratch *[]byte, startElement StartElement) Value {
writeStartElement(w, startElement)
return Value{w: w, scratch: scratch, startElement: startElement}
}
// writeStartElement takes in a start element and writes it.
// It handles namespace, attributes in start element.
func writeStartElement(w writer, el StartElement) error {
if el.isZero() {
return fmt.Errorf("xml start element cannot be nil")
}
w.WriteRune(leftAngleBracket)
if len(el.Name.Space) != 0 {
escapeString(w, el.Name.Space)
w.WriteRune(colon)
}
escapeString(w, el.Name.Local)
for _, attr := range el.Attr {
w.WriteRune(' ')
writeAttribute(w, &attr)
}
w.WriteRune(rightAngleBracket)
return nil
}
// writeAttribute writes an attribute from a provided Attribute
// For a namespace attribute, the attr.Name.Space must be defined as "xmlns".
// https://www.w3.org/TR/REC-xml-names/#NT-DefaultAttName
func writeAttribute(w writer, attr *Attr) {
// if local, space both are not empty
if len(attr.Name.Space) != 0 && len(attr.Name.Local) != 0 {
escapeString(w, attr.Name.Space)
w.WriteRune(colon)
}
// if prefix is empty, the default `xmlns` space should be used as prefix.
if len(attr.Name.Local) == 0 {
attr.Name.Local = attr.Name.Space
}
escapeString(w, attr.Name.Local)
w.WriteRune(equals)
w.WriteRune(quote)
escapeString(w, attr.Value)
w.WriteRune(quote)
}
// writeEndElement takes in a end element and writes it.
func writeEndElement(w writer, el EndElement) error {
if el.isZero() {
return fmt.Errorf("xml end element cannot be nil")
}
w.WriteRune(leftAngleBracket)
w.WriteRune(forwardSlash)
if len(el.Name.Space) != 0 {
escapeString(w, el.Name.Space)
w.WriteRune(colon)
}
escapeString(w, el.Name.Local)
w.WriteRune(rightAngleBracket)
return nil
}
// String encodes v as a XML string.
// It will auto close the parent xml element tag.
func (xv Value) String(v string) {
escapeString(xv.w, v)
xv.Close()
}
// Byte encodes v as a XML number.
// It will auto close the parent xml element tag.
func (xv Value) Byte(v int8) {
xv.Long(int64(v))
}
// Short encodes v as a XML number.
// It will auto close the parent xml element tag.
func (xv Value) Short(v int16) {
xv.Long(int64(v))
}
// Integer encodes v as a XML number.
// It will auto close the parent xml element tag.
func (xv Value) Integer(v int32) {
xv.Long(int64(v))
}
// Long encodes v as a XML number.
// It will auto close the parent xml element tag.
func (xv Value) Long(v int64) {
*xv.scratch = strconv.AppendInt((*xv.scratch)[:0], v, 10)
xv.w.Write(*xv.scratch)
xv.Close()
}
// Float encodes v as a XML number.
// It will auto close the parent xml element tag.
func (xv Value) Float(v float32) {
xv.float(float64(v), 32)
xv.Close()
}
// Double encodes v as a XML number.
// It will auto close the parent xml element tag.
func (xv Value) Double(v float64) {
xv.float(v, 64)
xv.Close()
}
func (xv Value) float(v float64, bits int) {
*xv.scratch = encoding.EncodeFloat((*xv.scratch)[:0], v, bits)
xv.w.Write(*xv.scratch)
}
// Boolean encodes v as a XML boolean.
// It will auto close the parent xml element tag.
func (xv Value) Boolean(v bool) {
*xv.scratch = strconv.AppendBool((*xv.scratch)[:0], v)
xv.w.Write(*xv.scratch)
xv.Close()
}
// Base64EncodeBytes writes v as a base64 value in XML string.
// It will auto close the parent xml element tag.
func (xv Value) Base64EncodeBytes(v []byte) {
encodeByteSlice(xv.w, (*xv.scratch)[:0], v)
xv.Close()
}
// BigInteger encodes v big.Int as XML value.
// It will auto close the parent xml element tag.
func (xv Value) BigInteger(v *big.Int) {
xv.w.Write([]byte(v.Text(10)))
xv.Close()
}
// BigDecimal encodes v big.Float as XML value.
// It will auto close the parent xml element tag.
func (xv Value) BigDecimal(v *big.Float) {
if i, accuracy := v.Int64(); accuracy == big.Exact {
xv.Long(i)
return
}
xv.w.Write([]byte(v.Text('e', -1)))
xv.Close()
}
// Write writes v directly to the xml document
// if escapeXMLText is set to true, write will escape text.
// It will auto close the parent xml element tag.
func (xv Value) Write(v []byte, escapeXMLText bool) {
// escape and write xml text
if escapeXMLText {
escapeText(xv.w, v)
} else {
// write xml directly
xv.w.Write(v)
}
xv.Close()
}
// MemberElement does member element encoding. It returns a Value.
// Member Element method should be used for all shapes except flattened shapes.
//
// A call to MemberElement will write nested element tags directly using the
// provided start element. The value returned by MemberElement should be closed.
func (xv Value) MemberElement(element StartElement) Value {
return newValue(xv.w, xv.scratch, element)
}
// FlattenedElement returns flattened element encoding. It returns a Value.
// This method should be used for flattened shapes.
//
// Unlike MemberElement, flattened element will NOT write element tags
// directly for the associated start element.
//
// The value returned by the FlattenedElement does not need to be closed.
func (xv Value) FlattenedElement(element StartElement) Value {
v := newFlattenedValue(xv.w, xv.scratch, element)
v.isFlattened = true
return v
}
// Array returns an array encoder. By default, the members of array are
// wrapped with `<member>` element tag.
// If value is marked as flattened, the start element is used to wrap the members instead of
// the `<member>` element.
func (xv Value) Array() *Array {
return newArray(xv.w, xv.scratch, arrayMemberWrapper, xv.startElement, xv.isFlattened)
}
/*
ArrayWithCustomName returns an array encoder.
It takes named start element as an argument, the named start element will used to wrap xml array entries.
for eg, `<someList><customName>entry1</customName></someList>`
Here `customName` named start element will be wrapped on each array member.
*/
func (xv Value) ArrayWithCustomName(element StartElement) *Array {
return newArray(xv.w, xv.scratch, element, xv.startElement, xv.isFlattened)
}
/*
Map returns a map encoder. By default, the map entries are
wrapped with `<entry>` element tag.
If value is marked as flattened, the start element is used to wrap the entry instead of
the `<member>` element.
*/
func (xv Value) Map() *Map {
// flattened map
if xv.isFlattened {
return newFlattenedMap(xv.w, xv.scratch, xv.startElement)
}
// un-flattened map
return newMap(xv.w, xv.scratch)
}
// encodeByteSlice is modified copy of json encoder's encodeByteSlice.
// It is used to base64 encode a byte slice.
func encodeByteSlice(w writer, scratch []byte, v []byte) {
if v == nil {
return
}
encodedLen := base64.StdEncoding.EncodedLen(len(v))
if encodedLen <= len(scratch) {
// If the encoded bytes fit in e.scratch, avoid an extra
// allocation and use the cheaper Encoding.Encode.
dst := scratch[:encodedLen]
base64.StdEncoding.Encode(dst, v)
w.Write(dst)
} else if encodedLen <= 1024 {
// The encoded bytes are short enough to allocate for, and
// Encoding.Encode is still cheaper.
dst := make([]byte, encodedLen)
base64.StdEncoding.Encode(dst, v)
w.Write(dst)
} else {
// The encoded bytes are too long to cheaply allocate, and
// Encoding.Encode is no longer noticeably cheaper.
enc := base64.NewEncoder(base64.StdEncoding, w)
enc.Write(v)
enc.Close()
}
}
// IsFlattened returns true if value is for flattened shape.
func (xv Value) IsFlattened() bool {
return xv.isFlattened
}
// Close closes the value.
func (xv Value) Close() {
writeEndElement(xv.w, xv.startElement.End())
}

View File

@ -0,0 +1,154 @@
package xml
import (
"encoding/xml"
"fmt"
"strings"
)
// NodeDecoder is a XML decoder wrapper that is responsible to decoding
// a single XML Node element and it's nested member elements. This wrapper decoder
// takes in the start element of the top level node being decoded.
type NodeDecoder struct {
Decoder *xml.Decoder
StartEl xml.StartElement
}
// WrapNodeDecoder returns an initialized XMLNodeDecoder
func WrapNodeDecoder(decoder *xml.Decoder, startEl xml.StartElement) NodeDecoder {
return NodeDecoder{
Decoder: decoder,
StartEl: startEl,
}
}
// Token on a Node Decoder returns a xml StartElement. It returns a boolean that indicates the
// a token is the node decoder's end node token; and an error which indicates any error
// that occurred while retrieving the start element
func (d NodeDecoder) Token() (t xml.StartElement, done bool, err error) {
for {
token, e := d.Decoder.Token()
if e != nil {
return t, done, e
}
// check if we reach end of the node being decoded
if el, ok := token.(xml.EndElement); ok {
return t, el == d.StartEl.End(), err
}
if t, ok := token.(xml.StartElement); ok {
return restoreAttrNamespaces(t), false, err
}
// skip token if it is a comment or preamble or empty space value due to indentation
// or if it's a value and is not expected
}
}
// restoreAttrNamespaces update XML attributes to restore the short namespaces found within
// the raw XML document.
func restoreAttrNamespaces(node xml.StartElement) xml.StartElement {
if len(node.Attr) == 0 {
return node
}
// Generate a mapping of XML namespace values to their short names.
ns := map[string]string{}
for _, a := range node.Attr {
if a.Name.Space == "xmlns" {
ns[a.Value] = a.Name.Local
break
}
}
for i, a := range node.Attr {
if a.Name.Space == "xmlns" {
continue
}
// By default, xml.Decoder will fully resolve these namespaces. So if you had <foo xmlns:bar=baz bar:bin=hi/>
// then by default the second attribute would have the `Name.Space` resolved to `baz`. But we need it to
// continue to resolve as `bar` so we can easily identify it later on.
if v, ok := ns[node.Attr[i].Name.Space]; ok {
node.Attr[i].Name.Space = v
}
}
return node
}
// GetElement looks for the given tag name at the current level, and returns the element if found, and
// skipping over non-matching elements. Returns an error if the node is not found, or if an error occurs while walking
// the document.
func (d NodeDecoder) GetElement(name string) (t xml.StartElement, err error) {
for {
token, done, err := d.Token()
if err != nil {
return t, err
}
if done {
return t, fmt.Errorf("%s node not found", name)
}
switch {
case strings.EqualFold(name, token.Name.Local):
return token, nil
default:
err = d.Decoder.Skip()
if err != nil {
return t, err
}
}
}
}
// Value provides an abstraction to retrieve char data value within an xml element.
// The method will return an error if it encounters a nested xml element instead of char data.
// This method should only be used to retrieve simple type or blob shape values as []byte.
func (d NodeDecoder) Value() (c []byte, err error) {
t, e := d.Decoder.Token()
if e != nil {
return c, e
}
endElement := d.StartEl.End()
switch ev := t.(type) {
case xml.CharData:
c = ev.Copy()
case xml.EndElement: // end tag or self-closing
if ev == endElement {
return []byte{}, err
}
return c, fmt.Errorf("expected value for %v element, got %T type %v instead", d.StartEl.Name.Local, t, t)
default:
return c, fmt.Errorf("expected value for %v element, got %T type %v instead", d.StartEl.Name.Local, t, t)
}
t, e = d.Decoder.Token()
if e != nil {
return c, e
}
if ev, ok := t.(xml.EndElement); ok {
if ev == endElement {
return c, err
}
}
return c, fmt.Errorf("expected end element %v, got %T type %v instead", endElement, t, t)
}
// FetchRootElement takes in a decoder and returns the first start element within the xml body.
// This function is useful in fetching the start element of an XML response and ignore the
// comments and preamble
func FetchRootElement(decoder *xml.Decoder) (startElement xml.StartElement, err error) {
for {
t, e := decoder.Token()
if e != nil {
return startElement, e
}
if startElement, ok := t.(xml.StartElement); ok {
return startElement, err
}
}
}

137
vendor/github.com/aws/smithy-go/errors.go generated vendored Normal file
View File

@ -0,0 +1,137 @@
package smithy
import "fmt"
// APIError provides the generic API and protocol agnostic error type all SDK
// generated exception types will implement.
type APIError interface {
error
// ErrorCode returns the error code for the API exception.
ErrorCode() string
// ErrorMessage returns the error message for the API exception.
ErrorMessage() string
// ErrorFault returns the fault for the API exception.
ErrorFault() ErrorFault
}
// GenericAPIError provides a generic concrete API error type that SDKs can use
// to deserialize error responses into. Should be used for unmodeled or untyped
// errors.
type GenericAPIError struct {
Code string
Message string
Fault ErrorFault
}
// ErrorCode returns the error code for the API exception.
func (e *GenericAPIError) ErrorCode() string { return e.Code }
// ErrorMessage returns the error message for the API exception.
func (e *GenericAPIError) ErrorMessage() string { return e.Message }
// ErrorFault returns the fault for the API exception.
func (e *GenericAPIError) ErrorFault() ErrorFault { return e.Fault }
func (e *GenericAPIError) Error() string {
return fmt.Sprintf("api error %s: %s", e.Code, e.Message)
}
var _ APIError = (*GenericAPIError)(nil)
// OperationError decorates an underlying error which occurred while invoking
// an operation with names of the operation and API.
type OperationError struct {
ServiceID string
OperationName string
Err error
}
// Service returns the name of the API service the error occurred with.
func (e *OperationError) Service() string { return e.ServiceID }
// Operation returns the name of the API operation the error occurred with.
func (e *OperationError) Operation() string { return e.OperationName }
// Unwrap returns the nested error if any, or nil.
func (e *OperationError) Unwrap() error { return e.Err }
func (e *OperationError) Error() string {
return fmt.Sprintf("operation error %s: %s, %v", e.ServiceID, e.OperationName, e.Err)
}
// DeserializationError provides a wrapper for an error that occurs during
// deserialization.
type DeserializationError struct {
Err error // original error
Snapshot []byte
}
// Error returns a formatted error for DeserializationError
func (e *DeserializationError) Error() string {
const msg = "deserialization failed"
if e.Err == nil {
return msg
}
return fmt.Sprintf("%s, %v", msg, e.Err)
}
// Unwrap returns the underlying Error in DeserializationError
func (e *DeserializationError) Unwrap() error { return e.Err }
// ErrorFault provides the type for a Smithy API error fault.
type ErrorFault int
// ErrorFault enumeration values
const (
FaultUnknown ErrorFault = iota
FaultServer
FaultClient
)
func (f ErrorFault) String() string {
switch f {
case FaultServer:
return "server"
case FaultClient:
return "client"
default:
return "unknown"
}
}
// SerializationError represents an error that occurred while attempting to serialize a request
type SerializationError struct {
Err error // original error
}
// Error returns a formatted error for SerializationError
func (e *SerializationError) Error() string {
const msg = "serialization failed"
if e.Err == nil {
return msg
}
return fmt.Sprintf("%s: %v", msg, e.Err)
}
// Unwrap returns the underlying Error in SerializationError
func (e *SerializationError) Unwrap() error { return e.Err }
// CanceledError is the error that will be returned by an API request that was
// canceled. API operations given a Context may return this error when
// canceled.
type CanceledError struct {
Err error
}
// CanceledError returns true to satisfy interfaces checking for canceled errors.
func (*CanceledError) CanceledError() bool { return true }
// Unwrap returns the underlying error, if there was one.
func (e *CanceledError) Unwrap() error {
return e.Err
}
func (e *CanceledError) Error() string {
return fmt.Sprintf("canceled, %v", e.Err)
}

View File

@ -0,0 +1,6 @@
// Code generated by internal/repotools/cmd/updatemodulemeta DO NOT EDIT.
package smithy
// goModuleVersion is the tagged release for this module
const goModuleVersion = "1.11.0"

12
vendor/github.com/aws/smithy-go/io/byte.go generated vendored Normal file
View File

@ -0,0 +1,12 @@
package io
const (
// Byte is 8 bits
Byte int64 = 1
// KibiByte (KiB) is 1024 Bytes
KibiByte = Byte * 1024
// MebiByte (MiB) is 1024 KiB
MebiByte = KibiByte * 1024
// GibiByte (GiB) is 1024 MiB
GibiByte = MebiByte * 1024
)

2
vendor/github.com/aws/smithy-go/io/doc.go generated vendored Normal file
View File

@ -0,0 +1,2 @@
// Package io provides utilities for Smithy generated API clients.
package io

16
vendor/github.com/aws/smithy-go/io/reader.go generated vendored Normal file
View File

@ -0,0 +1,16 @@
package io
import (
"io"
)
// ReadSeekNopCloser wraps an io.ReadSeeker with an additional Close method
// that does nothing.
type ReadSeekNopCloser struct {
io.ReadSeeker
}
// Close does nothing.
func (ReadSeekNopCloser) Close() error {
return nil
}

94
vendor/github.com/aws/smithy-go/io/ringbuffer.go generated vendored Normal file
View File

@ -0,0 +1,94 @@
package io
import (
"bytes"
"io"
)
// RingBuffer struct satisfies io.ReadWrite interface.
//
// ReadBuffer is a revolving buffer data structure, which can be used to store snapshots of data in a
// revolving window.
type RingBuffer struct {
slice []byte
start int
end int
size int
}
// NewRingBuffer method takes in a byte slice as an input and returns a RingBuffer.
func NewRingBuffer(slice []byte) *RingBuffer {
ringBuf := RingBuffer{
slice: slice,
}
return &ringBuf
}
// Write method inserts the elements in a byte slice, and returns the number of bytes written along with any error.
func (r *RingBuffer) Write(p []byte) (int, error) {
for _, b := range p {
// check if end points to invalid index, we need to circle back
if r.end == len(r.slice) {
r.end = 0
}
// check if start points to invalid index, we need to circle back
if r.start == len(r.slice) {
r.start = 0
}
// if ring buffer is filled, increment the start index
if r.size == len(r.slice) {
r.size--
r.start++
}
r.slice[r.end] = b
r.end++
r.size++
}
return len(p), nil
}
// Read copies the data on the ring buffer into the byte slice provided to the method.
// Returns the read count along with any error encountered while reading.
func (r *RingBuffer) Read(p []byte) (int, error) {
// readCount keeps track of the number of bytes read
var readCount int
for j := 0; j < len(p); j++ {
// if ring buffer is empty or completely read
// return EOF error.
if r.size == 0 {
return readCount, io.EOF
}
if r.start == len(r.slice) {
r.start = 0
}
p[j] = r.slice[r.start]
readCount++
// increment the start pointer for ring buffer
r.start++
// decrement the size of ring buffer
r.size--
}
return readCount, nil
}
// Len returns the number of unread bytes in the buffer.
func (r *RingBuffer) Len() int {
return r.size
}
// Bytes returns a copy of the RingBuffer's bytes.
func (r RingBuffer) Bytes() []byte {
var b bytes.Buffer
io.Copy(&b, &r)
return b.Bytes()
}
// Reset resets the ring buffer.
func (r *RingBuffer) Reset() {
*r = RingBuffer{
slice: r.slice,
}
}

39
vendor/github.com/aws/smithy-go/local-mod-replace.sh generated vendored Normal file
View File

@ -0,0 +1,39 @@
#1/usr/bin/env bash
PROJECT_DIR=""
SMITHY_SOURCE_DIR=$(cd `dirname $0` && pwd)
usage() {
echo "Usage: $0 [-s SMITHY_SOURCE_DIR] [-d PROJECT_DIR]" 1>&2
exit 1
}
while getopts "hs:d:" options; do
case "${options}" in
s)
SMITHY_SOURCE_DIR=${OPTARG}
if [ "$SMITHY_SOURCE_DIR" == "" ]; then
echo "path to smithy-go source directory is required" || exit
usage
fi
;;
d)
PROJECT_DIR=${OPTARG}
;;
h)
usage
;;
*)
usage
;;
esac
done
if [ "$PROJECT_DIR" != "" ]; then
cd $PROJECT_DIR || exit
fi
go mod graph | awk '{print $1}' | cut -d '@' -f 1 | sort | uniq | grep "github.com/aws/smithy-go" | while read x; do
repPath=${x/github.com\/aws\/smithy-go/${SMITHY_SOURCE_DIR}}
echo -replace $x=$repPath
done | xargs go mod edit

82
vendor/github.com/aws/smithy-go/logging/logger.go generated vendored Normal file
View File

@ -0,0 +1,82 @@
package logging
import (
"context"
"io"
"log"
)
// Classification is the type of the log entry's classification name.
type Classification string
// Set of standard classifications that can be used by clients and middleware
const (
Warn Classification = "WARN"
Debug Classification = "DEBUG"
)
// Logger is an interface for logging entries at certain classifications.
type Logger interface {
// Logf is expected to support the standard fmt package "verbs".
Logf(classification Classification, format string, v ...interface{})
}
// LoggerFunc is a wrapper around a function to satisfy the Logger interface.
type LoggerFunc func(classification Classification, format string, v ...interface{})
// Logf delegates the logging request to the wrapped function.
func (f LoggerFunc) Logf(classification Classification, format string, v ...interface{}) {
f(classification, format, v...)
}
// ContextLogger is an optional interface a Logger implementation may expose that provides
// the ability to create context aware log entries.
type ContextLogger interface {
WithContext(context.Context) Logger
}
// WithContext will pass the provided context to logger if it implements the ContextLogger interface and return the resulting
// logger. Otherwise the logger will be returned as is. As a special case if a nil logger is provided, a Nop logger will
// be returned to the caller.
func WithContext(ctx context.Context, logger Logger) Logger {
if logger == nil {
return Nop{}
}
cl, ok := logger.(ContextLogger)
if !ok {
return logger
}
return cl.WithContext(ctx)
}
// Nop is a Logger implementation that simply does not perform any logging.
type Nop struct{}
// Logf simply returns without performing any action
func (n Nop) Logf(Classification, string, ...interface{}) {
return
}
// StandardLogger is a Logger implementation that wraps the standard library logger, and delegates logging to it's
// Printf method.
type StandardLogger struct {
Logger *log.Logger
}
// Logf logs the given classification and message to the underlying logger.
func (s StandardLogger) Logf(classification Classification, format string, v ...interface{}) {
if len(classification) != 0 {
format = string(classification) + " " + format
}
s.Logger.Printf(format, v...)
}
// NewStandardLogger returns a new StandardLogger
func NewStandardLogger(writer io.Writer) *StandardLogger {
return &StandardLogger{
Logger: log.New(writer, "SDK ", log.LstdFlags),
}
}

67
vendor/github.com/aws/smithy-go/middleware/doc.go generated vendored Normal file
View File

@ -0,0 +1,67 @@
// Package middleware provides transport agnostic middleware for decorating SDK
// handlers.
//
// The Smithy middleware stack provides ordered behavior to be invoked on an
// underlying handler. The stack is separated into steps that are invoked in a
// static order. A step is a collection of middleware that are injected into a
// ordered list defined by the user. The user may add, insert, swap, and remove a
// step's middleware. When the stack is invoked the step middleware become static,
// and their order cannot be modified.
//
// A stack and its step middleware are **not** safe to modify concurrently.
//
// A stack will use the ordered list of middleware to decorate a underlying
// handler. A handler could be something like an HTTP Client that round trips an
// API operation over HTTP.
//
// Smithy Middleware Stack
//
// A Stack is a collection of middleware that wrap a handler. The stack can be
// broken down into discreet steps. Each step may contain zero or more middleware
// specific to that stack's step.
//
// A Stack Step is a predefined set of middleware that are invoked in a static
// order by the Stack. These steps represent fixed points in the middleware stack
// for organizing specific behavior, such as serialize and build. A Stack Step is
// composed of zero or more middleware that are specific to that step. A step may
// define its own set of input/output parameters the generic input/output
// parameters are cast from. A step calls its middleware recursively, before
// calling the next step in the stack returning the result or error of the step
// middleware decorating the underlying handler.
//
// * Initialize: Prepares the input, and sets any default parameters as needed,
// (e.g. idempotency token, and presigned URLs).
//
// * Serialize: Serializes the prepared input into a data structure that can be
// consumed by the target transport's message, (e.g. REST-JSON serialization).
//
// * Build: Adds additional metadata to the serialized transport message, (e.g.
// HTTP's Content-Length header, or body checksum). Decorations and
// modifications to the message should be copied to all message attempts.
//
// * Finalize: Performs final preparations needed before sending the message. The
// message should already be complete by this stage, and is only alternated to
// meet the expectations of the recipient, (e.g. Retry and AWS SigV4 request
// signing).
//
// * Deserialize: Reacts to the handler's response returned by the recipient of
// the request message. Deserializes the response into a structured type or
// error above stacks can react to.
//
// Adding Middleware to a Stack Step
//
// Middleware can be added to a step front or back, or relative, by name, to an
// existing middleware in that stack. If a middleware does not have a name, a
// unique name will be generated at the middleware and be added to the step.
//
// // Create middleware stack
// stack := middleware.NewStack()
//
// // Add middleware to stack steps
// stack.Initialize.Add(paramValidationMiddleware, middleware.After)
// stack.Serialize.Add(marshalOperationFoo, middleware.After)
// stack.Deserialize.Add(unmarshalOperationFoo, middleware.After)
//
// // Invoke middleware on handler.
// resp, err := stack.HandleMiddleware(ctx, req.Input, clientHandler)
package middleware

46
vendor/github.com/aws/smithy-go/middleware/logging.go generated vendored Normal file
View File

@ -0,0 +1,46 @@
package middleware
import (
"context"
"github.com/aws/smithy-go/logging"
)
// loggerKey is the context value key for which the logger is associated with.
type loggerKey struct{}
// GetLogger takes a context to retrieve a Logger from. If no logger is present on the context a logging.Nop logger
// is returned. If the logger retrieved from context supports the ContextLogger interface, the context will be passed
// to the WithContext method and the resulting logger will be returned. Otherwise the stored logger is returned as is.
func GetLogger(ctx context.Context) logging.Logger {
logger, ok := ctx.Value(loggerKey{}).(logging.Logger)
if !ok || logger == nil {
return logging.Nop{}
}
return logging.WithContext(ctx, logger)
}
// SetLogger sets the provided logger value on the provided ctx.
func SetLogger(ctx context.Context, logger logging.Logger) context.Context {
return context.WithValue(ctx, loggerKey{}, logger)
}
type setLogger struct {
Logger logging.Logger
}
// AddSetLoggerMiddleware adds a middleware that will add the provided logger to the middleware context.
func AddSetLoggerMiddleware(stack *Stack, logger logging.Logger) error {
return stack.Initialize.Add(&setLogger{Logger: logger}, After)
}
func (a *setLogger) ID() string {
return "SetLogger"
}
func (a *setLogger) HandleInitialize(ctx context.Context, in InitializeInput, next InitializeHandler) (
out InitializeOutput, metadata Metadata, err error,
) {
return next.HandleInitialize(SetLogger(ctx, a.Logger), in)
}

65
vendor/github.com/aws/smithy-go/middleware/metadata.go generated vendored Normal file
View File

@ -0,0 +1,65 @@
package middleware
// MetadataReader provides an interface for reading metadata from the
// underlying metadata container.
type MetadataReader interface {
Get(key interface{}) interface{}
}
// Metadata provides storing and reading metadata values. Keys may be any
// comparable value type. Get and set will panic if key is not a comparable
// value type.
//
// Metadata uses lazy initialization, and Set method must be called as an
// addressable value, or pointer. Not doing so may cause key/value pair to not
// be set.
type Metadata struct {
values map[interface{}]interface{}
}
// Get attempts to retrieve the value the key points to. Returns nil if the
// key was not found.
//
// Panics if key type is not comparable.
func (m Metadata) Get(key interface{}) interface{} {
return m.values[key]
}
// Clone creates a shallow copy of Metadata entries, returning a new Metadata
// value with the original entries copied into it.
func (m Metadata) Clone() Metadata {
vs := make(map[interface{}]interface{}, len(m.values))
for k, v := range m.values {
vs[k] = v
}
return Metadata{
values: vs,
}
}
// Set stores the value pointed to by the key. If a value already exists at
// that key it will be replaced with the new value.
//
// Set method must be called as an addressable value, or pointer. If Set is not
// called as an addressable value or pointer, the key value pair being set may
// be lost.
//
// Panics if the key type is not comparable.
func (m *Metadata) Set(key, value interface{}) {
if m.values == nil {
m.values = map[interface{}]interface{}{}
}
m.values[key] = value
}
// Has returns whether the key exists in the metadata.
//
// Panics if the key type is not comparable.
func (m Metadata) Has(key interface{}) bool {
if m.values == nil {
return false
}
_, ok := m.values[key]
return ok
}

View File

@ -0,0 +1,71 @@
package middleware
import (
"context"
)
// Handler provides the interface for performing the logic to obtain an output,
// or error for the given input.
type Handler interface {
// Handle performs logic to obtain an output for the given input. Handler
// should be decorated with middleware to perform input specific behavior.
Handle(ctx context.Context, input interface{}) (
output interface{}, metadata Metadata, err error,
)
}
// HandlerFunc provides a wrapper around a function pointer to be used as a
// middleware handler.
type HandlerFunc func(ctx context.Context, input interface{}) (
output interface{}, metadata Metadata, err error,
)
// Handle invokes the underlying function, returning the result.
func (fn HandlerFunc) Handle(ctx context.Context, input interface{}) (
output interface{}, metadata Metadata, err error,
) {
return fn(ctx, input)
}
// Middleware provides the interface to call handlers in a chain.
type Middleware interface {
// ID provides a unique identifier for the middleware.
ID() string
// Performs the middleware's handling of the input, returning the output,
// or error. The middleware can invoke the next Handler if handling should
// continue.
HandleMiddleware(ctx context.Context, input interface{}, next Handler) (
output interface{}, metadata Metadata, err error,
)
}
// decoratedHandler wraps a middleware in order to to call the next handler in
// the chain.
type decoratedHandler struct {
// The next handler to be called.
Next Handler
// The current middleware decorating the handler.
With Middleware
}
// Handle implements the Handler interface to handle a operation invocation.
func (m decoratedHandler) Handle(ctx context.Context, input interface{}) (
output interface{}, metadata Metadata, err error,
) {
return m.With.HandleMiddleware(ctx, input, m.Next)
}
// DecorateHandler decorates a handler with a middleware. Wrapping the handler
// with the middleware.
func DecorateHandler(h Handler, with ...Middleware) Handler {
for i := len(with) - 1; i >= 0; i-- {
h = decoratedHandler{
Next: h,
With: with[i],
}
}
return h
}

View File

@ -0,0 +1,268 @@
package middleware
import "fmt"
// RelativePosition provides specifying the relative position of a middleware
// in an ordered group.
type RelativePosition int
// Relative position for middleware in steps.
const (
After RelativePosition = iota
Before
)
type ider interface {
ID() string
}
// orderedIDs provides an ordered collection of items with relative ordering
// by name.
type orderedIDs struct {
order *relativeOrder
items map[string]ider
}
const baseOrderedItems = 5
func newOrderedIDs() *orderedIDs {
return &orderedIDs{
order: newRelativeOrder(),
items: make(map[string]ider, baseOrderedItems),
}
}
// Add injects the item to the relative position of the item group. Returns an
// error if the item already exists.
func (g *orderedIDs) Add(m ider, pos RelativePosition) error {
id := m.ID()
if len(id) == 0 {
return fmt.Errorf("empty ID, ID must not be empty")
}
if err := g.order.Add(pos, id); err != nil {
return err
}
g.items[id] = m
return nil
}
// Insert injects the item relative to an existing item id. Returns an error if
// the original item does not exist, or the item being added already exists.
func (g *orderedIDs) Insert(m ider, relativeTo string, pos RelativePosition) error {
if len(m.ID()) == 0 {
return fmt.Errorf("insert ID must not be empty")
}
if len(relativeTo) == 0 {
return fmt.Errorf("relative to ID must not be empty")
}
if err := g.order.Insert(relativeTo, pos, m.ID()); err != nil {
return err
}
g.items[m.ID()] = m
return nil
}
// Get returns the ider identified by id. If ider is not present, returns false.
func (g *orderedIDs) Get(id string) (ider, bool) {
v, ok := g.items[id]
return v, ok
}
// Swap removes the item by id, replacing it with the new item. Returns an error
// if the original item doesn't exist.
func (g *orderedIDs) Swap(id string, m ider) (ider, error) {
if len(id) == 0 {
return nil, fmt.Errorf("swap from ID must not be empty")
}
iderID := m.ID()
if len(iderID) == 0 {
return nil, fmt.Errorf("swap to ID must not be empty")
}
if err := g.order.Swap(id, iderID); err != nil {
return nil, err
}
removed := g.items[id]
delete(g.items, id)
g.items[iderID] = m
return removed, nil
}
// Remove removes the item by id. Returns an error if the item
// doesn't exist.
func (g *orderedIDs) Remove(id string) (ider, error) {
if len(id) == 0 {
return nil, fmt.Errorf("remove ID must not be empty")
}
if err := g.order.Remove(id); err != nil {
return nil, err
}
removed := g.items[id]
delete(g.items, id)
return removed, nil
}
func (g *orderedIDs) List() []string {
items := g.order.List()
order := make([]string, len(items))
copy(order, items)
return order
}
// Clear removes all entries and slots.
func (g *orderedIDs) Clear() {
g.order.Clear()
g.items = map[string]ider{}
}
// GetOrder returns the item in the order it should be invoked in.
func (g *orderedIDs) GetOrder() []interface{} {
order := g.order.List()
ordered := make([]interface{}, len(order))
for i := 0; i < len(order); i++ {
ordered[i] = g.items[order[i]]
}
return ordered
}
// relativeOrder provides ordering of item
type relativeOrder struct {
order []string
}
func newRelativeOrder() *relativeOrder {
return &relativeOrder{
order: make([]string, 0, baseOrderedItems),
}
}
// Add inserts an item into the order relative to the position provided.
func (s *relativeOrder) Add(pos RelativePosition, ids ...string) error {
if len(ids) == 0 {
return nil
}
for _, id := range ids {
if _, ok := s.has(id); ok {
return fmt.Errorf("already exists, %v", id)
}
}
switch pos {
case Before:
return s.insert(0, Before, ids...)
case After:
s.order = append(s.order, ids...)
default:
return fmt.Errorf("invalid position, %v", int(pos))
}
return nil
}
// Insert injects an item before or after the relative item. Returns
// an error if the relative item does not exist.
func (s *relativeOrder) Insert(relativeTo string, pos RelativePosition, ids ...string) error {
if len(ids) == 0 {
return nil
}
for _, id := range ids {
if _, ok := s.has(id); ok {
return fmt.Errorf("already exists, %v", id)
}
}
i, ok := s.has(relativeTo)
if !ok {
return fmt.Errorf("not found, %v", relativeTo)
}
return s.insert(i, pos, ids...)
}
// Swap will replace the item id with the to item. Returns an
// error if the original item id does not exist. Allows swapping out an
// item for another item with the same id.
func (s *relativeOrder) Swap(id, to string) error {
i, ok := s.has(id)
if !ok {
return fmt.Errorf("not found, %v", id)
}
if _, ok = s.has(to); ok && id != to {
return fmt.Errorf("already exists, %v", to)
}
s.order[i] = to
return nil
}
func (s *relativeOrder) Remove(id string) error {
i, ok := s.has(id)
if !ok {
return fmt.Errorf("not found, %v", id)
}
s.order = append(s.order[:i], s.order[i+1:]...)
return nil
}
func (s *relativeOrder) List() []string {
return s.order
}
func (s *relativeOrder) Clear() {
s.order = s.order[0:0]
}
func (s *relativeOrder) insert(i int, pos RelativePosition, ids ...string) error {
switch pos {
case Before:
n := len(ids)
var src []string
if n <= cap(s.order)-len(s.order) {
s.order = s.order[:len(s.order)+n]
src = s.order
} else {
src = s.order
s.order = make([]string, len(s.order)+n)
copy(s.order[:i], src[:i]) // only when allocating a new slice do we need to copy the front half
}
copy(s.order[i+n:], src[i:])
copy(s.order[i:], ids)
case After:
if i == len(s.order)-1 || len(s.order) == 0 {
s.order = append(s.order, ids...)
} else {
s.order = append(s.order[:i+1], append(ids, s.order[i+1:]...)...)
}
default:
return fmt.Errorf("invalid position, %v", int(pos))
}
return nil
}
func (s *relativeOrder) has(id string) (i int, found bool) {
for i := 0; i < len(s.order); i++ {
if s.order[i] == id {
return i, true
}
}
return 0, false
}

209
vendor/github.com/aws/smithy-go/middleware/stack.go generated vendored Normal file
View File

@ -0,0 +1,209 @@
package middleware
import (
"context"
"io"
"strings"
)
// Stack provides protocol and transport agnostic set of middleware split into
// distinct steps. Steps have specific transitions between them, that are
// managed by the individual step.
//
// Steps are composed as middleware around the underlying handler in the
// following order:
//
// Initialize -> Serialize -> Build -> Finalize -> Deserialize -> Handler
//
// Any middleware within the chain may choose to stop and return an error or
// response. Since the middleware decorate the handler like a call stack, each
// middleware will receive the result of the next middleware in the chain.
// Middleware that does not need to react to an input, or result must forward
// along the input down the chain, or return the result back up the chain.
//
// Initialize <- Serialize -> Build -> Finalize <- Deserialize <- Handler
type Stack struct {
// Initialize prepares the input, and sets any default parameters as
// needed, (e.g. idempotency token, and presigned URLs).
//
// Takes Input Parameters, and returns result or error.
//
// Receives result or error from Serialize step.
Initialize *InitializeStep
// Serialize serializes the prepared input into a data structure that can be consumed
// by the target transport's message, (e.g. REST-JSON serialization)
//
// Converts Input Parameters into a Request, and returns the result or error.
//
// Receives result or error from Build step.
Serialize *SerializeStep
// Build adds additional metadata to the serialized transport message
// (e.g. HTTP's Content-Length header, or body checksum). Decorations and
// modifications to the message should be copied to all message attempts.
//
// Takes Request, and returns result or error.
//
// Receives result or error from Finalize step.
Build *BuildStep
// Finalize performs final preparations needed before sending the message. The
// message should already be complete by this stage, and is only alternated
// to meet the expectations of the recipient (e.g. Retry and AWS SigV4
// request signing)
//
// Takes Request, and returns result or error.
//
// Receives result or error from Deserialize step.
Finalize *FinalizeStep
// Deserialize reacts to the handler's response returned by the recipient of the request
// message. Deserializes the response into a structured type or error above
// stacks can react to.
//
// Should only forward Request to underlying handler.
//
// Takes Request, and returns result or error.
//
// Receives raw response, or error from underlying handler.
Deserialize *DeserializeStep
id string
}
// NewStack returns an initialize empty stack.
func NewStack(id string, newRequestFn func() interface{}) *Stack {
return &Stack{
id: id,
Initialize: NewInitializeStep(),
Serialize: NewSerializeStep(newRequestFn),
Build: NewBuildStep(),
Finalize: NewFinalizeStep(),
Deserialize: NewDeserializeStep(),
}
}
// ID returns the unique ID for the stack as a middleware.
func (s *Stack) ID() string { return s.id }
// HandleMiddleware invokes the middleware stack decorating the next handler.
// Each step of stack will be invoked in order before calling the next step.
// With the next handler call last.
//
// The input value must be the input parameters of the operation being
// performed.
//
// Will return the result of the operation, or error.
func (s *Stack) HandleMiddleware(ctx context.Context, input interface{}, next Handler) (
output interface{}, metadata Metadata, err error,
) {
h := DecorateHandler(next,
s.Initialize,
s.Serialize,
s.Build,
s.Finalize,
s.Deserialize,
)
return h.Handle(ctx, input)
}
// List returns a list of all middleware in the stack by step.
func (s *Stack) List() []string {
var l []string
l = append(l, s.id)
l = append(l, s.Initialize.ID())
l = append(l, s.Initialize.List()...)
l = append(l, s.Serialize.ID())
l = append(l, s.Serialize.List()...)
l = append(l, s.Build.ID())
l = append(l, s.Build.List()...)
l = append(l, s.Finalize.ID())
l = append(l, s.Finalize.List()...)
l = append(l, s.Deserialize.ID())
l = append(l, s.Deserialize.List()...)
return l
}
func (s *Stack) String() string {
var b strings.Builder
w := &indentWriter{w: &b}
w.WriteLine(s.id)
w.Push()
writeStepItems(w, s.Initialize)
writeStepItems(w, s.Serialize)
writeStepItems(w, s.Build)
writeStepItems(w, s.Finalize)
writeStepItems(w, s.Deserialize)
return b.String()
}
type stackStepper interface {
ID() string
List() []string
}
func writeStepItems(w *indentWriter, s stackStepper) {
type lister interface {
List() []string
}
w.WriteLine(s.ID())
w.Push()
defer w.Pop()
// ignore stack to prevent circular iterations
if _, ok := s.(*Stack); ok {
return
}
for _, id := range s.List() {
w.WriteLine(id)
}
}
type stringWriter interface {
io.Writer
WriteString(string) (int, error)
WriteRune(rune) (int, error)
}
type indentWriter struct {
w stringWriter
depth int
}
const indentDepth = "\t\t\t\t\t\t\t\t\t\t"
func (w *indentWriter) Push() {
w.depth++
}
func (w *indentWriter) Pop() {
w.depth--
if w.depth < 0 {
w.depth = 0
}
}
func (w *indentWriter) WriteLine(v string) {
w.w.WriteString(indentDepth[:w.depth])
v = strings.ReplaceAll(v, "\n", "\\n")
v = strings.ReplaceAll(v, "\r", "\\r")
w.w.WriteString(v)
w.w.WriteRune('\n')
}

View File

@ -0,0 +1,100 @@
package middleware
import (
"context"
"reflect"
"strings"
)
// WithStackValue adds a key value pair to the context that is intended to be
// scoped to a stack. Use ClearStackValues to get a new context with all stack
// values cleared.
func WithStackValue(ctx context.Context, key, value interface{}) context.Context {
md, _ := ctx.Value(stackValuesKey{}).(*stackValues)
md = withStackValue(md, key, value)
return context.WithValue(ctx, stackValuesKey{}, md)
}
// ClearStackValues returns a context without any stack values.
func ClearStackValues(ctx context.Context) context.Context {
return context.WithValue(ctx, stackValuesKey{}, nil)
}
// GetStackValues returns the value pointed to by the key within the stack
// values, if it is present.
func GetStackValue(ctx context.Context, key interface{}) interface{} {
md, _ := ctx.Value(stackValuesKey{}).(*stackValues)
if md == nil {
return nil
}
return md.Value(key)
}
type stackValuesKey struct{}
type stackValues struct {
key interface{}
value interface{}
parent *stackValues
}
func withStackValue(parent *stackValues, key, value interface{}) *stackValues {
if key == nil {
panic("nil key")
}
if !reflect.TypeOf(key).Comparable() {
panic("key is not comparable")
}
return &stackValues{key: key, value: value, parent: parent}
}
func (m *stackValues) Value(key interface{}) interface{} {
if key == m.key {
return m.value
}
if m.parent == nil {
return nil
}
return m.parent.Value(key)
}
func (c *stackValues) String() string {
var str strings.Builder
cc := c
for cc == nil {
str.WriteString("(" +
reflect.TypeOf(c.key).String() +
": " +
stringify(cc.value) +
")")
if cc.parent != nil {
str.WriteString(" -> ")
}
cc = cc.parent
}
str.WriteRune('}')
return str.String()
}
type stringer interface {
String() string
}
// stringify tries a bit to stringify v, without using fmt, since we don't
// want context depending on the unicode tables. This is only used by
// *valueCtx.String().
func stringify(v interface{}) string {
switch s := v.(type) {
case stringer:
return s.String()
case string:
return s
}
return "<not Stringer>"
}

View File

@ -0,0 +1,211 @@
package middleware
import (
"context"
)
// BuildInput provides the input parameters for the BuildMiddleware to consume.
// BuildMiddleware may modify the Request value before forwarding the input
// along to the next BuildHandler.
type BuildInput struct {
Request interface{}
}
// BuildOutput provides the result returned by the next BuildHandler.
type BuildOutput struct {
Result interface{}
}
// BuildHandler provides the interface for the next handler the
// BuildMiddleware will call in the middleware chain.
type BuildHandler interface {
HandleBuild(ctx context.Context, in BuildInput) (
out BuildOutput, metadata Metadata, err error,
)
}
// BuildMiddleware provides the interface for middleware specific to the
// serialize step. Delegates to the next BuildHandler for further
// processing.
type BuildMiddleware interface {
// Unique ID for the middleware in theBuildStep. The step does not allow
// duplicate IDs.
ID() string
// Invokes the middleware behavior which must delegate to the next handler
// for the middleware chain to continue. The method must return a result or
// error to its caller.
HandleBuild(ctx context.Context, in BuildInput, next BuildHandler) (
out BuildOutput, metadata Metadata, err error,
)
}
// BuildMiddlewareFunc returns a BuildMiddleware with the unique ID provided,
// and the func to be invoked.
func BuildMiddlewareFunc(id string, fn func(context.Context, BuildInput, BuildHandler) (BuildOutput, Metadata, error)) BuildMiddleware {
return buildMiddlewareFunc{
id: id,
fn: fn,
}
}
type buildMiddlewareFunc struct {
// Unique ID for the middleware.
id string
// Middleware function to be called.
fn func(context.Context, BuildInput, BuildHandler) (BuildOutput, Metadata, error)
}
// ID returns the unique ID for the middleware.
func (s buildMiddlewareFunc) ID() string { return s.id }
// HandleBuild invokes the middleware Fn.
func (s buildMiddlewareFunc) HandleBuild(ctx context.Context, in BuildInput, next BuildHandler) (
out BuildOutput, metadata Metadata, err error,
) {
return s.fn(ctx, in, next)
}
var _ BuildMiddleware = (buildMiddlewareFunc{})
// BuildStep provides the ordered grouping of BuildMiddleware to be invoked on
// a handler.
type BuildStep struct {
ids *orderedIDs
}
// NewBuildStep returns a BuildStep ready to have middleware for
// initialization added to it.
func NewBuildStep() *BuildStep {
return &BuildStep{
ids: newOrderedIDs(),
}
}
var _ Middleware = (*BuildStep)(nil)
// ID returns the unique name of the step as a middleware.
func (s *BuildStep) ID() string {
return "Build stack step"
}
// HandleMiddleware invokes the middleware by decorating the next handler
// provided. Returns the result of the middleware and handler being invoked.
//
// Implements Middleware interface.
func (s *BuildStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
out interface{}, metadata Metadata, err error,
) {
order := s.ids.GetOrder()
var h BuildHandler = buildWrapHandler{Next: next}
for i := len(order) - 1; i >= 0; i-- {
h = decoratedBuildHandler{
Next: h,
With: order[i].(BuildMiddleware),
}
}
sIn := BuildInput{
Request: in,
}
res, metadata, err := h.HandleBuild(ctx, sIn)
return res.Result, metadata, err
}
// Get retrieves the middleware identified by id. If the middleware is not present, returns false.
func (s *BuildStep) Get(id string) (BuildMiddleware, bool) {
get, ok := s.ids.Get(id)
if !ok {
return nil, false
}
return get.(BuildMiddleware), ok
}
// Add injects the middleware to the relative position of the middleware group.
// Returns an error if the middleware already exists.
func (s *BuildStep) Add(m BuildMiddleware, pos RelativePosition) error {
return s.ids.Add(m, pos)
}
// Insert injects the middleware relative to an existing middleware id.
// Returns an error if the original middleware does not exist, or the middleware
// being added already exists.
func (s *BuildStep) Insert(m BuildMiddleware, relativeTo string, pos RelativePosition) error {
return s.ids.Insert(m, relativeTo, pos)
}
// Swap removes the middleware by id, replacing it with the new middleware.
// Returns the middleware removed, or an error if the middleware to be removed
// doesn't exist.
func (s *BuildStep) Swap(id string, m BuildMiddleware) (BuildMiddleware, error) {
removed, err := s.ids.Swap(id, m)
if err != nil {
return nil, err
}
return removed.(BuildMiddleware), nil
}
// Remove removes the middleware by id. Returns error if the middleware
// doesn't exist.
func (s *BuildStep) Remove(id string) (BuildMiddleware, error) {
removed, err := s.ids.Remove(id)
if err != nil {
return nil, err
}
return removed.(BuildMiddleware), nil
}
// List returns a list of the middleware in the step.
func (s *BuildStep) List() []string {
return s.ids.List()
}
// Clear removes all middleware in the step.
func (s *BuildStep) Clear() {
s.ids.Clear()
}
type buildWrapHandler struct {
Next Handler
}
var _ BuildHandler = (*buildWrapHandler)(nil)
// Implements BuildHandler, converts types and delegates to underlying
// generic handler.
func (w buildWrapHandler) HandleBuild(ctx context.Context, in BuildInput) (
out BuildOutput, metadata Metadata, err error,
) {
res, metadata, err := w.Next.Handle(ctx, in.Request)
return BuildOutput{
Result: res,
}, metadata, err
}
type decoratedBuildHandler struct {
Next BuildHandler
With BuildMiddleware
}
var _ BuildHandler = (*decoratedBuildHandler)(nil)
func (h decoratedBuildHandler) HandleBuild(ctx context.Context, in BuildInput) (
out BuildOutput, metadata Metadata, err error,
) {
return h.With.HandleBuild(ctx, in, h.Next)
}
// BuildHandlerFunc provides a wrapper around a function to be used as a build middleware handler.
type BuildHandlerFunc func(context.Context, BuildInput) (BuildOutput, Metadata, error)
// HandleBuild invokes the wrapped function with the provided arguments.
func (b BuildHandlerFunc) HandleBuild(ctx context.Context, in BuildInput) (BuildOutput, Metadata, error) {
return b(ctx, in)
}
var _ BuildHandler = BuildHandlerFunc(nil)

View File

@ -0,0 +1,217 @@
package middleware
import (
"context"
)
// DeserializeInput provides the input parameters for the DeserializeInput to
// consume. DeserializeMiddleware should not modify the Request, and instead
// forward it along to the next DeserializeHandler.
type DeserializeInput struct {
Request interface{}
}
// DeserializeOutput provides the result returned by the next
// DeserializeHandler. The DeserializeMiddleware should deserialize the
// RawResponse into a Result that can be consumed by middleware higher up in
// the stack.
type DeserializeOutput struct {
RawResponse interface{}
Result interface{}
}
// DeserializeHandler provides the interface for the next handler the
// DeserializeMiddleware will call in the middleware chain.
type DeserializeHandler interface {
HandleDeserialize(ctx context.Context, in DeserializeInput) (
out DeserializeOutput, metadata Metadata, err error,
)
}
// DeserializeMiddleware provides the interface for middleware specific to the
// serialize step. Delegates to the next DeserializeHandler for further
// processing.
type DeserializeMiddleware interface {
// ID returns a unique ID for the middleware in the DeserializeStep. The step does not
// allow duplicate IDs.
ID() string
// HandleDeserialize invokes the middleware behavior which must delegate to the next handler
// for the middleware chain to continue. The method must return a result or
// error to its caller.
HandleDeserialize(ctx context.Context, in DeserializeInput, next DeserializeHandler) (
out DeserializeOutput, metadata Metadata, err error,
)
}
// DeserializeMiddlewareFunc returns a DeserializeMiddleware with the unique ID
// provided, and the func to be invoked.
func DeserializeMiddlewareFunc(id string, fn func(context.Context, DeserializeInput, DeserializeHandler) (DeserializeOutput, Metadata, error)) DeserializeMiddleware {
return deserializeMiddlewareFunc{
id: id,
fn: fn,
}
}
type deserializeMiddlewareFunc struct {
// Unique ID for the middleware.
id string
// Middleware function to be called.
fn func(context.Context, DeserializeInput, DeserializeHandler) (
DeserializeOutput, Metadata, error,
)
}
// ID returns the unique ID for the middleware.
func (s deserializeMiddlewareFunc) ID() string { return s.id }
// HandleDeserialize invokes the middleware Fn.
func (s deserializeMiddlewareFunc) HandleDeserialize(ctx context.Context, in DeserializeInput, next DeserializeHandler) (
out DeserializeOutput, metadata Metadata, err error,
) {
return s.fn(ctx, in, next)
}
var _ DeserializeMiddleware = (deserializeMiddlewareFunc{})
// DeserializeStep provides the ordered grouping of DeserializeMiddleware to be
// invoked on a handler.
type DeserializeStep struct {
ids *orderedIDs
}
// NewDeserializeStep returns a DeserializeStep ready to have middleware for
// initialization added to it.
func NewDeserializeStep() *DeserializeStep {
return &DeserializeStep{
ids: newOrderedIDs(),
}
}
var _ Middleware = (*DeserializeStep)(nil)
// ID returns the unique ID of the step as a middleware.
func (s *DeserializeStep) ID() string {
return "Deserialize stack step"
}
// HandleMiddleware invokes the middleware by decorating the next handler
// provided. Returns the result of the middleware and handler being invoked.
//
// Implements Middleware interface.
func (s *DeserializeStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
out interface{}, metadata Metadata, err error,
) {
order := s.ids.GetOrder()
var h DeserializeHandler = deserializeWrapHandler{Next: next}
for i := len(order) - 1; i >= 0; i-- {
h = decoratedDeserializeHandler{
Next: h,
With: order[i].(DeserializeMiddleware),
}
}
sIn := DeserializeInput{
Request: in,
}
res, metadata, err := h.HandleDeserialize(ctx, sIn)
return res.Result, metadata, err
}
// Get retrieves the middleware identified by id. If the middleware is not present, returns false.
func (s *DeserializeStep) Get(id string) (DeserializeMiddleware, bool) {
get, ok := s.ids.Get(id)
if !ok {
return nil, false
}
return get.(DeserializeMiddleware), ok
}
// Add injects the middleware to the relative position of the middleware group.
// Returns an error if the middleware already exists.
func (s *DeserializeStep) Add(m DeserializeMiddleware, pos RelativePosition) error {
return s.ids.Add(m, pos)
}
// Insert injects the middleware relative to an existing middleware ID.
// Returns error if the original middleware does not exist, or the middleware
// being added already exists.
func (s *DeserializeStep) Insert(m DeserializeMiddleware, relativeTo string, pos RelativePosition) error {
return s.ids.Insert(m, relativeTo, pos)
}
// Swap removes the middleware by id, replacing it with the new middleware.
// Returns the middleware removed, or error if the middleware to be removed
// doesn't exist.
func (s *DeserializeStep) Swap(id string, m DeserializeMiddleware) (DeserializeMiddleware, error) {
removed, err := s.ids.Swap(id, m)
if err != nil {
return nil, err
}
return removed.(DeserializeMiddleware), nil
}
// Remove removes the middleware by id. Returns error if the middleware
// doesn't exist.
func (s *DeserializeStep) Remove(id string) (DeserializeMiddleware, error) {
removed, err := s.ids.Remove(id)
if err != nil {
return nil, err
}
return removed.(DeserializeMiddleware), nil
}
// List returns a list of the middleware in the step.
func (s *DeserializeStep) List() []string {
return s.ids.List()
}
// Clear removes all middleware in the step.
func (s *DeserializeStep) Clear() {
s.ids.Clear()
}
type deserializeWrapHandler struct {
Next Handler
}
var _ DeserializeHandler = (*deserializeWrapHandler)(nil)
// HandleDeserialize implements DeserializeHandler, converts types and delegates to underlying
// generic handler.
func (w deserializeWrapHandler) HandleDeserialize(ctx context.Context, in DeserializeInput) (
out DeserializeOutput, metadata Metadata, err error,
) {
resp, metadata, err := w.Next.Handle(ctx, in.Request)
return DeserializeOutput{
RawResponse: resp,
}, metadata, err
}
type decoratedDeserializeHandler struct {
Next DeserializeHandler
With DeserializeMiddleware
}
var _ DeserializeHandler = (*decoratedDeserializeHandler)(nil)
func (h decoratedDeserializeHandler) HandleDeserialize(ctx context.Context, in DeserializeInput) (
out DeserializeOutput, metadata Metadata, err error,
) {
return h.With.HandleDeserialize(ctx, in, h.Next)
}
// DeserializeHandlerFunc provides a wrapper around a function to be used as a deserialize middleware handler.
type DeserializeHandlerFunc func(context.Context, DeserializeInput) (DeserializeOutput, Metadata, error)
// HandleDeserialize invokes the wrapped function with the given arguments.
func (d DeserializeHandlerFunc) HandleDeserialize(ctx context.Context, in DeserializeInput) (DeserializeOutput, Metadata, error) {
return d(ctx, in)
}
var _ DeserializeHandler = DeserializeHandlerFunc(nil)

View File

@ -0,0 +1,211 @@
package middleware
import "context"
// FinalizeInput provides the input parameters for the FinalizeMiddleware to
// consume. FinalizeMiddleware may modify the Request value before forwarding
// the FinalizeInput along to the next next FinalizeHandler.
type FinalizeInput struct {
Request interface{}
}
// FinalizeOutput provides the result returned by the next FinalizeHandler.
type FinalizeOutput struct {
Result interface{}
}
// FinalizeHandler provides the interface for the next handler the
// FinalizeMiddleware will call in the middleware chain.
type FinalizeHandler interface {
HandleFinalize(ctx context.Context, in FinalizeInput) (
out FinalizeOutput, metadata Metadata, err error,
)
}
// FinalizeMiddleware provides the interface for middleware specific to the
// serialize step. Delegates to the next FinalizeHandler for further
// processing.
type FinalizeMiddleware interface {
// ID returns a unique ID for the middleware in the FinalizeStep. The step does not
// allow duplicate IDs.
ID() string
// HandleFinalize invokes the middleware behavior which must delegate to the next handler
// for the middleware chain to continue. The method must return a result or
// error to its caller.
HandleFinalize(ctx context.Context, in FinalizeInput, next FinalizeHandler) (
out FinalizeOutput, metadata Metadata, err error,
)
}
// FinalizeMiddlewareFunc returns a FinalizeMiddleware with the unique ID
// provided, and the func to be invoked.
func FinalizeMiddlewareFunc(id string, fn func(context.Context, FinalizeInput, FinalizeHandler) (FinalizeOutput, Metadata, error)) FinalizeMiddleware {
return finalizeMiddlewareFunc{
id: id,
fn: fn,
}
}
type finalizeMiddlewareFunc struct {
// Unique ID for the middleware.
id string
// Middleware function to be called.
fn func(context.Context, FinalizeInput, FinalizeHandler) (
FinalizeOutput, Metadata, error,
)
}
// ID returns the unique ID for the middleware.
func (s finalizeMiddlewareFunc) ID() string { return s.id }
// HandleFinalize invokes the middleware Fn.
func (s finalizeMiddlewareFunc) HandleFinalize(ctx context.Context, in FinalizeInput, next FinalizeHandler) (
out FinalizeOutput, metadata Metadata, err error,
) {
return s.fn(ctx, in, next)
}
var _ FinalizeMiddleware = (finalizeMiddlewareFunc{})
// FinalizeStep provides the ordered grouping of FinalizeMiddleware to be
// invoked on a handler.
type FinalizeStep struct {
ids *orderedIDs
}
// NewFinalizeStep returns a FinalizeStep ready to have middleware for
// initialization added to it.
func NewFinalizeStep() *FinalizeStep {
return &FinalizeStep{
ids: newOrderedIDs(),
}
}
var _ Middleware = (*FinalizeStep)(nil)
// ID returns the unique id of the step as a middleware.
func (s *FinalizeStep) ID() string {
return "Finalize stack step"
}
// HandleMiddleware invokes the middleware by decorating the next handler
// provided. Returns the result of the middleware and handler being invoked.
//
// Implements Middleware interface.
func (s *FinalizeStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
out interface{}, metadata Metadata, err error,
) {
order := s.ids.GetOrder()
var h FinalizeHandler = finalizeWrapHandler{Next: next}
for i := len(order) - 1; i >= 0; i-- {
h = decoratedFinalizeHandler{
Next: h,
With: order[i].(FinalizeMiddleware),
}
}
sIn := FinalizeInput{
Request: in,
}
res, metadata, err := h.HandleFinalize(ctx, sIn)
return res.Result, metadata, err
}
// Get retrieves the middleware identified by id. If the middleware is not present, returns false.
func (s *FinalizeStep) Get(id string) (FinalizeMiddleware, bool) {
get, ok := s.ids.Get(id)
if !ok {
return nil, false
}
return get.(FinalizeMiddleware), ok
}
// Add injects the middleware to the relative position of the middleware group.
// Returns an error if the middleware already exists.
func (s *FinalizeStep) Add(m FinalizeMiddleware, pos RelativePosition) error {
return s.ids.Add(m, pos)
}
// Insert injects the middleware relative to an existing middleware ID.
// Returns error if the original middleware does not exist, or the middleware
// being added already exists.
func (s *FinalizeStep) Insert(m FinalizeMiddleware, relativeTo string, pos RelativePosition) error {
return s.ids.Insert(m, relativeTo, pos)
}
// Swap removes the middleware by id, replacing it with the new middleware.
// Returns the middleware removed, or error if the middleware to be removed
// doesn't exist.
func (s *FinalizeStep) Swap(id string, m FinalizeMiddleware) (FinalizeMiddleware, error) {
removed, err := s.ids.Swap(id, m)
if err != nil {
return nil, err
}
return removed.(FinalizeMiddleware), nil
}
// Remove removes the middleware by id. Returns error if the middleware
// doesn't exist.
func (s *FinalizeStep) Remove(id string) (FinalizeMiddleware, error) {
removed, err := s.ids.Remove(id)
if err != nil {
return nil, err
}
return removed.(FinalizeMiddleware), nil
}
// List returns a list of the middleware in the step.
func (s *FinalizeStep) List() []string {
return s.ids.List()
}
// Clear removes all middleware in the step.
func (s *FinalizeStep) Clear() {
s.ids.Clear()
}
type finalizeWrapHandler struct {
Next Handler
}
var _ FinalizeHandler = (*finalizeWrapHandler)(nil)
// HandleFinalize implements FinalizeHandler, converts types and delegates to underlying
// generic handler.
func (w finalizeWrapHandler) HandleFinalize(ctx context.Context, in FinalizeInput) (
out FinalizeOutput, metadata Metadata, err error,
) {
res, metadata, err := w.Next.Handle(ctx, in.Request)
return FinalizeOutput{
Result: res,
}, metadata, err
}
type decoratedFinalizeHandler struct {
Next FinalizeHandler
With FinalizeMiddleware
}
var _ FinalizeHandler = (*decoratedFinalizeHandler)(nil)
func (h decoratedFinalizeHandler) HandleFinalize(ctx context.Context, in FinalizeInput) (
out FinalizeOutput, metadata Metadata, err error,
) {
return h.With.HandleFinalize(ctx, in, h.Next)
}
// FinalizeHandlerFunc provides a wrapper around a function to be used as a finalize middleware handler.
type FinalizeHandlerFunc func(context.Context, FinalizeInput) (FinalizeOutput, Metadata, error)
// HandleFinalize invokes the wrapped function with the given arguments.
func (f FinalizeHandlerFunc) HandleFinalize(ctx context.Context, in FinalizeInput) (FinalizeOutput, Metadata, error) {
return f(ctx, in)
}
var _ FinalizeHandler = FinalizeHandlerFunc(nil)

View File

@ -0,0 +1,211 @@
package middleware
import "context"
// InitializeInput wraps the input parameters for the InitializeMiddlewares to
// consume. InitializeMiddleware may modify the parameter value before
// forwarding it along to the next InitializeHandler.
type InitializeInput struct {
Parameters interface{}
}
// InitializeOutput provides the result returned by the next InitializeHandler.
type InitializeOutput struct {
Result interface{}
}
// InitializeHandler provides the interface for the next handler the
// InitializeMiddleware will call in the middleware chain.
type InitializeHandler interface {
HandleInitialize(ctx context.Context, in InitializeInput) (
out InitializeOutput, metadata Metadata, err error,
)
}
// InitializeMiddleware provides the interface for middleware specific to the
// initialize step. Delegates to the next InitializeHandler for further
// processing.
type InitializeMiddleware interface {
// ID returns a unique ID for the middleware in the InitializeStep. The step does not
// allow duplicate IDs.
ID() string
// HandleInitialize invokes the middleware behavior which must delegate to the next handler
// for the middleware chain to continue. The method must return a result or
// error to its caller.
HandleInitialize(ctx context.Context, in InitializeInput, next InitializeHandler) (
out InitializeOutput, metadata Metadata, err error,
)
}
// InitializeMiddlewareFunc returns a InitializeMiddleware with the unique ID provided,
// and the func to be invoked.
func InitializeMiddlewareFunc(id string, fn func(context.Context, InitializeInput, InitializeHandler) (InitializeOutput, Metadata, error)) InitializeMiddleware {
return initializeMiddlewareFunc{
id: id,
fn: fn,
}
}
type initializeMiddlewareFunc struct {
// Unique ID for the middleware.
id string
// Middleware function to be called.
fn func(context.Context, InitializeInput, InitializeHandler) (
InitializeOutput, Metadata, error,
)
}
// ID returns the unique ID for the middleware.
func (s initializeMiddlewareFunc) ID() string { return s.id }
// HandleInitialize invokes the middleware Fn.
func (s initializeMiddlewareFunc) HandleInitialize(ctx context.Context, in InitializeInput, next InitializeHandler) (
out InitializeOutput, metadata Metadata, err error,
) {
return s.fn(ctx, in, next)
}
var _ InitializeMiddleware = (initializeMiddlewareFunc{})
// InitializeStep provides the ordered grouping of InitializeMiddleware to be
// invoked on a handler.
type InitializeStep struct {
ids *orderedIDs
}
// NewInitializeStep returns an InitializeStep ready to have middleware for
// initialization added to it.
func NewInitializeStep() *InitializeStep {
return &InitializeStep{
ids: newOrderedIDs(),
}
}
var _ Middleware = (*InitializeStep)(nil)
// ID returns the unique ID of the step as a middleware.
func (s *InitializeStep) ID() string {
return "Initialize stack step"
}
// HandleMiddleware invokes the middleware by decorating the next handler
// provided. Returns the result of the middleware and handler being invoked.
//
// Implements Middleware interface.
func (s *InitializeStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
out interface{}, metadata Metadata, err error,
) {
order := s.ids.GetOrder()
var h InitializeHandler = initializeWrapHandler{Next: next}
for i := len(order) - 1; i >= 0; i-- {
h = decoratedInitializeHandler{
Next: h,
With: order[i].(InitializeMiddleware),
}
}
sIn := InitializeInput{
Parameters: in,
}
res, metadata, err := h.HandleInitialize(ctx, sIn)
return res.Result, metadata, err
}
// Get retrieves the middleware identified by id. If the middleware is not present, returns false.
func (s *InitializeStep) Get(id string) (InitializeMiddleware, bool) {
get, ok := s.ids.Get(id)
if !ok {
return nil, false
}
return get.(InitializeMiddleware), ok
}
// Add injects the middleware to the relative position of the middleware group.
// Returns an error if the middleware already exists.
func (s *InitializeStep) Add(m InitializeMiddleware, pos RelativePosition) error {
return s.ids.Add(m, pos)
}
// Insert injects the middleware relative to an existing middleware ID.
// Returns error if the original middleware does not exist, or the middleware
// being added already exists.
func (s *InitializeStep) Insert(m InitializeMiddleware, relativeTo string, pos RelativePosition) error {
return s.ids.Insert(m, relativeTo, pos)
}
// Swap removes the middleware by id, replacing it with the new middleware.
// Returns the middleware removed, or error if the middleware to be removed
// doesn't exist.
func (s *InitializeStep) Swap(id string, m InitializeMiddleware) (InitializeMiddleware, error) {
removed, err := s.ids.Swap(id, m)
if err != nil {
return nil, err
}
return removed.(InitializeMiddleware), nil
}
// Remove removes the middleware by id. Returns error if the middleware
// doesn't exist.
func (s *InitializeStep) Remove(id string) (InitializeMiddleware, error) {
removed, err := s.ids.Remove(id)
if err != nil {
return nil, err
}
return removed.(InitializeMiddleware), nil
}
// List returns a list of the middleware in the step.
func (s *InitializeStep) List() []string {
return s.ids.List()
}
// Clear removes all middleware in the step.
func (s *InitializeStep) Clear() {
s.ids.Clear()
}
type initializeWrapHandler struct {
Next Handler
}
var _ InitializeHandler = (*initializeWrapHandler)(nil)
// HandleInitialize implements InitializeHandler, converts types and delegates to underlying
// generic handler.
func (w initializeWrapHandler) HandleInitialize(ctx context.Context, in InitializeInput) (
out InitializeOutput, metadata Metadata, err error,
) {
res, metadata, err := w.Next.Handle(ctx, in.Parameters)
return InitializeOutput{
Result: res,
}, metadata, err
}
type decoratedInitializeHandler struct {
Next InitializeHandler
With InitializeMiddleware
}
var _ InitializeHandler = (*decoratedInitializeHandler)(nil)
func (h decoratedInitializeHandler) HandleInitialize(ctx context.Context, in InitializeInput) (
out InitializeOutput, metadata Metadata, err error,
) {
return h.With.HandleInitialize(ctx, in, h.Next)
}
// InitializeHandlerFunc provides a wrapper around a function to be used as an initialize middleware handler.
type InitializeHandlerFunc func(context.Context, InitializeInput) (InitializeOutput, Metadata, error)
// HandleInitialize calls the wrapped function with the provided arguments.
func (i InitializeHandlerFunc) HandleInitialize(ctx context.Context, in InitializeInput) (InitializeOutput, Metadata, error) {
return i(ctx, in)
}
var _ InitializeHandler = InitializeHandlerFunc(nil)

View File

@ -0,0 +1,219 @@
package middleware
import "context"
// SerializeInput provides the input parameters for the SerializeMiddleware to
// consume. SerializeMiddleware may modify the Request value before forwarding
// SerializeInput along to the next SerializeHandler. The Parameters member
// should not be modified by SerializeMiddleware, InitializeMiddleware should
// be responsible for modifying the provided Parameter value.
type SerializeInput struct {
Parameters interface{}
Request interface{}
}
// SerializeOutput provides the result returned by the next SerializeHandler.
type SerializeOutput struct {
Result interface{}
}
// SerializeHandler provides the interface for the next handler the
// SerializeMiddleware will call in the middleware chain.
type SerializeHandler interface {
HandleSerialize(ctx context.Context, in SerializeInput) (
out SerializeOutput, metadata Metadata, err error,
)
}
// SerializeMiddleware provides the interface for middleware specific to the
// serialize step. Delegates to the next SerializeHandler for further
// processing.
type SerializeMiddleware interface {
// ID returns a unique ID for the middleware in the SerializeStep. The step does not
// allow duplicate IDs.
ID() string
// HandleSerialize invokes the middleware behavior which must delegate to the next handler
// for the middleware chain to continue. The method must return a result or
// error to its caller.
HandleSerialize(ctx context.Context, in SerializeInput, next SerializeHandler) (
out SerializeOutput, metadata Metadata, err error,
)
}
// SerializeMiddlewareFunc returns a SerializeMiddleware with the unique ID
// provided, and the func to be invoked.
func SerializeMiddlewareFunc(id string, fn func(context.Context, SerializeInput, SerializeHandler) (SerializeOutput, Metadata, error)) SerializeMiddleware {
return serializeMiddlewareFunc{
id: id,
fn: fn,
}
}
type serializeMiddlewareFunc struct {
// Unique ID for the middleware.
id string
// Middleware function to be called.
fn func(context.Context, SerializeInput, SerializeHandler) (
SerializeOutput, Metadata, error,
)
}
// ID returns the unique ID for the middleware.
func (s serializeMiddlewareFunc) ID() string { return s.id }
// HandleSerialize invokes the middleware Fn.
func (s serializeMiddlewareFunc) HandleSerialize(ctx context.Context, in SerializeInput, next SerializeHandler) (
out SerializeOutput, metadata Metadata, err error,
) {
return s.fn(ctx, in, next)
}
var _ SerializeMiddleware = (serializeMiddlewareFunc{})
// SerializeStep provides the ordered grouping of SerializeMiddleware to be
// invoked on a handler.
type SerializeStep struct {
newRequest func() interface{}
ids *orderedIDs
}
// NewSerializeStep returns a SerializeStep ready to have middleware for
// initialization added to it. The newRequest func parameter is used to
// initialize the transport specific request for the stack SerializeStep to
// serialize the input parameters into.
func NewSerializeStep(newRequest func() interface{}) *SerializeStep {
return &SerializeStep{
ids: newOrderedIDs(),
newRequest: newRequest,
}
}
var _ Middleware = (*SerializeStep)(nil)
// ID returns the unique ID of the step as a middleware.
func (s *SerializeStep) ID() string {
return "Serialize stack step"
}
// HandleMiddleware invokes the middleware by decorating the next handler
// provided. Returns the result of the middleware and handler being invoked.
//
// Implements Middleware interface.
func (s *SerializeStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
out interface{}, metadata Metadata, err error,
) {
order := s.ids.GetOrder()
var h SerializeHandler = serializeWrapHandler{Next: next}
for i := len(order) - 1; i >= 0; i-- {
h = decoratedSerializeHandler{
Next: h,
With: order[i].(SerializeMiddleware),
}
}
sIn := SerializeInput{
Parameters: in,
Request: s.newRequest(),
}
res, metadata, err := h.HandleSerialize(ctx, sIn)
return res.Result, metadata, err
}
// Get retrieves the middleware identified by id. If the middleware is not present, returns false.
func (s *SerializeStep) Get(id string) (SerializeMiddleware, bool) {
get, ok := s.ids.Get(id)
if !ok {
return nil, false
}
return get.(SerializeMiddleware), ok
}
// Add injects the middleware to the relative position of the middleware group.
// Returns an error if the middleware already exists.
func (s *SerializeStep) Add(m SerializeMiddleware, pos RelativePosition) error {
return s.ids.Add(m, pos)
}
// Insert injects the middleware relative to an existing middleware ID.
// Returns error if the original middleware does not exist, or the middleware
// being added already exists.
func (s *SerializeStep) Insert(m SerializeMiddleware, relativeTo string, pos RelativePosition) error {
return s.ids.Insert(m, relativeTo, pos)
}
// Swap removes the middleware by id, replacing it with the new middleware.
// Returns the middleware removed, or error if the middleware to be removed
// doesn't exist.
func (s *SerializeStep) Swap(id string, m SerializeMiddleware) (SerializeMiddleware, error) {
removed, err := s.ids.Swap(id, m)
if err != nil {
return nil, err
}
return removed.(SerializeMiddleware), nil
}
// Remove removes the middleware by id. Returns error if the middleware
// doesn't exist.
func (s *SerializeStep) Remove(id string) (SerializeMiddleware, error) {
removed, err := s.ids.Remove(id)
if err != nil {
return nil, err
}
return removed.(SerializeMiddleware), nil
}
// List returns a list of the middleware in the step.
func (s *SerializeStep) List() []string {
return s.ids.List()
}
// Clear removes all middleware in the step.
func (s *SerializeStep) Clear() {
s.ids.Clear()
}
type serializeWrapHandler struct {
Next Handler
}
var _ SerializeHandler = (*serializeWrapHandler)(nil)
// Implements SerializeHandler, converts types and delegates to underlying
// generic handler.
func (w serializeWrapHandler) HandleSerialize(ctx context.Context, in SerializeInput) (
out SerializeOutput, metadata Metadata, err error,
) {
res, metadata, err := w.Next.Handle(ctx, in.Request)
return SerializeOutput{
Result: res,
}, metadata, err
}
type decoratedSerializeHandler struct {
Next SerializeHandler
With SerializeMiddleware
}
var _ SerializeHandler = (*decoratedSerializeHandler)(nil)
func (h decoratedSerializeHandler) HandleSerialize(ctx context.Context, in SerializeInput) (
out SerializeOutput, metadata Metadata, err error,
) {
return h.With.HandleSerialize(ctx, in, h.Next)
}
// SerializeHandlerFunc provides a wrapper around a function to be used as a serialize middleware handler.
type SerializeHandlerFunc func(context.Context, SerializeInput) (SerializeOutput, Metadata, error)
// HandleSerialize calls the wrapped function with the provided arguments.
func (s SerializeHandlerFunc) HandleSerialize(ctx context.Context, in SerializeInput) (SerializeOutput, Metadata, error) {
return s(ctx, in)
}
var _ SerializeHandler = SerializeHandlerFunc(nil)

5
vendor/github.com/aws/smithy-go/ptr/doc.go generated vendored Normal file
View File

@ -0,0 +1,5 @@
// Package ptr provides utilities for converting scalar literal type values to and from pointers inline.
package ptr
//go:generate go run -tags codegen generate.go
//go:generate gofmt -w -s .

601
vendor/github.com/aws/smithy-go/ptr/from_ptr.go generated vendored Normal file
View File

@ -0,0 +1,601 @@
// Code generated by smithy-go/ptr/generate.go DO NOT EDIT.
package ptr
import (
"time"
)
// ToBool returns bool value dereferenced if the passed
// in pointer was not nil. Returns a bool zero value if the
// pointer was nil.
func ToBool(p *bool) (v bool) {
if p == nil {
return v
}
return *p
}
// ToBoolSlice returns a slice of bool values, that are
// dereferenced if the passed in pointer was not nil. Returns a bool
// zero value if the pointer was nil.
func ToBoolSlice(vs []*bool) []bool {
ps := make([]bool, len(vs))
for i, v := range vs {
ps[i] = ToBool(v)
}
return ps
}
// ToBoolMap returns a map of bool values, that are
// dereferenced if the passed in pointer was not nil. The bool
// zero value is used if the pointer was nil.
func ToBoolMap(vs map[string]*bool) map[string]bool {
ps := make(map[string]bool, len(vs))
for k, v := range vs {
ps[k] = ToBool(v)
}
return ps
}
// ToByte returns byte value dereferenced if the passed
// in pointer was not nil. Returns a byte zero value if the
// pointer was nil.
func ToByte(p *byte) (v byte) {
if p == nil {
return v
}
return *p
}
// ToByteSlice returns a slice of byte values, that are
// dereferenced if the passed in pointer was not nil. Returns a byte
// zero value if the pointer was nil.
func ToByteSlice(vs []*byte) []byte {
ps := make([]byte, len(vs))
for i, v := range vs {
ps[i] = ToByte(v)
}
return ps
}
// ToByteMap returns a map of byte values, that are
// dereferenced if the passed in pointer was not nil. The byte
// zero value is used if the pointer was nil.
func ToByteMap(vs map[string]*byte) map[string]byte {
ps := make(map[string]byte, len(vs))
for k, v := range vs {
ps[k] = ToByte(v)
}
return ps
}
// ToString returns string value dereferenced if the passed
// in pointer was not nil. Returns a string zero value if the
// pointer was nil.
func ToString(p *string) (v string) {
if p == nil {
return v
}
return *p
}
// ToStringSlice returns a slice of string values, that are
// dereferenced if the passed in pointer was not nil. Returns a string
// zero value if the pointer was nil.
func ToStringSlice(vs []*string) []string {
ps := make([]string, len(vs))
for i, v := range vs {
ps[i] = ToString(v)
}
return ps
}
// ToStringMap returns a map of string values, that are
// dereferenced if the passed in pointer was not nil. The string
// zero value is used if the pointer was nil.
func ToStringMap(vs map[string]*string) map[string]string {
ps := make(map[string]string, len(vs))
for k, v := range vs {
ps[k] = ToString(v)
}
return ps
}
// ToInt returns int value dereferenced if the passed
// in pointer was not nil. Returns a int zero value if the
// pointer was nil.
func ToInt(p *int) (v int) {
if p == nil {
return v
}
return *p
}
// ToIntSlice returns a slice of int values, that are
// dereferenced if the passed in pointer was not nil. Returns a int
// zero value if the pointer was nil.
func ToIntSlice(vs []*int) []int {
ps := make([]int, len(vs))
for i, v := range vs {
ps[i] = ToInt(v)
}
return ps
}
// ToIntMap returns a map of int values, that are
// dereferenced if the passed in pointer was not nil. The int
// zero value is used if the pointer was nil.
func ToIntMap(vs map[string]*int) map[string]int {
ps := make(map[string]int, len(vs))
for k, v := range vs {
ps[k] = ToInt(v)
}
return ps
}
// ToInt8 returns int8 value dereferenced if the passed
// in pointer was not nil. Returns a int8 zero value if the
// pointer was nil.
func ToInt8(p *int8) (v int8) {
if p == nil {
return v
}
return *p
}
// ToInt8Slice returns a slice of int8 values, that are
// dereferenced if the passed in pointer was not nil. Returns a int8
// zero value if the pointer was nil.
func ToInt8Slice(vs []*int8) []int8 {
ps := make([]int8, len(vs))
for i, v := range vs {
ps[i] = ToInt8(v)
}
return ps
}
// ToInt8Map returns a map of int8 values, that are
// dereferenced if the passed in pointer was not nil. The int8
// zero value is used if the pointer was nil.
func ToInt8Map(vs map[string]*int8) map[string]int8 {
ps := make(map[string]int8, len(vs))
for k, v := range vs {
ps[k] = ToInt8(v)
}
return ps
}
// ToInt16 returns int16 value dereferenced if the passed
// in pointer was not nil. Returns a int16 zero value if the
// pointer was nil.
func ToInt16(p *int16) (v int16) {
if p == nil {
return v
}
return *p
}
// ToInt16Slice returns a slice of int16 values, that are
// dereferenced if the passed in pointer was not nil. Returns a int16
// zero value if the pointer was nil.
func ToInt16Slice(vs []*int16) []int16 {
ps := make([]int16, len(vs))
for i, v := range vs {
ps[i] = ToInt16(v)
}
return ps
}
// ToInt16Map returns a map of int16 values, that are
// dereferenced if the passed in pointer was not nil. The int16
// zero value is used if the pointer was nil.
func ToInt16Map(vs map[string]*int16) map[string]int16 {
ps := make(map[string]int16, len(vs))
for k, v := range vs {
ps[k] = ToInt16(v)
}
return ps
}
// ToInt32 returns int32 value dereferenced if the passed
// in pointer was not nil. Returns a int32 zero value if the
// pointer was nil.
func ToInt32(p *int32) (v int32) {
if p == nil {
return v
}
return *p
}
// ToInt32Slice returns a slice of int32 values, that are
// dereferenced if the passed in pointer was not nil. Returns a int32
// zero value if the pointer was nil.
func ToInt32Slice(vs []*int32) []int32 {
ps := make([]int32, len(vs))
for i, v := range vs {
ps[i] = ToInt32(v)
}
return ps
}
// ToInt32Map returns a map of int32 values, that are
// dereferenced if the passed in pointer was not nil. The int32
// zero value is used if the pointer was nil.
func ToInt32Map(vs map[string]*int32) map[string]int32 {
ps := make(map[string]int32, len(vs))
for k, v := range vs {
ps[k] = ToInt32(v)
}
return ps
}
// ToInt64 returns int64 value dereferenced if the passed
// in pointer was not nil. Returns a int64 zero value if the
// pointer was nil.
func ToInt64(p *int64) (v int64) {
if p == nil {
return v
}
return *p
}
// ToInt64Slice returns a slice of int64 values, that are
// dereferenced if the passed in pointer was not nil. Returns a int64
// zero value if the pointer was nil.
func ToInt64Slice(vs []*int64) []int64 {
ps := make([]int64, len(vs))
for i, v := range vs {
ps[i] = ToInt64(v)
}
return ps
}
// ToInt64Map returns a map of int64 values, that are
// dereferenced if the passed in pointer was not nil. The int64
// zero value is used if the pointer was nil.
func ToInt64Map(vs map[string]*int64) map[string]int64 {
ps := make(map[string]int64, len(vs))
for k, v := range vs {
ps[k] = ToInt64(v)
}
return ps
}
// ToUint returns uint value dereferenced if the passed
// in pointer was not nil. Returns a uint zero value if the
// pointer was nil.
func ToUint(p *uint) (v uint) {
if p == nil {
return v
}
return *p
}
// ToUintSlice returns a slice of uint values, that are
// dereferenced if the passed in pointer was not nil. Returns a uint
// zero value if the pointer was nil.
func ToUintSlice(vs []*uint) []uint {
ps := make([]uint, len(vs))
for i, v := range vs {
ps[i] = ToUint(v)
}
return ps
}
// ToUintMap returns a map of uint values, that are
// dereferenced if the passed in pointer was not nil. The uint
// zero value is used if the pointer was nil.
func ToUintMap(vs map[string]*uint) map[string]uint {
ps := make(map[string]uint, len(vs))
for k, v := range vs {
ps[k] = ToUint(v)
}
return ps
}
// ToUint8 returns uint8 value dereferenced if the passed
// in pointer was not nil. Returns a uint8 zero value if the
// pointer was nil.
func ToUint8(p *uint8) (v uint8) {
if p == nil {
return v
}
return *p
}
// ToUint8Slice returns a slice of uint8 values, that are
// dereferenced if the passed in pointer was not nil. Returns a uint8
// zero value if the pointer was nil.
func ToUint8Slice(vs []*uint8) []uint8 {
ps := make([]uint8, len(vs))
for i, v := range vs {
ps[i] = ToUint8(v)
}
return ps
}
// ToUint8Map returns a map of uint8 values, that are
// dereferenced if the passed in pointer was not nil. The uint8
// zero value is used if the pointer was nil.
func ToUint8Map(vs map[string]*uint8) map[string]uint8 {
ps := make(map[string]uint8, len(vs))
for k, v := range vs {
ps[k] = ToUint8(v)
}
return ps
}
// ToUint16 returns uint16 value dereferenced if the passed
// in pointer was not nil. Returns a uint16 zero value if the
// pointer was nil.
func ToUint16(p *uint16) (v uint16) {
if p == nil {
return v
}
return *p
}
// ToUint16Slice returns a slice of uint16 values, that are
// dereferenced if the passed in pointer was not nil. Returns a uint16
// zero value if the pointer was nil.
func ToUint16Slice(vs []*uint16) []uint16 {
ps := make([]uint16, len(vs))
for i, v := range vs {
ps[i] = ToUint16(v)
}
return ps
}
// ToUint16Map returns a map of uint16 values, that are
// dereferenced if the passed in pointer was not nil. The uint16
// zero value is used if the pointer was nil.
func ToUint16Map(vs map[string]*uint16) map[string]uint16 {
ps := make(map[string]uint16, len(vs))
for k, v := range vs {
ps[k] = ToUint16(v)
}
return ps
}
// ToUint32 returns uint32 value dereferenced if the passed
// in pointer was not nil. Returns a uint32 zero value if the
// pointer was nil.
func ToUint32(p *uint32) (v uint32) {
if p == nil {
return v
}
return *p
}
// ToUint32Slice returns a slice of uint32 values, that are
// dereferenced if the passed in pointer was not nil. Returns a uint32
// zero value if the pointer was nil.
func ToUint32Slice(vs []*uint32) []uint32 {
ps := make([]uint32, len(vs))
for i, v := range vs {
ps[i] = ToUint32(v)
}
return ps
}
// ToUint32Map returns a map of uint32 values, that are
// dereferenced if the passed in pointer was not nil. The uint32
// zero value is used if the pointer was nil.
func ToUint32Map(vs map[string]*uint32) map[string]uint32 {
ps := make(map[string]uint32, len(vs))
for k, v := range vs {
ps[k] = ToUint32(v)
}
return ps
}
// ToUint64 returns uint64 value dereferenced if the passed
// in pointer was not nil. Returns a uint64 zero value if the
// pointer was nil.
func ToUint64(p *uint64) (v uint64) {
if p == nil {
return v
}
return *p
}
// ToUint64Slice returns a slice of uint64 values, that are
// dereferenced if the passed in pointer was not nil. Returns a uint64
// zero value if the pointer was nil.
func ToUint64Slice(vs []*uint64) []uint64 {
ps := make([]uint64, len(vs))
for i, v := range vs {
ps[i] = ToUint64(v)
}
return ps
}
// ToUint64Map returns a map of uint64 values, that are
// dereferenced if the passed in pointer was not nil. The uint64
// zero value is used if the pointer was nil.
func ToUint64Map(vs map[string]*uint64) map[string]uint64 {
ps := make(map[string]uint64, len(vs))
for k, v := range vs {
ps[k] = ToUint64(v)
}
return ps
}
// ToFloat32 returns float32 value dereferenced if the passed
// in pointer was not nil. Returns a float32 zero value if the
// pointer was nil.
func ToFloat32(p *float32) (v float32) {
if p == nil {
return v
}
return *p
}
// ToFloat32Slice returns a slice of float32 values, that are
// dereferenced if the passed in pointer was not nil. Returns a float32
// zero value if the pointer was nil.
func ToFloat32Slice(vs []*float32) []float32 {
ps := make([]float32, len(vs))
for i, v := range vs {
ps[i] = ToFloat32(v)
}
return ps
}
// ToFloat32Map returns a map of float32 values, that are
// dereferenced if the passed in pointer was not nil. The float32
// zero value is used if the pointer was nil.
func ToFloat32Map(vs map[string]*float32) map[string]float32 {
ps := make(map[string]float32, len(vs))
for k, v := range vs {
ps[k] = ToFloat32(v)
}
return ps
}
// ToFloat64 returns float64 value dereferenced if the passed
// in pointer was not nil. Returns a float64 zero value if the
// pointer was nil.
func ToFloat64(p *float64) (v float64) {
if p == nil {
return v
}
return *p
}
// ToFloat64Slice returns a slice of float64 values, that are
// dereferenced if the passed in pointer was not nil. Returns a float64
// zero value if the pointer was nil.
func ToFloat64Slice(vs []*float64) []float64 {
ps := make([]float64, len(vs))
for i, v := range vs {
ps[i] = ToFloat64(v)
}
return ps
}
// ToFloat64Map returns a map of float64 values, that are
// dereferenced if the passed in pointer was not nil. The float64
// zero value is used if the pointer was nil.
func ToFloat64Map(vs map[string]*float64) map[string]float64 {
ps := make(map[string]float64, len(vs))
for k, v := range vs {
ps[k] = ToFloat64(v)
}
return ps
}
// ToTime returns time.Time value dereferenced if the passed
// in pointer was not nil. Returns a time.Time zero value if the
// pointer was nil.
func ToTime(p *time.Time) (v time.Time) {
if p == nil {
return v
}
return *p
}
// ToTimeSlice returns a slice of time.Time values, that are
// dereferenced if the passed in pointer was not nil. Returns a time.Time
// zero value if the pointer was nil.
func ToTimeSlice(vs []*time.Time) []time.Time {
ps := make([]time.Time, len(vs))
for i, v := range vs {
ps[i] = ToTime(v)
}
return ps
}
// ToTimeMap returns a map of time.Time values, that are
// dereferenced if the passed in pointer was not nil. The time.Time
// zero value is used if the pointer was nil.
func ToTimeMap(vs map[string]*time.Time) map[string]time.Time {
ps := make(map[string]time.Time, len(vs))
for k, v := range vs {
ps[k] = ToTime(v)
}
return ps
}
// ToDuration returns time.Duration value dereferenced if the passed
// in pointer was not nil. Returns a time.Duration zero value if the
// pointer was nil.
func ToDuration(p *time.Duration) (v time.Duration) {
if p == nil {
return v
}
return *p
}
// ToDurationSlice returns a slice of time.Duration values, that are
// dereferenced if the passed in pointer was not nil. Returns a time.Duration
// zero value if the pointer was nil.
func ToDurationSlice(vs []*time.Duration) []time.Duration {
ps := make([]time.Duration, len(vs))
for i, v := range vs {
ps[i] = ToDuration(v)
}
return ps
}
// ToDurationMap returns a map of time.Duration values, that are
// dereferenced if the passed in pointer was not nil. The time.Duration
// zero value is used if the pointer was nil.
func ToDurationMap(vs map[string]*time.Duration) map[string]time.Duration {
ps := make(map[string]time.Duration, len(vs))
for k, v := range vs {
ps[k] = ToDuration(v)
}
return ps
}

83
vendor/github.com/aws/smithy-go/ptr/gen_scalars.go generated vendored Normal file
View File

@ -0,0 +1,83 @@
//go:build codegen
// +build codegen
package ptr
import "strings"
func GetScalars() Scalars {
return Scalars{
{Type: "bool"},
{Type: "byte"},
{Type: "string"},
{Type: "int"},
{Type: "int8"},
{Type: "int16"},
{Type: "int32"},
{Type: "int64"},
{Type: "uint"},
{Type: "uint8"},
{Type: "uint16"},
{Type: "uint32"},
{Type: "uint64"},
{Type: "float32"},
{Type: "float64"},
{Type: "Time", Import: &Import{Path: "time"}},
{Type: "Duration", Import: &Import{Path: "time"}},
}
}
// Import provides the import path and optional alias
type Import struct {
Path string
Alias string
}
// Package returns the Go package name for the import. Returns alias if set.
func (i Import) Package() string {
if v := i.Alias; len(v) != 0 {
return v
}
if v := i.Path; len(v) != 0 {
parts := strings.Split(v, "/")
pkg := parts[len(parts)-1]
return pkg
}
return ""
}
// Scalar provides the definition of a type to generate pointer utilities for.
type Scalar struct {
Type string
Import *Import
}
// Name returns the exported function name for the type.
func (t Scalar) Name() string {
return strings.Title(t.Type)
}
// Symbol returns the scalar's Go symbol with path if needed.
func (t Scalar) Symbol() string {
if t.Import != nil {
return t.Import.Package() + "." + t.Type
}
return t.Type
}
// Scalars is a list of scalars.
type Scalars []Scalar
// Imports returns all imports for the scalars.
func (ts Scalars) Imports() []*Import {
imports := []*Import{}
for _, t := range ts {
if v := t.Import; v != nil {
imports = append(imports, v)
}
}
return imports
}

499
vendor/github.com/aws/smithy-go/ptr/to_ptr.go generated vendored Normal file
View File

@ -0,0 +1,499 @@
// Code generated by smithy-go/ptr/generate.go DO NOT EDIT.
package ptr
import (
"time"
)
// Bool returns a pointer value for the bool value passed in.
func Bool(v bool) *bool {
return &v
}
// BoolSlice returns a slice of bool pointers from the values
// passed in.
func BoolSlice(vs []bool) []*bool {
ps := make([]*bool, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// BoolMap returns a map of bool pointers from the values
// passed in.
func BoolMap(vs map[string]bool) map[string]*bool {
ps := make(map[string]*bool, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}
// Byte returns a pointer value for the byte value passed in.
func Byte(v byte) *byte {
return &v
}
// ByteSlice returns a slice of byte pointers from the values
// passed in.
func ByteSlice(vs []byte) []*byte {
ps := make([]*byte, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// ByteMap returns a map of byte pointers from the values
// passed in.
func ByteMap(vs map[string]byte) map[string]*byte {
ps := make(map[string]*byte, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}
// String returns a pointer value for the string value passed in.
func String(v string) *string {
return &v
}
// StringSlice returns a slice of string pointers from the values
// passed in.
func StringSlice(vs []string) []*string {
ps := make([]*string, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// StringMap returns a map of string pointers from the values
// passed in.
func StringMap(vs map[string]string) map[string]*string {
ps := make(map[string]*string, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}
// Int returns a pointer value for the int value passed in.
func Int(v int) *int {
return &v
}
// IntSlice returns a slice of int pointers from the values
// passed in.
func IntSlice(vs []int) []*int {
ps := make([]*int, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// IntMap returns a map of int pointers from the values
// passed in.
func IntMap(vs map[string]int) map[string]*int {
ps := make(map[string]*int, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}
// Int8 returns a pointer value for the int8 value passed in.
func Int8(v int8) *int8 {
return &v
}
// Int8Slice returns a slice of int8 pointers from the values
// passed in.
func Int8Slice(vs []int8) []*int8 {
ps := make([]*int8, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// Int8Map returns a map of int8 pointers from the values
// passed in.
func Int8Map(vs map[string]int8) map[string]*int8 {
ps := make(map[string]*int8, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}
// Int16 returns a pointer value for the int16 value passed in.
func Int16(v int16) *int16 {
return &v
}
// Int16Slice returns a slice of int16 pointers from the values
// passed in.
func Int16Slice(vs []int16) []*int16 {
ps := make([]*int16, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// Int16Map returns a map of int16 pointers from the values
// passed in.
func Int16Map(vs map[string]int16) map[string]*int16 {
ps := make(map[string]*int16, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}
// Int32 returns a pointer value for the int32 value passed in.
func Int32(v int32) *int32 {
return &v
}
// Int32Slice returns a slice of int32 pointers from the values
// passed in.
func Int32Slice(vs []int32) []*int32 {
ps := make([]*int32, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// Int32Map returns a map of int32 pointers from the values
// passed in.
func Int32Map(vs map[string]int32) map[string]*int32 {
ps := make(map[string]*int32, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}
// Int64 returns a pointer value for the int64 value passed in.
func Int64(v int64) *int64 {
return &v
}
// Int64Slice returns a slice of int64 pointers from the values
// passed in.
func Int64Slice(vs []int64) []*int64 {
ps := make([]*int64, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// Int64Map returns a map of int64 pointers from the values
// passed in.
func Int64Map(vs map[string]int64) map[string]*int64 {
ps := make(map[string]*int64, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}
// Uint returns a pointer value for the uint value passed in.
func Uint(v uint) *uint {
return &v
}
// UintSlice returns a slice of uint pointers from the values
// passed in.
func UintSlice(vs []uint) []*uint {
ps := make([]*uint, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// UintMap returns a map of uint pointers from the values
// passed in.
func UintMap(vs map[string]uint) map[string]*uint {
ps := make(map[string]*uint, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}
// Uint8 returns a pointer value for the uint8 value passed in.
func Uint8(v uint8) *uint8 {
return &v
}
// Uint8Slice returns a slice of uint8 pointers from the values
// passed in.
func Uint8Slice(vs []uint8) []*uint8 {
ps := make([]*uint8, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// Uint8Map returns a map of uint8 pointers from the values
// passed in.
func Uint8Map(vs map[string]uint8) map[string]*uint8 {
ps := make(map[string]*uint8, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}
// Uint16 returns a pointer value for the uint16 value passed in.
func Uint16(v uint16) *uint16 {
return &v
}
// Uint16Slice returns a slice of uint16 pointers from the values
// passed in.
func Uint16Slice(vs []uint16) []*uint16 {
ps := make([]*uint16, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// Uint16Map returns a map of uint16 pointers from the values
// passed in.
func Uint16Map(vs map[string]uint16) map[string]*uint16 {
ps := make(map[string]*uint16, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}
// Uint32 returns a pointer value for the uint32 value passed in.
func Uint32(v uint32) *uint32 {
return &v
}
// Uint32Slice returns a slice of uint32 pointers from the values
// passed in.
func Uint32Slice(vs []uint32) []*uint32 {
ps := make([]*uint32, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// Uint32Map returns a map of uint32 pointers from the values
// passed in.
func Uint32Map(vs map[string]uint32) map[string]*uint32 {
ps := make(map[string]*uint32, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}
// Uint64 returns a pointer value for the uint64 value passed in.
func Uint64(v uint64) *uint64 {
return &v
}
// Uint64Slice returns a slice of uint64 pointers from the values
// passed in.
func Uint64Slice(vs []uint64) []*uint64 {
ps := make([]*uint64, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// Uint64Map returns a map of uint64 pointers from the values
// passed in.
func Uint64Map(vs map[string]uint64) map[string]*uint64 {
ps := make(map[string]*uint64, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}
// Float32 returns a pointer value for the float32 value passed in.
func Float32(v float32) *float32 {
return &v
}
// Float32Slice returns a slice of float32 pointers from the values
// passed in.
func Float32Slice(vs []float32) []*float32 {
ps := make([]*float32, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// Float32Map returns a map of float32 pointers from the values
// passed in.
func Float32Map(vs map[string]float32) map[string]*float32 {
ps := make(map[string]*float32, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}
// Float64 returns a pointer value for the float64 value passed in.
func Float64(v float64) *float64 {
return &v
}
// Float64Slice returns a slice of float64 pointers from the values
// passed in.
func Float64Slice(vs []float64) []*float64 {
ps := make([]*float64, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// Float64Map returns a map of float64 pointers from the values
// passed in.
func Float64Map(vs map[string]float64) map[string]*float64 {
ps := make(map[string]*float64, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}
// Time returns a pointer value for the time.Time value passed in.
func Time(v time.Time) *time.Time {
return &v
}
// TimeSlice returns a slice of time.Time pointers from the values
// passed in.
func TimeSlice(vs []time.Time) []*time.Time {
ps := make([]*time.Time, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// TimeMap returns a map of time.Time pointers from the values
// passed in.
func TimeMap(vs map[string]time.Time) map[string]*time.Time {
ps := make(map[string]*time.Time, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}
// Duration returns a pointer value for the time.Duration value passed in.
func Duration(v time.Duration) *time.Duration {
return &v
}
// DurationSlice returns a slice of time.Duration pointers from the values
// passed in.
func DurationSlice(vs []time.Duration) []*time.Duration {
ps := make([]*time.Duration, len(vs))
for i, v := range vs {
vv := v
ps[i] = &vv
}
return ps
}
// DurationMap returns a map of time.Duration pointers from the values
// passed in.
func DurationMap(vs map[string]time.Duration) map[string]*time.Duration {
ps := make(map[string]*time.Duration, len(vs))
for k, v := range vs {
vv := v
ps[k] = &vv
}
return ps
}

3
vendor/github.com/aws/smithy-go/rand/doc.go generated vendored Normal file
View File

@ -0,0 +1,3 @@
// Package rand provides utilities for creating and working with random value
// generators.
package rand

31
vendor/github.com/aws/smithy-go/rand/rand.go generated vendored Normal file
View File

@ -0,0 +1,31 @@
package rand
import (
"crypto/rand"
"fmt"
"io"
"math/big"
)
func init() {
Reader = rand.Reader
}
// Reader provides a random reader that can reset during testing.
var Reader io.Reader
// Int63n returns a int64 between zero and value of max, read from an io.Reader source.
func Int63n(reader io.Reader, max int64) (int64, error) {
bi, err := rand.Int(reader, big.NewInt(max))
if err != nil {
return 0, fmt.Errorf("failed to read random value, %w", err)
}
return bi.Int64(), nil
}
// CryptoRandInt63n returns a random int64 between zero and value of max
// obtained from the crypto rand source.
func CryptoRandInt63n(max int64) (int64, error) {
return Int63n(Reader, max)
}

87
vendor/github.com/aws/smithy-go/rand/uuid.go generated vendored Normal file
View File

@ -0,0 +1,87 @@
package rand
import (
"encoding/hex"
"io"
)
const dash byte = '-'
// UUIDIdempotencyToken provides a utility to get idempotency tokens in the
// UUID format.
type UUIDIdempotencyToken struct {
uuid *UUID
}
// NewUUIDIdempotencyToken returns a idempotency token provider returning
// tokens in the UUID random format using the reader provided.
func NewUUIDIdempotencyToken(r io.Reader) *UUIDIdempotencyToken {
return &UUIDIdempotencyToken{uuid: NewUUID(r)}
}
// GetIdempotencyToken returns a random UUID value for Idempotency token.
func (u UUIDIdempotencyToken) GetIdempotencyToken() (string, error) {
return u.uuid.GetUUID()
}
// UUID provides computing random UUID version 4 values from a random source
// reader.
type UUID struct {
randSrc io.Reader
}
// NewUUID returns an initialized UUID value that can be used to retrieve
// random UUID version 4 values.
func NewUUID(r io.Reader) *UUID {
return &UUID{randSrc: r}
}
// GetUUID returns a random UUID version 4 string representation sourced from the random reader the
// UUID was created with. Returns an error if unable to compute the UUID.
func (r *UUID) GetUUID() (string, error) {
var b [16]byte
if _, err := io.ReadFull(r.randSrc, b[:]); err != nil {
return "", err
}
r.makeUUIDv4(b[:])
return format(b), nil
}
// GetBytes returns a byte slice containing a random UUID version 4 sourced from the random reader the
// UUID was created with. Returns an error if unable to compute the UUID.
func (r *UUID) GetBytes() (u []byte, err error) {
u = make([]byte, 16)
if _, err = io.ReadFull(r.randSrc, u); err != nil {
return u, err
}
r.makeUUIDv4(u)
return u, nil
}
func (r *UUID) makeUUIDv4(u []byte) {
// 13th character is "4"
u[6] = (u[6] & 0x0f) | 0x40 // Version 4
// 17th character is "8", "9", "a", or "b"
u[8] = (u[8] & 0x3f) | 0x80 // Variant most significant bits are 10x where x can be either 1 or 0
}
// Format returns the canonical text representation of a UUID.
// This implementation is optimized to not use fmt.
// Example: 82e42f16-b6cc-4d5b-95f5-d403c4befd3d
func format(u [16]byte) string {
// https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_.28random.29
var scratch [36]byte
hex.Encode(scratch[:8], u[0:4])
scratch[8] = dash
hex.Encode(scratch[9:13], u[4:6])
scratch[13] = dash
hex.Encode(scratch[14:18], u[6:8])
scratch[18] = dash
hex.Encode(scratch[19:23], u[8:10])
scratch[23] = dash
hex.Encode(scratch[24:], u[10:])
return string(scratch[:])
}

134
vendor/github.com/aws/smithy-go/time/time.go generated vendored Normal file
View File

@ -0,0 +1,134 @@
package time
import (
"context"
"fmt"
"math/big"
"strings"
"time"
)
const (
// dateTimeFormat is a IMF-fixdate formatted RFC3339 section 5.6
dateTimeFormatInput = "2006-01-02T15:04:05.999999999Z"
dateTimeFormatInputNoZ = "2006-01-02T15:04:05.999999999"
dateTimeFormatOutput = "2006-01-02T15:04:05.999Z"
// httpDateFormat is a date time defined by RFC 7231#section-7.1.1.1
// IMF-fixdate with no UTC offset.
httpDateFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
// Additional formats needed for compatibility.
httpDateFormatSingleDigitDay = "Mon, _2 Jan 2006 15:04:05 GMT"
httpDateFormatSingleDigitDayTwoDigitYear = "Mon, _2 Jan 06 15:04:05 GMT"
)
var millisecondFloat = big.NewFloat(1e3)
// FormatDateTime formats value as a date-time, (RFC3339 section 5.6)
//
// Example: 1985-04-12T23:20:50.52Z
func FormatDateTime(value time.Time) string {
return value.UTC().Format(dateTimeFormatOutput)
}
// ParseDateTime parses a string as a date-time, (RFC3339 section 5.6)
//
// Example: 1985-04-12T23:20:50.52Z
func ParseDateTime(value string) (time.Time, error) {
return tryParse(value,
dateTimeFormatInput,
dateTimeFormatInputNoZ,
time.RFC3339Nano,
time.RFC3339,
)
}
// FormatHTTPDate formats value as a http-date, (RFC 7231#section-7.1.1.1 IMF-fixdate)
//
// Example: Tue, 29 Apr 2014 18:30:38 GMT
func FormatHTTPDate(value time.Time) string {
return value.UTC().Format(httpDateFormat)
}
// ParseHTTPDate parses a string as a http-date, (RFC 7231#section-7.1.1.1 IMF-fixdate)
//
// Example: Tue, 29 Apr 2014 18:30:38 GMT
func ParseHTTPDate(value string) (time.Time, error) {
return tryParse(value,
httpDateFormat,
httpDateFormatSingleDigitDay,
httpDateFormatSingleDigitDayTwoDigitYear,
time.RFC850,
time.ANSIC,
)
}
// FormatEpochSeconds returns value as a Unix time in seconds with with decimal precision
//
// Example: 1515531081.123
func FormatEpochSeconds(value time.Time) float64 {
ms := value.UnixNano() / int64(time.Millisecond)
return float64(ms) / 1e3
}
// ParseEpochSeconds returns value as a Unix time in seconds with with decimal precision
//
// Example: 1515531081.123
func ParseEpochSeconds(value float64) time.Time {
f := big.NewFloat(value)
f = f.Mul(f, millisecondFloat)
i, _ := f.Int64()
// Offset to `UTC` because time.Unix returns the time value based on system
// local setting.
return time.Unix(0, i*1e6).UTC()
}
func tryParse(v string, formats ...string) (time.Time, error) {
var errs parseErrors
for _, f := range formats {
t, err := time.Parse(f, v)
if err != nil {
errs = append(errs, parseError{
Format: f,
Err: err,
})
continue
}
return t, nil
}
return time.Time{}, fmt.Errorf("unable to parse time string, %w", errs)
}
type parseErrors []parseError
func (es parseErrors) Error() string {
var s strings.Builder
for _, e := range es {
fmt.Fprintf(&s, "\n * %q: %v", e.Format, e.Err)
}
return "parse errors:" + s.String()
}
type parseError struct {
Format string
Err error
}
// SleepWithContext will wait for the timer duration to expire, or until the context
// is canceled. Whichever happens first. If the context is canceled the
// Context's error will be returned.
func SleepWithContext(ctx context.Context, dur time.Duration) error {
t := time.NewTimer(dur)
defer t.Stop()
select {
case <-t.C:
break
case <-ctx.Done():
return ctx.Err()
}
return nil
}

View File

@ -0,0 +1,65 @@
package http
import (
"context"
"fmt"
"github.com/aws/smithy-go/middleware"
)
const contentMD5Header = "Content-Md5"
// contentMD5Checksum provides a middleware to compute and set
// content-md5 checksum for a http request
type contentMD5Checksum struct {
}
// AddContentChecksumMiddleware adds checksum middleware to middleware's
// build step.
func AddContentChecksumMiddleware(stack *middleware.Stack) error {
// This middleware must be executed before request body is set.
return stack.Build.Add(&contentMD5Checksum{}, middleware.Before)
}
// ID returns the identifier for the checksum middleware
func (m *contentMD5Checksum) ID() string { return "ContentChecksum" }
// HandleBuild adds behavior to compute md5 checksum and add content-md5 header
// on http request
func (m *contentMD5Checksum) HandleBuild(
ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler,
) (
out middleware.BuildOutput, metadata middleware.Metadata, err error,
) {
req, ok := in.Request.(*Request)
if !ok {
return out, metadata, fmt.Errorf("unknown request type %T", req)
}
// if Content-MD5 header is already present, return
if v := req.Header.Get(contentMD5Header); len(v) != 0 {
return next.HandleBuild(ctx, in)
}
// fetch the request stream.
stream := req.GetStream()
// compute checksum if payload is explicit
if stream != nil {
v, err := computeMD5Checksum(stream)
if err != nil {
return out, metadata, fmt.Errorf("error computing md5 checksum, %w", err)
}
// reset the request stream
if err := req.RewindStream(); err != nil {
return out, metadata, fmt.Errorf(
"error rewinding request stream after computing md5 checksum, %w", err)
}
// set the 'Content-MD5' header
req.Header.Set(contentMD5Header, string(v))
}
// set md5 header value
return next.HandleBuild(ctx, in)
}

View File

@ -0,0 +1,120 @@
package http
import (
"context"
"fmt"
"net/http"
smithy "github.com/aws/smithy-go"
"github.com/aws/smithy-go/middleware"
)
// ClientDo provides the interface for custom HTTP client implementations.
type ClientDo interface {
Do(*http.Request) (*http.Response, error)
}
// ClientDoFunc provides a helper to wrap a function as an HTTP client for
// round tripping requests.
type ClientDoFunc func(*http.Request) (*http.Response, error)
// Do will invoke the underlying func, returning the result.
func (fn ClientDoFunc) Do(r *http.Request) (*http.Response, error) {
return fn(r)
}
// ClientHandler wraps a client that implements the HTTP Do method. Standard
// implementation is http.Client.
type ClientHandler struct {
client ClientDo
}
// NewClientHandler returns an initialized middleware handler for the client.
func NewClientHandler(client ClientDo) ClientHandler {
return ClientHandler{
client: client,
}
}
// Handle implements the middleware Handler interface, that will invoke the
// underlying HTTP client. Requires the input to be a Smithy *Request. Returns
// a smithy *Response, or error if the request failed.
func (c ClientHandler) Handle(ctx context.Context, input interface{}) (
out interface{}, metadata middleware.Metadata, err error,
) {
req, ok := input.(*Request)
if !ok {
return nil, metadata, fmt.Errorf("expect Smithy http.Request value as input, got unsupported type %T", input)
}
builtRequest := req.Build(ctx)
if err := ValidateEndpointHost(builtRequest.Host); err != nil {
return nil, metadata, err
}
resp, err := c.client.Do(builtRequest)
if resp == nil {
// Ensure a http response value is always present to prevent unexpected
// panics.
resp = &http.Response{
Header: http.Header{},
Body: http.NoBody,
}
}
if err != nil {
err = &RequestSendError{Err: err}
// Override the error with a context canceled error, if that was canceled.
select {
case <-ctx.Done():
err = &smithy.CanceledError{Err: ctx.Err()}
default:
}
}
// HTTP RoundTripper *should* close the request body. But this may not happen in a timely manner.
// So instead Smithy *Request Build wraps the body to be sent in a safe closer that will clear the
// stream reference so that it can be safely reused.
if builtRequest.Body != nil {
_ = builtRequest.Body.Close()
}
return &Response{Response: resp}, metadata, err
}
// RequestSendError provides a generic request transport error. This error
// should wrap errors making HTTP client requests.
//
// The ClientHandler will wrap the HTTP client's error if the client request
// fails, and did not fail because of context canceled.
type RequestSendError struct {
Err error
}
// ConnectionError returns that the error is related to not being able to send
// the request, or receive a response from the service.
func (e *RequestSendError) ConnectionError() bool {
return true
}
// Unwrap returns the underlying error, if there was one.
func (e *RequestSendError) Unwrap() error {
return e.Err
}
func (e *RequestSendError) Error() string {
return fmt.Sprintf("request send failed, %v", e.Err)
}
// NopClient provides a client that ignores the request, and returns an empty
// successful HTTP response value.
type NopClient struct{}
// Do ignores the request and returns a 200 status empty response.
func (NopClient) Do(r *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: 200,
Header: http.Header{},
Body: http.NoBody,
}, nil
}

View File

@ -0,0 +1,5 @@
/*
Package http provides the HTTP transport client and request/response types
needed to round trip API operation calls with an service.
*/
package http

View File

@ -0,0 +1,163 @@
package http
import (
"fmt"
"strconv"
"strings"
"unicode"
)
func splitHeaderListValues(vs []string, splitFn func(string) ([]string, error)) ([]string, error) {
values := make([]string, 0, len(vs))
for i := 0; i < len(vs); i++ {
parts, err := splitFn(vs[i])
if err != nil {
return nil, err
}
values = append(values, parts...)
}
return values, nil
}
// SplitHeaderListValues attempts to split the elements of the slice by commas,
// and return a list of all values separated. Returns error if unable to
// separate the values.
func SplitHeaderListValues(vs []string) ([]string, error) {
return splitHeaderListValues(vs, quotedCommaSplit)
}
func quotedCommaSplit(v string) (parts []string, err error) {
v = strings.TrimSpace(v)
expectMore := true
for i := 0; i < len(v); i++ {
if unicode.IsSpace(rune(v[i])) {
continue
}
expectMore = false
// leading space in part is ignored.
// Start of value must be non-space, or quote.
//
// - If quote, enter quoted mode, find next non-escaped quote to
// terminate the value.
// - Otherwise, find next comma to terminate value.
remaining := v[i:]
var value string
var valueLen int
if remaining[0] == '"' {
//------------------------------
// Quoted value
//------------------------------
var j int
var skipQuote bool
for j += 1; j < len(remaining); j++ {
if remaining[j] == '\\' || (remaining[j] != '\\' && skipQuote) {
skipQuote = !skipQuote
continue
}
if remaining[j] == '"' {
break
}
}
if j == len(remaining) || j == 1 {
return nil, fmt.Errorf("value %v missing closing double quote",
remaining)
}
valueLen = j + 1
tail := remaining[valueLen:]
var k int
for ; k < len(tail); k++ {
if !unicode.IsSpace(rune(tail[k])) && tail[k] != ',' {
return nil, fmt.Errorf("value %v has non-space trailing characters",
remaining)
}
if tail[k] == ',' {
expectMore = true
break
}
}
value = remaining[:valueLen]
value, err = strconv.Unquote(value)
if err != nil {
return nil, fmt.Errorf("failed to unquote value %v, %w", value, err)
}
// Pad valueLen to include trailing space(s) so `i` is updated correctly.
valueLen += k
} else {
//------------------------------
// Unquoted value
//------------------------------
// Index of the next comma is the length of the value, or end of string.
valueLen = strings.Index(remaining, ",")
if valueLen != -1 {
expectMore = true
} else {
valueLen = len(remaining)
}
value = strings.TrimSpace(remaining[:valueLen])
}
i += valueLen
parts = append(parts, value)
}
if expectMore {
parts = append(parts, "")
}
return parts, nil
}
// SplitHTTPDateTimestampHeaderListValues attempts to split the HTTP-Date
// timestamp values in the slice by commas, and return a list of all values
// separated. The split is aware of the HTTP-Date timestamp format, and will skip
// comma within the timestamp value. Returns an error if unable to split the
// timestamp values.
func SplitHTTPDateTimestampHeaderListValues(vs []string) ([]string, error) {
return splitHeaderListValues(vs, splitHTTPDateHeaderValue)
}
func splitHTTPDateHeaderValue(v string) ([]string, error) {
if n := strings.Count(v, ","); n <= 1 {
// Nothing to do if only contains a no, or single HTTPDate value
return []string{v}, nil
} else if n%2 == 0 {
return nil, fmt.Errorf("invalid timestamp HTTPDate header comma separations, %q", v)
}
var parts []string
var i, j int
var doSplit bool
for ; i < len(v); i++ {
if v[i] == ',' {
if doSplit {
doSplit = false
parts = append(parts, strings.TrimSpace(v[j:i]))
j = i + 1
} else {
// Skip the first comma in the timestamp value since that
// separates the day from the rest of the timestamp.
//
// Tue, 17 Dec 2019 23:48:18 GMT
doSplit = true
}
}
}
// Add final part
if j < len(v) {
parts = append(parts, strings.TrimSpace(v[j:]))
}
return parts, nil
}

89
vendor/github.com/aws/smithy-go/transport/http/host.go generated vendored Normal file
View File

@ -0,0 +1,89 @@
package http
import (
"fmt"
"net"
"strconv"
"strings"
)
// ValidateEndpointHost validates that the host string passed in is a valid RFC
// 3986 host. Returns error if the host is not valid.
func ValidateEndpointHost(host string) error {
var errors strings.Builder
var hostname string
var port string
var err error
if strings.Contains(host, ":") {
hostname, port, err = net.SplitHostPort(host)
if err != nil {
errors.WriteString(fmt.Sprintf("\n endpoint %v, failed to parse, got ", host))
errors.WriteString(err.Error())
}
if !ValidPortNumber(port) {
errors.WriteString(fmt.Sprintf("port number should be in range [0-65535], got %v", port))
}
} else {
hostname = host
}
labels := strings.Split(hostname, ".")
for i, label := range labels {
if i == len(labels)-1 && len(label) == 0 {
// Allow trailing dot for FQDN hosts.
continue
}
if !ValidHostLabel(label) {
errors.WriteString("\nendpoint host domain labels must match \"[a-zA-Z0-9-]{1,63}\", but found: ")
errors.WriteString(label)
}
}
if len(hostname) == 0 && len(port) != 0 {
errors.WriteString("\nendpoint host with port must not be empty")
}
if len(hostname) > 255 {
errors.WriteString(fmt.Sprintf("\nendpoint host must be less than 255 characters, but was %d", len(hostname)))
}
if len(errors.String()) > 0 {
return fmt.Errorf("invalid endpoint host%s", errors.String())
}
return nil
}
// ValidPortNumber returns whether the port is valid RFC 3986 port.
func ValidPortNumber(port string) bool {
i, err := strconv.Atoi(port)
if err != nil {
return false
}
if i < 0 || i > 65535 {
return false
}
return true
}
// ValidHostLabel returns whether the label is a valid RFC 3986 host abel.
func ValidHostLabel(label string) bool {
if l := len(label); l == 0 || l > 63 {
return false
}
for _, r := range label {
switch {
case r >= '0' && r <= '9':
case r >= 'A' && r <= 'Z':
case r >= 'a' && r <= 'z':
case r == '-':
default:
return false
}
}
return true
}

View File

@ -0,0 +1,75 @@
package io
import (
"io"
"sync"
)
// NewSafeReadCloser returns a new safeReadCloser that wraps readCloser.
func NewSafeReadCloser(readCloser io.ReadCloser) io.ReadCloser {
sr := &safeReadCloser{
readCloser: readCloser,
}
if _, ok := readCloser.(io.WriterTo); ok {
return &safeWriteToReadCloser{safeReadCloser: sr}
}
return sr
}
// safeWriteToReadCloser wraps a safeReadCloser but exposes a WriteTo interface implementation. This will panic
// if the underlying io.ReadClose does not support WriteTo. Use NewSafeReadCloser to ensure the proper handling of this
// type.
type safeWriteToReadCloser struct {
*safeReadCloser
}
// WriteTo implements the io.WriteTo interface.
func (r *safeWriteToReadCloser) WriteTo(w io.Writer) (int64, error) {
r.safeReadCloser.mtx.Lock()
defer r.safeReadCloser.mtx.Unlock()
if r.safeReadCloser.closed {
return 0, io.EOF
}
return r.safeReadCloser.readCloser.(io.WriterTo).WriteTo(w)
}
// safeReadCloser wraps a io.ReadCloser and presents an io.ReadCloser interface. When Close is called on safeReadCloser
// the underlying Close method will be executed, and then the reference to the reader will be dropped. This type
// is meant to be used with the net/http library which will retain a reference to the request body for the lifetime
// of a goroutine connection. Wrapping in this manner will ensure that no data race conditions are falsely reported.
// This type is thread-safe.
type safeReadCloser struct {
readCloser io.ReadCloser
closed bool
mtx sync.Mutex
}
// Read reads up to len(p) bytes into p from the underlying read. If the reader is closed io.EOF will be returned.
func (r *safeReadCloser) Read(p []byte) (n int, err error) {
r.mtx.Lock()
defer r.mtx.Unlock()
if r.closed {
return 0, io.EOF
}
return r.readCloser.Read(p)
}
// Close calls the underlying io.ReadCloser's Close method, removes the reference to the reader, and returns any error
// reported from Close. Subsequent calls to Close will always return a nil error.
func (r *safeReadCloser) Close() error {
r.mtx.Lock()
defer r.mtx.Unlock()
if r.closed {
return nil
}
r.closed = true
rc := r.readCloser
r.readCloser = nil
return rc.Close()
}

View File

@ -0,0 +1,25 @@
package http
import (
"crypto/md5"
"encoding/base64"
"fmt"
"io"
)
// computeMD5Checksum computes base64 md5 checksum of an io.Reader's contents.
// Returns the byte slice of md5 checksum and an error.
func computeMD5Checksum(r io.Reader) ([]byte, error) {
h := md5.New()
// copy errors may be assumed to be from the body.
_, err := io.Copy(h, r)
if err != nil {
return nil, fmt.Errorf("failed to read body: %w", err)
}
// encode the md5 checksum in base64.
sum := h.Sum(nil)
sum64 := make([]byte, base64.StdEncoding.EncodedLen(len(sum)))
base64.StdEncoding.Encode(sum64, sum)
return sum64, nil
}

View File

@ -0,0 +1,79 @@
package http
import (
"context"
"github.com/aws/smithy-go/logging"
"github.com/aws/smithy-go/middleware"
"io"
"io/ioutil"
)
// AddErrorCloseResponseBodyMiddleware adds the middleware to automatically
// close the response body of an operation request if the request response
// failed.
func AddErrorCloseResponseBodyMiddleware(stack *middleware.Stack) error {
return stack.Deserialize.Insert(&errorCloseResponseBodyMiddleware{}, "OperationDeserializer", middleware.Before)
}
type errorCloseResponseBodyMiddleware struct{}
func (*errorCloseResponseBodyMiddleware) ID() string {
return "ErrorCloseResponseBody"
}
func (m *errorCloseResponseBodyMiddleware) HandleDeserialize(
ctx context.Context, input middleware.DeserializeInput, next middleware.DeserializeHandler,
) (
output middleware.DeserializeOutput, metadata middleware.Metadata, err error,
) {
out, metadata, err := next.HandleDeserialize(ctx, input)
if err != nil {
if resp, ok := out.RawResponse.(*Response); ok && resp != nil && resp.Body != nil {
// Consume the full body to prevent TCP connection resets on some platforms
_, _ = io.Copy(ioutil.Discard, resp.Body)
// Do not validate that the response closes successfully.
resp.Body.Close()
}
}
return out, metadata, err
}
// AddCloseResponseBodyMiddleware adds the middleware to automatically close
// the response body of an operation request, after the response had been
// deserialized.
func AddCloseResponseBodyMiddleware(stack *middleware.Stack) error {
return stack.Deserialize.Insert(&closeResponseBody{}, "OperationDeserializer", middleware.Before)
}
type closeResponseBody struct{}
func (*closeResponseBody) ID() string {
return "CloseResponseBody"
}
func (m *closeResponseBody) HandleDeserialize(
ctx context.Context, input middleware.DeserializeInput, next middleware.DeserializeHandler,
) (
output middleware.DeserializeOutput, metadata middleware.Metadata, err error,
) {
out, metadata, err := next.HandleDeserialize(ctx, input)
if err != nil {
return out, metadata, err
}
if resp, ok := out.RawResponse.(*Response); ok {
// Consume the full body to prevent TCP connection resets on some platforms
_, copyErr := io.Copy(ioutil.Discard, resp.Body)
if copyErr != nil {
middleware.GetLogger(ctx).Logf(logging.Warn, "failed to discard remaining HTTP response body, this may affect connection reuse")
}
closeErr := resp.Body.Close()
if closeErr != nil {
middleware.GetLogger(ctx).Logf(logging.Warn, "failed to close HTTP response body, this may affect connection reuse")
}
}
return out, metadata, err
}

View File

@ -0,0 +1,90 @@
package http
import (
"context"
"fmt"
"github.com/aws/smithy-go/middleware"
)
// ComputeContentLength provides a middleware to set the content-length
// header for the length of a serialize request body.
type ComputeContentLength struct {
}
// AddComputeContentLengthMiddleware adds ComputeContentLength to the middleware
// stack's Build step.
func AddComputeContentLengthMiddleware(stack *middleware.Stack) error {
return stack.Build.Add(&ComputeContentLength{}, middleware.After)
}
// ID returns the identifier for the ComputeContentLength.
func (m *ComputeContentLength) ID() string { return "ComputeContentLength" }
// HandleBuild adds the length of the serialized request to the HTTP header
// if the length can be determined.
func (m *ComputeContentLength) HandleBuild(
ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler,
) (
out middleware.BuildOutput, metadata middleware.Metadata, err error,
) {
req, ok := in.Request.(*Request)
if !ok {
return out, metadata, fmt.Errorf("unknown request type %T", req)
}
// do nothing if request content-length was set to 0 or above.
if req.ContentLength >= 0 {
return next.HandleBuild(ctx, in)
}
// attempt to compute stream length
if n, ok, err := req.StreamLength(); err != nil {
return out, metadata, fmt.Errorf(
"failed getting length of request stream, %w", err)
} else if ok {
req.ContentLength = n
if n == 0 {
// If the content length could be determined, and the body is empty
// the stream must be cleared to prevent unexpected chunk encoding.
req, _ = req.SetStream(nil)
in.Request = req
}
}
return next.HandleBuild(ctx, in)
}
// validateContentLength provides a middleware to validate the content-length
// is valid (greater than zero), for the serialized request payload.
type validateContentLength struct{}
// ValidateContentLengthHeader adds middleware that validates request content-length
// is set to value greater than zero.
func ValidateContentLengthHeader(stack *middleware.Stack) error {
return stack.Build.Add(&validateContentLength{}, middleware.After)
}
// ID returns the identifier for the ComputeContentLength.
func (m *validateContentLength) ID() string { return "ValidateContentLength" }
// HandleBuild adds the length of the serialized request to the HTTP header
// if the length can be determined.
func (m *validateContentLength) HandleBuild(
ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler,
) (
out middleware.BuildOutput, metadata middleware.Metadata, err error,
) {
req, ok := in.Request.(*Request)
if !ok {
return out, metadata, fmt.Errorf("unknown request type %T", req)
}
// if request content-length was set to less than 0, return an error
if req.ContentLength < 0 {
return out, metadata, fmt.Errorf(
"content length for payload is required and must be at least 0")
}
return next.HandleBuild(ctx, in)
}

View File

@ -0,0 +1,88 @@
package http
import (
"context"
"fmt"
"github.com/aws/smithy-go/middleware"
)
type headerValue struct {
header string
value string
append bool
}
type headerValueHelper struct {
headerValues []headerValue
}
func (h *headerValueHelper) addHeaderValue(value headerValue) {
h.headerValues = append(h.headerValues, value)
}
func (h *headerValueHelper) ID() string {
return "HTTPHeaderHelper"
}
func (h *headerValueHelper) HandleBuild(ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler) (out middleware.BuildOutput, metadata middleware.Metadata, err error) {
req, ok := in.Request.(*Request)
if !ok {
return out, metadata, fmt.Errorf("unknown transport type %T", in.Request)
}
for _, value := range h.headerValues {
if value.append {
req.Header.Add(value.header, value.value)
} else {
req.Header.Set(value.header, value.value)
}
}
return next.HandleBuild(ctx, in)
}
func getOrAddHeaderValueHelper(stack *middleware.Stack) (*headerValueHelper, error) {
id := (*headerValueHelper)(nil).ID()
m, ok := stack.Build.Get(id)
if !ok {
m = &headerValueHelper{}
err := stack.Build.Add(m, middleware.After)
if err != nil {
return nil, err
}
}
requestUserAgent, ok := m.(*headerValueHelper)
if !ok {
return nil, fmt.Errorf("%T for %s middleware did not match expected type", m, id)
}
return requestUserAgent, nil
}
// AddHeaderValue returns a stack mutator that adds the header value pair to header.
// Appends to any existing values if present.
func AddHeaderValue(header string, value string) func(stack *middleware.Stack) error {
return func(stack *middleware.Stack) error {
helper, err := getOrAddHeaderValueHelper(stack)
if err != nil {
return err
}
helper.addHeaderValue(headerValue{header: header, value: value, append: true})
return nil
}
}
// SetHeaderValue returns a stack mutator that adds the header value pair to header.
// Replaces any existing values if present.
func SetHeaderValue(header string, value string) func(stack *middleware.Stack) error {
return func(stack *middleware.Stack) error {
helper, err := getOrAddHeaderValueHelper(stack)
if err != nil {
return err
}
helper.addHeaderValue(headerValue{header: header, value: value, append: false})
return nil
}
}

View File

@ -0,0 +1,75 @@
package http
import (
"context"
"fmt"
"net/http/httputil"
"github.com/aws/smithy-go/logging"
"github.com/aws/smithy-go/middleware"
)
// RequestResponseLogger is a deserialize middleware that will log the request and response HTTP messages and optionally
// their respective bodies. Will not perform any logging if none of the options are set.
type RequestResponseLogger struct {
LogRequest bool
LogRequestWithBody bool
LogResponse bool
LogResponseWithBody bool
}
// ID is the middleware identifier.
func (r *RequestResponseLogger) ID() string {
return "RequestResponseLogger"
}
// HandleDeserialize will log the request and response HTTP messages if configured accordingly.
func (r *RequestResponseLogger) HandleDeserialize(
ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler,
) (
out middleware.DeserializeOutput, metadata middleware.Metadata, err error,
) {
logger := middleware.GetLogger(ctx)
if r.LogRequest || r.LogRequestWithBody {
smithyRequest, ok := in.Request.(*Request)
if !ok {
return out, metadata, fmt.Errorf("unknown transport type %T", in)
}
rc := smithyRequest.Build(ctx)
reqBytes, err := httputil.DumpRequestOut(rc, r.LogRequestWithBody)
if err != nil {
return out, metadata, err
}
logger.Logf(logging.Debug, "Request\n%v", string(reqBytes))
if r.LogRequestWithBody {
smithyRequest, err = smithyRequest.SetStream(rc.Body)
if err != nil {
return out, metadata, err
}
in.Request = smithyRequest
}
}
out, metadata, err = next.HandleDeserialize(ctx, in)
if (err == nil) && (r.LogResponse || r.LogResponseWithBody) {
smithyResponse, ok := out.RawResponse.(*Response)
if !ok {
return out, metadata, fmt.Errorf("unknown transport type %T", out.RawResponse)
}
respBytes, err := httputil.DumpResponse(smithyResponse.Response, r.LogResponseWithBody)
if err != nil {
return out, metadata, fmt.Errorf("failed to dump response %w", err)
}
logger.Logf(logging.Debug, "Response\n%v", string(respBytes))
}
return out, metadata, err
}

View File

@ -0,0 +1,51 @@
package http
import (
"context"
"github.com/aws/smithy-go/middleware"
)
type (
hostnameImmutableKey struct{}
hostPrefixDisableKey struct{}
)
// GetHostnameImmutable retrieves whether the endpoint hostname should be considered
// immutable or not.
//
// Scoped to stack values. Use middleware#ClearStackValues to clear all stack
// values.
func GetHostnameImmutable(ctx context.Context) (v bool) {
v, _ = middleware.GetStackValue(ctx, hostnameImmutableKey{}).(bool)
return v
}
// SetHostnameImmutable sets or modifies whether the request's endpoint hostname
// should be considered immutable or not.
//
// Scoped to stack values. Use middleware#ClearStackValues to clear all stack
// values.
func SetHostnameImmutable(ctx context.Context, value bool) context.Context {
return middleware.WithStackValue(ctx, hostnameImmutableKey{}, value)
}
// IsEndpointHostPrefixDisabled retrieves whether the hostname prefixing is
// disabled.
//
// Scoped to stack values. Use middleware#ClearStackValues to clear all stack
// values.
func IsEndpointHostPrefixDisabled(ctx context.Context) (v bool) {
v, _ = middleware.GetStackValue(ctx, hostPrefixDisableKey{}).(bool)
return v
}
// DisableEndpointHostPrefix sets or modifies whether the request's endpoint host
// prefixing should be disabled. If value is true, endpoint host prefixing
// will be disabled.
//
// Scoped to stack values. Use middleware#ClearStackValues to clear all stack
// values.
func DisableEndpointHostPrefix(ctx context.Context, value bool) context.Context {
return middleware.WithStackValue(ctx, hostPrefixDisableKey{}, value)
}

View File

@ -0,0 +1,79 @@
package http
import (
"context"
"fmt"
"github.com/aws/smithy-go/middleware"
"strings"
)
// MinimumProtocolError is an error type indicating that the established connection did not meet the expected minimum
// HTTP protocol version.
type MinimumProtocolError struct {
proto string
expectedProtoMajor int
expectedProtoMinor int
}
// Error returns the error message.
func (m *MinimumProtocolError) Error() string {
return fmt.Sprintf("operation requires minimum HTTP protocol of HTTP/%d.%d, but was %s",
m.expectedProtoMajor, m.expectedProtoMinor, m.proto)
}
// RequireMinimumProtocol is a deserialization middleware that asserts that the established HTTP connection
// meets the minimum major ad minor version.
type RequireMinimumProtocol struct {
ProtoMajor int
ProtoMinor int
}
// AddRequireMinimumProtocol adds the RequireMinimumProtocol middleware to the stack using the provided minimum
// protocol major and minor version.
func AddRequireMinimumProtocol(stack *middleware.Stack, major, minor int) error {
return stack.Deserialize.Insert(&RequireMinimumProtocol{
ProtoMajor: major,
ProtoMinor: minor,
}, "OperationDeserializer", middleware.Before)
}
// ID returns the middleware identifier string.
func (r *RequireMinimumProtocol) ID() string {
return "RequireMinimumProtocol"
}
// HandleDeserialize asserts that the established connection is a HTTP connection with the minimum major and minor
// protocol version.
func (r *RequireMinimumProtocol) HandleDeserialize(
ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler,
) (
out middleware.DeserializeOutput, metadata middleware.Metadata, err error,
) {
out, metadata, err = next.HandleDeserialize(ctx, in)
if err != nil {
return out, metadata, err
}
response, ok := out.RawResponse.(*Response)
if !ok {
return out, metadata, fmt.Errorf("unknown transport type: %T", out.RawResponse)
}
if !strings.HasPrefix(response.Proto, "HTTP") {
return out, metadata, &MinimumProtocolError{
proto: response.Proto,
expectedProtoMajor: r.ProtoMajor,
expectedProtoMinor: r.ProtoMinor,
}
}
if response.ProtoMajor < r.ProtoMajor || response.ProtoMinor < r.ProtoMinor {
return out, metadata, &MinimumProtocolError{
proto: response.Proto,
expectedProtoMajor: r.ProtoMajor,
expectedProtoMinor: r.ProtoMinor,
}
}
return out, metadata, err
}

View File

@ -0,0 +1,154 @@
package http
import (
"context"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/url"
iointernal "github.com/aws/smithy-go/transport/http/internal/io"
)
// Request provides the HTTP specific request structure for HTTP specific
// middleware steps to use to serialize input, and send an operation's request.
type Request struct {
*http.Request
stream io.Reader
isStreamSeekable bool
streamStartPos int64
}
// NewStackRequest returns an initialized request ready to be populated with the
// HTTP request details. Returns empty interface so the function can be used as
// a parameter to the Smithy middleware Stack constructor.
func NewStackRequest() interface{} {
return &Request{
Request: &http.Request{
URL: &url.URL{},
Header: http.Header{},
ContentLength: -1, // default to unknown length
},
}
}
// Clone returns a deep copy of the Request for the new context. A reference to
// the Stream is copied, but the underlying stream is not copied.
func (r *Request) Clone() *Request {
rc := *r
rc.Request = rc.Request.Clone(context.TODO())
return &rc
}
// StreamLength returns the number of bytes of the serialized stream attached
// to the request and ok set. If the length cannot be determined, an error will
// be returned.
func (r *Request) StreamLength() (size int64, ok bool, err error) {
if r.stream == nil {
return 0, true, nil
}
if l, ok := r.stream.(interface{ Len() int }); ok {
return int64(l.Len()), true, nil
}
if !r.isStreamSeekable {
return 0, false, nil
}
s := r.stream.(io.Seeker)
endOffset, err := s.Seek(0, io.SeekEnd)
if err != nil {
return 0, false, err
}
// The reason to seek to streamStartPos instead of 0 is to ensure that the
// SDK only sends the stream from the starting position the user's
// application provided it to the SDK at. For example application opens a
// file, and wants to skip the first N bytes uploading the rest. The
// application would move the file's offset N bytes, then hand it off to
// the SDK to send the remaining. The SDK should respect that initial offset.
_, err = s.Seek(r.streamStartPos, io.SeekStart)
if err != nil {
return 0, false, err
}
return endOffset - r.streamStartPos, true, nil
}
// RewindStream will rewind the io.Reader to the relative start position if it
// is an io.Seeker.
func (r *Request) RewindStream() error {
// If there is no stream there is nothing to rewind.
if r.stream == nil {
return nil
}
if !r.isStreamSeekable {
return fmt.Errorf("request stream is not seekable")
}
_, err := r.stream.(io.Seeker).Seek(r.streamStartPos, io.SeekStart)
return err
}
// GetStream returns the request stream io.Reader if a stream is set. If no
// stream is present nil will be returned.
func (r *Request) GetStream() io.Reader {
return r.stream
}
// IsStreamSeekable returns whether the stream is seekable.
func (r *Request) IsStreamSeekable() bool {
return r.isStreamSeekable
}
// SetStream returns a clone of the request with the stream set to the provided reader.
// May return an error if the provided reader is seekable but returns an error.
func (r *Request) SetStream(reader io.Reader) (rc *Request, err error) {
rc = r.Clone()
switch v := reader.(type) {
case io.Seeker:
n, err := v.Seek(0, io.SeekCurrent)
if err != nil {
return r, err
}
rc.isStreamSeekable = true
rc.streamStartPos = n
default:
rc.isStreamSeekable = false
}
rc.stream = reader
return rc, err
}
// Build returns a build standard HTTP request value from the Smithy request.
// The request's stream is wrapped in a safe container that allows it to be
// reused for subsequent attempts.
func (r *Request) Build(ctx context.Context) *http.Request {
req := r.Request.Clone(ctx)
if r.stream == nil && req.ContentLength == -1 {
req.ContentLength = 0
}
switch stream := r.stream.(type) {
case *io.PipeReader:
req.Body = ioutil.NopCloser(stream)
req.ContentLength = -1
default:
if r.stream != nil {
req.Body = iointernal.NewSafeReadCloser(ioutil.NopCloser(stream))
}
}
return req
}
// RequestCloner is a function that can take an input request type and clone the request
// for use in a subsequent retry attempt.
func RequestCloner(v interface{}) interface{} {
return v.(*Request).Clone()
}

View File

@ -0,0 +1,34 @@
package http
import (
"fmt"
"net/http"
)
// Response provides the HTTP specific response structure for HTTP specific
// middleware steps to use to deserialize the response from an operation call.
type Response struct {
*http.Response
}
// ResponseError provides the HTTP centric error type wrapping the underlying
// error with the HTTP response value.
type ResponseError struct {
Response *Response
Err error
}
// HTTPStatusCode returns the HTTP response status code received from the service.
func (e *ResponseError) HTTPStatusCode() int { return e.Response.StatusCode }
// HTTPResponse returns the HTTP response received from the service.
func (e *ResponseError) HTTPResponse() *Response { return e.Response }
// Unwrap returns the nested error if any, or nil.
func (e *ResponseError) Unwrap() error { return e.Err }
func (e *ResponseError) Error() string {
return fmt.Sprintf(
"http response error StatusCode: %d, %v",
e.Response.StatusCode, e.Err)
}

13
vendor/github.com/aws/smithy-go/transport/http/time.go generated vendored Normal file
View File

@ -0,0 +1,13 @@
package http
import (
"time"
smithytime "github.com/aws/smithy-go/time"
)
// ParseTime parses a time string like the HTTP Date header. This uses a more
// relaxed rule set for date parsing compared to the standard library.
func ParseTime(text string) (t time.Time, err error) {
return smithytime.ParseHTTPDate(text)
}

44
vendor/github.com/aws/smithy-go/transport/http/url.go generated vendored Normal file
View File

@ -0,0 +1,44 @@
package http
import "strings"
// JoinPath returns an absolute URL path composed of the two paths provided.
// Enforces that the returned path begins with '/'. If added path is empty the
// returned path suffix will match the first parameter suffix.
func JoinPath(a, b string) string {
if len(a) == 0 {
a = "/"
} else if a[0] != '/' {
a = "/" + a
}
if len(b) != 0 && b[0] == '/' {
b = b[1:]
}
if len(b) != 0 && len(a) > 1 && a[len(a)-1] != '/' {
a = a + "/"
}
return a + b
}
// JoinRawQuery returns an absolute raw query expression. Any duplicate '&'
// will be collapsed to single separator between values.
func JoinRawQuery(a, b string) string {
a = strings.TrimFunc(a, isAmpersand)
b = strings.TrimFunc(b, isAmpersand)
if len(a) == 0 {
return b
}
if len(b) == 0 {
return a
}
return a + "&" + b
}
func isAmpersand(v rune) bool {
return v == '&'
}

View File

@ -0,0 +1,37 @@
package http
import (
"strings"
)
// UserAgentBuilder is a builder for a HTTP User-Agent string.
type UserAgentBuilder struct {
sb strings.Builder
}
// NewUserAgentBuilder returns a new UserAgentBuilder.
func NewUserAgentBuilder() *UserAgentBuilder {
return &UserAgentBuilder{sb: strings.Builder{}}
}
// AddKey adds the named component/product to the agent string
func (u *UserAgentBuilder) AddKey(key string) {
u.appendTo(key)
}
// AddKeyValue adds the named key to the agent string with the given value.
func (u *UserAgentBuilder) AddKeyValue(key, value string) {
u.appendTo(key + "/" + value)
}
// Build returns the constructed User-Agent string. May be called multiple times.
func (u *UserAgentBuilder) Build() string {
return u.sb.String()
}
func (u *UserAgentBuilder) appendTo(value string) {
if u.sb.Len() > 0 {
u.sb.WriteRune(' ')
}
u.sb.WriteString(value)
}

140
vendor/github.com/aws/smithy-go/validation.go generated vendored Normal file
View File

@ -0,0 +1,140 @@
package smithy
import (
"bytes"
"fmt"
"strings"
)
// An InvalidParamsError provides wrapping of invalid parameter errors found when
// validating API operation input parameters.
type InvalidParamsError struct {
// Context is the base context of the invalid parameter group.
Context string
errs []InvalidParamError
}
// Add adds a new invalid parameter error to the collection of invalid
// parameters. The context of the invalid parameter will be updated to reflect
// this collection.
func (e *InvalidParamsError) Add(err InvalidParamError) {
err.SetContext(e.Context)
e.errs = append(e.errs, err)
}
// AddNested adds the invalid parameter errors from another InvalidParamsError
// value into this collection. The nested errors will have their nested context
// updated and base context to reflect the merging.
//
// Use for nested validations errors.
func (e *InvalidParamsError) AddNested(nestedCtx string, nested InvalidParamsError) {
for _, err := range nested.errs {
err.SetContext(e.Context)
err.AddNestedContext(nestedCtx)
e.errs = append(e.errs, err)
}
}
// Len returns the number of invalid parameter errors
func (e *InvalidParamsError) Len() int {
return len(e.errs)
}
// Error returns the string formatted form of the invalid parameters.
func (e InvalidParamsError) Error() string {
w := &bytes.Buffer{}
fmt.Fprintf(w, "%d validation error(s) found.\n", len(e.errs))
for _, err := range e.errs {
fmt.Fprintf(w, "- %s\n", err.Error())
}
return w.String()
}
// Errs returns a slice of the invalid parameters
func (e InvalidParamsError) Errs() []error {
errs := make([]error, len(e.errs))
for i := 0; i < len(errs); i++ {
errs[i] = e.errs[i]
}
return errs
}
// An InvalidParamError represents an invalid parameter error type.
type InvalidParamError interface {
error
// Field name the error occurred on.
Field() string
// SetContext updates the context of the error.
SetContext(string)
// AddNestedContext updates the error's context to include a nested level.
AddNestedContext(string)
}
type invalidParamError struct {
context string
nestedContext string
field string
reason string
}
// Error returns the string version of the invalid parameter error.
func (e invalidParamError) Error() string {
return fmt.Sprintf("%s, %s.", e.reason, e.Field())
}
// Field Returns the field and context the error occurred.
func (e invalidParamError) Field() string {
sb := &strings.Builder{}
sb.WriteString(e.context)
if sb.Len() > 0 {
if len(e.nestedContext) == 0 || (len(e.nestedContext) > 0 && e.nestedContext[:1] != "[") {
sb.WriteRune('.')
}
}
if len(e.nestedContext) > 0 {
sb.WriteString(e.nestedContext)
sb.WriteRune('.')
}
sb.WriteString(e.field)
return sb.String()
}
// SetContext updates the base context of the error.
func (e *invalidParamError) SetContext(ctx string) {
e.context = ctx
}
// AddNestedContext prepends a context to the field's path.
func (e *invalidParamError) AddNestedContext(ctx string) {
if len(e.nestedContext) == 0 {
e.nestedContext = ctx
return
}
// Check if our nested context is an index into a slice or map
if e.nestedContext[:1] != "[" {
e.nestedContext = fmt.Sprintf("%s.%s", ctx, e.nestedContext)
return
}
e.nestedContext = ctx + e.nestedContext
}
// An ParamRequiredError represents an required parameter error.
type ParamRequiredError struct {
invalidParamError
}
// NewErrParamRequired creates a new required parameter error.
func NewErrParamRequired(field string) *ParamRequiredError {
return &ParamRequiredError{
invalidParamError{
field: field,
reason: fmt.Sprintf("missing required field"),
},
}
}